source: mainline/uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c@ 6068476

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6068476 was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

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