xref: /rk3399_rockchip-uboot/drivers/video/fsl_diu_fb.c (revision 14f88c43fcb7cee954648daeaba08b8e881ec01b)
1*14f88c43SAnatolij Gustschin /*
2*14f88c43SAnatolij Gustschin  * Copyright 2007, 2010 Freescale Semiconductor, Inc.
3*14f88c43SAnatolij Gustschin  * York Sun <yorksun@freescale.com>
4*14f88c43SAnatolij Gustschin  *
5*14f88c43SAnatolij Gustschin  * FSL DIU Framebuffer driver
6*14f88c43SAnatolij Gustschin  *
7*14f88c43SAnatolij Gustschin  * See file CREDITS for list of people who contributed to this
8*14f88c43SAnatolij Gustschin  * project.
9*14f88c43SAnatolij Gustschin  *
10*14f88c43SAnatolij Gustschin  * This program is free software; you can redistribute it and/or
11*14f88c43SAnatolij Gustschin  * modify it under the terms of the GNU General Public License as
12*14f88c43SAnatolij Gustschin  * published by the Free Software Foundation; either version 2 of
13*14f88c43SAnatolij Gustschin  * the License, or (at your option) any later version.
14*14f88c43SAnatolij Gustschin  *
15*14f88c43SAnatolij Gustschin  * This program is distributed in the hope that it will be useful,
16*14f88c43SAnatolij Gustschin  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*14f88c43SAnatolij Gustschin  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*14f88c43SAnatolij Gustschin  * GNU General Public License for more details.
19*14f88c43SAnatolij Gustschin  *
20*14f88c43SAnatolij Gustschin  * You should have received a copy of the GNU General Public License
21*14f88c43SAnatolij Gustschin  * along with this program; if not, write to the Free Software
22*14f88c43SAnatolij Gustschin  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23*14f88c43SAnatolij Gustschin  * MA 02111-1307 USA
24*14f88c43SAnatolij Gustschin  */
25*14f88c43SAnatolij Gustschin 
26*14f88c43SAnatolij Gustschin #include <common.h>
27*14f88c43SAnatolij Gustschin #include <i2c.h>
28*14f88c43SAnatolij Gustschin #include <malloc.h>
29*14f88c43SAnatolij Gustschin #include <asm/io.h>
30*14f88c43SAnatolij Gustschin 
31*14f88c43SAnatolij Gustschin #include <fsl_diu_fb.h>
32*14f88c43SAnatolij Gustschin 
33*14f88c43SAnatolij Gustschin struct fb_videomode {
34*14f88c43SAnatolij Gustschin 	const char *name;	/* optional */
35*14f88c43SAnatolij Gustschin 	unsigned int refresh;		/* optional */
36*14f88c43SAnatolij Gustschin 	unsigned int xres;
37*14f88c43SAnatolij Gustschin 	unsigned int yres;
38*14f88c43SAnatolij Gustschin 	unsigned int pixclock;
39*14f88c43SAnatolij Gustschin 	unsigned int left_margin;
40*14f88c43SAnatolij Gustschin 	unsigned int right_margin;
41*14f88c43SAnatolij Gustschin 	unsigned int upper_margin;
42*14f88c43SAnatolij Gustschin 	unsigned int lower_margin;
43*14f88c43SAnatolij Gustschin 	unsigned int hsync_len;
44*14f88c43SAnatolij Gustschin 	unsigned int vsync_len;
45*14f88c43SAnatolij Gustschin 	unsigned int sync;
46*14f88c43SAnatolij Gustschin 	unsigned int vmode;
47*14f88c43SAnatolij Gustschin 	unsigned int flag;
48*14f88c43SAnatolij Gustschin };
49*14f88c43SAnatolij Gustschin 
50*14f88c43SAnatolij Gustschin #define FB_SYNC_VERT_HIGH_ACT	2	/* vertical sync high active	*/
51*14f88c43SAnatolij Gustschin #define FB_SYNC_COMP_HIGH_ACT	8	/* composite sync high active   */
52*14f88c43SAnatolij Gustschin #define FB_VMODE_NONINTERLACED  0	/* non interlaced */
53*14f88c43SAnatolij Gustschin 
54*14f88c43SAnatolij Gustschin /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
55*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_800 = {
56*14f88c43SAnatolij Gustschin 	.refresh	= 60,
57*14f88c43SAnatolij Gustschin 	.xres		= 800,
58*14f88c43SAnatolij Gustschin 	.yres		= 480,
59*14f88c43SAnatolij Gustschin 	.pixclock	= 31250,
60*14f88c43SAnatolij Gustschin 	.left_margin	= 86,
61*14f88c43SAnatolij Gustschin 	.right_margin	= 42,
62*14f88c43SAnatolij Gustschin 	.upper_margin	= 33,
63*14f88c43SAnatolij Gustschin 	.lower_margin	= 10,
64*14f88c43SAnatolij Gustschin 	.hsync_len	= 128,
65*14f88c43SAnatolij Gustschin 	.vsync_len	= 2,
66*14f88c43SAnatolij Gustschin 	.sync		= 0,
67*14f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
68*14f88c43SAnatolij Gustschin };
69*14f88c43SAnatolij Gustschin 
70*14f88c43SAnatolij Gustschin /*
71*14f88c43SAnatolij Gustschin  * These parameters give default parameters
72*14f88c43SAnatolij Gustschin  * for video output 1024x768,
73*14f88c43SAnatolij Gustschin  * FIXME - change timing to proper amounts
74*14f88c43SAnatolij Gustschin  * hsync 31.5kHz, vsync 60Hz
75*14f88c43SAnatolij Gustschin  */
76*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_1024 = {
77*14f88c43SAnatolij Gustschin 	.refresh	= 60,
78*14f88c43SAnatolij Gustschin 	.xres		= 1024,
79*14f88c43SAnatolij Gustschin 	.yres		= 768,
80*14f88c43SAnatolij Gustschin 	.pixclock	= 15385,
81*14f88c43SAnatolij Gustschin 	.left_margin	= 160,
82*14f88c43SAnatolij Gustschin 	.right_margin	= 24,
83*14f88c43SAnatolij Gustschin 	.upper_margin	= 29,
84*14f88c43SAnatolij Gustschin 	.lower_margin	= 3,
85*14f88c43SAnatolij Gustschin 	.hsync_len	= 136,
86*14f88c43SAnatolij Gustschin 	.vsync_len	= 6,
87*14f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
88*14f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
89*14f88c43SAnatolij Gustschin };
90*14f88c43SAnatolij Gustschin 
91*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_1280 = {
92*14f88c43SAnatolij Gustschin 	.name		= "1280x1024-60",
93*14f88c43SAnatolij Gustschin 	.refresh	= 60,
94*14f88c43SAnatolij Gustschin 	.xres		= 1280,
95*14f88c43SAnatolij Gustschin 	.yres		= 1024,
96*14f88c43SAnatolij Gustschin 	.pixclock	= 9375,
97*14f88c43SAnatolij Gustschin 	.left_margin	= 38,
98*14f88c43SAnatolij Gustschin 	.right_margin	= 128,
99*14f88c43SAnatolij Gustschin 	.upper_margin	= 2,
100*14f88c43SAnatolij Gustschin 	.lower_margin	= 7,
101*14f88c43SAnatolij Gustschin 	.hsync_len	= 216,
102*14f88c43SAnatolij Gustschin 	.vsync_len	= 37,
103*14f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
104*14f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
105*14f88c43SAnatolij Gustschin };
106*14f88c43SAnatolij Gustschin 
107*14f88c43SAnatolij Gustschin /*
108*14f88c43SAnatolij Gustschin  * These are the fields of area descriptor(in DDR memory) for every plane
109*14f88c43SAnatolij Gustschin  */
110*14f88c43SAnatolij Gustschin struct diu_ad {
111*14f88c43SAnatolij Gustschin 	/* Word 0(32-bit) in DDR memory */
112*14f88c43SAnatolij Gustschin 	unsigned int pix_fmt; /* hard coding pixel format */
113*14f88c43SAnatolij Gustschin 	/* Word 1(32-bit) in DDR memory */
114*14f88c43SAnatolij Gustschin 	unsigned int addr;
115*14f88c43SAnatolij Gustschin 	/* Word 2(32-bit) in DDR memory */
116*14f88c43SAnatolij Gustschin 	unsigned int src_size_g_alpha;
117*14f88c43SAnatolij Gustschin 	/* Word 3(32-bit) in DDR memory */
118*14f88c43SAnatolij Gustschin 	unsigned int aoi_size;
119*14f88c43SAnatolij Gustschin 	/* Word 4(32-bit) in DDR memory */
120*14f88c43SAnatolij Gustschin 	unsigned int offset_xyi;
121*14f88c43SAnatolij Gustschin 	/* Word 5(32-bit) in DDR memory */
122*14f88c43SAnatolij Gustschin 	unsigned int offset_xyd;
123*14f88c43SAnatolij Gustschin 	/* Word 6(32-bit) in DDR memory */
124*14f88c43SAnatolij Gustschin 	unsigned int ckmax_r:8;
125*14f88c43SAnatolij Gustschin 	unsigned int ckmax_g:8;
126*14f88c43SAnatolij Gustschin 	unsigned int ckmax_b:8;
127*14f88c43SAnatolij Gustschin 	unsigned int res9:8;
128*14f88c43SAnatolij Gustschin 	/* Word 7(32-bit) in DDR memory */
129*14f88c43SAnatolij Gustschin 	unsigned int ckmin_r:8;
130*14f88c43SAnatolij Gustschin 	unsigned int ckmin_g:8;
131*14f88c43SAnatolij Gustschin 	unsigned int ckmin_b:8;
132*14f88c43SAnatolij Gustschin 	unsigned int res10:8;
133*14f88c43SAnatolij Gustschin 	/* Word 8(32-bit) in DDR memory */
134*14f88c43SAnatolij Gustschin 	unsigned int next_ad;
135*14f88c43SAnatolij Gustschin 	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
136*14f88c43SAnatolij Gustschin 	unsigned int res1;
137*14f88c43SAnatolij Gustschin 	unsigned int res2;
138*14f88c43SAnatolij Gustschin 	unsigned int res3;
139*14f88c43SAnatolij Gustschin }__attribute__ ((packed));
140*14f88c43SAnatolij Gustschin 
141*14f88c43SAnatolij Gustschin /*
142*14f88c43SAnatolij Gustschin  * DIU register map
143*14f88c43SAnatolij Gustschin  */
144*14f88c43SAnatolij Gustschin struct diu {
145*14f88c43SAnatolij Gustschin 	unsigned int desc[3];
146*14f88c43SAnatolij Gustschin 	unsigned int gamma;
147*14f88c43SAnatolij Gustschin 	unsigned int pallete;
148*14f88c43SAnatolij Gustschin 	unsigned int cursor;
149*14f88c43SAnatolij Gustschin 	unsigned int curs_pos;
150*14f88c43SAnatolij Gustschin 	unsigned int diu_mode;
151*14f88c43SAnatolij Gustschin 	unsigned int bgnd;
152*14f88c43SAnatolij Gustschin 	unsigned int bgnd_wb;
153*14f88c43SAnatolij Gustschin 	unsigned int disp_size;
154*14f88c43SAnatolij Gustschin 	unsigned int wb_size;
155*14f88c43SAnatolij Gustschin 	unsigned int wb_mem_addr;
156*14f88c43SAnatolij Gustschin 	unsigned int hsyn_para;
157*14f88c43SAnatolij Gustschin 	unsigned int vsyn_para;
158*14f88c43SAnatolij Gustschin 	unsigned int syn_pol;
159*14f88c43SAnatolij Gustschin 	unsigned int thresholds;
160*14f88c43SAnatolij Gustschin 	unsigned int int_status;
161*14f88c43SAnatolij Gustschin 	unsigned int int_mask;
162*14f88c43SAnatolij Gustschin 	unsigned int colorbar[8];
163*14f88c43SAnatolij Gustschin 	unsigned int filling;
164*14f88c43SAnatolij Gustschin 	unsigned int plut;
165*14f88c43SAnatolij Gustschin } __attribute__ ((packed));
166*14f88c43SAnatolij Gustschin 
167*14f88c43SAnatolij Gustschin struct diu_hw {
168*14f88c43SAnatolij Gustschin 	struct diu *diu_reg;
169*14f88c43SAnatolij Gustschin 	volatile unsigned int mode;		/* DIU operation mode */
170*14f88c43SAnatolij Gustschin };
171*14f88c43SAnatolij Gustschin 
172*14f88c43SAnatolij Gustschin struct diu_addr {
173*14f88c43SAnatolij Gustschin 	unsigned char  *  paddr;	/* Virtual address */
174*14f88c43SAnatolij Gustschin 	unsigned int	   offset;
175*14f88c43SAnatolij Gustschin };
176*14f88c43SAnatolij Gustschin 
177*14f88c43SAnatolij Gustschin /*
178*14f88c43SAnatolij Gustschin  * Modes of operation of DIU
179*14f88c43SAnatolij Gustschin  */
180*14f88c43SAnatolij Gustschin #define MFB_MODE0	0	/* DIU off */
181*14f88c43SAnatolij Gustschin #define MFB_MODE1	1	/* All three planes output to display */
182*14f88c43SAnatolij Gustschin #define MFB_MODE2	2	/* Plane 1 to display,
183*14f88c43SAnatolij Gustschin 				 * planes 2+3 written back to memory */
184*14f88c43SAnatolij Gustschin #define MFB_MODE3	3	/* All three planes written back to memory */
185*14f88c43SAnatolij Gustschin #define MFB_MODE4	4	/* Color bar generation */
186*14f88c43SAnatolij Gustschin 
187*14f88c43SAnatolij Gustschin #define MAX_CURS		32
188*14f88c43SAnatolij Gustschin 
189*14f88c43SAnatolij Gustschin static struct fb_info fsl_fb_info;
190*14f88c43SAnatolij Gustschin static struct diu_addr gamma, cursor;
191*14f88c43SAnatolij Gustschin static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32)));
192*14f88c43SAnatolij Gustschin static struct diu_ad dummy_ad __attribute__ ((aligned(32)));
193*14f88c43SAnatolij Gustschin static unsigned char *dummy_fb;
194*14f88c43SAnatolij Gustschin static struct diu_hw dr = {
195*14f88c43SAnatolij Gustschin 	.mode = MFB_MODE1,
196*14f88c43SAnatolij Gustschin };
197*14f88c43SAnatolij Gustschin 
198*14f88c43SAnatolij Gustschin int fb_enabled = 0;
199*14f88c43SAnatolij Gustschin int fb_initialized = 0;
200*14f88c43SAnatolij Gustschin const int default_xres = 1280;
201*14f88c43SAnatolij Gustschin const int default_pixel_format = 0x88882317;
202*14f88c43SAnatolij Gustschin 
203*14f88c43SAnatolij Gustschin static int map_video_memory(struct fb_info *info, unsigned long bytes_align);
204*14f88c43SAnatolij Gustschin static void enable_lcdc(void);
205*14f88c43SAnatolij Gustschin static void disable_lcdc(void);
206*14f88c43SAnatolij Gustschin static int fsl_diu_enable_panel(struct fb_info *info);
207*14f88c43SAnatolij Gustschin static int fsl_diu_disable_panel(struct fb_info *info);
208*14f88c43SAnatolij Gustschin static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align);
209*14f88c43SAnatolij Gustschin void diu_set_pixel_clock(unsigned int pixclock);
210*14f88c43SAnatolij Gustschin 
211*14f88c43SAnatolij Gustschin int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix)
212*14f88c43SAnatolij Gustschin {
213*14f88c43SAnatolij Gustschin 	struct fb_videomode *fsl_diu_mode_db;
214*14f88c43SAnatolij Gustschin 	struct diu_ad *ad = &fsl_diu_fb_ad;
215*14f88c43SAnatolij Gustschin 	struct diu *hw;
216*14f88c43SAnatolij Gustschin 	struct fb_info *info = &fsl_fb_info;
217*14f88c43SAnatolij Gustschin 	struct fb_var_screeninfo *var = &info->var;
218*14f88c43SAnatolij Gustschin 	unsigned char *gamma_table_base;
219*14f88c43SAnatolij Gustschin 	unsigned int i, j;
220*14f88c43SAnatolij Gustschin 
221*14f88c43SAnatolij Gustschin 	debug("Enter fsl_diu_init\n");
222*14f88c43SAnatolij Gustschin 	dr.diu_reg = (struct diu *) (CONFIG_SYS_DIU_ADDR);
223*14f88c43SAnatolij Gustschin 	hw = (struct diu *) dr.diu_reg;
224*14f88c43SAnatolij Gustschin 
225*14f88c43SAnatolij Gustschin 	disable_lcdc();
226*14f88c43SAnatolij Gustschin 
227*14f88c43SAnatolij Gustschin 	switch (xres) {
228*14f88c43SAnatolij Gustschin 	case 800:
229*14f88c43SAnatolij Gustschin 		fsl_diu_mode_db = &fsl_diu_mode_800;
230*14f88c43SAnatolij Gustschin 		break;
231*14f88c43SAnatolij Gustschin 	case 1280:
232*14f88c43SAnatolij Gustschin 		fsl_diu_mode_db = &fsl_diu_mode_1280;
233*14f88c43SAnatolij Gustschin 		break;
234*14f88c43SAnatolij Gustschin 	default:
235*14f88c43SAnatolij Gustschin 		fsl_diu_mode_db = &fsl_diu_mode_1024;
236*14f88c43SAnatolij Gustschin 	}
237*14f88c43SAnatolij Gustschin 
238*14f88c43SAnatolij Gustschin 	if (0 == fb_initialized) {
239*14f88c43SAnatolij Gustschin 		allocate_buf(&gamma, 768, 32);
240*14f88c43SAnatolij Gustschin 		debug("gamma is allocated @ 0x%x\n",
241*14f88c43SAnatolij Gustschin 			(unsigned int)gamma.paddr);
242*14f88c43SAnatolij Gustschin 		allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32);
243*14f88c43SAnatolij Gustschin 		debug("curosr is allocated @ 0x%x\n",
244*14f88c43SAnatolij Gustschin 			(unsigned int)cursor.paddr);
245*14f88c43SAnatolij Gustschin 
246*14f88c43SAnatolij Gustschin 		/* create a dummy fb and dummy ad */
247*14f88c43SAnatolij Gustschin 		dummy_fb = malloc(64);
248*14f88c43SAnatolij Gustschin 		if (NULL == dummy_fb) {
249*14f88c43SAnatolij Gustschin 			printf("Cannot allocate dummy fb\n");
250*14f88c43SAnatolij Gustschin 			return -1;
251*14f88c43SAnatolij Gustschin 		}
252*14f88c43SAnatolij Gustschin 		dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb);
253*14f88c43SAnatolij Gustschin 		dummy_ad.pix_fmt = 0x88882317;
254*14f88c43SAnatolij Gustschin 		dummy_ad.src_size_g_alpha = 0x04400000;	/* alpha = 0 */
255*14f88c43SAnatolij Gustschin 		dummy_ad.aoi_size = 0x02000400;
256*14f88c43SAnatolij Gustschin 		dummy_ad.offset_xyi = 0;
257*14f88c43SAnatolij Gustschin 		dummy_ad.offset_xyd = 0;
258*14f88c43SAnatolij Gustschin 		dummy_ad.next_ad = 0;
259*14f88c43SAnatolij Gustschin 		/* Memory allocation for framebuffer */
260*14f88c43SAnatolij Gustschin 		if (map_video_memory(info, 32)) {
261*14f88c43SAnatolij Gustschin 			printf("Unable to allocate fb memory 1\n");
262*14f88c43SAnatolij Gustschin 			return -1;
263*14f88c43SAnatolij Gustschin 		}
264*14f88c43SAnatolij Gustschin 	}
265*14f88c43SAnatolij Gustschin 
266*14f88c43SAnatolij Gustschin 	memset(info->screen_base, 0, info->smem_len);
267*14f88c43SAnatolij Gustschin 
268*14f88c43SAnatolij Gustschin 	out_be32(&dr.diu_reg->desc[0], (int)&dummy_ad);
269*14f88c43SAnatolij Gustschin 	out_be32(&dr.diu_reg->desc[1], (int)&dummy_ad);
270*14f88c43SAnatolij Gustschin 	out_be32(&dr.diu_reg->desc[2], (int)&dummy_ad);
271*14f88c43SAnatolij Gustschin 	debug("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]);
272*14f88c43SAnatolij Gustschin 	debug("dummy desc[0] = 0x%x\n", hw->desc[0]);
273*14f88c43SAnatolij Gustschin 
274*14f88c43SAnatolij Gustschin 	/* read mode info */
275*14f88c43SAnatolij Gustschin 	var->xres = fsl_diu_mode_db->xres;
276*14f88c43SAnatolij Gustschin 	var->yres = fsl_diu_mode_db->yres;
277*14f88c43SAnatolij Gustschin 	var->bits_per_pixel = 32;
278*14f88c43SAnatolij Gustschin 	var->pixclock = fsl_diu_mode_db->pixclock;
279*14f88c43SAnatolij Gustschin 	var->left_margin = fsl_diu_mode_db->left_margin;
280*14f88c43SAnatolij Gustschin 	var->right_margin = fsl_diu_mode_db->right_margin;
281*14f88c43SAnatolij Gustschin 	var->upper_margin = fsl_diu_mode_db->upper_margin;
282*14f88c43SAnatolij Gustschin 	var->lower_margin = fsl_diu_mode_db->lower_margin;
283*14f88c43SAnatolij Gustschin 	var->hsync_len = fsl_diu_mode_db->hsync_len;
284*14f88c43SAnatolij Gustschin 	var->vsync_len = fsl_diu_mode_db->vsync_len;
285*14f88c43SAnatolij Gustschin 	var->sync = fsl_diu_mode_db->sync;
286*14f88c43SAnatolij Gustschin 	var->vmode = fsl_diu_mode_db->vmode;
287*14f88c43SAnatolij Gustschin 	info->line_length = var->xres * var->bits_per_pixel / 8;
288*14f88c43SAnatolij Gustschin 
289*14f88c43SAnatolij Gustschin 	ad->pix_fmt = pixel_format;
290*14f88c43SAnatolij Gustschin 	ad->addr    = cpu_to_le32((unsigned int)info->screen_base);
291*14f88c43SAnatolij Gustschin 	ad->src_size_g_alpha
292*14f88c43SAnatolij Gustschin 			= cpu_to_le32((var->yres << 12) | var->xres);
293*14f88c43SAnatolij Gustschin 	/* fix me. AOI should not be greater than display size */
294*14f88c43SAnatolij Gustschin 	ad->aoi_size	= cpu_to_le32(( var->yres << 16) |  var->xres);
295*14f88c43SAnatolij Gustschin 	ad->offset_xyi = 0;
296*14f88c43SAnatolij Gustschin 	ad->offset_xyd = 0;
297*14f88c43SAnatolij Gustschin 
298*14f88c43SAnatolij Gustschin 	/* Disable chroma keying function */
299*14f88c43SAnatolij Gustschin 	ad->ckmax_r = 0;
300*14f88c43SAnatolij Gustschin 	ad->ckmax_g = 0;
301*14f88c43SAnatolij Gustschin 	ad->ckmax_b = 0;
302*14f88c43SAnatolij Gustschin 
303*14f88c43SAnatolij Gustschin 	ad->ckmin_r = 255;
304*14f88c43SAnatolij Gustschin 	ad->ckmin_g = 255;
305*14f88c43SAnatolij Gustschin 	ad->ckmin_b = 255;
306*14f88c43SAnatolij Gustschin 
307*14f88c43SAnatolij Gustschin 	gamma_table_base = gamma.paddr;
308*14f88c43SAnatolij Gustschin 	debug("gamma_table_base is allocated @ 0x%x\n",
309*14f88c43SAnatolij Gustschin 		(unsigned int)gamma_table_base);
310*14f88c43SAnatolij Gustschin 
311*14f88c43SAnatolij Gustschin 	/* Prep for DIU init  - gamma table */
312*14f88c43SAnatolij Gustschin 
313*14f88c43SAnatolij Gustschin 	for (i = 0; i <= 2; i++)
314*14f88c43SAnatolij Gustschin 		for (j = 0; j <= 255; j++)
315*14f88c43SAnatolij Gustschin 			*gamma_table_base++ = j;
316*14f88c43SAnatolij Gustschin 
317*14f88c43SAnatolij Gustschin 	if (gamma_fix == 1) {	/* fix the gamma */
318*14f88c43SAnatolij Gustschin 		debug("Fix gamma table\n");
319*14f88c43SAnatolij Gustschin 		gamma_table_base = gamma.paddr;
320*14f88c43SAnatolij Gustschin 		for (i = 0; i < 256*3; i++) {
321*14f88c43SAnatolij Gustschin 			gamma_table_base[i] = (gamma_table_base[i] << 2)
322*14f88c43SAnatolij Gustschin 				| ((gamma_table_base[i] >> 6) & 0x03);
323*14f88c43SAnatolij Gustschin 		}
324*14f88c43SAnatolij Gustschin 	}
325*14f88c43SAnatolij Gustschin 
326*14f88c43SAnatolij Gustschin 	debug("update-lcdc: HW - %p\n Disabling DIU\n", hw);
327*14f88c43SAnatolij Gustschin 
328*14f88c43SAnatolij Gustschin 	/* Program DIU registers */
329*14f88c43SAnatolij Gustschin 
330*14f88c43SAnatolij Gustschin 	out_be32(&hw->gamma, (int)gamma.paddr);
331*14f88c43SAnatolij Gustschin 	out_be32(&hw->cursor, (int)cursor.paddr);
332*14f88c43SAnatolij Gustschin 	out_be32(&hw->bgnd, 0x007F7F7F);
333*14f88c43SAnatolij Gustschin 	out_be32(&hw->bgnd_wb, 0);				/* BGND_WB */
334*14f88c43SAnatolij Gustschin 	out_be32(&hw->disp_size, var->yres << 16 | var->xres);	/* DISP SIZE */
335*14f88c43SAnatolij Gustschin 	out_be32(&hw->wb_size, 0);				/* WB SIZE */
336*14f88c43SAnatolij Gustschin 	out_be32(&hw->wb_mem_addr, 0);				/* WB MEM ADDR */
337*14f88c43SAnatolij Gustschin 	out_be32(&hw->hsyn_para, var->left_margin << 22 |	/* BP_H */
338*14f88c43SAnatolij Gustschin 			var->hsync_len << 11   |	/* PW_H */
339*14f88c43SAnatolij Gustschin 			var->right_margin);		/* FP_H */
340*14f88c43SAnatolij Gustschin 
341*14f88c43SAnatolij Gustschin 	out_be32(&hw->vsyn_para, var->upper_margin << 22 |	/* BP_V */
342*14f88c43SAnatolij Gustschin 			var->vsync_len << 11    |	/* PW_V  */
343*14f88c43SAnatolij Gustschin 			var->lower_margin);		/* FP_V  */
344*14f88c43SAnatolij Gustschin 
345*14f88c43SAnatolij Gustschin 	out_be32(&hw->syn_pol, 0);			/* SYNC SIGNALS POLARITY */
346*14f88c43SAnatolij Gustschin 	out_be32(&hw->thresholds, 0x00037800);		/* The Thresholds */
347*14f88c43SAnatolij Gustschin 	out_be32(&hw->int_status, 0);			/* INTERRUPT STATUS */
348*14f88c43SAnatolij Gustschin 	out_be32(&hw->int_mask, 0);			/* INT MASK */
349*14f88c43SAnatolij Gustschin 	out_be32(&hw->plut, 0x01F5F666);
350*14f88c43SAnatolij Gustschin 	/* Pixel Clock configuration */
351*14f88c43SAnatolij Gustschin 	debug("DIU pixclock in ps - %d\n", var->pixclock);
352*14f88c43SAnatolij Gustschin 	diu_set_pixel_clock(var->pixclock);
353*14f88c43SAnatolij Gustschin 
354*14f88c43SAnatolij Gustschin 	fb_initialized = 1;
355*14f88c43SAnatolij Gustschin 
356*14f88c43SAnatolij Gustschin 	/* Enable the DIU */
357*14f88c43SAnatolij Gustschin 	fsl_diu_enable_panel(info);
358*14f88c43SAnatolij Gustschin 	enable_lcdc();
359*14f88c43SAnatolij Gustschin 
360*14f88c43SAnatolij Gustschin 	return 0;
361*14f88c43SAnatolij Gustschin }
362*14f88c43SAnatolij Gustschin 
363*14f88c43SAnatolij Gustschin char *fsl_fb_open(struct fb_info **info)
364*14f88c43SAnatolij Gustschin {
365*14f88c43SAnatolij Gustschin 	*info = &fsl_fb_info;
366*14f88c43SAnatolij Gustschin 	return fsl_fb_info.screen_base;
367*14f88c43SAnatolij Gustschin }
368*14f88c43SAnatolij Gustschin 
369*14f88c43SAnatolij Gustschin void fsl_diu_close(void)
370*14f88c43SAnatolij Gustschin {
371*14f88c43SAnatolij Gustschin 	struct fb_info *info = &fsl_fb_info;
372*14f88c43SAnatolij Gustschin 	fsl_diu_disable_panel(info);
373*14f88c43SAnatolij Gustschin }
374*14f88c43SAnatolij Gustschin 
375*14f88c43SAnatolij Gustschin static int fsl_diu_enable_panel(struct fb_info *info)
376*14f88c43SAnatolij Gustschin {
377*14f88c43SAnatolij Gustschin 	struct diu *hw = dr.diu_reg;
378*14f88c43SAnatolij Gustschin 	struct diu_ad *ad = &fsl_diu_fb_ad;
379*14f88c43SAnatolij Gustschin 
380*14f88c43SAnatolij Gustschin 	debug("Entered: enable_panel\n");
381*14f88c43SAnatolij Gustschin 	if (in_be32(&hw->desc[0]) != (unsigned)ad)
382*14f88c43SAnatolij Gustschin 		out_be32(&hw->desc[0], (unsigned)ad);
383*14f88c43SAnatolij Gustschin 	debug("desc[0] = 0x%x\n", hw->desc[0]);
384*14f88c43SAnatolij Gustschin 	return 0;
385*14f88c43SAnatolij Gustschin }
386*14f88c43SAnatolij Gustschin 
387*14f88c43SAnatolij Gustschin static int fsl_diu_disable_panel(struct fb_info *info)
388*14f88c43SAnatolij Gustschin {
389*14f88c43SAnatolij Gustschin 	struct diu *hw = dr.diu_reg;
390*14f88c43SAnatolij Gustschin 
391*14f88c43SAnatolij Gustschin 	debug("Entered: disable_panel\n");
392*14f88c43SAnatolij Gustschin 	if (in_be32(&hw->desc[0]) != (unsigned)&dummy_ad)
393*14f88c43SAnatolij Gustschin 		out_be32(&hw->desc[0], (unsigned)&dummy_ad);
394*14f88c43SAnatolij Gustschin 	return 0;
395*14f88c43SAnatolij Gustschin }
396*14f88c43SAnatolij Gustschin 
397*14f88c43SAnatolij Gustschin static int map_video_memory(struct fb_info *info, unsigned long bytes_align)
398*14f88c43SAnatolij Gustschin {
399*14f88c43SAnatolij Gustschin 	unsigned long offset;
400*14f88c43SAnatolij Gustschin 	unsigned long mask;
401*14f88c43SAnatolij Gustschin 
402*14f88c43SAnatolij Gustschin 	debug("Entered: map_video_memory\n");
403*14f88c43SAnatolij Gustschin 	/* allocate maximum 1280*1024 with 32bpp */
404*14f88c43SAnatolij Gustschin 	info->smem_len = 1280 * 4 *1024 + bytes_align;
405*14f88c43SAnatolij Gustschin 	debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len);
406*14f88c43SAnatolij Gustschin 	info->screen_base = malloc(info->smem_len);
407*14f88c43SAnatolij Gustschin 	if (info->screen_base == NULL) {
408*14f88c43SAnatolij Gustschin 		printf("Unable to allocate fb memory\n");
409*14f88c43SAnatolij Gustschin 		return -1;
410*14f88c43SAnatolij Gustschin 	}
411*14f88c43SAnatolij Gustschin 	info->smem_start = (unsigned int) info->screen_base;
412*14f88c43SAnatolij Gustschin 	mask = bytes_align - 1;
413*14f88c43SAnatolij Gustschin 	offset = (unsigned long)info->screen_base & mask;
414*14f88c43SAnatolij Gustschin 	if (offset) {
415*14f88c43SAnatolij Gustschin 		info->screen_base += (bytes_align - offset);
416*14f88c43SAnatolij Gustschin 		info->smem_len = info->smem_len - (bytes_align - offset);
417*14f88c43SAnatolij Gustschin 	} else
418*14f88c43SAnatolij Gustschin 		info->smem_len = info->smem_len - bytes_align;
419*14f88c43SAnatolij Gustschin 
420*14f88c43SAnatolij Gustschin 	info->screen_size = info->smem_len;
421*14f88c43SAnatolij Gustschin 
422*14f88c43SAnatolij Gustschin 	debug("Allocated fb @ 0x%08lx, size=%d.\n",
423*14f88c43SAnatolij Gustschin 		info->smem_start, info->smem_len);
424*14f88c43SAnatolij Gustschin 
425*14f88c43SAnatolij Gustschin 	return 0;
426*14f88c43SAnatolij Gustschin }
427*14f88c43SAnatolij Gustschin 
428*14f88c43SAnatolij Gustschin static void enable_lcdc(void)
429*14f88c43SAnatolij Gustschin {
430*14f88c43SAnatolij Gustschin 	struct diu *hw = dr.diu_reg;
431*14f88c43SAnatolij Gustschin 
432*14f88c43SAnatolij Gustschin 	debug("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled);
433*14f88c43SAnatolij Gustschin 	if (!fb_enabled) {
434*14f88c43SAnatolij Gustschin 		out_be32(&hw->diu_mode, dr.mode);
435*14f88c43SAnatolij Gustschin 		fb_enabled++;
436*14f88c43SAnatolij Gustschin 	}
437*14f88c43SAnatolij Gustschin 	debug("diu_mode = %d\n", hw->diu_mode);
438*14f88c43SAnatolij Gustschin }
439*14f88c43SAnatolij Gustschin 
440*14f88c43SAnatolij Gustschin static void disable_lcdc(void)
441*14f88c43SAnatolij Gustschin {
442*14f88c43SAnatolij Gustschin 	struct diu *hw = dr.diu_reg;
443*14f88c43SAnatolij Gustschin 
444*14f88c43SAnatolij Gustschin 	debug("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled);
445*14f88c43SAnatolij Gustschin 	if (fb_enabled) {
446*14f88c43SAnatolij Gustschin 		out_be32(&hw->diu_mode, 0);
447*14f88c43SAnatolij Gustschin 		fb_enabled = 0;
448*14f88c43SAnatolij Gustschin 	}
449*14f88c43SAnatolij Gustschin }
450*14f88c43SAnatolij Gustschin 
451*14f88c43SAnatolij Gustschin /*
452*14f88c43SAnatolij Gustschin  * Align to 64-bit(8-byte), 32-byte, etc.
453*14f88c43SAnatolij Gustschin  */
454*14f88c43SAnatolij Gustschin static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
455*14f88c43SAnatolij Gustschin {
456*14f88c43SAnatolij Gustschin 	u32 offset, ssize;
457*14f88c43SAnatolij Gustschin 	u32 mask;
458*14f88c43SAnatolij Gustschin 
459*14f88c43SAnatolij Gustschin 	debug("Entered: allocate_buf\n");
460*14f88c43SAnatolij Gustschin 	ssize = size + bytes_align;
461*14f88c43SAnatolij Gustschin 	buf->paddr = malloc(ssize);
462*14f88c43SAnatolij Gustschin 	if (!buf->paddr)
463*14f88c43SAnatolij Gustschin 		return -1;
464*14f88c43SAnatolij Gustschin 
465*14f88c43SAnatolij Gustschin 	memset(buf->paddr, 0, ssize);
466*14f88c43SAnatolij Gustschin 	mask = bytes_align - 1;
467*14f88c43SAnatolij Gustschin 	offset = (u32)buf->paddr & mask;
468*14f88c43SAnatolij Gustschin 	if (offset) {
469*14f88c43SAnatolij Gustschin 		buf->offset = bytes_align - offset;
470*14f88c43SAnatolij Gustschin 		buf->paddr = (unsigned char *) ((u32)buf->paddr + offset);
471*14f88c43SAnatolij Gustschin 	} else
472*14f88c43SAnatolij Gustschin 		buf->offset = 0;
473*14f88c43SAnatolij Gustschin 	return 0;
474*14f88c43SAnatolij Gustschin }
475*14f88c43SAnatolij Gustschin 
476*14f88c43SAnatolij Gustschin #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
477*14f88c43SAnatolij Gustschin #include <stdio_dev.h>
478*14f88c43SAnatolij Gustschin #include <video_fb.h>
479*14f88c43SAnatolij Gustschin /*
480*14f88c43SAnatolij Gustschin  * The Graphic Device
481*14f88c43SAnatolij Gustschin  */
482*14f88c43SAnatolij Gustschin static GraphicDevice ctfb;
483*14f88c43SAnatolij Gustschin 
484*14f88c43SAnatolij Gustschin void *video_hw_init(void)
485*14f88c43SAnatolij Gustschin {
486*14f88c43SAnatolij Gustschin 	struct fb_info *info;
487*14f88c43SAnatolij Gustschin 
488*14f88c43SAnatolij Gustschin 	if (platform_diu_init(&ctfb.winSizeX, &ctfb.winSizeY) < 0)
489*14f88c43SAnatolij Gustschin 		return NULL;
490*14f88c43SAnatolij Gustschin 
491*14f88c43SAnatolij Gustschin 	/* fill in Graphic device struct */
492*14f88c43SAnatolij Gustschin 	sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
493*14f88c43SAnatolij Gustschin 		ctfb.winSizeX, ctfb.winSizeY, 32, 64, 60);
494*14f88c43SAnatolij Gustschin 
495*14f88c43SAnatolij Gustschin 	ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info);
496*14f88c43SAnatolij Gustschin 	ctfb.plnSizeX = ctfb.winSizeX;
497*14f88c43SAnatolij Gustschin 	ctfb.plnSizeY = ctfb.winSizeY;
498*14f88c43SAnatolij Gustschin 
499*14f88c43SAnatolij Gustschin 	ctfb.gdfBytesPP = 4;
500*14f88c43SAnatolij Gustschin 	ctfb.gdfIndex = GDF_32BIT_X888RGB;
501*14f88c43SAnatolij Gustschin 
502*14f88c43SAnatolij Gustschin 	ctfb.isaBase = 0;
503*14f88c43SAnatolij Gustschin 	ctfb.pciBase = 0;
504*14f88c43SAnatolij Gustschin 	ctfb.memSize = info->screen_size;
505*14f88c43SAnatolij Gustschin 
506*14f88c43SAnatolij Gustschin 	/* Cursor Start Address */
507*14f88c43SAnatolij Gustschin 	ctfb.dprBase = 0;
508*14f88c43SAnatolij Gustschin 	ctfb.vprBase = 0;
509*14f88c43SAnatolij Gustschin 	ctfb.cprBase = 0;
510*14f88c43SAnatolij Gustschin 
511*14f88c43SAnatolij Gustschin 	return &ctfb;
512*14f88c43SAnatolij Gustschin }
513*14f88c43SAnatolij Gustschin #endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */
514