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

Last change on this file since f08da1c 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
RevLine 
[9cc4b2b4]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
[4122410]29/** @addtogroup amdm37x_dispc
[9cc4b2b4]30 * @{
31 */
32/**
33 * @file
34 */
35
[8e4a408]36#include <align.h>
[96228d0]37#include <assert.h>
[9cc4b2b4]38#include <errno.h>
[7fa2031]39#include <ddf/log.h>
40#include <ddi.h>
[bf9cb2f]41#include <as.h>
[9cc4b2b4]42
43#include "amdm37x_dispc.h"
44
[0e63d34]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
[b7fd2a0]57static errno_t change_mode(visualizer_t *vis, vslmode_t mode);
58static errno_t handle_damage(visualizer_t *vs,
[96228d0]59 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
[7fa2031]60 sysarg_t x_offset, sysarg_t y_offset);
[b7fd2a0]61static errno_t dummy(visualizer_t *vs)
[c7d11a0b]62{
63 return EOK;
64}
[96228d0]65
66static const visualizer_ops_t amdm37x_dispc_vis_ops = {
[7fa2031]67 .change_mode = change_mode,
[96228d0]68 .handle_damage = handle_damage,
[c7d11a0b]69 .claim = dummy,
70 .yield = dummy,
71 .suspend = dummy,
72 .wakeup = dummy,
[96228d0]73};
74
[943a1dc6]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
[96228d0]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;
[9cc4b2b4]109
[96228d0]110 link_initialize(&mode->link);
111
112}
113
[b7fd2a0]114errno_t amdm37x_dispc_init(amdm37x_dispc_t *instance, visualizer_t *vis)
[9cc4b2b4]115{
[96228d0]116 assert(instance);
117 assert(vis);
118
[7fa2031]119 instance->fb_data = NULL;
120 instance->size = 0;
121
[0e63d34]122 /* Default is 24bpp, use config option if available */
123 visual_t visual = VISUAL_BGR_8_8_8;
[7fa2031]124 switch (CONFIG_BFB_BPP) {
[3bacee1]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;
[7fa2031]137 default:
138 return EINVAL;
139 }
[96228d0]140
[3bacee1]141 errno_t ret = pio_enable((void *)AMDM37x_DISPC_BASE_ADDRESS,
142 AMDM37x_DISPC_SIZE, (void **)&instance->regs);
[7fa2031]143 if (ret != EOK) {
144 return EIO;
145 }
146
147 mode_init(&instance->modes[0],
148 CONFIG_BFB_WIDTH, CONFIG_BFB_HEIGHT, visual);
[96228d0]149
150 /* Handle vis stuff */
151 vis->dev_ctx = instance;
152 vis->def_mode_idx = 0;
[c7d11a0b]153 vis->ops = amdm37x_dispc_vis_ops;
[96228d0]154 list_append(&instance->modes[0].link, &vis->modes);
155
[9cc4b2b4]156 return EOK;
[850fd32]157}
[9cc4b2b4]158
[b7fd2a0]159errno_t amdm37x_dispc_fini(amdm37x_dispc_t *instance)
[9cc4b2b4]160{
161 return EOK;
[850fd32]162}
[9cc4b2b4]163
[b7fd2a0]164static errno_t amdm37x_dispc_setup_fb(amdm37x_dispc_regs_t *regs,
[7fa2031]165 unsigned x, unsigned y, unsigned bpp, uint32_t pa)
166{
167 assert(regs);
[7c3fb9b]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 */
[7fa2031]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;
[3bacee1]179 switch (bpp) {
[7fa2031]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 =
[3bacee1]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);
[7fa2031]202
203 /* modes taken from u-boot, for 1024x768 */
204 // TODO replace magic values with actual correct values
[3fafe5e0]205#if 0
206 regs->timing_h = 0x1a4024c9;
207 regs->timing_v = 0x02c00509;
208 regs->pol_freq = 0x00007028;
209 regs->divisor = 0x00010001;
210#endif
[7fa2031]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 |
[3bacee1]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;
[7fa2031]226 regs->control = control;
227
228 /* No gamma stuff only data */
[3bacee1]229 uint32_t config = (AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME <<
230 AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT);
[7fa2031]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;
[7c3fb9b]248 /*
249 * This value should be stride - width, 1 means next pixel i.e.
250 * stride == width
251 */
[7fa2031]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;
[c7d11a0b]268 return EOK;
[7fa2031]269}
270
[b7fd2a0]271static errno_t change_mode(visualizer_t *vis, vslmode_t mode)
[7fa2031]272{
273 assert(vis);
274 assert(vis->dev_ctx);
275
276 amdm37x_dispc_t *dispc = vis->dev_ctx;
[f03f107]277 const visual_t visual = mode.cell_visual.pixel_visual;
[05b59393]278 assert((size_t)visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
[943a1dc6]279 const unsigned bpp = pixel2visual_table[visual].bpp;
280 pixel2visual_t p2v = pixel2visual_table[visual].func;
[7fa2031]281 const unsigned x = mode.screen_width;
282 const unsigned y = mode.screen_height;
[3bacee1]283 ddf_log_note("Setting mode: %ux%ux%u\n", x, y, bpp * 8);
[c7d11a0b]284 const size_t size = ALIGN_UP(x * y * bpp, PAGE_SIZE);
[8442d10]285 uintptr_t pa;
[bf9cb2f]286 void *buffer = AS_AREA_ANY;
[b7fd2a0]287 errno_t ret = dmamem_map_anonymous(size, DMAMEM_4GiB,
[8442d10]288 AS_AREA_READ | AS_AREA_WRITE, 0, &pa, &buffer);
[7fa2031]289 if (ret != EOK) {
290 ddf_log_error("Failed to get new FB\n");
291 return ret;
292 }
[0683992]293 if (dispc->fb_data)
294 dmamem_unmap_anonymous(dispc->fb_data);
[a35b458]295
[0683992]296 dispc->fb_data = buffer;
[3bacee1]297 amdm37x_dispc_setup_fb(dispc->regs, x, y, bpp * 8, (uint32_t)pa);
[f03f107]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;
[943a1dc6]303 dispc->active_fb.pixel2visual = p2v;
[c7d11a0b]304 dispc->size = size;
[f03f107]305 assert(mode.index < 1);
[7fa2031]306
307 return EOK;
308}
[f03f107]309
[b7fd2a0]310static errno_t handle_damage(visualizer_t *vs,
[f03f107]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) {
[943a1dc6]327 dispc->active_fb.pixel2visual(
[f03f107]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) {
[943a1dc6]334 dispc->active_fb.pixel2visual(
[f03f107]335 dispc->fb_data + FB_POS(x, y),
336 *pixelmap_pixel_at(map,
[3bacee1]337 (x + x_offset) % map->width,
338 (y + y_offset) % map->height));
[f03f107]339 }
340 }
341 }
342
343 return EOK;
344}
[4122410]345
346/**
347 * @}
348 */
Note: See TracBrowser for help on using the repository browser.