source: mainline/uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c@ 35ab943

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

arm32: Fix build failures.

  • Property mode set to 100644
File size: 9.8 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#ifndef CONFIG_BFB_BPP
45#define CONFIG_BFB_BPP 24
46#endif
47
48#ifndef CONFIG_BFB_WIDTH
49#define CONFIG_BFB_WIDTH 1024
50#endif
51
52#ifndef CONFIG_BFB_HEIGHT
53#define CONFIG_BFB_HEIGHT 768
54#endif
55
56
57static int change_mode(visualizer_t *vis, vslmode_t mode);
58static int handle_damage(visualizer_t *vs,
59 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
60 sysarg_t x_offset, sysarg_t y_offset);
61static int dummy(visualizer_t *vs)
62{
63 return EOK;
64}
65
66static const visualizer_ops_t amdm37x_dispc_vis_ops = {
67 .change_mode = change_mode,
68 .handle_damage = handle_damage,
69 .claim = dummy,
70 .yield = dummy,
71 .suspend = dummy,
72 .wakeup = dummy,
73};
74
75static const struct {
76 unsigned bpp;
77 pixel2visual_t func;
78} pixel2visual_table[] = {
79 [VISUAL_INDIRECT_8] = { .bpp = 1, .func = pixel2bgr_323 },
80 [VISUAL_RGB_5_5_5_LE] = { .bpp = 2, .func = pixel2rgb_555_le },
81 [VISUAL_RGB_5_5_5_BE] = { .bpp = 2, .func = pixel2rgb_555_be },
82 [VISUAL_RGB_5_6_5_LE] = { .bpp = 2, .func = pixel2rgb_565_le },
83 [VISUAL_RGB_5_6_5_BE] = { .bpp = 2, .func = pixel2rgb_565_be },
84 [VISUAL_BGR_8_8_8] = { .bpp = 3, .func = pixel2bgr_888 },
85 [VISUAL_RGB_8_8_8] = { .bpp = 3, .func = pixel2rgb_888 },
86 [VISUAL_BGR_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
87 [VISUAL_BGR_8_8_8_0] = { .bpp = 4, .func = pixel2bgr_8880 },
88 [VISUAL_ABGR_8_8_8_8] = { .bpp = 4, .func = pixel2abgr_8888 },
89 [VISUAL_BGRA_8_8_8_8] = { .bpp = 4, .func = pixel2bgra_8888 },
90 [VISUAL_RGB_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
91 [VISUAL_RGB_8_8_8_0] = { .bpp = 4, .func = pixel2rgb_8880 },
92 [VISUAL_ARGB_8_8_8_8] = { .bpp = 4, .func = pixel2argb_8888 },
93 [VISUAL_RGBA_8_8_8_8] = { .bpp = 4, .func = pixel2rgba_8888 },
94};
95
96
97
98static void mode_init(vslmode_list_element_t *mode,
99 unsigned width, unsigned height, visual_t visual)
100{
101 mode->mode.index = 0;
102 mode->mode.version = 0;
103 mode->mode.refresh_rate = 0;
104 mode->mode.screen_aspect.width = width;
105 mode->mode.screen_aspect.height = height;
106 mode->mode.screen_width = width;
107 mode->mode.screen_height = height;
108 mode->mode.cell_aspect.width = 1;
109 mode->mode.cell_aspect.height = 1;
110 mode->mode.cell_visual.pixel_visual = visual;
111
112 link_initialize(&mode->link);
113
114}
115
116int amdm37x_dispc_init(amdm37x_dispc_t *instance, visualizer_t *vis)
117{
118 assert(instance);
119 assert(vis);
120
121 instance->fb_data = NULL;
122 instance->size = 0;
123
124 /* Default is 24bpp, use config option if available */
125 visual_t visual = VISUAL_BGR_8_8_8;
126 switch (CONFIG_BFB_BPP) {
127 case 8: visual = VISUAL_INDIRECT_8; break;
128 case 16: visual = VISUAL_RGB_5_6_5_LE; break;
129 case 24: visual = VISUAL_BGR_8_8_8; break;
130 case 32: visual = VISUAL_RGB_8_8_8_0; break;
131 default:
132 return EINVAL;
133 }
134
135 int ret = pio_enable((void*)AMDM37x_DISPC_BASE_ADDRESS,
136 AMDM37x_DISPC_SIZE, (void**)&instance->regs);
137 if (ret != EOK) {
138 return EIO;
139 }
140
141 mode_init(&instance->modes[0],
142 CONFIG_BFB_WIDTH, CONFIG_BFB_HEIGHT, visual);
143
144 /* Handle vis stuff */
145 vis->dev_ctx = instance;
146 vis->def_mode_idx = 0;
147 vis->ops = amdm37x_dispc_vis_ops;
148 list_append(&instance->modes[0].link, &vis->modes);
149
150 return EOK;
151};
152
153int amdm37x_dispc_fini(amdm37x_dispc_t *instance)
154{
155 return EOK;
156};
157
158static int amdm37x_dispc_setup_fb(amdm37x_dispc_regs_t *regs,
159 unsigned x, unsigned y, unsigned bpp, uint32_t pa)
160{
161 assert(regs);
162 /* Init sequence for dispc is in chapter 7.6.5.1.4 p. 1810,
163 * no idea what parts of that work. */
164
165 /* Disable all interrupts */
166 regs->irqenable = 0;
167
168 /* Pixel format specifics*/
169 uint32_t attrib_pixel_format = 0;
170 uint32_t control_data_lanes = 0;
171 switch (bpp)
172 {
173 case 32:
174 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX;
175 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
176 break;
177 case 24:
178 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24;
179 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
180 break;
181 case 16:
182 attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16;
183 control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_16B;
184 break;
185 default:
186 return EINVAL;
187 }
188
189 /* Prepare sizes */
190 const uint32_t size_reg =
191 (((x - 1) & AMDM37X_DISPC_SIZE_WIDTH_MASK)
192 << AMDM37X_DISPC_SIZE_WIDTH_SHIFT) |
193 (((y - 1) & AMDM37X_DISPC_SIZE_HEIGHT_MASK)
194 << AMDM37X_DISPC_SIZE_HEIGHT_SHIFT);
195
196 /* modes taken from u-boot, for 1024x768 */
197 // TODO replace magic values with actual correct values
198// regs->timing_h = 0x1a4024c9;
199// regs->timing_v = 0x02c00509;
200// regs->pol_freq = 0x00007028;
201// regs->divisor = 0x00010001;
202
203 /* setup output */
204 regs->size_lcd = size_reg;
205 regs->size_dig = size_reg;
206
207 /* Nice blue default color */
208 regs->default_color[0] = 0x0000ff;
209 regs->default_color[1] = 0x0000ff;
210
211 /* Setup control register */
212 uint32_t control = 0 |
213 AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG |
214 (control_data_lanes << AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT) |
215 AMDM37X_DISPC_CONTROL_GPOUT0_FLAG |
216 AMDM37X_DISPC_CONTROL_GPOUT1_FLAG;
217 regs->control = control;
218
219 /* No gamma stuff only data */
220 uint32_t config = (AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME
221 << AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT);
222 regs->config = config;
223
224
225 /* Set framebuffer base address */
226 regs->gfx.ba[0] = pa;
227 regs->gfx.ba[1] = pa;
228 regs->gfx.position = 0;
229
230 /* Setup fb size */
231 regs->gfx.size = size_reg;
232
233 /* Set pixel format */
234 uint32_t attribs = 0 |
235 (attrib_pixel_format << AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT);
236 regs->gfx.attributes = attribs;
237
238 /* 0x03ff03c0 is the default */
239 regs->gfx.fifo_threshold = 0x03ff03c0;
240 /* This value should be stride - width, 1 means next pixel i.e.
241 * stride == width */
242 regs->gfx.row_inc = 1;
243 /* number of bytes to next pixel in BPP multiples */
244 regs->gfx.pixel_inc = 1;
245 /* only used if video is played over fb */
246 regs->gfx.window_skip = 0;
247 /* Gamma and palette table */
248 regs->gfx.table_ba = 0;
249
250 /* enable frame buffer graphics */
251 regs->gfx.attributes |= AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG;
252 /* Update register values */
253 regs->control |= AMDM37X_DISPC_CONTROL_GOLCD_FLAG;
254 regs->control |= AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG;
255 /* Enable output */
256 regs->control |= AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG;
257 regs->control |= AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG;
258 return EOK;
259}
260
261static int change_mode(visualizer_t *vis, vslmode_t mode)
262{
263 assert(vis);
264 assert(vis->dev_ctx);
265
266 amdm37x_dispc_t *dispc = vis->dev_ctx;
267 const visual_t visual = mode.cell_visual.pixel_visual;
268 assert(visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
269 const unsigned bpp = pixel2visual_table[visual].bpp;
270 pixel2visual_t p2v = pixel2visual_table[visual].func;
271 const unsigned x = mode.screen_width;
272 const unsigned y = mode.screen_height;
273 ddf_log_note("Setting mode: %ux%ux%u\n", x, y, bpp*8);
274 const size_t size = ALIGN_UP(x * y * bpp, PAGE_SIZE);
275 void *buffer, *pa;
276 int ret = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE,
277 0, &pa, &buffer);
278 if (ret != EOK) {
279 ddf_log_error("Failed to get new FB\n");
280 return ret;
281 }
282 amdm37x_dispc_setup_fb(dispc->regs, x, y, bpp *8, (uint32_t)pa);
283 dispc->active_fb.idx = mode.index;
284 dispc->active_fb.width = x;
285 dispc->active_fb.height = y;
286 dispc->active_fb.pitch = 0;
287 dispc->active_fb.bpp = bpp;
288 dispc->active_fb.pixel2visual = p2v;
289 dispc->fb_data = buffer;
290 dispc->size = size;
291 assert(mode.index < 1);
292
293 if (dispc->fb_data)
294 dmamem_unmap_anonymous(dispc->fb_data);
295 return EOK;
296}
297
298static int handle_damage(visualizer_t *vs,
299 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
300 sysarg_t x_offset, sysarg_t y_offset)
301{
302 assert(vs);
303 assert(vs->dev_ctx);
304 amdm37x_dispc_t *dispc = vs->dev_ctx;
305 pixelmap_t *map = &vs->cells;
306
307#define FB_POS(x, y) \
308 (((y) * (dispc->active_fb.width + dispc->active_fb.pitch) + (x)) \
309 * dispc->active_fb.bpp)
310 if (x_offset == 0 && y_offset == 0) {
311 /* Faster damage routine ignoring offsets. */
312 for (sysarg_t y = y0; y < height + y0; ++y) {
313 pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
314 for (sysarg_t x = x0; x < width + x0; ++x) {
315 dispc->active_fb.pixel2visual(
316 dispc->fb_data + FB_POS(x, y), *pixel++);
317 }
318 }
319 } else {
320 for (sysarg_t y = y0; y < height + y0; ++y) {
321 for (sysarg_t x = x0; x < width + x0; ++x) {
322 dispc->active_fb.pixel2visual(
323 dispc->fb_data + FB_POS(x, y),
324 *pixelmap_pixel_at(map,
325 (x + x_offset) % map->width,
326 (y + y_offset) % map->height));
327 }
328 }
329 }
330
331 return EOK;
332}
Note: See TracBrowser for help on using the repository browser.