xref: /openbmc/u-boot/drivers/video/fsl_diu_fb.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
214f88c43SAnatolij Gustschin /*
3ba8e76bdSTimur Tabi  * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
4ba8e76bdSTimur Tabi  * Authors: York Sun <yorksun@freescale.com>
5ba8e76bdSTimur Tabi  *          Timur Tabi <timur@freescale.com>
614f88c43SAnatolij Gustschin  *
714f88c43SAnatolij Gustschin  * FSL DIU Framebuffer driver
814f88c43SAnatolij Gustschin  */
914f88c43SAnatolij Gustschin 
1014f88c43SAnatolij Gustschin #include <common.h>
1114f88c43SAnatolij Gustschin #include <malloc.h>
1214f88c43SAnatolij Gustschin #include <asm/io.h>
1314f88c43SAnatolij Gustschin 
14ba8e76bdSTimur Tabi #include "videomodes.h"
15ba8e76bdSTimur Tabi #include <video_fb.h>
1614f88c43SAnatolij Gustschin #include <fsl_diu_fb.h>
178c6b2504STimur Tabi #include <linux/list.h>
188c6b2504STimur Tabi #include <linux/fb.h>
1914f88c43SAnatolij Gustschin 
2014f88c43SAnatolij Gustschin /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
213b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_480 = {
223b4a2263STimur Tabi 	.name		= "800x480-60",
2314f88c43SAnatolij Gustschin 	.refresh	= 60,
2414f88c43SAnatolij Gustschin 	.xres		= 800,
2514f88c43SAnatolij Gustschin 	.yres		= 480,
2614f88c43SAnatolij Gustschin 	.pixclock	= 31250,
2714f88c43SAnatolij Gustschin 	.left_margin	= 86,
2814f88c43SAnatolij Gustschin 	.right_margin	= 42,
2914f88c43SAnatolij Gustschin 	.upper_margin	= 33,
3014f88c43SAnatolij Gustschin 	.lower_margin	= 10,
3114f88c43SAnatolij Gustschin 	.hsync_len	= 128,
3214f88c43SAnatolij Gustschin 	.vsync_len	= 2,
3314f88c43SAnatolij Gustschin 	.sync		= 0,
3414f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
3514f88c43SAnatolij Gustschin };
3614f88c43SAnatolij Gustschin 
373b4a2263STimur Tabi /* For the SHARP LQ084S3LG01, used on the P1022DS board */
383b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_600 = {
393b4a2263STimur Tabi 	.name		= "800x600-60",
403b4a2263STimur Tabi 	.refresh	= 60,
413b4a2263STimur Tabi 	.xres		= 800,
423b4a2263STimur Tabi 	.yres		= 600,
433b4a2263STimur Tabi 	.pixclock	= 25000,
443b4a2263STimur Tabi 	.left_margin	= 88,
453b4a2263STimur Tabi 	.right_margin	= 40,
463b4a2263STimur Tabi 	.upper_margin	= 23,
473b4a2263STimur Tabi 	.lower_margin	= 1,
483b4a2263STimur Tabi 	.hsync_len	= 128,
493b4a2263STimur Tabi 	.vsync_len	= 4,
503b4a2263STimur Tabi 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
513b4a2263STimur Tabi 	.vmode		= FB_VMODE_NONINTERLACED
523b4a2263STimur Tabi };
533b4a2263STimur Tabi 
5414f88c43SAnatolij Gustschin /*
5514f88c43SAnatolij Gustschin  * These parameters give default parameters
5614f88c43SAnatolij Gustschin  * for video output 1024x768,
5714f88c43SAnatolij Gustschin  * FIXME - change timing to proper amounts
5814f88c43SAnatolij Gustschin  * hsync 31.5kHz, vsync 60Hz
5914f88c43SAnatolij Gustschin  */
603b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1024_768 = {
61ba8e76bdSTimur Tabi 	.name		= "1024x768-60",
6214f88c43SAnatolij Gustschin 	.refresh	= 60,
6314f88c43SAnatolij Gustschin 	.xres		= 1024,
6414f88c43SAnatolij Gustschin 	.yres		= 768,
6514f88c43SAnatolij Gustschin 	.pixclock	= 15385,
6614f88c43SAnatolij Gustschin 	.left_margin	= 160,
6714f88c43SAnatolij Gustschin 	.right_margin	= 24,
6814f88c43SAnatolij Gustschin 	.upper_margin	= 29,
6914f88c43SAnatolij Gustschin 	.lower_margin	= 3,
7014f88c43SAnatolij Gustschin 	.hsync_len	= 136,
7114f88c43SAnatolij Gustschin 	.vsync_len	= 6,
7214f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
7314f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
7414f88c43SAnatolij Gustschin };
7514f88c43SAnatolij Gustschin 
763b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1280_1024 = {
7714f88c43SAnatolij Gustschin 	.name		= "1280x1024-60",
7814f88c43SAnatolij Gustschin 	.refresh	= 60,
7914f88c43SAnatolij Gustschin 	.xres		= 1280,
8014f88c43SAnatolij Gustschin 	.yres		= 1024,
8114f88c43SAnatolij Gustschin 	.pixclock	= 9375,
8214f88c43SAnatolij Gustschin 	.left_margin	= 38,
8314f88c43SAnatolij Gustschin 	.right_margin	= 128,
8414f88c43SAnatolij Gustschin 	.upper_margin	= 2,
8514f88c43SAnatolij Gustschin 	.lower_margin	= 7,
8614f88c43SAnatolij Gustschin 	.hsync_len	= 216,
8714f88c43SAnatolij Gustschin 	.vsync_len	= 37,
8814f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
8914f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
9014f88c43SAnatolij Gustschin };
9114f88c43SAnatolij Gustschin 
92debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1280_720 = {
93debef5cdSJerry Huang 	.name		= "1280x720-60",
94debef5cdSJerry Huang 	.refresh	= 60,
95debef5cdSJerry Huang 	.xres		= 1280,
96debef5cdSJerry Huang 	.yres		= 720,
97debef5cdSJerry Huang 	.pixclock	= 13426,
98debef5cdSJerry Huang 	.left_margin	= 192,
99debef5cdSJerry Huang 	.right_margin	= 64,
100debef5cdSJerry Huang 	.upper_margin	= 22,
101debef5cdSJerry Huang 	.lower_margin	= 1,
102debef5cdSJerry Huang 	.hsync_len	= 136,
103debef5cdSJerry Huang 	.vsync_len	= 3,
104debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
105debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
106debef5cdSJerry Huang };
107debef5cdSJerry Huang 
108debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1920_1080 = {
109debef5cdSJerry Huang 	.name		= "1920x1080-60",
110debef5cdSJerry Huang 	.refresh	= 60,
111debef5cdSJerry Huang 	.xres		= 1920,
112debef5cdSJerry Huang 	.yres		= 1080,
113debef5cdSJerry Huang 	.pixclock	= 5787,
114debef5cdSJerry Huang 	.left_margin	= 328,
115debef5cdSJerry Huang 	.right_margin	= 120,
116debef5cdSJerry Huang 	.upper_margin	= 34,
117debef5cdSJerry Huang 	.lower_margin	= 1,
118debef5cdSJerry Huang 	.hsync_len	= 208,
119debef5cdSJerry Huang 	.vsync_len	= 3,
120debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
121debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
122debef5cdSJerry Huang };
123debef5cdSJerry Huang 
12414f88c43SAnatolij Gustschin /*
12514f88c43SAnatolij Gustschin  * These are the fields of area descriptor(in DDR memory) for every plane
12614f88c43SAnatolij Gustschin  */
12714f88c43SAnatolij Gustschin struct diu_ad {
12814f88c43SAnatolij Gustschin 	/* Word 0(32-bit) in DDR memory */
129ba8e76bdSTimur Tabi 	__le32 pix_fmt; /* hard coding pixel format */
13014f88c43SAnatolij Gustschin 	/* Word 1(32-bit) in DDR memory */
131ba8e76bdSTimur Tabi 	__le32 addr;
13214f88c43SAnatolij Gustschin 	/* Word 2(32-bit) in DDR memory */
133ba8e76bdSTimur Tabi 	__le32 src_size_g_alpha;
13414f88c43SAnatolij Gustschin 	/* Word 3(32-bit) in DDR memory */
135ba8e76bdSTimur Tabi 	__le32 aoi_size;
13614f88c43SAnatolij Gustschin 	/* Word 4(32-bit) in DDR memory */
137ba8e76bdSTimur Tabi 	__le32 offset_xyi;
13814f88c43SAnatolij Gustschin 	/* Word 5(32-bit) in DDR memory */
139ba8e76bdSTimur Tabi 	__le32 offset_xyd;
14014f88c43SAnatolij Gustschin 	/* Word 6(32-bit) in DDR memory */
141ba8e76bdSTimur Tabi 	__le32 ckmax_r:8;
142ba8e76bdSTimur Tabi 	__le32 ckmax_g:8;
143ba8e76bdSTimur Tabi 	__le32 ckmax_b:8;
144ba8e76bdSTimur Tabi 	__le32 res9:8;
14514f88c43SAnatolij Gustschin 	/* Word 7(32-bit) in DDR memory */
146ba8e76bdSTimur Tabi 	__le32 ckmin_r:8;
147ba8e76bdSTimur Tabi 	__le32 ckmin_g:8;
148ba8e76bdSTimur Tabi 	__le32 ckmin_b:8;
149ba8e76bdSTimur Tabi 	__le32 res10:8;
15014f88c43SAnatolij Gustschin 	/* Word 8(32-bit) in DDR memory */
151ba8e76bdSTimur Tabi 	__le32 next_ad;
15214f88c43SAnatolij Gustschin 	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
153ba8e76bdSTimur Tabi 	__le32 res[3];
15414f88c43SAnatolij Gustschin } __attribute__ ((packed));
15514f88c43SAnatolij Gustschin 
15614f88c43SAnatolij Gustschin /*
15714f88c43SAnatolij Gustschin  * DIU register map
15814f88c43SAnatolij Gustschin  */
15914f88c43SAnatolij Gustschin struct diu {
160ba8e76bdSTimur Tabi 	__be32 desc[3];
161ba8e76bdSTimur Tabi 	__be32 gamma;
162ba8e76bdSTimur Tabi 	__be32 pallete;
163ba8e76bdSTimur Tabi 	__be32 cursor;
164ba8e76bdSTimur Tabi 	__be32 curs_pos;
165ba8e76bdSTimur Tabi 	__be32 diu_mode;
166ba8e76bdSTimur Tabi 	__be32 bgnd;
167ba8e76bdSTimur Tabi 	__be32 bgnd_wb;
168ba8e76bdSTimur Tabi 	__be32 disp_size;
169ba8e76bdSTimur Tabi 	__be32 wb_size;
170ba8e76bdSTimur Tabi 	__be32 wb_mem_addr;
171ba8e76bdSTimur Tabi 	__be32 hsyn_para;
172ba8e76bdSTimur Tabi 	__be32 vsyn_para;
173ba8e76bdSTimur Tabi 	__be32 syn_pol;
174ba8e76bdSTimur Tabi 	__be32 thresholds;
175ba8e76bdSTimur Tabi 	__be32 int_status;
176ba8e76bdSTimur Tabi 	__be32 int_mask;
177ba8e76bdSTimur Tabi 	__be32 colorbar[8];
178ba8e76bdSTimur Tabi 	__be32 filling;
179ba8e76bdSTimur Tabi 	__be32 plut;
18014f88c43SAnatolij Gustschin } __attribute__ ((packed));
18114f88c43SAnatolij Gustschin 
182ba8e76bdSTimur Tabi struct diu_addr {
183ba8e76bdSTimur Tabi 	void *vaddr;		/* Virtual address */
184ba8e76bdSTimur Tabi 	u32 paddr;		/* 32-bit physical address */
185ba8e76bdSTimur Tabi 	unsigned int offset;	/* Alignment offset */
18614f88c43SAnatolij Gustschin };
18714f88c43SAnatolij Gustschin 
188ba8e76bdSTimur Tabi static struct fb_info info;
18914f88c43SAnatolij Gustschin 
19014f88c43SAnatolij Gustschin /*
191ba8e76bdSTimur Tabi  * Align to 64-bit(8-byte), 32-byte, etc.
19214f88c43SAnatolij Gustschin  */
allocate_buf(struct diu_addr * buf,u32 size,u32 bytes_align)193ba8e76bdSTimur Tabi static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
194ba8e76bdSTimur Tabi {
195ba8e76bdSTimur Tabi 	u32 offset, ssize;
196ba8e76bdSTimur Tabi 	u32 mask;
19714f88c43SAnatolij Gustschin 
198ba8e76bdSTimur Tabi 	ssize = size + bytes_align;
199ba8e76bdSTimur Tabi 	buf->vaddr = malloc(ssize);
200ba8e76bdSTimur Tabi 	if (!buf->vaddr)
201ba8e76bdSTimur Tabi 		return -1;
20214f88c43SAnatolij Gustschin 
203ba8e76bdSTimur Tabi 	memset(buf->vaddr, 0, ssize);
204ba8e76bdSTimur Tabi 	mask = bytes_align - 1;
205ba8e76bdSTimur Tabi 	offset = (u32)buf->vaddr & mask;
206ba8e76bdSTimur Tabi 	if (offset) {
207ba8e76bdSTimur Tabi 		buf->offset = bytes_align - offset;
208ba8e76bdSTimur Tabi 		buf->vaddr += offset;
209ba8e76bdSTimur Tabi 	} else
210ba8e76bdSTimur Tabi 		buf->offset = 0;
21114f88c43SAnatolij Gustschin 
212ba8e76bdSTimur Tabi 	buf->paddr = virt_to_phys(buf->vaddr);
213ba8e76bdSTimur Tabi 	return 0;
214ba8e76bdSTimur Tabi }
21514f88c43SAnatolij Gustschin 
216ba8e76bdSTimur Tabi /*
217ba8e76bdSTimur Tabi  * Allocate a framebuffer and an Area Descriptor that points to it.  Both
218ba8e76bdSTimur Tabi  * are created in the same memory block.  The Area Descriptor is updated to
219ba8e76bdSTimur Tabi  * point to the framebuffer memory. Memory is aligned as needed.
220ba8e76bdSTimur Tabi  */
allocate_fb(unsigned int xres,unsigned int yres,unsigned int depth,char ** fb)221ba8e76bdSTimur Tabi static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
2228c6b2504STimur Tabi 				  unsigned int depth, char **fb)
223ba8e76bdSTimur Tabi {
224ba8e76bdSTimur Tabi 	unsigned long size = xres * yres * depth;
225ba8e76bdSTimur Tabi 	struct diu_addr addr;
226ba8e76bdSTimur Tabi 	struct diu_ad *ad;
227ba8e76bdSTimur Tabi 	size_t ad_size = roundup(sizeof(struct diu_ad), 32);
22814f88c43SAnatolij Gustschin 
229ba8e76bdSTimur Tabi 	/*
230ba8e76bdSTimur Tabi 	 * Allocate a memory block that holds the Area Descriptor and the
231ba8e76bdSTimur Tabi 	 * frame buffer right behind it.  To keep the code simple, everything
232ba8e76bdSTimur Tabi 	 * is aligned on a 32-byte address.
233ba8e76bdSTimur Tabi 	 */
234ba8e76bdSTimur Tabi 	if (allocate_buf(&addr, ad_size + size, 32) < 0)
235ba8e76bdSTimur Tabi 		return NULL;
236ba8e76bdSTimur Tabi 
237ba8e76bdSTimur Tabi 	ad = addr.vaddr;
238ba8e76bdSTimur Tabi 	ad->addr = cpu_to_le32(addr.paddr + ad_size);
239ba8e76bdSTimur Tabi 	ad->aoi_size = cpu_to_le32((yres << 16) | xres);
240ba8e76bdSTimur Tabi 	ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
241ba8e76bdSTimur Tabi 	ad->offset_xyi = 0;
242ba8e76bdSTimur Tabi 	ad->offset_xyd = 0;
243ba8e76bdSTimur Tabi 
244ba8e76bdSTimur Tabi 	if (fb)
245ba8e76bdSTimur Tabi 		*fb = addr.vaddr + ad_size;
246ba8e76bdSTimur Tabi 
247ba8e76bdSTimur Tabi 	return ad;
248ba8e76bdSTimur Tabi }
249ba8e76bdSTimur Tabi 
fsl_diu_init(u16 xres,u16 yres,u32 pixel_format,int gamma_fix)2503b4a2263STimur Tabi int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
25114f88c43SAnatolij Gustschin {
25214f88c43SAnatolij Gustschin 	struct fb_videomode *fsl_diu_mode_db;
253ba8e76bdSTimur Tabi 	struct diu_ad *ad;
254ba8e76bdSTimur Tabi 	struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
255ba8e76bdSTimur Tabi 	u8 *gamma_table_base;
25614f88c43SAnatolij Gustschin 	unsigned int i, j;
257ba8e76bdSTimur Tabi 	struct diu_addr gamma;
258ba8e76bdSTimur Tabi 	struct diu_addr cursor;
25914f88c43SAnatolij Gustschin 
2603b4a2263STimur Tabi /* Convert the X,Y resolution pair into a single number */
2613b4a2263STimur Tabi #define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
2623b4a2263STimur Tabi 
2633b4a2263STimur Tabi 	switch (RESOLUTION(xres, yres)) {
2643b4a2263STimur Tabi 	case RESOLUTION(800, 480):
2653b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_480;
26614f88c43SAnatolij Gustschin 		break;
2673b4a2263STimur Tabi 	case RESOLUTION(800, 600):
2683b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_600;
26915006cb7SJerry Huang 		break;
2703b4a2263STimur Tabi 	case RESOLUTION(1024, 768):
2713b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1024_768;
27215006cb7SJerry Huang 		break;
2733b4a2263STimur Tabi 	case RESOLUTION(1280, 1024):
2743b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
27514f88c43SAnatolij Gustschin 		break;
276debef5cdSJerry Huang 	case RESOLUTION(1280, 720):
277debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1280_720;
278debef5cdSJerry Huang 		break;
279debef5cdSJerry Huang 	case RESOLUTION(1920, 1080):
280debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
281debef5cdSJerry Huang 		break;
28214f88c43SAnatolij Gustschin 	default:
2833b4a2263STimur Tabi 		printf("DIU:   Unsupported resolution %ux%u\n", xres, yres);
2843b4a2263STimur Tabi 		return -1;
28514f88c43SAnatolij Gustschin 	}
28614f88c43SAnatolij Gustschin 
28714f88c43SAnatolij Gustschin 	/* read mode info */
288ba8e76bdSTimur Tabi 	info.var.xres = fsl_diu_mode_db->xres;
289ba8e76bdSTimur Tabi 	info.var.yres = fsl_diu_mode_db->yres;
290ba8e76bdSTimur Tabi 	info.var.bits_per_pixel = 32;
291ba8e76bdSTimur Tabi 	info.var.pixclock = fsl_diu_mode_db->pixclock;
292ba8e76bdSTimur Tabi 	info.var.left_margin = fsl_diu_mode_db->left_margin;
293ba8e76bdSTimur Tabi 	info.var.right_margin = fsl_diu_mode_db->right_margin;
294ba8e76bdSTimur Tabi 	info.var.upper_margin = fsl_diu_mode_db->upper_margin;
295ba8e76bdSTimur Tabi 	info.var.lower_margin = fsl_diu_mode_db->lower_margin;
296ba8e76bdSTimur Tabi 	info.var.hsync_len = fsl_diu_mode_db->hsync_len;
297ba8e76bdSTimur Tabi 	info.var.vsync_len = fsl_diu_mode_db->vsync_len;
298ba8e76bdSTimur Tabi 	info.var.sync = fsl_diu_mode_db->sync;
299ba8e76bdSTimur Tabi 	info.var.vmode = fsl_diu_mode_db->vmode;
3008c6b2504STimur Tabi 	info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
301ba8e76bdSTimur Tabi 
302ba8e76bdSTimur Tabi 	/* Memory allocation for framebuffer */
3038c6b2504STimur Tabi 	info.screen_size =
304ba8e76bdSTimur Tabi 		info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
305ba8e76bdSTimur Tabi 	ad = allocate_fb(info.var.xres, info.var.yres,
306ba8e76bdSTimur Tabi 			 info.var.bits_per_pixel / 8, &info.screen_base);
307ba8e76bdSTimur Tabi 	if (!ad) {
308ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
309ba8e76bdSTimur Tabi 		return -1;
310ba8e76bdSTimur Tabi 	}
31114f88c43SAnatolij Gustschin 
31214f88c43SAnatolij Gustschin 	ad->pix_fmt = pixel_format;
31314f88c43SAnatolij Gustschin 
31414f88c43SAnatolij Gustschin 	/* Disable chroma keying function */
31514f88c43SAnatolij Gustschin 	ad->ckmax_r = 0;
31614f88c43SAnatolij Gustschin 	ad->ckmax_g = 0;
31714f88c43SAnatolij Gustschin 	ad->ckmax_b = 0;
31814f88c43SAnatolij Gustschin 
31914f88c43SAnatolij Gustschin 	ad->ckmin_r = 255;
32014f88c43SAnatolij Gustschin 	ad->ckmin_g = 255;
32114f88c43SAnatolij Gustschin 	ad->ckmin_b = 255;
32214f88c43SAnatolij Gustschin 
323ba8e76bdSTimur Tabi 	/* Initialize the gamma table */
324ba8e76bdSTimur Tabi 	if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
325ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
326ba8e76bdSTimur Tabi 		return -1;
327ba8e76bdSTimur Tabi 	}
328ba8e76bdSTimur Tabi 	gamma_table_base = gamma.vaddr;
32914f88c43SAnatolij Gustschin 	for (i = 0; i <= 2; i++)
330ba8e76bdSTimur Tabi 		for (j = 0; j < 256; j++)
33114f88c43SAnatolij Gustschin 			*gamma_table_base++ = j;
33214f88c43SAnatolij Gustschin 
33314f88c43SAnatolij Gustschin 	if (gamma_fix == 1) {	/* fix the gamma */
334ba8e76bdSTimur Tabi 		gamma_table_base = gamma.vaddr;
33514f88c43SAnatolij Gustschin 		for (i = 0; i < 256 * 3; i++) {
33614f88c43SAnatolij Gustschin 			gamma_table_base[i] = (gamma_table_base[i] << 2)
33714f88c43SAnatolij Gustschin 				| ((gamma_table_base[i] >> 6) & 0x03);
33814f88c43SAnatolij Gustschin 		}
33914f88c43SAnatolij Gustschin 	}
34014f88c43SAnatolij Gustschin 
341ba8e76bdSTimur Tabi 	/* Initialize the cursor */
342ba8e76bdSTimur Tabi 	if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
343ba8e76bdSTimur Tabi 		printf("DIU:   Can't alloc cursor data\n");
344ba8e76bdSTimur Tabi 		return -1;
345ba8e76bdSTimur Tabi 	}
34614f88c43SAnatolij Gustschin 
34714f88c43SAnatolij Gustschin 	/* Program DIU registers */
348ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 0);	/* Temporarily disable the DIU */
34914f88c43SAnatolij Gustschin 
350ba8e76bdSTimur Tabi 	out_be32(&hw->gamma, gamma.paddr);
351ba8e76bdSTimur Tabi 	out_be32(&hw->cursor, cursor.paddr);
35214f88c43SAnatolij Gustschin 	out_be32(&hw->bgnd, 0x007F7F7F);
353ba8e76bdSTimur Tabi 	out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
354ba8e76bdSTimur Tabi 	out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
355ba8e76bdSTimur Tabi 			info.var.hsync_len << 11 |
356ba8e76bdSTimur Tabi 			info.var.right_margin);
35714f88c43SAnatolij Gustschin 
358ba8e76bdSTimur Tabi 	out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
359ba8e76bdSTimur Tabi 			info.var.vsync_len << 11 |
360ba8e76bdSTimur Tabi 			info.var.lower_margin);
36114f88c43SAnatolij Gustschin 
36214f88c43SAnatolij Gustschin 	/* Pixel Clock configuration */
363ba8e76bdSTimur Tabi 	diu_set_pixel_clock(info.var.pixclock);
36414f88c43SAnatolij Gustschin 
365ba8e76bdSTimur Tabi 	/* Set the frame buffers */
366ba8e76bdSTimur Tabi 	out_be32(&hw->desc[0], virt_to_phys(ad));
36715b83386STimur Tabi 	out_be32(&hw->desc[1], 0);
36815b83386STimur Tabi 	out_be32(&hw->desc[2], 0);
36914f88c43SAnatolij Gustschin 
370ba8e76bdSTimur Tabi 	/* Enable the DIU, set display to all three planes */
371ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 1);
37214f88c43SAnatolij Gustschin 
37314f88c43SAnatolij Gustschin 	return 0;
37414f88c43SAnatolij Gustschin }
37514f88c43SAnatolij Gustschin 
video_hw_init(void)37614f88c43SAnatolij Gustschin void *video_hw_init(void)
37714f88c43SAnatolij Gustschin {
378ba8e76bdSTimur Tabi 	static GraphicDevice ctfb;
379ba8e76bdSTimur Tabi 	const char *options;
380ba8e76bdSTimur Tabi 	unsigned int depth = 0, freq = 0;
38114f88c43SAnatolij Gustschin 
382ba8e76bdSTimur Tabi 	if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
383ba8e76bdSTimur Tabi 				  &options))
384ba8e76bdSTimur Tabi 		return NULL;
385ba8e76bdSTimur Tabi 
386ba8e76bdSTimur Tabi 	/* Find the monitor port, which is a required option */
387ba8e76bdSTimur Tabi 	if (!options)
388ba8e76bdSTimur Tabi 		return NULL;
389ba8e76bdSTimur Tabi 	if (strncmp(options, "monitor=", 8) != 0)
390ba8e76bdSTimur Tabi 		return NULL;
391ba8e76bdSTimur Tabi 
392ba8e76bdSTimur Tabi 	if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
39314f88c43SAnatolij Gustschin 		return NULL;
39414f88c43SAnatolij Gustschin 
39514f88c43SAnatolij Gustschin 	/* fill in Graphic device struct */
39614f88c43SAnatolij Gustschin 	sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
397ba8e76bdSTimur Tabi 		ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
39814f88c43SAnatolij Gustschin 
399ba8e76bdSTimur Tabi 	ctfb.frameAdrs = (unsigned int)info.screen_base;
40014f88c43SAnatolij Gustschin 	ctfb.plnSizeX = ctfb.winSizeX;
40114f88c43SAnatolij Gustschin 	ctfb.plnSizeY = ctfb.winSizeY;
40214f88c43SAnatolij Gustschin 
40314f88c43SAnatolij Gustschin 	ctfb.gdfBytesPP = 4;
40414f88c43SAnatolij Gustschin 	ctfb.gdfIndex = GDF_32BIT_X888RGB;
40514f88c43SAnatolij Gustschin 
40614f88c43SAnatolij Gustschin 	ctfb.isaBase = 0;
40714f88c43SAnatolij Gustschin 	ctfb.pciBase = 0;
408ba8e76bdSTimur Tabi 	ctfb.memSize = info.screen_size;
40914f88c43SAnatolij Gustschin 
41014f88c43SAnatolij Gustschin 	/* Cursor Start Address */
41114f88c43SAnatolij Gustschin 	ctfb.dprBase = 0;
41214f88c43SAnatolij Gustschin 	ctfb.vprBase = 0;
41314f88c43SAnatolij Gustschin 	ctfb.cprBase = 0;
41414f88c43SAnatolij Gustschin 
41514f88c43SAnatolij Gustschin 	return &ctfb;
41614f88c43SAnatolij Gustschin }
417