xref: /rk3399_rockchip-uboot/drivers/video/fsl_diu_fb.c (revision 326ea986ac150acdc7656d57fca647db80b50158)
114f88c43SAnatolij Gustschin /*
2ba8e76bdSTimur Tabi  * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
3ba8e76bdSTimur Tabi  * Authors: York Sun <yorksun@freescale.com>
4ba8e76bdSTimur Tabi  *          Timur Tabi <timur@freescale.com>
514f88c43SAnatolij Gustschin  *
614f88c43SAnatolij Gustschin  * FSL DIU Framebuffer driver
714f88c43SAnatolij Gustschin  *
8*1a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
914f88c43SAnatolij Gustschin  */
1014f88c43SAnatolij Gustschin 
1114f88c43SAnatolij Gustschin #include <common.h>
1214f88c43SAnatolij Gustschin #include <malloc.h>
1314f88c43SAnatolij Gustschin #include <asm/io.h>
1414f88c43SAnatolij Gustschin 
15ba8e76bdSTimur Tabi #include "videomodes.h"
16ba8e76bdSTimur Tabi #include <video_fb.h>
1714f88c43SAnatolij Gustschin #include <fsl_diu_fb.h>
188c6b2504STimur Tabi #include <linux/list.h>
198c6b2504STimur Tabi #include <linux/fb.h>
2014f88c43SAnatolij Gustschin 
2114f88c43SAnatolij Gustschin /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
223b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_480 = {
233b4a2263STimur Tabi 	.name		= "800x480-60",
2414f88c43SAnatolij Gustschin 	.refresh	= 60,
2514f88c43SAnatolij Gustschin 	.xres		= 800,
2614f88c43SAnatolij Gustschin 	.yres		= 480,
2714f88c43SAnatolij Gustschin 	.pixclock	= 31250,
2814f88c43SAnatolij Gustschin 	.left_margin	= 86,
2914f88c43SAnatolij Gustschin 	.right_margin	= 42,
3014f88c43SAnatolij Gustschin 	.upper_margin	= 33,
3114f88c43SAnatolij Gustschin 	.lower_margin	= 10,
3214f88c43SAnatolij Gustschin 	.hsync_len	= 128,
3314f88c43SAnatolij Gustschin 	.vsync_len	= 2,
3414f88c43SAnatolij Gustschin 	.sync		= 0,
3514f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
3614f88c43SAnatolij Gustschin };
3714f88c43SAnatolij Gustschin 
383b4a2263STimur Tabi /* For the SHARP LQ084S3LG01, used on the P1022DS board */
393b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_600 = {
403b4a2263STimur Tabi 	.name		= "800x600-60",
413b4a2263STimur Tabi 	.refresh	= 60,
423b4a2263STimur Tabi 	.xres		= 800,
433b4a2263STimur Tabi 	.yres		= 600,
443b4a2263STimur Tabi 	.pixclock	= 25000,
453b4a2263STimur Tabi 	.left_margin	= 88,
463b4a2263STimur Tabi 	.right_margin	= 40,
473b4a2263STimur Tabi 	.upper_margin	= 23,
483b4a2263STimur Tabi 	.lower_margin	= 1,
493b4a2263STimur Tabi 	.hsync_len	= 128,
503b4a2263STimur Tabi 	.vsync_len	= 4,
513b4a2263STimur Tabi 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
523b4a2263STimur Tabi 	.vmode		= FB_VMODE_NONINTERLACED
533b4a2263STimur Tabi };
543b4a2263STimur Tabi 
5514f88c43SAnatolij Gustschin /*
5614f88c43SAnatolij Gustschin  * These parameters give default parameters
5714f88c43SAnatolij Gustschin  * for video output 1024x768,
5814f88c43SAnatolij Gustschin  * FIXME - change timing to proper amounts
5914f88c43SAnatolij Gustschin  * hsync 31.5kHz, vsync 60Hz
6014f88c43SAnatolij Gustschin  */
613b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1024_768 = {
62ba8e76bdSTimur Tabi 	.name		= "1024x768-60",
6314f88c43SAnatolij Gustschin 	.refresh	= 60,
6414f88c43SAnatolij Gustschin 	.xres		= 1024,
6514f88c43SAnatolij Gustschin 	.yres		= 768,
6614f88c43SAnatolij Gustschin 	.pixclock	= 15385,
6714f88c43SAnatolij Gustschin 	.left_margin	= 160,
6814f88c43SAnatolij Gustschin 	.right_margin	= 24,
6914f88c43SAnatolij Gustschin 	.upper_margin	= 29,
7014f88c43SAnatolij Gustschin 	.lower_margin	= 3,
7114f88c43SAnatolij Gustschin 	.hsync_len	= 136,
7214f88c43SAnatolij Gustschin 	.vsync_len	= 6,
7314f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
7414f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
7514f88c43SAnatolij Gustschin };
7614f88c43SAnatolij Gustschin 
773b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1280_1024 = {
7814f88c43SAnatolij Gustschin 	.name		= "1280x1024-60",
7914f88c43SAnatolij Gustschin 	.refresh	= 60,
8014f88c43SAnatolij Gustschin 	.xres		= 1280,
8114f88c43SAnatolij Gustschin 	.yres		= 1024,
8214f88c43SAnatolij Gustschin 	.pixclock	= 9375,
8314f88c43SAnatolij Gustschin 	.left_margin	= 38,
8414f88c43SAnatolij Gustschin 	.right_margin	= 128,
8514f88c43SAnatolij Gustschin 	.upper_margin	= 2,
8614f88c43SAnatolij Gustschin 	.lower_margin	= 7,
8714f88c43SAnatolij Gustschin 	.hsync_len	= 216,
8814f88c43SAnatolij Gustschin 	.vsync_len	= 37,
8914f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
9014f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
9114f88c43SAnatolij Gustschin };
9214f88c43SAnatolij Gustschin 
93debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1280_720 = {
94debef5cdSJerry Huang 	.name		= "1280x720-60",
95debef5cdSJerry Huang 	.refresh	= 60,
96debef5cdSJerry Huang 	.xres		= 1280,
97debef5cdSJerry Huang 	.yres		= 720,
98debef5cdSJerry Huang 	.pixclock	= 13426,
99debef5cdSJerry Huang 	.left_margin	= 192,
100debef5cdSJerry Huang 	.right_margin	= 64,
101debef5cdSJerry Huang 	.upper_margin	= 22,
102debef5cdSJerry Huang 	.lower_margin	= 1,
103debef5cdSJerry Huang 	.hsync_len	= 136,
104debef5cdSJerry Huang 	.vsync_len	= 3,
105debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
106debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
107debef5cdSJerry Huang };
108debef5cdSJerry Huang 
109debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1920_1080 = {
110debef5cdSJerry Huang 	.name		= "1920x1080-60",
111debef5cdSJerry Huang 	.refresh	= 60,
112debef5cdSJerry Huang 	.xres		= 1920,
113debef5cdSJerry Huang 	.yres		= 1080,
114debef5cdSJerry Huang 	.pixclock	= 5787,
115debef5cdSJerry Huang 	.left_margin	= 328,
116debef5cdSJerry Huang 	.right_margin	= 120,
117debef5cdSJerry Huang 	.upper_margin	= 34,
118debef5cdSJerry Huang 	.lower_margin	= 1,
119debef5cdSJerry Huang 	.hsync_len	= 208,
120debef5cdSJerry Huang 	.vsync_len	= 3,
121debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
122debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
123debef5cdSJerry Huang };
124debef5cdSJerry Huang 
12514f88c43SAnatolij Gustschin /*
12614f88c43SAnatolij Gustschin  * These are the fields of area descriptor(in DDR memory) for every plane
12714f88c43SAnatolij Gustschin  */
12814f88c43SAnatolij Gustschin struct diu_ad {
12914f88c43SAnatolij Gustschin 	/* Word 0(32-bit) in DDR memory */
130ba8e76bdSTimur Tabi 	__le32 pix_fmt; /* hard coding pixel format */
13114f88c43SAnatolij Gustschin 	/* Word 1(32-bit) in DDR memory */
132ba8e76bdSTimur Tabi 	__le32 addr;
13314f88c43SAnatolij Gustschin 	/* Word 2(32-bit) in DDR memory */
134ba8e76bdSTimur Tabi 	__le32 src_size_g_alpha;
13514f88c43SAnatolij Gustschin 	/* Word 3(32-bit) in DDR memory */
136ba8e76bdSTimur Tabi 	__le32 aoi_size;
13714f88c43SAnatolij Gustschin 	/* Word 4(32-bit) in DDR memory */
138ba8e76bdSTimur Tabi 	__le32 offset_xyi;
13914f88c43SAnatolij Gustschin 	/* Word 5(32-bit) in DDR memory */
140ba8e76bdSTimur Tabi 	__le32 offset_xyd;
14114f88c43SAnatolij Gustschin 	/* Word 6(32-bit) in DDR memory */
142ba8e76bdSTimur Tabi 	__le32 ckmax_r:8;
143ba8e76bdSTimur Tabi 	__le32 ckmax_g:8;
144ba8e76bdSTimur Tabi 	__le32 ckmax_b:8;
145ba8e76bdSTimur Tabi 	__le32 res9:8;
14614f88c43SAnatolij Gustschin 	/* Word 7(32-bit) in DDR memory */
147ba8e76bdSTimur Tabi 	__le32 ckmin_r:8;
148ba8e76bdSTimur Tabi 	__le32 ckmin_g:8;
149ba8e76bdSTimur Tabi 	__le32 ckmin_b:8;
150ba8e76bdSTimur Tabi 	__le32 res10:8;
15114f88c43SAnatolij Gustschin 	/* Word 8(32-bit) in DDR memory */
152ba8e76bdSTimur Tabi 	__le32 next_ad;
15314f88c43SAnatolij Gustschin 	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
154ba8e76bdSTimur Tabi 	__le32 res[3];
15514f88c43SAnatolij Gustschin } __attribute__ ((packed));
15614f88c43SAnatolij Gustschin 
15714f88c43SAnatolij Gustschin /*
15814f88c43SAnatolij Gustschin  * DIU register map
15914f88c43SAnatolij Gustschin  */
16014f88c43SAnatolij Gustschin struct diu {
161ba8e76bdSTimur Tabi 	__be32 desc[3];
162ba8e76bdSTimur Tabi 	__be32 gamma;
163ba8e76bdSTimur Tabi 	__be32 pallete;
164ba8e76bdSTimur Tabi 	__be32 cursor;
165ba8e76bdSTimur Tabi 	__be32 curs_pos;
166ba8e76bdSTimur Tabi 	__be32 diu_mode;
167ba8e76bdSTimur Tabi 	__be32 bgnd;
168ba8e76bdSTimur Tabi 	__be32 bgnd_wb;
169ba8e76bdSTimur Tabi 	__be32 disp_size;
170ba8e76bdSTimur Tabi 	__be32 wb_size;
171ba8e76bdSTimur Tabi 	__be32 wb_mem_addr;
172ba8e76bdSTimur Tabi 	__be32 hsyn_para;
173ba8e76bdSTimur Tabi 	__be32 vsyn_para;
174ba8e76bdSTimur Tabi 	__be32 syn_pol;
175ba8e76bdSTimur Tabi 	__be32 thresholds;
176ba8e76bdSTimur Tabi 	__be32 int_status;
177ba8e76bdSTimur Tabi 	__be32 int_mask;
178ba8e76bdSTimur Tabi 	__be32 colorbar[8];
179ba8e76bdSTimur Tabi 	__be32 filling;
180ba8e76bdSTimur Tabi 	__be32 plut;
18114f88c43SAnatolij Gustschin } __attribute__ ((packed));
18214f88c43SAnatolij Gustschin 
183ba8e76bdSTimur Tabi struct diu_addr {
184ba8e76bdSTimur Tabi 	void *vaddr;		/* Virtual address */
185ba8e76bdSTimur Tabi 	u32 paddr;		/* 32-bit physical address */
186ba8e76bdSTimur Tabi 	unsigned int offset;	/* Alignment offset */
18714f88c43SAnatolij Gustschin };
18814f88c43SAnatolij Gustschin 
189ba8e76bdSTimur Tabi static struct fb_info info;
19014f88c43SAnatolij Gustschin 
19114f88c43SAnatolij Gustschin /*
192ba8e76bdSTimur Tabi  * Align to 64-bit(8-byte), 32-byte, etc.
19314f88c43SAnatolij Gustschin  */
allocate_buf(struct diu_addr * buf,u32 size,u32 bytes_align)194ba8e76bdSTimur Tabi static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
195ba8e76bdSTimur Tabi {
196ba8e76bdSTimur Tabi 	u32 offset, ssize;
197ba8e76bdSTimur Tabi 	u32 mask;
19814f88c43SAnatolij Gustschin 
199ba8e76bdSTimur Tabi 	ssize = size + bytes_align;
200ba8e76bdSTimur Tabi 	buf->vaddr = malloc(ssize);
201ba8e76bdSTimur Tabi 	if (!buf->vaddr)
202ba8e76bdSTimur Tabi 		return -1;
20314f88c43SAnatolij Gustschin 
204ba8e76bdSTimur Tabi 	memset(buf->vaddr, 0, ssize);
205ba8e76bdSTimur Tabi 	mask = bytes_align - 1;
206ba8e76bdSTimur Tabi 	offset = (u32)buf->vaddr & mask;
207ba8e76bdSTimur Tabi 	if (offset) {
208ba8e76bdSTimur Tabi 		buf->offset = bytes_align - offset;
209ba8e76bdSTimur Tabi 		buf->vaddr += offset;
210ba8e76bdSTimur Tabi 	} else
211ba8e76bdSTimur Tabi 		buf->offset = 0;
21214f88c43SAnatolij Gustschin 
213ba8e76bdSTimur Tabi 	buf->paddr = virt_to_phys(buf->vaddr);
214ba8e76bdSTimur Tabi 	return 0;
215ba8e76bdSTimur Tabi }
21614f88c43SAnatolij Gustschin 
217ba8e76bdSTimur Tabi /*
218ba8e76bdSTimur Tabi  * Allocate a framebuffer and an Area Descriptor that points to it.  Both
219ba8e76bdSTimur Tabi  * are created in the same memory block.  The Area Descriptor is updated to
220ba8e76bdSTimur Tabi  * point to the framebuffer memory. Memory is aligned as needed.
221ba8e76bdSTimur Tabi  */
allocate_fb(unsigned int xres,unsigned int yres,unsigned int depth,char ** fb)222ba8e76bdSTimur Tabi static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
2238c6b2504STimur Tabi 				  unsigned int depth, char **fb)
224ba8e76bdSTimur Tabi {
225ba8e76bdSTimur Tabi 	unsigned long size = xres * yres * depth;
226ba8e76bdSTimur Tabi 	struct diu_addr addr;
227ba8e76bdSTimur Tabi 	struct diu_ad *ad;
228ba8e76bdSTimur Tabi 	size_t ad_size = roundup(sizeof(struct diu_ad), 32);
22914f88c43SAnatolij Gustschin 
230ba8e76bdSTimur Tabi 	/*
231ba8e76bdSTimur Tabi 	 * Allocate a memory block that holds the Area Descriptor and the
232ba8e76bdSTimur Tabi 	 * frame buffer right behind it.  To keep the code simple, everything
233ba8e76bdSTimur Tabi 	 * is aligned on a 32-byte address.
234ba8e76bdSTimur Tabi 	 */
235ba8e76bdSTimur Tabi 	if (allocate_buf(&addr, ad_size + size, 32) < 0)
236ba8e76bdSTimur Tabi 		return NULL;
237ba8e76bdSTimur Tabi 
238ba8e76bdSTimur Tabi 	ad = addr.vaddr;
239ba8e76bdSTimur Tabi 	ad->addr = cpu_to_le32(addr.paddr + ad_size);
240ba8e76bdSTimur Tabi 	ad->aoi_size = cpu_to_le32((yres << 16) | xres);
241ba8e76bdSTimur Tabi 	ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
242ba8e76bdSTimur Tabi 	ad->offset_xyi = 0;
243ba8e76bdSTimur Tabi 	ad->offset_xyd = 0;
244ba8e76bdSTimur Tabi 
245ba8e76bdSTimur Tabi 	if (fb)
246ba8e76bdSTimur Tabi 		*fb = addr.vaddr + ad_size;
247ba8e76bdSTimur Tabi 
248ba8e76bdSTimur Tabi 	return ad;
249ba8e76bdSTimur Tabi }
250ba8e76bdSTimur Tabi 
fsl_diu_init(u16 xres,u16 yres,u32 pixel_format,int gamma_fix)2513b4a2263STimur Tabi int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
25214f88c43SAnatolij Gustschin {
25314f88c43SAnatolij Gustschin 	struct fb_videomode *fsl_diu_mode_db;
254ba8e76bdSTimur Tabi 	struct diu_ad *ad;
255ba8e76bdSTimur Tabi 	struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
256ba8e76bdSTimur Tabi 	u8 *gamma_table_base;
25714f88c43SAnatolij Gustschin 	unsigned int i, j;
258ba8e76bdSTimur Tabi 	struct diu_addr gamma;
259ba8e76bdSTimur Tabi 	struct diu_addr cursor;
26014f88c43SAnatolij Gustschin 
2613b4a2263STimur Tabi /* Convert the X,Y resolution pair into a single number */
2623b4a2263STimur Tabi #define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
2633b4a2263STimur Tabi 
2643b4a2263STimur Tabi 	switch (RESOLUTION(xres, yres)) {
2653b4a2263STimur Tabi 	case RESOLUTION(800, 480):
2663b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_480;
26714f88c43SAnatolij Gustschin 		break;
2683b4a2263STimur Tabi 	case RESOLUTION(800, 600):
2693b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_600;
27015006cb7SJerry Huang 		break;
2713b4a2263STimur Tabi 	case RESOLUTION(1024, 768):
2723b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1024_768;
27315006cb7SJerry Huang 		break;
2743b4a2263STimur Tabi 	case RESOLUTION(1280, 1024):
2753b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
27614f88c43SAnatolij Gustschin 		break;
277debef5cdSJerry Huang 	case RESOLUTION(1280, 720):
278debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1280_720;
279debef5cdSJerry Huang 		break;
280debef5cdSJerry Huang 	case RESOLUTION(1920, 1080):
281debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
282debef5cdSJerry Huang 		break;
28314f88c43SAnatolij Gustschin 	default:
2843b4a2263STimur Tabi 		printf("DIU:   Unsupported resolution %ux%u\n", xres, yres);
2853b4a2263STimur Tabi 		return -1;
28614f88c43SAnatolij Gustschin 	}
28714f88c43SAnatolij Gustschin 
28814f88c43SAnatolij Gustschin 	/* read mode info */
289ba8e76bdSTimur Tabi 	info.var.xres = fsl_diu_mode_db->xres;
290ba8e76bdSTimur Tabi 	info.var.yres = fsl_diu_mode_db->yres;
291ba8e76bdSTimur Tabi 	info.var.bits_per_pixel = 32;
292ba8e76bdSTimur Tabi 	info.var.pixclock = fsl_diu_mode_db->pixclock;
293ba8e76bdSTimur Tabi 	info.var.left_margin = fsl_diu_mode_db->left_margin;
294ba8e76bdSTimur Tabi 	info.var.right_margin = fsl_diu_mode_db->right_margin;
295ba8e76bdSTimur Tabi 	info.var.upper_margin = fsl_diu_mode_db->upper_margin;
296ba8e76bdSTimur Tabi 	info.var.lower_margin = fsl_diu_mode_db->lower_margin;
297ba8e76bdSTimur Tabi 	info.var.hsync_len = fsl_diu_mode_db->hsync_len;
298ba8e76bdSTimur Tabi 	info.var.vsync_len = fsl_diu_mode_db->vsync_len;
299ba8e76bdSTimur Tabi 	info.var.sync = fsl_diu_mode_db->sync;
300ba8e76bdSTimur Tabi 	info.var.vmode = fsl_diu_mode_db->vmode;
3018c6b2504STimur Tabi 	info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
302ba8e76bdSTimur Tabi 
303ba8e76bdSTimur Tabi 	/* Memory allocation for framebuffer */
3048c6b2504STimur Tabi 	info.screen_size =
305ba8e76bdSTimur Tabi 		info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
306ba8e76bdSTimur Tabi 	ad = allocate_fb(info.var.xres, info.var.yres,
307ba8e76bdSTimur Tabi 			 info.var.bits_per_pixel / 8, &info.screen_base);
308ba8e76bdSTimur Tabi 	if (!ad) {
309ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
310ba8e76bdSTimur Tabi 		return -1;
311ba8e76bdSTimur Tabi 	}
31214f88c43SAnatolij Gustschin 
31314f88c43SAnatolij Gustschin 	ad->pix_fmt = pixel_format;
31414f88c43SAnatolij Gustschin 
31514f88c43SAnatolij Gustschin 	/* Disable chroma keying function */
31614f88c43SAnatolij Gustschin 	ad->ckmax_r = 0;
31714f88c43SAnatolij Gustschin 	ad->ckmax_g = 0;
31814f88c43SAnatolij Gustschin 	ad->ckmax_b = 0;
31914f88c43SAnatolij Gustschin 
32014f88c43SAnatolij Gustschin 	ad->ckmin_r = 255;
32114f88c43SAnatolij Gustschin 	ad->ckmin_g = 255;
32214f88c43SAnatolij Gustschin 	ad->ckmin_b = 255;
32314f88c43SAnatolij Gustschin 
324ba8e76bdSTimur Tabi 	/* Initialize the gamma table */
325ba8e76bdSTimur Tabi 	if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
326ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
327ba8e76bdSTimur Tabi 		return -1;
328ba8e76bdSTimur Tabi 	}
329ba8e76bdSTimur Tabi 	gamma_table_base = gamma.vaddr;
33014f88c43SAnatolij Gustschin 	for (i = 0; i <= 2; i++)
331ba8e76bdSTimur Tabi 		for (j = 0; j < 256; j++)
33214f88c43SAnatolij Gustschin 			*gamma_table_base++ = j;
33314f88c43SAnatolij Gustschin 
33414f88c43SAnatolij Gustschin 	if (gamma_fix == 1) {	/* fix the gamma */
335ba8e76bdSTimur Tabi 		gamma_table_base = gamma.vaddr;
33614f88c43SAnatolij Gustschin 		for (i = 0; i < 256 * 3; i++) {
33714f88c43SAnatolij Gustschin 			gamma_table_base[i] = (gamma_table_base[i] << 2)
33814f88c43SAnatolij Gustschin 				| ((gamma_table_base[i] >> 6) & 0x03);
33914f88c43SAnatolij Gustschin 		}
34014f88c43SAnatolij Gustschin 	}
34114f88c43SAnatolij Gustschin 
342ba8e76bdSTimur Tabi 	/* Initialize the cursor */
343ba8e76bdSTimur Tabi 	if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
344ba8e76bdSTimur Tabi 		printf("DIU:   Can't alloc cursor data\n");
345ba8e76bdSTimur Tabi 		return -1;
346ba8e76bdSTimur Tabi 	}
34714f88c43SAnatolij Gustschin 
34814f88c43SAnatolij Gustschin 	/* Program DIU registers */
349ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 0);	/* Temporarily disable the DIU */
35014f88c43SAnatolij Gustschin 
351ba8e76bdSTimur Tabi 	out_be32(&hw->gamma, gamma.paddr);
352ba8e76bdSTimur Tabi 	out_be32(&hw->cursor, cursor.paddr);
35314f88c43SAnatolij Gustschin 	out_be32(&hw->bgnd, 0x007F7F7F);
354ba8e76bdSTimur Tabi 	out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
355ba8e76bdSTimur Tabi 	out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
356ba8e76bdSTimur Tabi 			info.var.hsync_len << 11 |
357ba8e76bdSTimur Tabi 			info.var.right_margin);
35814f88c43SAnatolij Gustschin 
359ba8e76bdSTimur Tabi 	out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
360ba8e76bdSTimur Tabi 			info.var.vsync_len << 11 |
361ba8e76bdSTimur Tabi 			info.var.lower_margin);
36214f88c43SAnatolij Gustschin 
36314f88c43SAnatolij Gustschin 	/* Pixel Clock configuration */
364ba8e76bdSTimur Tabi 	diu_set_pixel_clock(info.var.pixclock);
36514f88c43SAnatolij Gustschin 
366ba8e76bdSTimur Tabi 	/* Set the frame buffers */
367ba8e76bdSTimur Tabi 	out_be32(&hw->desc[0], virt_to_phys(ad));
36815b83386STimur Tabi 	out_be32(&hw->desc[1], 0);
36915b83386STimur Tabi 	out_be32(&hw->desc[2], 0);
37014f88c43SAnatolij Gustschin 
371ba8e76bdSTimur Tabi 	/* Enable the DIU, set display to all three planes */
372ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 1);
37314f88c43SAnatolij Gustschin 
37414f88c43SAnatolij Gustschin 	return 0;
37514f88c43SAnatolij Gustschin }
37614f88c43SAnatolij Gustschin 
video_hw_init(void)37714f88c43SAnatolij Gustschin void *video_hw_init(void)
37814f88c43SAnatolij Gustschin {
379ba8e76bdSTimur Tabi 	static GraphicDevice ctfb;
380ba8e76bdSTimur Tabi 	const char *options;
381ba8e76bdSTimur Tabi 	unsigned int depth = 0, freq = 0;
38214f88c43SAnatolij Gustschin 
383ba8e76bdSTimur Tabi 	if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
384ba8e76bdSTimur Tabi 				  &options))
385ba8e76bdSTimur Tabi 		return NULL;
386ba8e76bdSTimur Tabi 
387ba8e76bdSTimur Tabi 	/* Find the monitor port, which is a required option */
388ba8e76bdSTimur Tabi 	if (!options)
389ba8e76bdSTimur Tabi 		return NULL;
390ba8e76bdSTimur Tabi 	if (strncmp(options, "monitor=", 8) != 0)
391ba8e76bdSTimur Tabi 		return NULL;
392ba8e76bdSTimur Tabi 
393ba8e76bdSTimur Tabi 	if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
39414f88c43SAnatolij Gustschin 		return NULL;
39514f88c43SAnatolij Gustschin 
39614f88c43SAnatolij Gustschin 	/* fill in Graphic device struct */
39714f88c43SAnatolij Gustschin 	sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
398ba8e76bdSTimur Tabi 		ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
39914f88c43SAnatolij Gustschin 
400ba8e76bdSTimur Tabi 	ctfb.frameAdrs = (unsigned int)info.screen_base;
40114f88c43SAnatolij Gustschin 	ctfb.plnSizeX = ctfb.winSizeX;
40214f88c43SAnatolij Gustschin 	ctfb.plnSizeY = ctfb.winSizeY;
40314f88c43SAnatolij Gustschin 
40414f88c43SAnatolij Gustschin 	ctfb.gdfBytesPP = 4;
40514f88c43SAnatolij Gustschin 	ctfb.gdfIndex = GDF_32BIT_X888RGB;
40614f88c43SAnatolij Gustschin 
40714f88c43SAnatolij Gustschin 	ctfb.isaBase = 0;
40814f88c43SAnatolij Gustschin 	ctfb.pciBase = 0;
409ba8e76bdSTimur Tabi 	ctfb.memSize = info.screen_size;
41014f88c43SAnatolij Gustschin 
41114f88c43SAnatolij Gustschin 	/* Cursor Start Address */
41214f88c43SAnatolij Gustschin 	ctfb.dprBase = 0;
41314f88c43SAnatolij Gustschin 	ctfb.vprBase = 0;
41414f88c43SAnatolij Gustschin 	ctfb.cprBase = 0;
41514f88c43SAnatolij Gustschin 
41614f88c43SAnatolij Gustschin 	return &ctfb;
41714f88c43SAnatolij Gustschin }
418