source: mainline/uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c@ 6ab189f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6ab189f was 943a1dc6, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

amdm37x_dispc: Set workhorse function on mode switch.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 * Copyright (c) 2013 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup amdm37x
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <ddf/log.h>
39#include <ddi.h>
40#include <abi/mm/as.h>
41
42#include "amdm37x_dispc.h"
43
44
45static int change_mode(visualizer_t *vis, vslmode_t mode);
46static int handle_damage(visualizer_t *vs,
47 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
48 sysarg_t x_offset, sysarg_t y_offset);
49
50static const visualizer_ops_t amdm37x_dispc_vis_ops = {
51 .change_mode = change_mode,
52 .handle_damage = handle_damage,
53 // TODO DO we need dummy implementations of stuff like claim, yield, ...
54};
55
56
57static const struct {
58 unsigned bpp;
59 pixel2visual_t func;
60} pixel2visual_table[] = {
61 [VISUAL_INDIRECT_8] = { .bpp = 1, .func = pixel2bgr_323 },
62 [VISUAL_RGB_5_5_5_LE] = { .bpp = 2, .func = pixel2rgb_555_le },
63 [VISUAL_RGB_5_5_5_BE] = { .bpp = 2, .func = pixel2rgb_555_be },
64 [VISUAL_RGB_5_6_5_LE] = { .bpp = 2, .func = pixel2rgb_565_le },
65 [VISUAL_RGB_5_6_5_BE] = { .bpp = 2, .func = pixel2rgb_565_be },
66 [VISUAL_BGR_8_8_8] = { .bpp = 3, .func = pixel2bgr_888 },
67 [VISUAL_RGB_8_8_8] = { .bpp = 3, .func = pixel2rgb_888 },
68 [VISUAL_BGR_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
69 [VISUAL_BGR_8_8_8_0] = { .bpp = 4, .func = pixel2bgr_8880 },
70 [VISUAL_ABGR_8_8_8_8] = { .bpp = 4, .func = pixel2abgr_8888 },
71 [VISUAL_BGRA_8_8_8_8] = { .bpp = 4, .func = pixel2bgra_8888 },
72 [VISUAL_RGB_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
73 [VISUAL_RGB_8_8_8_0] = { .bpp = 4, .func = pixel2rgb_8880 },
74 [VISUAL_ARGB_8_8_8_8] = { .bpp = 4, .func = pixel2argb_8888 },
75 [VISUAL_RGBA_8_8_8_8] = { .bpp = 4, .func = pixel2rgba_8888 },
76};
77
78
79
80static void mode_init(vslmode_list_element_t *mode,
81 unsigned width, unsigned height, visual_t visual)
82{
83 mode->mode.index = 0;
84 mode->mode.version = 0;
85 mode->mode.refresh_rate = 0;
86 mode->mode.screen_aspect.width = width;
87 mode->mode.screen_aspect.height = height;
88 mode->mode.screen_width = width;
89 mode->mode.screen_height = height;
90 mode->mode.cell_aspect.width = 1;
91 mode->mode.cell_aspect.height = 1;
92 mode->mode.cell_visual.pixel_visual = visual;
93
94 link_initialize(&mode->link);
95
96}
97
98int amdm37x_dispc_init(amdm37x_dispc_t *instance, visualizer_t *vis)
99{
100 assert(instance);
101 assert(vis);
102
103 instance->fb_data = NULL;
104 instance->size = 0;
105
106 visual_t visual = VISUAL_UNKNOWN;
107
108 switch (CONFIG_BFB_BPP) {
109 case 8: visual = VISUAL_INDIRECT_8; break;
110 case 16: visual = VISUAL_RGB_5_6_5_LE; break;
111 case 24: visual = VISUAL_BGR_8_8_8; break;
112 case 32: visual = VISUAL_RGB_8_8_8_0; break;
113 default:
114 return EINVAL;
115 }
116
117 int ret = pio_enable((void*)AMDM37x_DISPC_BASE_ADDRESS,
118 AMDM37x_DISPC_SIZE, (void**)&instance->regs);
119 if (ret != EOK) {
120 return EIO;
121 }
122
123 mode_init(&instance->modes[0],
124 CONFIG_BFB_WIDTH, CONFIG_BFB_HEIGHT, visual);
125
126 /* Handle vis stuff */
127 vis->dev_ctx = instance;
128 vis->def_mode_idx = 0;
129 list_append(&instance->modes[0].link, &vis->modes);
130
131 return EOK;
132};
133
134int amdm37x_dispc_fini(amdm37x_dispc_t *instance)
135{
136 return EOK;
137};
138
139static int amdm37x_dispc_setup_fb(amdm37x_dispc_regs_t *regs,
140 unsigned x, unsigned y, unsigned bpp, uint32_t pa)
141{
142 assert(regs);
143 /* Init sequence for dispc is in chapter 7.6.5.1.4 p. 1810,
144 * no idea what parts of that work. */
145
146 /* Disable all interrupts */
147 regs->irqenable = 0;
148
149 /* Pixel format specifics*/
150 uint32_t attrib_pixel_format = 0;
151 uint32_t control_data_lanes = 0;
152 switch (bpp)
153 {
154 case 32:
155 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX;
156 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
157 break;
158 case 24:
159 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24;
160 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
161 break;
162 case 16:
163 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16;
164 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_16B;
165 break;
166 default:
167 return EINVAL;
168 }
169
170 /* Prepare sizes */
171 const uint32_t size_reg =
172 (((x - 1) & AMDM37X_DISPC_SIZE_WIDTH_MASK)
173 << AMDM37X_DISPC_SIZE_WIDTH_SHIFT) |
174 (((y - 1) & AMDM37X_DISPC_SIZE_HEIGHT_MASK)
175 << AMDM37X_DISPC_SIZE_HEIGHT_SHIFT);
176
177 /* modes taken from u-boot, for 1024x768 */
178 // TODO replace magic values with actual correct values
179// regs->timing_h = 0x1a4024c9;
180// regs->timing_v = 0x02c00509;
181// regs->pol_freq = 0x00007028;
182// regs->divisor = 0x00010001;
183
184 /* setup output */
185 regs->size_lcd = size_reg;
186 regs->size_dig = size_reg;
187
188 /* Nice blue default color */
189 regs->default_color[0] = 0x0000ff;
190 regs->default_color[1] = 0x0000ff;
191
192 /* Setup control register */
193 uint32_t control = 0 |
194 AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG |
195 (control_data_lanes << AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT) |
196 AMDM37X_DISPC_CONTROL_GPOUT0_FLAG |
197 AMDM37X_DISPC_CONTROL_GPOUT1_FLAG;
198 regs->control = control;
199
200 /* No gamma stuff only data */
201 uint32_t config = (AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME
202 << AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT);
203 regs->config = config;
204
205
206 /* Set framebuffer base address */
207 regs->gfx.ba[0] = pa;
208 regs->gfx.ba[1] = pa;
209 regs->gfx.position = 0;
210
211 /* Setup fb size */
212 regs->gfx.size = size_reg;
213
214 /* Set pixel format */
215 uint32_t attribs = 0 |
216 (attrib_pixel_format << AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT);
217 regs->gfx.attributes = attribs;
218
219 /* 0x03ff03c0 is the default */
220 regs->gfx.fifo_threshold = 0x03ff03c0;
221 /* This value should be stride - width, 1 means next pixel i.e.
222 * stride == width */
223 regs->gfx.row_inc = 1;
224 /* number of bytes to next pixel in BPP multiples */
225 regs->gfx.pixel_inc = 1;
226 /* only used if video is played over fb */
227 regs->gfx.window_skip = 0;
228 /* Gamma and palette table */
229 regs->gfx.table_ba = 0;
230
231 /* enable frame buffer graphics */
232 regs->gfx.attributes |= AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG;
233 /* Update register values */
234 regs->control |= AMDM37X_DISPC_CONTROL_GOLCD_FLAG;
235 regs->control |= AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG;
236 /* Enable output */
237 regs->control |= AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG;
238 regs->control |= AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG;
239}
240
241static int change_mode(visualizer_t *vis, vslmode_t mode)
242{
243 assert(vis);
244 assert(vis->dev_ctx);
245
246 amdm37x_dispc_t *dispc = vis->dev_ctx;
247 const visual_t visual = mode.cell_visual.pixel_visual;
248 assert(visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
249 const unsigned bpp = pixel2visual_table[visual].bpp;
250 pixel2visual_t p2v = pixel2visual_table[visual].func;
251 const unsigned x = mode.screen_width;
252 const unsigned y = mode.screen_height;
253 ddf_log_note("Setting mode: %ux%ux%u\n", x, y, bpp);
254 const size_t size = x * y * bpp;
255 void *buffer, *pa;
256 int ret = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE,
257 0, &pa, &buffer);
258 if (ret != EOK) {
259 ddf_log_error("Failed to get new FB\n");
260 return ret;
261 }
262 amdm37x_dispc_setup_fb(dispc->regs, x, y, bpp, (uint32_t)pa);
263 dispc->active_fb.idx = mode.index;
264 dispc->active_fb.width = x;
265 dispc->active_fb.height = y;
266 dispc->active_fb.pitch = 0;
267 dispc->active_fb.bpp = bpp;
268 dispc->active_fb.pixel2visual = p2v;
269 assert(mode.index < 1);
270
271 if (dispc->fb_data)
272 dmamem_unmap_anonymous(dispc->fb_data);
273 return EOK;
274}
275
276static int handle_damage(visualizer_t *vs,
277 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
278 sysarg_t x_offset, sysarg_t y_offset)
279{
280 assert(vs);
281 assert(vs->dev_ctx);
282 amdm37x_dispc_t *dispc = vs->dev_ctx;
283 pixelmap_t *map = &vs->cells;
284
285#define FB_POS(x, y) \
286 (((y) * (dispc->active_fb.width + dispc->active_fb.pitch) + (x)) \
287 * dispc->active_fb.bpp)
288 if (x_offset == 0 && y_offset == 0) {
289 /* Faster damage routine ignoring offsets. */
290 for (sysarg_t y = y0; y < height + y0; ++y) {
291 pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
292 for (sysarg_t x = x0; x < width + x0; ++x) {
293 dispc->active_fb.pixel2visual(
294 dispc->fb_data + FB_POS(x, y), *pixel++);
295 }
296 }
297 } else {
298 for (sysarg_t y = y0; y < height + y0; ++y) {
299 for (sysarg_t x = x0; x < width + x0; ++x) {
300 dispc->active_fb.pixel2visual(
301 dispc->fb_data + FB_POS(x, y),
302 *pixelmap_pixel_at(map,
303 (x + x_offset) % map->width,
304 (y + y_offset) % map->height));
305 }
306 }
307 }
308
309 ddf_log_note("Handling damage\n");
310 return EOK;
311}
312
Note: See TracBrowser for help on using the repository browser.