blob: 89c7ad7eedb6aa29c361d3e518699b39f44b49a8 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * (C) Copyright 2012
3 * Marvell Semiconductor <www.marvell.com>
4 * Written-by: Green Wan <gwan@marvell.com>
5 * Jun Nie <njun@marvell.com>
6 * Kevin Liu <kliu5@marvell.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <config.h>
12#include <common.h>
13#include <malloc.h>
14#include <linux/types.h>
15#include <asm/io.h>
16#include <i2c.h>
17#include <asm/gpio.h>
18#include <mmp_disp.h>
19
20struct mmp_disp_info *mmp_disp_fbi;
21int g_panel_id;
22
23struct lcd_regs *get_regs(struct mmp_disp_info *fbi)
24{
25 struct lcd_regs *regs = (struct lcd_regs *)((uintptr_t)fbi->reg_base);
26
27 if (fbi->id == 0)
28 regs = (struct lcd_regs *)((uintptr_t)fbi->reg_base + 0xc0);
29 if (fbi->id == 2)
30 regs = (struct lcd_regs *)((uintptr_t)fbi->reg_base + 0x200);
31
32 return regs;
33}
34
35u32 dma_ctrl_read(struct mmp_disp_info *fbi, int ctrl1)
36{
37 u32 reg = (uintptr_t)fbi->reg_base + dma_ctrl(ctrl1, fbi->id);
38 return __raw_readl((uintptr_t)reg);
39}
40
41void dma_ctrl_write(struct mmp_disp_info *fbi, int ctrl1, u32 value)
42{
43 u32 reg = (u32)(uintptr_t)fbi->reg_base + dma_ctrl(ctrl1, fbi->id);
44 __raw_writel(value, (uintptr_t)reg);
45}
46
47void dma_ctrl_set(struct mmp_disp_info *fbi, int ctrl1, u32 mask, u32 value)
48{
49 u32 reg = (u32)(uintptr_t)fbi->reg_base + dma_ctrl(ctrl1, fbi->id);
50 u32 tmp1, tmp2;
51
52 tmp1 = __raw_readl((uintptr_t)reg);
53 tmp2 = tmp1;
54 tmp2 &= ~mask;
55 tmp2 |= value;
56 if (tmp1 != tmp2)
57 __raw_writel(tmp2, (uintptr_t)reg);
58}
59
60static void set_pix_fmt(struct mmp_disp_plat_info *mi, int pix_fmt)
61{
62 switch (pix_fmt) {
63 case PIX_FMT_RGB565:
64 mi->bits_per_pixel = 16;
65 break;
66 case PIX_FMT_BGR565:
67 mi->bits_per_pixel = 16;
68 break;
69 case PIX_FMT_RGB1555:
70 mi->bits_per_pixel = 16;
71 break;
72 case PIX_FMT_BGR1555:
73 mi->bits_per_pixel = 16;
74 break;
75 case PIX_FMT_RGB888PACK:
76 mi->bits_per_pixel = 24;
77 break;
78 case PIX_FMT_BGR888PACK:
79 mi->bits_per_pixel = 24;
80 break;
81 case PIX_FMT_RGB888UNPACK:
82 mi->bits_per_pixel = 32;
83 break;
84 case PIX_FMT_BGR888UNPACK:
85 mi->bits_per_pixel = 32;
86 break;
87 case PIX_FMT_RGBA888:
88 mi->bits_per_pixel = 32;
89 break;
90 case PIX_FMT_BGRA888:
91 mi->bits_per_pixel = 32;
92 break;
93 }
94}
95
96/*
97 * The hardware clock divider has an integer and a fractional
98 * stage:
99 *
100 * clk2 = clk_in / integer_divider
101 * clk_out = clk2 * (1 - (fractional_divider >> 12))
102 *
103 * Calculate integer and fractional divider for given clk_in
104 * and clk_out.
105 */
106static void set_clock_divider(struct mmp_disp_info *fbi)
107{
108 struct mmp_disp_plat_info *mi = fbi->mi;
109 struct dsi_info *di = (struct dsi_info *)mi->phy_info;
110 u32 val = mi->sclk_div, reg;
111
112 /* for lcd controller */
113 writel(val & (~0xf00), fbi->reg_base + clk_div(fbi->id));
114 /* for dsi clock */
115 if (mi->phy_type & (DSI | DSI2DPI)) {
116 if (di->id == 1) {
117 reg = readl(fbi->reg_base + clk_div(0));
118 reg &= ~0xf00;
119 reg |= val & 0xf00;
120 writel(reg, fbi->reg_base + clk_div(0));
121 } else if (di->id == 2) {
122 reg = readl(fbi->reg_base + clk_div(1));
123 reg &= ~0xf00;
124 reg |= val & 0xf00;
125 writel(reg, fbi->reg_base + clk_div(1));
126 writel(val & (~0xf00), fbi->reg_base + clk_div(2));
127 }
128 }
129}
130
131static u32 dma_ctrl0_update(int active, struct mmp_disp_plat_info *mi,
132 u32 x, u32 pix_fmt)
133{
134 int tmp, shift1, shift2;
135
136 tmp = 0x100;
137 shift1 = 16;
138 shift2 = 12;
139
140 if (active)
141 x |= tmp;
142 else
143 x &= ~tmp;
144
145 /* If we are in a pseudo-color mode, we need to enable
146 * palette lookup */
147 if (pix_fmt == PIX_FMT_PSEUDOCOLOR)
148 x |= 0x10000000;
149
150 /* Configure hardware pixel format */
151 x &= ~(0xF << shift1);
152 x |= (pix_fmt >> 1) << shift1;
153
154 /* Check YUV422PACK */
155 x &= ~((1 << 9) | (1 << 11) | (1 << 10) | (1 << 12));
156 if (((pix_fmt >> 1) == 5) || (pix_fmt & 0x1000)) {
157 x |= 1 << 9;
158 x |= (mi->panel_rbswap) << 12;
159 if (pix_fmt == 11)
160 x |= 1 << 11;
161 if (pix_fmt & 0x1000)
162 x |= 1 << 10;
163 } else {
164 /* Check red and blue pixel swap.
165 * 1. source data swap. BGR[M:L] rather than RGB[M:L] is
166 * stored in memeory as source format.
167 * 2. panel output data swap
168 */
169 x |= (((pix_fmt & 1) ^ 1) ^ (mi->panel_rbswap)) << shift2;
170 }
171 /* enable horizontal smooth filter for both graphic and video layers */
172 x |= CFG_GRA_HSMOOTH(1) | CFG_DMA_HSMOOTH(1);
173
174 return x;
175}
176
177static void set_dma_control0(struct mmp_disp_info *fbi)
178{
179 struct mmp_disp_plat_info *mi;
180 u32 x = 0, active, pix_fmt = fbi->pix_fmt;
181
182 /* Set bit to enable graphics DMA */
183 dma_ctrl_set(fbi, 0, CFG_ARBFAST_ENA(1), CFG_ARBFAST_ENA(1));
184
185 mi = fbi->mi;
186 active = fbi->active;
187 x = dma_ctrl_read(fbi, 0);
188 active = 1;
189 x = dma_ctrl0_update(active, mi, x, pix_fmt);
190 dma_ctrl_write(fbi, 0, x);
191 /* enable multiple burst request in DMA AXI bus arbiter for
192 * faster read
193 */
194 x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
195 x |= CFG_ARBFAST_ENA(1);
196 writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0);
197}
198
199static void set_graphics_start(struct mmp_disp_info *fb, int xoffset,
200 int yoffset)
201{
202 struct mmp_disp_info *fbi = fb;
203 int pixel_offset;
204 unsigned int phys_addr;
205 static int debugcount;
206#ifdef CONFIG_VDMA
207 struct mmp_vdma_reg *vdma_reg = (struct mmp_vdma_reg *)fbi->vdma_reg_base;
208 struct mmp_vdma_ch_reg *ch_reg = &vdma_reg->ch0_reg;
209#else
210 struct lcd_regs *regs = get_regs(fbi);
211#endif
212 if (debugcount < 10)
213 debugcount++;
214
215 pixel_offset = (yoffset * ALIGN(fbi->mi->modes->xres, 16)) + xoffset;
216 phys_addr = (unsigned int)fbi->fb_start +
217 (pixel_offset * (fbi->mi->bits_per_pixel >> 3));
218
219
220#ifdef CONFIG_VDMA
221 /* Set VDMA Source address */
222 writel(phys_addr, &ch_reg->src_addr);
223#else
224 writel(phys_addr, &regs->g_0);
225#endif
226}
227
228static void set_screen(struct mmp_disp_info *fbi, struct mmp_disp_plat_info *mi)
229{
230 struct lcd_regs *regs = get_regs(fbi);
231 struct dsi_info *di = NULL;
232 u32 x, h_porch, vsync_ctrl, vec = 10;
233 u32 xres = mi->modes->xres, yres = mi->modes->yres;
234 u32 xres_z = mi->modes->xres, yres_z = mi->modes->yres;
235 u32 bits_per_pixel = mi->bits_per_pixel;
236
237 if (mi->phy_type & (DSI2DPI | DSI)) {
238 di = (struct dsi_info *)mi->phy_info;
239 vec = ((di->lanes <= 2) ? 1 : 2) * 10 * di->bpp / 8 / di->lanes;
240 }
241 /* resolution, active */
242 writel((mi->modes->yres << 16) | mi->modes->xres, &regs->screen_active);
243 /* pitch, pixels per line */
244 x = readl(&regs->g_pitch);
245 x = (x & ~0xFFFF) | ((ALIGN(xres, 16) * bits_per_pixel) >> 3);
246 writel(x, &regs->g_pitch);
247 /* resolution, src size */
248 writel((yres << 16) | xres, &regs->g_size);
249
250 /* resolution, dst size */
251 if (DISP_GEN4(fbi->mi->version)) {
252 if (xres != xres_z || yres != yres_z)
253 printf("resize not support for graphic layer of GEN4\n");
254 } else {
255 writel((yres_z << 16) | xres_z, &regs->g_size_z);
256 }
257
258 /* h porch, left/right margin */
259 if (mi->phy_type & (DSI2DPI | DSI)) {
260 h_porch = (mi->modes->xres + mi->modes->right_margin) * vec / 10
261 - mi->modes->xres;
262 h_porch = (mi->modes->left_margin * vec / 10) << 16 | h_porch;
263 } else {
264 h_porch = (mi->modes->left_margin) << 16 | mi->modes->right_margin;
265 }
266 writel(h_porch, &regs->screen_h_porch);
267 /* v porch, upper/lower margin */
268 writel((mi->modes->upper_margin << 16) | mi->modes->lower_margin,
269 &regs->screen_v_porch);
270
271 /* vsync ctrl */
272 if (mi->phy_type & (DSI2DPI | DSI)) {
273 vsync_ctrl = (((mi->modes->xres + mi->modes->right_margin) * vec / 10) << 16)
274 | ((mi->modes->xres + mi->modes->right_margin) * vec / 10);
275 } else {
276 vsync_ctrl = ((mi->modes->xres + mi->modes->right_margin) << 16)
277 | (mi->modes->xres + mi->modes->right_margin);
278 }
279 writel(vsync_ctrl, &regs->vsync_ctrl); /* FIXME */
280
281 /* blank color */
282 writel(0x00000000, &regs->blank_color);
283}
284
285static void set_dumb_panel_control(struct mmp_disp_info *fbi,
286 struct mmp_disp_plat_info *mi)
287{
288 u32 x;
289
290 x = readl(fbi->reg_base + intf_ctrl(fbi->id)) & 0x00000001;
291 x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28;
292 x |= (mi->modes->sync & 2) ? 0 : 0x00000008;
293 x |= (mi->modes->sync & 1) ? 0 : 0x00000004;
294 x |= (mi->modes->sync & 8) ? 0 : 0x00000020;
295
296 x |= mi->gpio_output_data << 20;
297 x |= mi->gpio_output_mask << 12;
298 x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0;
299 x |= mi->invert_composite_blank ? 0x00000040 : 0;
300 x |= mi->invert_pix_val_ena ? 0x00000010 : 0;
301 x |= mi->invert_pixclock ? 0x00000002 : 0;
302
303 writel(x, fbi->reg_base + intf_ctrl(fbi->id)); /* FIXME */
304}
305
306static void set_dumb_screen_dimensions(struct mmp_disp_info *fbi,
307 struct mmp_disp_plat_info *mi)
308{
309 struct lcd_regs *regs = get_regs(fbi);
310 struct dsi_info *di = NULL;
311 int x;
312 int y;
313 int vec = 10;
314
315 /* FIXME - need to double check (*3) and (*2) */
316 if (mi->phy_type & (DSI2DPI | DSI)) {
317 di = (struct dsi_info *)mi->phy_info;
318 vec = ((di->lanes <= 2) ? 1 : 2) * 10 * di->bpp / 8 / di->lanes;
319 if (di->master_mode) {
320 if (DISP_GEN4(fbi->mi->version))
321 writel(timing_master_config_dc4(fbi->id,
322 di->id - 1, di->id - 1),
323 fbi->reg_base + TIMING_MASTER_CONTROL_DC4);
324 else
325 writel(timing_master_config(fbi->id,
326 di->id - 1, di->id - 1),
327 fbi->reg_base + TIMING_MASTER_CONTROL);
328 }
329 }
330
331 x = mi->modes->xres + mi->modes->right_margin +
332 mi->modes->hsync_len + mi->modes->left_margin;
333 x = x * vec / 10;
334 y = mi->modes->yres + mi->modes->lower_margin +
335 mi->modes->vsync_len + mi->modes->upper_margin;
336
337 writel((y << 16) | x, &regs->screen_size);
338}
339
340static int mmp_disp_set_par(struct mmp_disp_info *fb,
341 struct mmp_disp_plat_info *mi)
342{
343 struct mmp_disp_info *fbi = fb;
344 int pix_fmt;
345 u32 x;
346
347 /* Determine which pixel format we're going to use */
348 pix_fmt = mi->pix_fmt; /* choose one */
349
350 if (pix_fmt < 0)
351 return pix_fmt;
352 fbi->pix_fmt = pix_fmt;
353
354 set_pix_fmt(mi, pix_fmt);
355
356 /* Calculate clock divisor. */
357 set_clock_divider(fbi);
358
359 /* Configure graphics DMA parameters.
360 * Configure global panel parameters.
361 */
362 set_screen(fbi, mi);
363 /* Configure dumb panel ctrl regs & timings */
364 set_dumb_panel_control(fbi, mi);
365 set_dumb_screen_dimensions(fbi, mi);
366 x = readl(fbi->reg_base + intf_ctrl(fbi->id));
367 if ((x & 1) == 0)
368 writel(x | 1, fbi->reg_base + intf_ctrl(fbi->id));
369
370 set_graphics_start(fbi, 0, 0);
371 set_dma_control0(fbi);
372 return 0;
373}
374
375static void mmp_disp_set_default(struct mmp_disp_info *fbi,
376 struct mmp_disp_plat_info *mi)
377{
378 struct lcd_regs *regs = get_regs(fbi);
379 u32 dma_ctrl1 = 0x20320081;
380
381 u32 burst_length = (mi->burst_len == 16) ?
382 CFG_CYC_BURST_LEN16 : CFG_CYC_BURST_LEN8;
383 /* Configure default register values */
384 writel(mi->io_pin_allocation_mode | burst_length,
385 fbi->reg_base + SPU_IOPAD_CONTROL);
386 /* enable 16 cycle burst length to get better formance */
387 writel(0x00000000, &regs->blank_color);
388 writel(0x00000000, &regs->g_1);
389 writel(0x00000000, &regs->g_start);
390
391 /*
392 * vsync in LCD internal controller is always positive,
393 * we default configure dma trigger @vsync falling edge,
394 * so that DMA idle time between DMA frame done and
395 * next DMA transfer begin can be as large as possible
396 */
397 dma_ctrl1 |= CFG_VSYNC_INV_MASK;
398 dma_ctrl_write(fbi, 1, dma_ctrl1);
399}
400
401static void rect_fill(void *addr, int left, int up, int right,
402 int down, int width, unsigned int color, int pix_fmt)
403{
404 int i, j;
405 for (j = up; j < down; j++)
406 for (i = left; i < right; i++)
407 if (pix_fmt == PIX_FMT_RGB565)
408 *((unsigned short *)addr + j * width + i) = color;
409 else if (pix_fmt == PIX_FMT_RGBA888)
410 *((unsigned int *)addr + j * width + i) = color;
411}
412
413void test_panel(int xres, int yres, int pix_fmt)
414{
415 int w = xres, h = yres, bpp = 2;
416 int x = w / 8, y = h / 8;
417 int color_blue = 0x1f, color_green = 0x7e0, color_red = 0xf800;
418
419 printf("panel test: white background, test RGB color\r\n");
420
421 if (pix_fmt == PIX_FMT_RGB565) {
422 color_blue = 0x1f;
423 color_green = 0x7e0;
424 color_red = 0xf800;
425 bpp = 2;
426 } else if (pix_fmt == PIX_FMT_RGBA888) {
427 color_blue = 0xff0000ff;
428 color_green = 0xff00ff00;
429 color_red = 0xffff0000;
430 bpp = 4;
431 }
432
433 memset((void *)DEFAULT_FB_BASE, 0xff,
434 w * h * bpp);
435 udelay(50 * 1000);
436 rect_fill((void *)DEFAULT_FB_BASE, x, y, w - x,
437 h - y, w, color_blue, pix_fmt);
438 udelay(50 * 1000);
439 rect_fill((void *)DEFAULT_FB_BASE, x * 2, y * 2,
440 w - x * 2, h - y * 2, w, color_green, pix_fmt);
441 udelay(50 * 1000);
442 rect_fill((void *)DEFAULT_FB_BASE, x * 3, y * 3,
443 w - x * 3, h - y * 3, w, color_red, pix_fmt);
444 udelay(50 * 1000);
445
446 flush_cache(DEFAULT_FB_BASE, DEFAULT_FB_SIZE);
447}
448
449#ifdef CONFIG_VDMA
450static void vdma_enable(struct mmp_disp_info *fbi)
451{
452 struct lcd_regs *regs = get_regs(fbi);
453 struct mmp_vdma_reg *vdma_reg =
454 (struct mmp_vdma_reg *)(fbi->vdma_reg_base);
455 struct mmp_vdma_ch_reg *ch_reg = &vdma_reg->ch0_reg;
456 u32 pitch, size, src_sz, height;
457 u32 tmp, tmp1, tmp2, mask, set;
458
459 /*
460 * Select VDMA Channel 0: VMDA1
461 * LCD_VDMA_SEL_CTRL bit21:20->0 : PN graphic path use VMDA1
462 * LCD_VDMA_SEL_CTRL bit2:0->0 : VDMA1 map to PN graphic path
463 */
464 tmp = readl(fbi->reg_base + LCD_VDMA_SEL_CTRL);
465 tmp &= ~((0x3 << 20) | 0x7);
466 writel(tmp, fbi->reg_base + LCD_VDMA_SEL_CTRL);
467
468 if (!DISP_GEN4(fbi->mi->version)) {
469 /* Select PN Graphic SQU Line Buffer @0x2ac bit27:26 ->0 */
470 tmp = readl(fbi->reg_base + LCD_SCALING_SQU_CTL_INDEX);
471 tmp &= ~(0x3 << 26);
472 writel(tmp, fbi->reg_base + LCD_SCALING_SQU_CTL_INDEX);
473 }
474
475 pitch = ((ALIGN(fbi->mi->modes->xres, 16)
476 * fbi->mi->bits_per_pixel) >> 3) & 0xffff;
477
478 /*
479 * Set source address in SQU of LCD Controller
480 * and destination address in SQU of VDMA
481 */
482 if (DISP_GEN4(fbi->mi->version)) {
483 writel(0x00000000, &regs->g_squln);
484 writel(0x00000000, &ch_reg->dst_addr);
485 } else {
486 if (pitch * VDMA_SRAM_LINES > 64*1024) {
487 printf("error: requested vdma size exceed 64KB!\n");
488 hang();
489 }
490 /* The sram bank size is 64k and use the tail for vdma */
491 writel(CONFIG_SRAM_BASE + 64 * 1024 - pitch * VDMA_SRAM_LINES,
492 fbi->reg_base + LCD_PN_SQULN_CTRL);
493 writel(CONFIG_SRAM_BASE + 64 * 1024 - pitch * VDMA_SRAM_LINES,
494 &ch_reg->dst_addr);
495 }
496
497 /* Set and Enable Panel Graphic Path SQU Line Buffers */
498 tmp2 = readl(fbi->reg_base + LCD_PN_SQULN_CTRL);
499 tmp1 = tmp2;
500 tmp1 &= ~0x3f;
501 tmp1 |= ((VDMA_SRAM_LINES / 2 - 1) << 1) | 0x1;
502 if (tmp1 != tmp2)
503 writel(tmp1, fbi->reg_base + LCD_PN_SQULN_CTRL);
504
505 height = fbi->mi->modes->yres & 0xffff;
506 src_sz = pitch * height;
507 size = height << 16 | pitch;
508 /* FIXME: set dst and src with the same pitch */
509 pitch |= pitch << 16;
510 writel(pitch, &ch_reg->pitch);
511 writel(src_sz, &ch_reg->src_size);
512 writel(size, &ch_reg->dst_size);
513
514 tmp = readl(&ch_reg->ctrl) & (~(0xff << 8));
515 tmp |= VDMA_SRAM_LINES << 8;
516 writel(tmp, &ch_reg->ctrl);
517
518 /* Enable VDMA Channel 0 */
519 if (DISP_GEN4(fbi->mi->version)) {
520 mask = (0x1f << 20) | 0x3;
521 set = (0x10 << 20) | 0x1;
522 /* FIXME: bypass decompression */
523 tmp = readl((uintptr_t)&vdma_reg->dec_ctrl) | (1 << 31);
524 writel(tmp, &vdma_reg->dec_ctrl);
525 } else {
526 mask = (0x3 << 4) | (0x3 << 6) | 0x3;
527 set = (0x2 << 4) | (0x2 << 6) | 0x1;
528 }
529 tmp2 = readl(&ch_reg->ctrl);
530 tmp1 = tmp2;
531 tmp1 &= ~mask;
532 tmp1 |= set;
533 if (tmp1 != tmp2)
534 writel(tmp1, &ch_reg->ctrl);
535
536 /*Load All VDMA Path 0 Configure Registers */
537 tmp = readl(&vdma_reg->main_ctrl) | (1 << 24);
538 writel(tmp, &vdma_reg->main_ctrl);
539}
540#endif
541
542void *mmp_disp_init(struct mmp_disp_plat_info *mi)
543{
544 struct mmp_disp_info *fbi = malloc(sizeof(struct mmp_disp_info));
545 struct dsi_info *di = NULL;
546#if defined(DEBUG_MMP_DISP)
547 u32 i;
548#endif
549 int ret = 0;
550
551 memset(fbi, 0, sizeof(struct mmp_disp_info));
552 /* Initialize private data */
553 fbi->panel_rbswap = mi->panel_rbswap;
554 fbi->id = mi->index;
555 mmp_disp_fbi = fbi;
556 fbi->mi = mi;
557
558 fbi->is_blanked = 0;
559 fbi->debug = 0;
560 fbi->active = mi->active;
561
562 /* Map LCD controller registers */
563 fbi->reg_base = (void *)DISPLAY_CONTROLLER_BASE;
564#ifdef CONFIG_VDMA
565 /* Map VDMA Controller Registers */
566 fbi->vdma_reg_base = (void *)VDMA_CONTROLLER_BASE;
567#endif
568
569 if (mi->phy_type & (DSI2DPI | DSI)) {
570 di = (struct dsi_info *)mi->phy_info;
571 di->regs = DSI1_REG_BASE; /* DSI 1 */
572 }
573
574 /*
575 * Allocate framebuffer memory
576 */
577 fbi->fb_size = DEFAULT_FB_SIZE;
578 fbi->fb_start = (unsigned int *)DEFAULT_FB_BASE;
579 memset(fbi->fb_start, 0x0, fbi->fb_size);
580
581 /* LCD_TOP_CTRL control reg */
582 writel(VDMA_ENABLE, fbi->reg_base + LCD_TOP_CTRL);
583
584 /* Get DISP Subsystem Verison */
585 fbi->mi->version = readl(fbi->reg_base + LCD_VERSION);
586
587 /*
588 * Fill in sane defaults
589 */
590 mmp_disp_set_default(fbi, mi); /* FIXME */
591 mmp_disp_set_par(fbi, mi);
592
593#ifdef CONFIG_VDMA
594 vdma_enable(fbi);
595#endif
596 /* Load All Configure Registers with Shadow Registers */
597 if (DISP_GEN4(fbi->mi->version))
598 writel(1 << 30, fbi->reg_base + LCD_SHADOW_CTRL);
599
600 if (mi->phy_type & (DSI2DPI | DSI)) {
601 /* phy interface init */
602 ret = mmp_disp_dsi_init(fbi);
603 if (ret)
604 goto err;
605 }
606
607 /* dump all lcd and dsi registers for debug purpose */
608#if defined(DEBUG_MMP_DISP)
609 printf("lcd regs:\n");
610 for (i = 0; i < 0x300; i += 4) {
611 if (!(i % 16) && i)
612 printf("\n0x%3x: ", i);
613 printf(" %8x", readl(fbi->reg_base + i));
614 }
615 if (mi->phy_type & (DSI2DPI | DSI)) {
616 printf("\n dsi regs:");
617 for (i = 0x0; i < 0x200; i += 4) {
618 if (!(i % 16))
619 printf("\n0x%3x: ", i);
620 printf(" %8x", readl(di->regs + i));
621 }
622 }
623 printf("\n");
624 test_panel(fbi->mi->modes->xres, fbi->mi->modes->yres, fbi->pix_fmt);
625#endif
626
627 return (void *)fbi;
628
629err:
630 free(fbi);
631 return NULL;
632}