1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2014 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * FSL DCU Framebuffer driver
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <asm/io.h>
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <fdt_support.h>
12*4882a593Smuzhiyun #include <fsl_dcu_fb.h>
13*4882a593Smuzhiyun #include <linux/fb.h>
14*4882a593Smuzhiyun #include <malloc.h>
15*4882a593Smuzhiyun #include <video_fb.h>
16*4882a593Smuzhiyun #include "videomodes.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* Convert the X,Y resolution pair into a single number */
19*4882a593Smuzhiyun #define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #ifdef CONFIG_SYS_FSL_DCU_LE
22*4882a593Smuzhiyun #define dcu_read32 in_le32
23*4882a593Smuzhiyun #define dcu_write32 out_le32
24*4882a593Smuzhiyun #elif defined(CONFIG_SYS_FSL_DCU_BE)
25*4882a593Smuzhiyun #define dcu_read32 in_be32
26*4882a593Smuzhiyun #define dcu_write32 out_be32
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define DCU_MODE_BLEND_ITER(x) ((x) << 20)
30*4882a593Smuzhiyun #define DCU_MODE_RASTER_EN (1 << 14)
31*4882a593Smuzhiyun #define DCU_MODE_NORMAL 1
32*4882a593Smuzhiyun #define DCU_MODE_COLORBAR 3
33*4882a593Smuzhiyun #define DCU_BGND_R(x) ((x) << 16)
34*4882a593Smuzhiyun #define DCU_BGND_G(x) ((x) << 8)
35*4882a593Smuzhiyun #define DCU_BGND_B(x) (x)
36*4882a593Smuzhiyun #define DCU_DISP_SIZE_DELTA_Y(x) ((x) << 16)
37*4882a593Smuzhiyun #define DCU_DISP_SIZE_DELTA_X(x) (x)
38*4882a593Smuzhiyun #define DCU_HSYN_PARA_BP(x) ((x) << 22)
39*4882a593Smuzhiyun #define DCU_HSYN_PARA_PW(x) ((x) << 11)
40*4882a593Smuzhiyun #define DCU_HSYN_PARA_FP(x) (x)
41*4882a593Smuzhiyun #define DCU_VSYN_PARA_BP(x) ((x) << 22)
42*4882a593Smuzhiyun #define DCU_VSYN_PARA_PW(x) ((x) << 11)
43*4882a593Smuzhiyun #define DCU_VSYN_PARA_FP(x) (x)
44*4882a593Smuzhiyun #define DCU_SYN_POL_INV_PXCK_FALL (1 << 6)
45*4882a593Smuzhiyun #define DCU_SYN_POL_NEG_REMAIN (0 << 5)
46*4882a593Smuzhiyun #define DCU_SYN_POL_INV_VS_LOW (1 << 1)
47*4882a593Smuzhiyun #define DCU_SYN_POL_INV_HS_LOW (1)
48*4882a593Smuzhiyun #define DCU_THRESHOLD_LS_BF_VS(x) ((x) << 16)
49*4882a593Smuzhiyun #define DCU_THRESHOLD_OUT_BUF_HIGH(x) ((x) << 8)
50*4882a593Smuzhiyun #define DCU_THRESHOLD_OUT_BUF_LOW(x) (x)
51*4882a593Smuzhiyun #define DCU_UPDATE_MODE_MODE (1 << 31)
52*4882a593Smuzhiyun #define DCU_UPDATE_MODE_READREG (1 << 30)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define DCU_CTRLDESCLN_1_HEIGHT(x) ((x) << 16)
55*4882a593Smuzhiyun #define DCU_CTRLDESCLN_1_WIDTH(x) (x)
56*4882a593Smuzhiyun #define DCU_CTRLDESCLN_2_POSY(x) ((x) << 16)
57*4882a593Smuzhiyun #define DCU_CTRLDESCLN_2_POSX(x) (x)
58*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_EN (1 << 31)
59*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_TILE_EN (1 << 30)
60*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_DATA_SEL_CLUT (1 << 29)
61*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_SAFETY_EN (1 << 28)
62*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_TRANS(x) ((x) << 20)
63*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_BPP(x) ((x) << 16)
64*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_RLE_EN (1 << 15)
65*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_LUOFFS(x) ((x) << 4)
66*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_BB_ON (1 << 2)
67*4882a593Smuzhiyun #define DCU_CTRLDESCLN_4_AB(x) (x)
68*4882a593Smuzhiyun #define DCU_CTRLDESCLN_5_CKMAX_R(x) ((x) << 16)
69*4882a593Smuzhiyun #define DCU_CTRLDESCLN_5_CKMAX_G(x) ((x) << 8)
70*4882a593Smuzhiyun #define DCU_CTRLDESCLN_5_CKMAX_B(x) (x)
71*4882a593Smuzhiyun #define DCU_CTRLDESCLN_6_CKMIN_R(x) ((x) << 16)
72*4882a593Smuzhiyun #define DCU_CTRLDESCLN_6_CKMIN_G(x) ((x) << 8)
73*4882a593Smuzhiyun #define DCU_CTRLDESCLN_6_CKMIN_B(x) (x)
74*4882a593Smuzhiyun #define DCU_CTRLDESCLN_7_TILE_VER(x) ((x) << 16)
75*4882a593Smuzhiyun #define DCU_CTRLDESCLN_7_TILE_HOR(x) (x)
76*4882a593Smuzhiyun #define DCU_CTRLDESCLN_8_FG_FCOLOR(x) (x)
77*4882a593Smuzhiyun #define DCU_CTRLDESCLN_9_BG_BCOLOR(x) (x)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define BPP_16_RGB565 4
80*4882a593Smuzhiyun #define BPP_24_RGB888 5
81*4882a593Smuzhiyun #define BPP_32_ARGB8888 6
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /*
86*4882a593Smuzhiyun * This setting is used for the TWR_LCD_RGB card
87*4882a593Smuzhiyun */
88*4882a593Smuzhiyun static struct fb_videomode fsl_dcu_mode_480_272 = {
89*4882a593Smuzhiyun .name = "480x272-60",
90*4882a593Smuzhiyun .refresh = 60,
91*4882a593Smuzhiyun .xres = 480,
92*4882a593Smuzhiyun .yres = 272,
93*4882a593Smuzhiyun .pixclock = 91996,
94*4882a593Smuzhiyun .left_margin = 2,
95*4882a593Smuzhiyun .right_margin = 2,
96*4882a593Smuzhiyun .upper_margin = 1,
97*4882a593Smuzhiyun .lower_margin = 1,
98*4882a593Smuzhiyun .hsync_len = 41,
99*4882a593Smuzhiyun .vsync_len = 2,
100*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
101*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun * This setting is used for Siliconimage SiI9022A HDMI
106*4882a593Smuzhiyun */
107*4882a593Smuzhiyun static struct fb_videomode fsl_dcu_cea_mode_640_480 = {
108*4882a593Smuzhiyun .name = "640x480-60",
109*4882a593Smuzhiyun .refresh = 60,
110*4882a593Smuzhiyun .xres = 640,
111*4882a593Smuzhiyun .yres = 480,
112*4882a593Smuzhiyun .pixclock = 39722,
113*4882a593Smuzhiyun .left_margin = 48,
114*4882a593Smuzhiyun .right_margin = 16,
115*4882a593Smuzhiyun .upper_margin = 33,
116*4882a593Smuzhiyun .lower_margin = 10,
117*4882a593Smuzhiyun .hsync_len = 96,
118*4882a593Smuzhiyun .vsync_len = 2,
119*4882a593Smuzhiyun .sync = 0,
120*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED,
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static struct fb_videomode fsl_dcu_mode_640_480 = {
124*4882a593Smuzhiyun .name = "640x480-60",
125*4882a593Smuzhiyun .refresh = 60,
126*4882a593Smuzhiyun .xres = 640,
127*4882a593Smuzhiyun .yres = 480,
128*4882a593Smuzhiyun .pixclock = 25175,
129*4882a593Smuzhiyun .left_margin = 40,
130*4882a593Smuzhiyun .right_margin = 24,
131*4882a593Smuzhiyun .upper_margin = 32,
132*4882a593Smuzhiyun .lower_margin = 11,
133*4882a593Smuzhiyun .hsync_len = 96,
134*4882a593Smuzhiyun .vsync_len = 2,
135*4882a593Smuzhiyun .sync = 0,
136*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED,
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun static struct fb_videomode fsl_dcu_mode_800_480 = {
140*4882a593Smuzhiyun .name = "800x480-60",
141*4882a593Smuzhiyun .refresh = 60,
142*4882a593Smuzhiyun .xres = 800,
143*4882a593Smuzhiyun .yres = 480,
144*4882a593Smuzhiyun .pixclock = 33260,
145*4882a593Smuzhiyun .left_margin = 216,
146*4882a593Smuzhiyun .right_margin = 40,
147*4882a593Smuzhiyun .upper_margin = 35,
148*4882a593Smuzhiyun .lower_margin = 10,
149*4882a593Smuzhiyun .hsync_len = 128,
150*4882a593Smuzhiyun .vsync_len = 2,
151*4882a593Smuzhiyun .sync = 0,
152*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED,
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun static struct fb_videomode fsl_dcu_mode_1024_600 = {
156*4882a593Smuzhiyun .name = "1024x600-60",
157*4882a593Smuzhiyun .refresh = 60,
158*4882a593Smuzhiyun .xres = 1024,
159*4882a593Smuzhiyun .yres = 600,
160*4882a593Smuzhiyun .pixclock = 48000,
161*4882a593Smuzhiyun .left_margin = 104,
162*4882a593Smuzhiyun .right_margin = 43,
163*4882a593Smuzhiyun .upper_margin = 24,
164*4882a593Smuzhiyun .lower_margin = 20,
165*4882a593Smuzhiyun .hsync_len = 5,
166*4882a593Smuzhiyun .vsync_len = 5,
167*4882a593Smuzhiyun .sync = 0,
168*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED,
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /*
172*4882a593Smuzhiyun * DCU register map
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun struct dcu_reg {
175*4882a593Smuzhiyun u32 desc_cursor[4];
176*4882a593Smuzhiyun u32 mode;
177*4882a593Smuzhiyun u32 bgnd;
178*4882a593Smuzhiyun u32 disp_size;
179*4882a593Smuzhiyun u32 hsyn_para;
180*4882a593Smuzhiyun u32 vsyn_para;
181*4882a593Smuzhiyun u32 synpol;
182*4882a593Smuzhiyun u32 threshold;
183*4882a593Smuzhiyun u32 int_status;
184*4882a593Smuzhiyun u32 int_mask;
185*4882a593Smuzhiyun u32 colbar[8];
186*4882a593Smuzhiyun u32 div_ratio;
187*4882a593Smuzhiyun u32 sign_calc[2];
188*4882a593Smuzhiyun u32 crc_val;
189*4882a593Smuzhiyun u8 res_064[0x6c-0x64];
190*4882a593Smuzhiyun u32 parr_err_status1;
191*4882a593Smuzhiyun u8 res_070[0x7c-0x70];
192*4882a593Smuzhiyun u32 parr_err_status3;
193*4882a593Smuzhiyun u32 mparr_err_status1;
194*4882a593Smuzhiyun u8 res_084[0x90-0x84];
195*4882a593Smuzhiyun u32 mparr_err_status3;
196*4882a593Smuzhiyun u32 threshold_inp_buf[2];
197*4882a593Smuzhiyun u8 res_09c[0xa0-0x9c];
198*4882a593Smuzhiyun u32 luma_comp;
199*4882a593Smuzhiyun u32 chroma_red;
200*4882a593Smuzhiyun u32 chroma_green;
201*4882a593Smuzhiyun u32 chroma_blue;
202*4882a593Smuzhiyun u32 crc_pos;
203*4882a593Smuzhiyun u32 lyr_intpol_en;
204*4882a593Smuzhiyun u32 lyr_luma_comp;
205*4882a593Smuzhiyun u32 lyr_chrm_red;
206*4882a593Smuzhiyun u32 lyr_chrm_grn;
207*4882a593Smuzhiyun u32 lyr_chrm_blue;
208*4882a593Smuzhiyun u8 res_0c4[0xcc-0xc8];
209*4882a593Smuzhiyun u32 update_mode;
210*4882a593Smuzhiyun u32 underrun;
211*4882a593Smuzhiyun u8 res_0d4[0x100-0xd4];
212*4882a593Smuzhiyun u32 gpr;
213*4882a593Smuzhiyun u32 slr_l[2];
214*4882a593Smuzhiyun u32 slr_disp_size;
215*4882a593Smuzhiyun u32 slr_hvsync_para;
216*4882a593Smuzhiyun u32 slr_pol;
217*4882a593Smuzhiyun u32 slr_l_transp[2];
218*4882a593Smuzhiyun u8 res_120[0x200-0x120];
219*4882a593Smuzhiyun u32 ctrldescl[DCU_LAYER_MAX_NUM][16];
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun static struct fb_info info;
223*4882a593Smuzhiyun
reset_total_layers(void)224*4882a593Smuzhiyun static void reset_total_layers(void)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
227*4882a593Smuzhiyun int i;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun for (i = 0; i < DCU_LAYER_MAX_NUM; i++) {
230*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][0], 0);
231*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][1], 0);
232*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][2], 0);
233*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][3], 0);
234*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][4], 0);
235*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][5], 0);
236*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][6], 0);
237*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][7], 0);
238*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][8], 0);
239*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][9], 0);
240*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[i][10], 0);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
layer_ctrldesc_init(int index,u32 pixel_format)244*4882a593Smuzhiyun static int layer_ctrldesc_init(int index, u32 pixel_format)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
247*4882a593Smuzhiyun unsigned int bpp = BPP_24_RGB888;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][0],
250*4882a593Smuzhiyun DCU_CTRLDESCLN_1_HEIGHT(info.var.yres) |
251*4882a593Smuzhiyun DCU_CTRLDESCLN_1_WIDTH(info.var.xres));
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][1],
254*4882a593Smuzhiyun DCU_CTRLDESCLN_2_POSY(0) |
255*4882a593Smuzhiyun DCU_CTRLDESCLN_2_POSX(0));
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][2], (unsigned int)info.screen_base);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun switch (pixel_format) {
260*4882a593Smuzhiyun case 16:
261*4882a593Smuzhiyun bpp = BPP_16_RGB565;
262*4882a593Smuzhiyun break;
263*4882a593Smuzhiyun case 24:
264*4882a593Smuzhiyun bpp = BPP_24_RGB888;
265*4882a593Smuzhiyun break;
266*4882a593Smuzhiyun case 32:
267*4882a593Smuzhiyun bpp = BPP_32_ARGB8888;
268*4882a593Smuzhiyun break;
269*4882a593Smuzhiyun default:
270*4882a593Smuzhiyun printf("unsupported color depth: %u\n", pixel_format);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][3],
274*4882a593Smuzhiyun DCU_CTRLDESCLN_4_EN |
275*4882a593Smuzhiyun DCU_CTRLDESCLN_4_TRANS(0xff) |
276*4882a593Smuzhiyun DCU_CTRLDESCLN_4_BPP(bpp) |
277*4882a593Smuzhiyun DCU_CTRLDESCLN_4_AB(0));
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][4],
280*4882a593Smuzhiyun DCU_CTRLDESCLN_5_CKMAX_R(0xff) |
281*4882a593Smuzhiyun DCU_CTRLDESCLN_5_CKMAX_G(0xff) |
282*4882a593Smuzhiyun DCU_CTRLDESCLN_5_CKMAX_B(0xff));
283*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][5],
284*4882a593Smuzhiyun DCU_CTRLDESCLN_6_CKMIN_R(0) |
285*4882a593Smuzhiyun DCU_CTRLDESCLN_6_CKMIN_G(0) |
286*4882a593Smuzhiyun DCU_CTRLDESCLN_6_CKMIN_B(0));
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][6],
289*4882a593Smuzhiyun DCU_CTRLDESCLN_7_TILE_VER(0) |
290*4882a593Smuzhiyun DCU_CTRLDESCLN_7_TILE_HOR(0));
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][7], DCU_CTRLDESCLN_8_FG_FCOLOR(0));
293*4882a593Smuzhiyun dcu_write32(®s->ctrldescl[index][8], DCU_CTRLDESCLN_9_BG_BCOLOR(0));
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun return 0;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
fsl_dcu_init(unsigned int xres,unsigned int yres,unsigned int pixel_format)298*4882a593Smuzhiyun int fsl_dcu_init(unsigned int xres, unsigned int yres,
299*4882a593Smuzhiyun unsigned int pixel_format)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
302*4882a593Smuzhiyun unsigned int div, mode;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun info.screen_size =
305*4882a593Smuzhiyun info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun if (info.screen_size > CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB) {
308*4882a593Smuzhiyun info.screen_size = 0;
309*4882a593Smuzhiyun return -ENOMEM;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /* Reserve framebuffer at the end of memory */
313*4882a593Smuzhiyun gd->fb_base = gd->bd->bi_dram[0].start +
314*4882a593Smuzhiyun gd->bd->bi_dram[0].size - info.screen_size;
315*4882a593Smuzhiyun info.screen_base = (char *)gd->fb_base;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun memset(info.screen_base, 0, info.screen_size);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun reset_total_layers();
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun dcu_write32(®s->disp_size,
322*4882a593Smuzhiyun DCU_DISP_SIZE_DELTA_Y(info.var.yres) |
323*4882a593Smuzhiyun DCU_DISP_SIZE_DELTA_X(info.var.xres / 16));
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun dcu_write32(®s->hsyn_para,
326*4882a593Smuzhiyun DCU_HSYN_PARA_BP(info.var.left_margin) |
327*4882a593Smuzhiyun DCU_HSYN_PARA_PW(info.var.hsync_len) |
328*4882a593Smuzhiyun DCU_HSYN_PARA_FP(info.var.right_margin));
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun dcu_write32(®s->vsyn_para,
331*4882a593Smuzhiyun DCU_VSYN_PARA_BP(info.var.upper_margin) |
332*4882a593Smuzhiyun DCU_VSYN_PARA_PW(info.var.vsync_len) |
333*4882a593Smuzhiyun DCU_VSYN_PARA_FP(info.var.lower_margin));
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun dcu_write32(®s->synpol,
336*4882a593Smuzhiyun DCU_SYN_POL_INV_PXCK_FALL |
337*4882a593Smuzhiyun DCU_SYN_POL_NEG_REMAIN |
338*4882a593Smuzhiyun DCU_SYN_POL_INV_VS_LOW |
339*4882a593Smuzhiyun DCU_SYN_POL_INV_HS_LOW);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun dcu_write32(®s->bgnd,
342*4882a593Smuzhiyun DCU_BGND_R(0) | DCU_BGND_G(0) | DCU_BGND_B(0));
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun dcu_write32(®s->mode,
345*4882a593Smuzhiyun DCU_MODE_BLEND_ITER(2) |
346*4882a593Smuzhiyun DCU_MODE_RASTER_EN);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun dcu_write32(®s->threshold,
349*4882a593Smuzhiyun DCU_THRESHOLD_LS_BF_VS(0x3) |
350*4882a593Smuzhiyun DCU_THRESHOLD_OUT_BUF_HIGH(0x78) |
351*4882a593Smuzhiyun DCU_THRESHOLD_OUT_BUF_LOW(0));
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun mode = dcu_read32(®s->mode);
354*4882a593Smuzhiyun dcu_write32(®s->mode, mode | DCU_MODE_NORMAL);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun layer_ctrldesc_init(0, pixel_format);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun div = dcu_set_pixel_clock(info.var.pixclock);
359*4882a593Smuzhiyun dcu_write32(®s->div_ratio, (div - 1));
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun dcu_write32(®s->update_mode, DCU_UPDATE_MODE_READREG);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return 0;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
board_get_usable_ram_top(ulong total_size)366*4882a593Smuzhiyun ulong board_get_usable_ram_top(ulong total_size)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun return gd->ram_top - CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
video_hw_init(void)371*4882a593Smuzhiyun void *video_hw_init(void)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun static GraphicDevice ctfb;
374*4882a593Smuzhiyun const char *options;
375*4882a593Smuzhiyun unsigned int depth = 0, freq = 0;
376*4882a593Smuzhiyun struct fb_videomode *fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
379*4882a593Smuzhiyun &options))
380*4882a593Smuzhiyun return NULL;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* Find the monitor port, which is a required option */
383*4882a593Smuzhiyun if (!options)
384*4882a593Smuzhiyun return NULL;
385*4882a593Smuzhiyun if (strncmp(options, "monitor=", 8) != 0)
386*4882a593Smuzhiyun return NULL;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun switch (RESOLUTION(ctfb.winSizeX, ctfb.winSizeY)) {
389*4882a593Smuzhiyun case RESOLUTION(480, 272):
390*4882a593Smuzhiyun fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
391*4882a593Smuzhiyun break;
392*4882a593Smuzhiyun case RESOLUTION(640, 480):
393*4882a593Smuzhiyun if (!strncmp(options, "monitor=hdmi", 12))
394*4882a593Smuzhiyun fsl_dcu_mode_db = &fsl_dcu_cea_mode_640_480;
395*4882a593Smuzhiyun else
396*4882a593Smuzhiyun fsl_dcu_mode_db = &fsl_dcu_mode_640_480;
397*4882a593Smuzhiyun break;
398*4882a593Smuzhiyun case RESOLUTION(800, 480):
399*4882a593Smuzhiyun fsl_dcu_mode_db = &fsl_dcu_mode_800_480;
400*4882a593Smuzhiyun break;
401*4882a593Smuzhiyun case RESOLUTION(1024, 600):
402*4882a593Smuzhiyun fsl_dcu_mode_db = &fsl_dcu_mode_1024_600;
403*4882a593Smuzhiyun break;
404*4882a593Smuzhiyun default:
405*4882a593Smuzhiyun printf("unsupported resolution %ux%u\n",
406*4882a593Smuzhiyun ctfb.winSizeX, ctfb.winSizeY);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun info.var.xres = fsl_dcu_mode_db->xres;
410*4882a593Smuzhiyun info.var.yres = fsl_dcu_mode_db->yres;
411*4882a593Smuzhiyun info.var.bits_per_pixel = 32;
412*4882a593Smuzhiyun info.var.pixclock = fsl_dcu_mode_db->pixclock;
413*4882a593Smuzhiyun info.var.left_margin = fsl_dcu_mode_db->left_margin;
414*4882a593Smuzhiyun info.var.right_margin = fsl_dcu_mode_db->right_margin;
415*4882a593Smuzhiyun info.var.upper_margin = fsl_dcu_mode_db->upper_margin;
416*4882a593Smuzhiyun info.var.lower_margin = fsl_dcu_mode_db->lower_margin;
417*4882a593Smuzhiyun info.var.hsync_len = fsl_dcu_mode_db->hsync_len;
418*4882a593Smuzhiyun info.var.vsync_len = fsl_dcu_mode_db->vsync_len;
419*4882a593Smuzhiyun info.var.sync = fsl_dcu_mode_db->sync;
420*4882a593Smuzhiyun info.var.vmode = fsl_dcu_mode_db->vmode;
421*4882a593Smuzhiyun info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (platform_dcu_init(ctfb.winSizeX, ctfb.winSizeY,
424*4882a593Smuzhiyun options + 8, fsl_dcu_mode_db) < 0)
425*4882a593Smuzhiyun return NULL;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun ctfb.frameAdrs = (unsigned int)info.screen_base;
428*4882a593Smuzhiyun ctfb.plnSizeX = ctfb.winSizeX;
429*4882a593Smuzhiyun ctfb.plnSizeY = ctfb.winSizeY;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun ctfb.gdfBytesPP = 4;
432*4882a593Smuzhiyun ctfb.gdfIndex = GDF_32BIT_X888RGB;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun ctfb.memSize = info.screen_size;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun return &ctfb;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun #if defined(CONFIG_OF_BOARD_SETUP)
fsl_dcu_fixedfb_setup(void * blob)440*4882a593Smuzhiyun int fsl_dcu_fixedfb_setup(void *blob)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun u64 start, size;
443*4882a593Smuzhiyun int ret;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun start = gd->bd->bi_dram[0].start;
446*4882a593Smuzhiyun size = gd->bd->bi_dram[0].size - info.screen_size;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun /*
449*4882a593Smuzhiyun * Align size on section size (1 MiB).
450*4882a593Smuzhiyun */
451*4882a593Smuzhiyun size &= 0xfff00000;
452*4882a593Smuzhiyun ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
453*4882a593Smuzhiyun if (ret) {
454*4882a593Smuzhiyun eprintf("Cannot setup fb: Error reserving memory\n");
455*4882a593Smuzhiyun return ret;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun return 0;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun #endif
461