]> Git Repo - J-u-boot.git/blame - drivers/video/imx/mxc_ipuv3_fb.c
common: Drop net.h from common header
[J-u-boot.git] / drivers / video / imx / mxc_ipuv3_fb.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
5dda7945
SB
2/*
3 * Porting to u-boot:
4 *
5 * (C) Copyright 2010
6 * Stefano Babic, DENX Software Engineering, [email protected]
7 *
8 * MX51 Linux framebuffer:
9 *
10 * (C) Copyright 2004-2010 Freescale Semiconductor, Inc.
5dda7945
SB
11 */
12
5dda7945 13#include <common.h>
90526e9f 14#include <asm/cache.h>
1221ce45 15#include <linux/errno.h>
a69214dc 16#include <asm/global_data.h>
5dda7945
SB
17#include <linux/string.h>
18#include <linux/list.h>
19#include <linux/fb.h>
20#include <asm/io.h>
57f065fe 21#include <asm/mach-imx/video.h>
5dda7945 22#include <malloc.h>
e9934f0b 23#include <video_fb.h>
bffd1314 24#include "../videomodes.h"
5dda7945
SB
25#include "ipu.h"
26#include "mxcfb.h"
5f8e17ce 27#include "ipu_regs.h"
f4ec1ae0 28#include "display.h"
42a7ce27 29#include <panel.h>
5dda7945 30
57f065fe
AG
31#include <dm.h>
32#include <video.h>
33
a69214dc
EN
34DECLARE_GLOBAL_DATA_PTR;
35
5dda7945
SB
36static int mxcfb_map_video_memory(struct fb_info *fbi);
37static int mxcfb_unmap_video_memory(struct fb_info *fbi);
38
e9934f0b
SB
39/* graphics setup */
40static GraphicDevice panel;
09c8bb26 41static struct fb_videomode const *gmode;
02ae1a18
MV
42static uint8_t gdisp;
43static uint32_t gpixfmt;
5dda7945 44
c5fe2532 45static void fb_videomode_to_var(struct fb_var_screeninfo *var,
5dda7945
SB
46 const struct fb_videomode *mode)
47{
48 var->xres = mode->xres;
49 var->yres = mode->yres;
50 var->xres_virtual = mode->xres;
51 var->yres_virtual = mode->yres;
52 var->xoffset = 0;
53 var->yoffset = 0;
54 var->pixclock = mode->pixclock;
55 var->left_margin = mode->left_margin;
56 var->right_margin = mode->right_margin;
57 var->upper_margin = mode->upper_margin;
58 var->lower_margin = mode->lower_margin;
59 var->hsync_len = mode->hsync_len;
60 var->vsync_len = mode->vsync_len;
61 var->sync = mode->sync;
62 var->vmode = mode->vmode & FB_VMODE_MASK;
63}
64
65/*
66 * Structure containing the MXC specific framebuffer information.
67 */
68struct mxcfb_info {
69 int blank;
70 ipu_channel_t ipu_ch;
71 int ipu_di;
72 u32 ipu_di_pix_fmt;
73 unsigned char overlay;
74 unsigned char alpha_chan_en;
75 dma_addr_t alpha_phy_addr0;
76 dma_addr_t alpha_phy_addr1;
77 void *alpha_virt_addr0;
78 void *alpha_virt_addr1;
79 uint32_t alpha_mem_len;
80 uint32_t cur_ipu_buf;
81 uint32_t cur_ipu_alpha_buf;
82
83 u32 pseudo_palette[16];
84};
85
86enum {
87 BOTH_ON,
88 SRC_ON,
89 TGT_ON,
90 BOTH_OFF
91};
92
93static unsigned long default_bpp = 16;
94static unsigned char g_dp_in_use;
95static struct fb_info *mxcfb_info[3];
96static int ext_clk_used;
97
98static uint32_t bpp_to_pixfmt(struct fb_info *fbi)
99{
100 uint32_t pixfmt = 0;
101
102 debug("bpp_to_pixfmt: %d\n", fbi->var.bits_per_pixel);
103
104 if (fbi->var.nonstd)
105 return fbi->var.nonstd;
106
107 switch (fbi->var.bits_per_pixel) {
108 case 24:
109 pixfmt = IPU_PIX_FMT_BGR24;
110 break;
111 case 32:
112 pixfmt = IPU_PIX_FMT_BGR32;
113 break;
114 case 16:
115 pixfmt = IPU_PIX_FMT_RGB565;
116 break;
117 }
118 return pixfmt;
119}
120
121/*
122 * Set fixed framebuffer parameters based on variable settings.
123 *
124 * @param info framebuffer information pointer
125 */
126static int mxcfb_set_fix(struct fb_info *info)
127{
128 struct fb_fix_screeninfo *fix = &info->fix;
129 struct fb_var_screeninfo *var = &info->var;
130
131 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
132
133 fix->type = FB_TYPE_PACKED_PIXELS;
134 fix->accel = FB_ACCEL_NONE;
135 fix->visual = FB_VISUAL_TRUECOLOR;
136 fix->xpanstep = 1;
137 fix->ypanstep = 1;
138
139 return 0;
140}
141
142static int setup_disp_channel1(struct fb_info *fbi)
143{
144 ipu_channel_params_t params;
145 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
146
147 memset(&params, 0, sizeof(params));
148 params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
149
150 debug("%s called\n", __func__);
151 /*
152 * Assuming interlaced means yuv output, below setting also
153 * valid for mem_dc_sync. FG should have the same vmode as BG.
154 */
155 if (fbi->var.vmode & FB_VMODE_INTERLACED) {
156 params.mem_dp_bg_sync.interlaced = 1;
157 params.mem_dp_bg_sync.out_pixel_fmt =
158 IPU_PIX_FMT_YUV444;
159 } else {
160 if (mxc_fbi->ipu_di_pix_fmt) {
161 params.mem_dp_bg_sync.out_pixel_fmt =
162 mxc_fbi->ipu_di_pix_fmt;
163 } else {
164 params.mem_dp_bg_sync.out_pixel_fmt =
165 IPU_PIX_FMT_RGB666;
166 }
167 }
168 params.mem_dp_bg_sync.in_pixel_fmt = bpp_to_pixfmt(fbi);
169 if (mxc_fbi->alpha_chan_en)
170 params.mem_dp_bg_sync.alpha_chan_en = 1;
171
172 ipu_init_channel(mxc_fbi->ipu_ch, &params);
173
174 return 0;
175}
176
177static int setup_disp_channel2(struct fb_info *fbi)
178{
179 int retval = 0;
180 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
181
182 mxc_fbi->cur_ipu_buf = 1;
183 if (mxc_fbi->alpha_chan_en)
184 mxc_fbi->cur_ipu_alpha_buf = 1;
185
186 fbi->var.xoffset = fbi->var.yoffset = 0;
187
188 debug("%s: %x %d %d %d %lx %lx\n",
189 __func__,
190 mxc_fbi->ipu_ch,
191 fbi->var.xres,
192 fbi->var.yres,
193 fbi->fix.line_length,
194 fbi->fix.smem_start,
195 fbi->fix.smem_start +
196 (fbi->fix.line_length * fbi->var.yres));
197
198 retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
199 bpp_to_pixfmt(fbi),
200 fbi->var.xres, fbi->var.yres,
201 fbi->fix.line_length,
202 fbi->fix.smem_start +
203 (fbi->fix.line_length * fbi->var.yres),
204 fbi->fix.smem_start,
205 0, 0);
206 if (retval)
207 printf("ipu_init_channel_buffer error %d\n", retval);
208
209 return retval;
210}
211
212/*
213 * Set framebuffer parameters and change the operating mode.
214 *
215 * @param info framebuffer information pointer
216 */
217static int mxcfb_set_par(struct fb_info *fbi)
218{
219 int retval = 0;
220 u32 mem_len;
221 ipu_di_signal_cfg_t sig_cfg;
222 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
223 uint32_t out_pixel_fmt;
224
225 ipu_disable_channel(mxc_fbi->ipu_ch);
226 ipu_uninit_channel(mxc_fbi->ipu_ch);
227 mxcfb_set_fix(fbi);
228
229 mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
230 if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {
231 if (fbi->fix.smem_start)
232 mxcfb_unmap_video_memory(fbi);
233
234 if (mxcfb_map_video_memory(fbi) < 0)
235 return -ENOMEM;
236 }
237
238 setup_disp_channel1(fbi);
239
240 memset(&sig_cfg, 0, sizeof(sig_cfg));
241 if (fbi->var.vmode & FB_VMODE_INTERLACED) {
242 sig_cfg.interlaced = 1;
243 out_pixel_fmt = IPU_PIX_FMT_YUV444;
244 } else {
245 if (mxc_fbi->ipu_di_pix_fmt)
246 out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
247 else
248 out_pixel_fmt = IPU_PIX_FMT_RGB666;
249 }
250 if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
251 sig_cfg.odd_field_first = 1;
252 if ((fbi->var.sync & FB_SYNC_EXT) || ext_clk_used)
253 sig_cfg.ext_clk = 1;
254 if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
255 sig_cfg.Hsync_pol = 1;
256 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
257 sig_cfg.Vsync_pol = 1;
258 if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))
259 sig_cfg.clk_pol = 1;
260 if (fbi->var.sync & FB_SYNC_DATA_INVERT)
261 sig_cfg.data_pol = 1;
262 if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
263 sig_cfg.enable_pol = 1;
264 if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
265 sig_cfg.clkidle_en = 1;
266
c1420328 267 debug("pixclock = %lu Hz\n", PICOS2KHZ(fbi->var.pixclock) * 1000UL);
5dda7945
SB
268
269 if (ipu_init_sync_panel(mxc_fbi->ipu_di,
270 (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
271 fbi->var.xres, fbi->var.yres,
272 out_pixel_fmt,
273 fbi->var.left_margin,
274 fbi->var.hsync_len,
275 fbi->var.right_margin,
276 fbi->var.upper_margin,
277 fbi->var.vsync_len,
278 fbi->var.lower_margin,
279 0, sig_cfg) != 0) {
280 puts("mxcfb: Error initializing panel.\n");
281 return -EINVAL;
282 }
283
284 retval = setup_disp_channel2(fbi);
285 if (retval)
286 return retval;
287
288 if (mxc_fbi->blank == FB_BLANK_UNBLANK)
289 ipu_enable_channel(mxc_fbi->ipu_ch);
290
291 return retval;
292}
293
294/*
295 * Check framebuffer variable parameters and adjust to valid values.
296 *
297 * @param var framebuffer variable parameters
298 *
299 * @param info framebuffer information pointer
300 */
301static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
302{
303 u32 vtotal;
304 u32 htotal;
305
306 if (var->xres_virtual < var->xres)
307 var->xres_virtual = var->xres;
308 if (var->yres_virtual < var->yres)
309 var->yres_virtual = var->yres;
310
311 if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
312 (var->bits_per_pixel != 16) && (var->bits_per_pixel != 8))
313 var->bits_per_pixel = default_bpp;
314
315 switch (var->bits_per_pixel) {
316 case 8:
317 var->red.length = 3;
318 var->red.offset = 5;
319 var->red.msb_right = 0;
320
321 var->green.length = 3;
322 var->green.offset = 2;
323 var->green.msb_right = 0;
324
325 var->blue.length = 2;
326 var->blue.offset = 0;
327 var->blue.msb_right = 0;
328
329 var->transp.length = 0;
330 var->transp.offset = 0;
331 var->transp.msb_right = 0;
332 break;
333 case 16:
334 var->red.length = 5;
335 var->red.offset = 11;
336 var->red.msb_right = 0;
337
338 var->green.length = 6;
339 var->green.offset = 5;
340 var->green.msb_right = 0;
341
342 var->blue.length = 5;
343 var->blue.offset = 0;
344 var->blue.msb_right = 0;
345
346 var->transp.length = 0;
347 var->transp.offset = 0;
348 var->transp.msb_right = 0;
349 break;
350 case 24:
351 var->red.length = 8;
352 var->red.offset = 16;
353 var->red.msb_right = 0;
354
355 var->green.length = 8;
356 var->green.offset = 8;
357 var->green.msb_right = 0;
358
359 var->blue.length = 8;
360 var->blue.offset = 0;
361 var->blue.msb_right = 0;
362
363 var->transp.length = 0;
364 var->transp.offset = 0;
365 var->transp.msb_right = 0;
366 break;
367 case 32:
368 var->red.length = 8;
369 var->red.offset = 16;
370 var->red.msb_right = 0;
371
372 var->green.length = 8;
373 var->green.offset = 8;
374 var->green.msb_right = 0;
375
376 var->blue.length = 8;
377 var->blue.offset = 0;
378 var->blue.msb_right = 0;
379
380 var->transp.length = 8;
381 var->transp.offset = 24;
382 var->transp.msb_right = 0;
383 break;
384 }
385
386 if (var->pixclock < 1000) {
387 htotal = var->xres + var->right_margin + var->hsync_len +
388 var->left_margin;
389 vtotal = var->yres + var->lower_margin + var->vsync_len +
390 var->upper_margin;
391 var->pixclock = (vtotal * htotal * 6UL) / 100UL;
392 var->pixclock = KHZ2PICOS(var->pixclock);
393 printf("pixclock set for 60Hz refresh = %u ps\n",
394 var->pixclock);
395 }
396
397 var->height = -1;
398 var->width = -1;
399 var->grayscale = 0;
400
401 return 0;
402}
403
404static int mxcfb_map_video_memory(struct fb_info *fbi)
405{
406 if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length) {
407 fbi->fix.smem_len = fbi->var.yres_virtual *
408 fbi->fix.line_length;
409 }
4acb4d39 410 fbi->fix.smem_len = roundup(fbi->fix.smem_len, ARCH_DMA_MINALIGN);
57f065fe
AG
411
412#if CONFIG_IS_ENABLED(DM_VIDEO)
413 fbi->screen_base = (char *)gd->video_bottom;
414#else
4acb4d39
EN
415 fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN,
416 fbi->fix.smem_len);
57f065fe
AG
417#endif
418
e9934f0b 419 fbi->fix.smem_start = (unsigned long)fbi->screen_base;
5dda7945
SB
420 if (fbi->screen_base == 0) {
421 puts("Unable to allocate framebuffer memory\n");
422 fbi->fix.smem_len = 0;
423 fbi->fix.smem_start = 0;
424 return -EBUSY;
425 }
426
427 debug("allocated fb @ paddr=0x%08X, size=%d.\n",
428 (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
429
430 fbi->screen_size = fbi->fix.smem_len;
431
57f065fe 432#if CONFIG_IS_ENABLED(VIDEO)
a69214dc 433 gd->fb_base = fbi->fix.smem_start;
57f065fe 434#endif
a69214dc 435
5dda7945
SB
436 /* Clear the screen */
437 memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
438
439 return 0;
440}
441
442static int mxcfb_unmap_video_memory(struct fb_info *fbi)
443{
444 fbi->screen_base = 0;
445 fbi->fix.smem_start = 0;
446 fbi->fix.smem_len = 0;
447 return 0;
448}
449
450/*
451 * Initializes the framebuffer information pointer. After allocating
452 * sufficient memory for the framebuffer structure, the fields are
453 * filled with custom information passed in from the configurable
454 * structures. This includes information such as bits per pixel,
455 * color maps, screen width/height and RGBA offsets.
456 *
457 * @return Framebuffer structure initialized with our information
458 */
459static struct fb_info *mxcfb_init_fbinfo(void)
460{
461#define BYTES_PER_LONG 4
462#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
463 struct fb_info *fbi;
464 struct mxcfb_info *mxcfbi;
465 char *p;
466 int size = sizeof(struct mxcfb_info) + PADDING +
467 sizeof(struct fb_info);
468
469 debug("%s: %d %d %d %d\n",
470 __func__,
471 PADDING,
472 size,
473 sizeof(struct mxcfb_info),
474 sizeof(struct fb_info));
475 /*
476 * Allocate sufficient memory for the fb structure
477 */
478
479 p = malloc(size);
480 if (!p)
481 return NULL;
482
483 memset(p, 0, size);
484
485 fbi = (struct fb_info *)p;
486 fbi->par = p + sizeof(struct fb_info) + PADDING;
487
488 mxcfbi = (struct mxcfb_info *)fbi->par;
489 debug("Framebuffer structures at: fbi=0x%x mxcfbi=0x%x\n",
490 (unsigned int)fbi, (unsigned int)mxcfbi);
491
492 fbi->var.activate = FB_ACTIVATE_NOW;
493
494 fbi->flags = FBINFO_FLAG_DEFAULT;
495 fbi->pseudo_palette = mxcfbi->pseudo_palette;
496
497 return fbi;
498}
499
500/*
501 * Probe routine for the framebuffer driver. It is called during the
c1420328 502 * driver binding process. The following functions are performed in
5dda7945
SB
503 * this routine: Framebuffer initialization, Memory allocation and
504 * mapping, Framebuffer registration, IPU initialization.
505 *
506 * @return Appropriate error code to the kernel common code
507 */
02ae1a18 508static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp,
09c8bb26 509 struct fb_videomode const *mode)
5dda7945
SB
510{
511 struct fb_info *fbi;
512 struct mxcfb_info *mxcfbi;
513 int ret = 0;
514
515 /*
516 * Initialize FB structures
517 */
518 fbi = mxcfb_init_fbinfo();
519 if (!fbi) {
520 ret = -ENOMEM;
521 goto err0;
522 }
523 mxcfbi = (struct mxcfb_info *)fbi->par;
524
525 if (!g_dp_in_use) {
526 mxcfbi->ipu_ch = MEM_BG_SYNC;
527 mxcfbi->blank = FB_BLANK_UNBLANK;
528 } else {
529 mxcfbi->ipu_ch = MEM_DC_SYNC;
530 mxcfbi->blank = FB_BLANK_POWERDOWN;
531 }
532
02ae1a18 533 mxcfbi->ipu_di = disp;
5dda7945
SB
534
535 ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80);
536 ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0);
537 strcpy(fbi->fix.id, "DISP3 BG");
538
539 g_dp_in_use = 1;
540
541 mxcfb_info[mxcfbi->ipu_di] = fbi;
542
543 /* Need dummy values until real panel is configured */
5dda7945
SB
544
545 mxcfbi->ipu_di_pix_fmt = interface_pix_fmt;
546 fb_videomode_to_var(&fbi->var, mode);
e9934f0b
SB
547 fbi->var.bits_per_pixel = 16;
548 fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8);
549 fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length;
5dda7945
SB
550
551 mxcfb_check_var(&fbi->var, fbi);
552
553 /* Default Y virtual size is 2x panel size */
554 fbi->var.yres_virtual = fbi->var.yres * 2;
555
556 mxcfb_set_fix(fbi);
557
c1420328 558 /* allocate fb first */
5dda7945
SB
559 if (mxcfb_map_video_memory(fbi) < 0)
560 return -ENOMEM;
561
562 mxcfb_set_par(fbi);
563
e9934f0b
SB
564 panel.winSizeX = mode->xres;
565 panel.winSizeY = mode->yres;
566 panel.plnSizeX = mode->xres;
567 panel.plnSizeY = mode->yres;
5dda7945 568
e9934f0b
SB
569 panel.frameAdrs = (u32)fbi->screen_base;
570 panel.memSize = fbi->screen_size;
5dda7945 571
e9934f0b
SB
572 panel.gdfBytesPP = 2;
573 panel.gdfIndex = GDF_16BIT_565RGB;
5dda7945
SB
574
575 ipu_dump_registers();
576
577 return 0;
578
579err0:
580 return ret;
581}
582
5f8e17ce
EN
583void ipuv3_fb_shutdown(void)
584{
0d1ae97c 585 int i;
9493d05a 586 struct ipu_stat *stat = (struct ipu_stat *)IPU_STAT;
5f8e17ce 587
f8ba7f27
AG
588 if (!ipu_clk_enabled())
589 return;
590
5f8e17ce
EN
591 for (i = 0; i < ARRAY_SIZE(mxcfb_info); i++) {
592 struct fb_info *fbi = mxcfb_info[i];
593 if (fbi) {
594 struct mxcfb_info *mxc_fbi = fbi->par;
595 ipu_disable_channel(mxc_fbi->ipu_ch);
596 ipu_uninit_channel(mxc_fbi->ipu_ch);
597 }
598 }
599 for (i = 0; i < ARRAY_SIZE(stat->int_stat); i++) {
600 __raw_writel(__raw_readl(&stat->int_stat[i]),
601 &stat->int_stat[i]);
602 }
603}
604
e9934f0b 605void *video_hw_init(void)
5dda7945
SB
606{
607 int ret;
608
609 ret = ipu_probe();
610 if (ret)
611 puts("Error initializing IPU\n");
612
02ae1a18 613 ret = mxcfb_probe(gpixfmt, gdisp, gmode);
e9934f0b 614 debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs);
f03e56ad 615 gd->fb_base = panel.frameAdrs;
5dda7945 616
e9934f0b
SB
617 return (void *)&panel;
618}
5dda7945 619
09c8bb26
EN
620int ipuv3_fb_init(struct fb_videomode const *mode,
621 uint8_t disp,
622 uint32_t pixfmt)
e9934f0b
SB
623{
624 gmode = mode;
02ae1a18
MV
625 gdisp = disp;
626 gpixfmt = pixfmt;
e9934f0b
SB
627
628 return 0;
5dda7945 629}
57f065fe
AG
630
631#if CONFIG_IS_ENABLED(DM_VIDEO)
632enum {
633 /* Maximum display size we support */
634 LCD_MAX_WIDTH = 1920,
635 LCD_MAX_HEIGHT = 1080,
636 LCD_MAX_LOG2_BPP = VIDEO_BPP16,
637};
638
639static int ipuv3_video_probe(struct udevice *dev)
640{
641 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
642 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
f4ec1ae0
HS
643#if defined(CONFIG_DISPLAY)
644 struct udevice *disp_dev;
645#endif
42a7ce27 646 struct udevice *panel_dev;
57f065fe
AG
647 u32 fb_start, fb_end;
648 int ret;
649
650 debug("%s() plat: base 0x%lx, size 0x%x\n",
651 __func__, plat->base, plat->size);
652
653 ret = ipu_probe();
654 if (ret)
655 return ret;
656
657 ret = ipu_displays_init();
658 if (ret < 0)
659 return ret;
660
661 ret = mxcfb_probe(gpixfmt, gdisp, gmode);
662 if (ret < 0)
663 return ret;
664
f4ec1ae0
HS
665#if defined(CONFIG_DISPLAY)
666 ret = uclass_first_device(UCLASS_DISPLAY, &disp_dev);
667 if (disp_dev) {
668 ret = display_enable(disp_dev, 16, NULL);
669 if (ret < 0)
670 return ret;
671 }
672#endif
42a7ce27
HS
673 ret = uclass_get_device(UCLASS_PANEL, 0, &panel_dev);
674 if (panel_dev)
675 panel_enable_backlight(panel_dev);
f4ec1ae0 676
57f065fe
AG
677 uc_priv->xsize = gmode->xres;
678 uc_priv->ysize = gmode->yres;
679 uc_priv->bpix = LCD_MAX_LOG2_BPP;
680
681 /* Enable dcache for the frame buffer */
682 fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
683 fb_end = plat->base + plat->size;
684 fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
685 mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
686 DCACHE_WRITEBACK);
687 video_set_flush_dcache(dev, true);
f03e56ad 688 gd->fb_base = fb_start;
57f065fe
AG
689
690 return 0;
691}
692
693struct ipuv3_video_priv {
694 ulong regs;
695};
696
697static int ipuv3_video_bind(struct udevice *dev)
698{
699 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
700
701 plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
b5e1a82e 702 (1 << VIDEO_BPP32) / 8;
57f065fe
AG
703
704 return 0;
705}
706
707static const struct udevice_id ipuv3_video_ids[] = {
708 { .compatible = "fsl,imx6q-ipu" },
01c9dd21 709 { .compatible = "fsl,imx53-ipu" },
57f065fe
AG
710 { }
711};
712
713U_BOOT_DRIVER(ipuv3_video) = {
714 .name = "ipuv3_video",
715 .id = UCLASS_VIDEO,
716 .of_match = ipuv3_video_ids,
717 .bind = ipuv3_video_bind,
718 .probe = ipuv3_video_probe,
719 .priv_auto_alloc_size = sizeof(struct ipuv3_video_priv),
720 .flags = DM_FLAG_PRE_RELOC,
721};
722#endif /* CONFIG_DM_VIDEO */
This page took 0.500048 seconds and 4 git commands to generate.