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

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

amdm37x_dispc: Unmap the old buffer, not the new.

Fixes #608

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