xref: /rk3399_rockchip-uboot/drivers/video/fsl_diu_fb.c (revision debef5cd9e362645cc4ae7a4dcc035175c2fb170)
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  *
814f88c43SAnatolij Gustschin  * See file CREDITS for list of people who contributed to this
914f88c43SAnatolij Gustschin  * project.
1014f88c43SAnatolij Gustschin  *
1114f88c43SAnatolij Gustschin  * This program is free software; you can redistribute it and/or
1214f88c43SAnatolij Gustschin  * modify it under the terms of the GNU General Public License as
1314f88c43SAnatolij Gustschin  * published by the Free Software Foundation; either version 2 of
1414f88c43SAnatolij Gustschin  * the License, or (at your option) any later version.
1514f88c43SAnatolij Gustschin  *
1614f88c43SAnatolij Gustschin  * This program is distributed in the hope that it will be useful,
1714f88c43SAnatolij Gustschin  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1814f88c43SAnatolij Gustschin  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1914f88c43SAnatolij Gustschin  * GNU General Public License for more details.
2014f88c43SAnatolij Gustschin  *
2114f88c43SAnatolij Gustschin  * You should have received a copy of the GNU General Public License
2214f88c43SAnatolij Gustschin  * along with this program; if not, write to the Free Software
2314f88c43SAnatolij Gustschin  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2414f88c43SAnatolij Gustschin  * MA 02111-1307 USA
2514f88c43SAnatolij Gustschin  */
2614f88c43SAnatolij Gustschin 
2714f88c43SAnatolij Gustschin #include <common.h>
2814f88c43SAnatolij Gustschin #include <malloc.h>
2914f88c43SAnatolij Gustschin #include <asm/io.h>
3014f88c43SAnatolij Gustschin 
31ba8e76bdSTimur Tabi #include "videomodes.h"
32ba8e76bdSTimur Tabi #include <video_fb.h>
3314f88c43SAnatolij Gustschin #include <fsl_diu_fb.h>
348c6b2504STimur Tabi #include <linux/list.h>
358c6b2504STimur Tabi #include <linux/fb.h>
3614f88c43SAnatolij Gustschin 
3714f88c43SAnatolij Gustschin /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
383b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_480 = {
393b4a2263STimur Tabi 	.name		= "800x480-60",
4014f88c43SAnatolij Gustschin 	.refresh	= 60,
4114f88c43SAnatolij Gustschin 	.xres		= 800,
4214f88c43SAnatolij Gustschin 	.yres		= 480,
4314f88c43SAnatolij Gustschin 	.pixclock	= 31250,
4414f88c43SAnatolij Gustschin 	.left_margin	= 86,
4514f88c43SAnatolij Gustschin 	.right_margin	= 42,
4614f88c43SAnatolij Gustschin 	.upper_margin	= 33,
4714f88c43SAnatolij Gustschin 	.lower_margin	= 10,
4814f88c43SAnatolij Gustschin 	.hsync_len	= 128,
4914f88c43SAnatolij Gustschin 	.vsync_len	= 2,
5014f88c43SAnatolij Gustschin 	.sync		= 0,
5114f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
5214f88c43SAnatolij Gustschin };
5314f88c43SAnatolij Gustschin 
543b4a2263STimur Tabi /* For the SHARP LQ084S3LG01, used on the P1022DS board */
553b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_800_600 = {
563b4a2263STimur Tabi 	.name		= "800x600-60",
573b4a2263STimur Tabi 	.refresh	= 60,
583b4a2263STimur Tabi 	.xres		= 800,
593b4a2263STimur Tabi 	.yres		= 600,
603b4a2263STimur Tabi 	.pixclock	= 25000,
613b4a2263STimur Tabi 	.left_margin	= 88,
623b4a2263STimur Tabi 	.right_margin	= 40,
633b4a2263STimur Tabi 	.upper_margin	= 23,
643b4a2263STimur Tabi 	.lower_margin	= 1,
653b4a2263STimur Tabi 	.hsync_len	= 128,
663b4a2263STimur Tabi 	.vsync_len	= 4,
673b4a2263STimur Tabi 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
683b4a2263STimur Tabi 	.vmode		= FB_VMODE_NONINTERLACED
693b4a2263STimur Tabi };
703b4a2263STimur Tabi 
7114f88c43SAnatolij Gustschin /*
7214f88c43SAnatolij Gustschin  * These parameters give default parameters
7314f88c43SAnatolij Gustschin  * for video output 1024x768,
7414f88c43SAnatolij Gustschin  * FIXME - change timing to proper amounts
7514f88c43SAnatolij Gustschin  * hsync 31.5kHz, vsync 60Hz
7614f88c43SAnatolij Gustschin  */
773b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1024_768 = {
78ba8e76bdSTimur Tabi 	.name		= "1024x768-60",
7914f88c43SAnatolij Gustschin 	.refresh	= 60,
8014f88c43SAnatolij Gustschin 	.xres		= 1024,
8114f88c43SAnatolij Gustschin 	.yres		= 768,
8214f88c43SAnatolij Gustschin 	.pixclock	= 15385,
8314f88c43SAnatolij Gustschin 	.left_margin	= 160,
8414f88c43SAnatolij Gustschin 	.right_margin	= 24,
8514f88c43SAnatolij Gustschin 	.upper_margin	= 29,
8614f88c43SAnatolij Gustschin 	.lower_margin	= 3,
8714f88c43SAnatolij Gustschin 	.hsync_len	= 136,
8814f88c43SAnatolij Gustschin 	.vsync_len	= 6,
8914f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
9014f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
9114f88c43SAnatolij Gustschin };
9214f88c43SAnatolij Gustschin 
933b4a2263STimur Tabi static struct fb_videomode fsl_diu_mode_1280_1024 = {
9414f88c43SAnatolij Gustschin 	.name		= "1280x1024-60",
9514f88c43SAnatolij Gustschin 	.refresh	= 60,
9614f88c43SAnatolij Gustschin 	.xres		= 1280,
9714f88c43SAnatolij Gustschin 	.yres		= 1024,
9814f88c43SAnatolij Gustschin 	.pixclock	= 9375,
9914f88c43SAnatolij Gustschin 	.left_margin	= 38,
10014f88c43SAnatolij Gustschin 	.right_margin	= 128,
10114f88c43SAnatolij Gustschin 	.upper_margin	= 2,
10214f88c43SAnatolij Gustschin 	.lower_margin	= 7,
10314f88c43SAnatolij Gustschin 	.hsync_len	= 216,
10414f88c43SAnatolij Gustschin 	.vsync_len	= 37,
10514f88c43SAnatolij Gustschin 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
10614f88c43SAnatolij Gustschin 	.vmode		= FB_VMODE_NONINTERLACED
10714f88c43SAnatolij Gustschin };
10814f88c43SAnatolij Gustschin 
109*debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1280_720 = {
110*debef5cdSJerry Huang 	.name		= "1280x720-60",
111*debef5cdSJerry Huang 	.refresh	= 60,
112*debef5cdSJerry Huang 	.xres		= 1280,
113*debef5cdSJerry Huang 	.yres		= 720,
114*debef5cdSJerry Huang 	.pixclock	= 13426,
115*debef5cdSJerry Huang 	.left_margin	= 192,
116*debef5cdSJerry Huang 	.right_margin	= 64,
117*debef5cdSJerry Huang 	.upper_margin	= 22,
118*debef5cdSJerry Huang 	.lower_margin	= 1,
119*debef5cdSJerry Huang 	.hsync_len	= 136,
120*debef5cdSJerry Huang 	.vsync_len	= 3,
121*debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
122*debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
123*debef5cdSJerry Huang };
124*debef5cdSJerry Huang 
125*debef5cdSJerry Huang static struct fb_videomode fsl_diu_mode_1920_1080 = {
126*debef5cdSJerry Huang 	.name		= "1920x1080-60",
127*debef5cdSJerry Huang 	.refresh	= 60,
128*debef5cdSJerry Huang 	.xres		= 1920,
129*debef5cdSJerry Huang 	.yres		= 1080,
130*debef5cdSJerry Huang 	.pixclock	= 5787,
131*debef5cdSJerry Huang 	.left_margin	= 328,
132*debef5cdSJerry Huang 	.right_margin	= 120,
133*debef5cdSJerry Huang 	.upper_margin	= 34,
134*debef5cdSJerry Huang 	.lower_margin	= 1,
135*debef5cdSJerry Huang 	.hsync_len	= 208,
136*debef5cdSJerry Huang 	.vsync_len	= 3,
137*debef5cdSJerry Huang 	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
138*debef5cdSJerry Huang 	.vmode		= FB_VMODE_NONINTERLACED
139*debef5cdSJerry Huang };
140*debef5cdSJerry Huang 
14114f88c43SAnatolij Gustschin /*
14214f88c43SAnatolij Gustschin  * These are the fields of area descriptor(in DDR memory) for every plane
14314f88c43SAnatolij Gustschin  */
14414f88c43SAnatolij Gustschin struct diu_ad {
14514f88c43SAnatolij Gustschin 	/* Word 0(32-bit) in DDR memory */
146ba8e76bdSTimur Tabi 	__le32 pix_fmt; /* hard coding pixel format */
14714f88c43SAnatolij Gustschin 	/* Word 1(32-bit) in DDR memory */
148ba8e76bdSTimur Tabi 	__le32 addr;
14914f88c43SAnatolij Gustschin 	/* Word 2(32-bit) in DDR memory */
150ba8e76bdSTimur Tabi 	__le32 src_size_g_alpha;
15114f88c43SAnatolij Gustschin 	/* Word 3(32-bit) in DDR memory */
152ba8e76bdSTimur Tabi 	__le32 aoi_size;
15314f88c43SAnatolij Gustschin 	/* Word 4(32-bit) in DDR memory */
154ba8e76bdSTimur Tabi 	__le32 offset_xyi;
15514f88c43SAnatolij Gustschin 	/* Word 5(32-bit) in DDR memory */
156ba8e76bdSTimur Tabi 	__le32 offset_xyd;
15714f88c43SAnatolij Gustschin 	/* Word 6(32-bit) in DDR memory */
158ba8e76bdSTimur Tabi 	__le32 ckmax_r:8;
159ba8e76bdSTimur Tabi 	__le32 ckmax_g:8;
160ba8e76bdSTimur Tabi 	__le32 ckmax_b:8;
161ba8e76bdSTimur Tabi 	__le32 res9:8;
16214f88c43SAnatolij Gustschin 	/* Word 7(32-bit) in DDR memory */
163ba8e76bdSTimur Tabi 	__le32 ckmin_r:8;
164ba8e76bdSTimur Tabi 	__le32 ckmin_g:8;
165ba8e76bdSTimur Tabi 	__le32 ckmin_b:8;
166ba8e76bdSTimur Tabi 	__le32 res10:8;
16714f88c43SAnatolij Gustschin 	/* Word 8(32-bit) in DDR memory */
168ba8e76bdSTimur Tabi 	__le32 next_ad;
16914f88c43SAnatolij Gustschin 	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
170ba8e76bdSTimur Tabi 	__le32 res[3];
17114f88c43SAnatolij Gustschin } __attribute__ ((packed));
17214f88c43SAnatolij Gustschin 
17314f88c43SAnatolij Gustschin /*
17414f88c43SAnatolij Gustschin  * DIU register map
17514f88c43SAnatolij Gustschin  */
17614f88c43SAnatolij Gustschin struct diu {
177ba8e76bdSTimur Tabi 	__be32 desc[3];
178ba8e76bdSTimur Tabi 	__be32 gamma;
179ba8e76bdSTimur Tabi 	__be32 pallete;
180ba8e76bdSTimur Tabi 	__be32 cursor;
181ba8e76bdSTimur Tabi 	__be32 curs_pos;
182ba8e76bdSTimur Tabi 	__be32 diu_mode;
183ba8e76bdSTimur Tabi 	__be32 bgnd;
184ba8e76bdSTimur Tabi 	__be32 bgnd_wb;
185ba8e76bdSTimur Tabi 	__be32 disp_size;
186ba8e76bdSTimur Tabi 	__be32 wb_size;
187ba8e76bdSTimur Tabi 	__be32 wb_mem_addr;
188ba8e76bdSTimur Tabi 	__be32 hsyn_para;
189ba8e76bdSTimur Tabi 	__be32 vsyn_para;
190ba8e76bdSTimur Tabi 	__be32 syn_pol;
191ba8e76bdSTimur Tabi 	__be32 thresholds;
192ba8e76bdSTimur Tabi 	__be32 int_status;
193ba8e76bdSTimur Tabi 	__be32 int_mask;
194ba8e76bdSTimur Tabi 	__be32 colorbar[8];
195ba8e76bdSTimur Tabi 	__be32 filling;
196ba8e76bdSTimur Tabi 	__be32 plut;
19714f88c43SAnatolij Gustschin } __attribute__ ((packed));
19814f88c43SAnatolij Gustschin 
199ba8e76bdSTimur Tabi struct diu_addr {
200ba8e76bdSTimur Tabi 	void *vaddr;		/* Virtual address */
201ba8e76bdSTimur Tabi 	u32 paddr;		/* 32-bit physical address */
202ba8e76bdSTimur Tabi 	unsigned int offset;	/* Alignment offset */
20314f88c43SAnatolij Gustschin };
20414f88c43SAnatolij Gustschin 
205ba8e76bdSTimur Tabi static struct fb_info info;
20614f88c43SAnatolij Gustschin 
20714f88c43SAnatolij Gustschin /*
208ba8e76bdSTimur Tabi  * Align to 64-bit(8-byte), 32-byte, etc.
20914f88c43SAnatolij Gustschin  */
210ba8e76bdSTimur Tabi static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
211ba8e76bdSTimur Tabi {
212ba8e76bdSTimur Tabi 	u32 offset, ssize;
213ba8e76bdSTimur Tabi 	u32 mask;
21414f88c43SAnatolij Gustschin 
215ba8e76bdSTimur Tabi 	ssize = size + bytes_align;
216ba8e76bdSTimur Tabi 	buf->vaddr = malloc(ssize);
217ba8e76bdSTimur Tabi 	if (!buf->vaddr)
218ba8e76bdSTimur Tabi 		return -1;
21914f88c43SAnatolij Gustschin 
220ba8e76bdSTimur Tabi 	memset(buf->vaddr, 0, ssize);
221ba8e76bdSTimur Tabi 	mask = bytes_align - 1;
222ba8e76bdSTimur Tabi 	offset = (u32)buf->vaddr & mask;
223ba8e76bdSTimur Tabi 	if (offset) {
224ba8e76bdSTimur Tabi 		buf->offset = bytes_align - offset;
225ba8e76bdSTimur Tabi 		buf->vaddr += offset;
226ba8e76bdSTimur Tabi 	} else
227ba8e76bdSTimur Tabi 		buf->offset = 0;
22814f88c43SAnatolij Gustschin 
229ba8e76bdSTimur Tabi 	buf->paddr = virt_to_phys(buf->vaddr);
230ba8e76bdSTimur Tabi 	return 0;
231ba8e76bdSTimur Tabi }
23214f88c43SAnatolij Gustschin 
233ba8e76bdSTimur Tabi /*
234ba8e76bdSTimur Tabi  * Allocate a framebuffer and an Area Descriptor that points to it.  Both
235ba8e76bdSTimur Tabi  * are created in the same memory block.  The Area Descriptor is updated to
236ba8e76bdSTimur Tabi  * point to the framebuffer memory. Memory is aligned as needed.
237ba8e76bdSTimur Tabi  */
238ba8e76bdSTimur Tabi static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
2398c6b2504STimur Tabi 				  unsigned int depth, char **fb)
240ba8e76bdSTimur Tabi {
241ba8e76bdSTimur Tabi 	unsigned long size = xres * yres * depth;
242ba8e76bdSTimur Tabi 	struct diu_addr addr;
243ba8e76bdSTimur Tabi 	struct diu_ad *ad;
244ba8e76bdSTimur Tabi 	size_t ad_size = roundup(sizeof(struct diu_ad), 32);
24514f88c43SAnatolij Gustschin 
246ba8e76bdSTimur Tabi 	/*
247ba8e76bdSTimur Tabi 	 * Allocate a memory block that holds the Area Descriptor and the
248ba8e76bdSTimur Tabi 	 * frame buffer right behind it.  To keep the code simple, everything
249ba8e76bdSTimur Tabi 	 * is aligned on a 32-byte address.
250ba8e76bdSTimur Tabi 	 */
251ba8e76bdSTimur Tabi 	if (allocate_buf(&addr, ad_size + size, 32) < 0)
252ba8e76bdSTimur Tabi 		return NULL;
253ba8e76bdSTimur Tabi 
254ba8e76bdSTimur Tabi 	ad = addr.vaddr;
255ba8e76bdSTimur Tabi 	ad->addr = cpu_to_le32(addr.paddr + ad_size);
256ba8e76bdSTimur Tabi 	ad->aoi_size = cpu_to_le32((yres << 16) | xres);
257ba8e76bdSTimur Tabi 	ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
258ba8e76bdSTimur Tabi 	ad->offset_xyi = 0;
259ba8e76bdSTimur Tabi 	ad->offset_xyd = 0;
260ba8e76bdSTimur Tabi 
261ba8e76bdSTimur Tabi 	if (fb)
262ba8e76bdSTimur Tabi 		*fb = addr.vaddr + ad_size;
263ba8e76bdSTimur Tabi 
264ba8e76bdSTimur Tabi 	return ad;
265ba8e76bdSTimur Tabi }
266ba8e76bdSTimur Tabi 
2673b4a2263STimur Tabi int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
26814f88c43SAnatolij Gustschin {
26914f88c43SAnatolij Gustschin 	struct fb_videomode *fsl_diu_mode_db;
270ba8e76bdSTimur Tabi 	struct diu_ad *ad;
271ba8e76bdSTimur Tabi 	struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
272ba8e76bdSTimur Tabi 	u8 *gamma_table_base;
27314f88c43SAnatolij Gustschin 	unsigned int i, j;
274ba8e76bdSTimur Tabi 	struct diu_ad *dummy_ad;
275ba8e76bdSTimur Tabi 	struct diu_addr gamma;
276ba8e76bdSTimur Tabi 	struct diu_addr cursor;
27714f88c43SAnatolij Gustschin 
2783b4a2263STimur Tabi /* Convert the X,Y resolution pair into a single number */
2793b4a2263STimur Tabi #define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
2803b4a2263STimur Tabi 
2813b4a2263STimur Tabi 	switch (RESOLUTION(xres, yres)) {
2823b4a2263STimur Tabi 	case RESOLUTION(800, 480):
2833b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_480;
28414f88c43SAnatolij Gustschin 		break;
2853b4a2263STimur Tabi 	case RESOLUTION(800, 600):
2863b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_800_600;
28715006cb7SJerry Huang 		break;
2883b4a2263STimur Tabi 	case RESOLUTION(1024, 768):
2893b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1024_768;
29015006cb7SJerry Huang 		break;
2913b4a2263STimur Tabi 	case RESOLUTION(1280, 1024):
2923b4a2263STimur Tabi 		fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
29314f88c43SAnatolij Gustschin 		break;
294*debef5cdSJerry Huang 	case RESOLUTION(1280, 720):
295*debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1280_720;
296*debef5cdSJerry Huang 		break;
297*debef5cdSJerry Huang 	case RESOLUTION(1920, 1080):
298*debef5cdSJerry Huang 		fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
299*debef5cdSJerry Huang 		break;
30014f88c43SAnatolij Gustschin 	default:
3013b4a2263STimur Tabi 		printf("DIU:   Unsupported resolution %ux%u\n", xres, yres);
3023b4a2263STimur Tabi 		return -1;
30314f88c43SAnatolij Gustschin 	}
30414f88c43SAnatolij Gustschin 
305ba8e76bdSTimur Tabi 	/* The AD struct for the dummy framebuffer and the FB itself */
306ba8e76bdSTimur Tabi 	dummy_ad = allocate_fb(2, 4, 4, NULL);
307ba8e76bdSTimur Tabi 	if (!dummy_ad) {
308ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
30914f88c43SAnatolij Gustschin 		return -1;
31014f88c43SAnatolij Gustschin 	}
311ba8e76bdSTimur Tabi 	dummy_ad->pix_fmt = 0x88883316;
31214f88c43SAnatolij Gustschin 
31314f88c43SAnatolij Gustschin 	/* read mode info */
314ba8e76bdSTimur Tabi 	info.var.xres = fsl_diu_mode_db->xres;
315ba8e76bdSTimur Tabi 	info.var.yres = fsl_diu_mode_db->yres;
316ba8e76bdSTimur Tabi 	info.var.bits_per_pixel = 32;
317ba8e76bdSTimur Tabi 	info.var.pixclock = fsl_diu_mode_db->pixclock;
318ba8e76bdSTimur Tabi 	info.var.left_margin = fsl_diu_mode_db->left_margin;
319ba8e76bdSTimur Tabi 	info.var.right_margin = fsl_diu_mode_db->right_margin;
320ba8e76bdSTimur Tabi 	info.var.upper_margin = fsl_diu_mode_db->upper_margin;
321ba8e76bdSTimur Tabi 	info.var.lower_margin = fsl_diu_mode_db->lower_margin;
322ba8e76bdSTimur Tabi 	info.var.hsync_len = fsl_diu_mode_db->hsync_len;
323ba8e76bdSTimur Tabi 	info.var.vsync_len = fsl_diu_mode_db->vsync_len;
324ba8e76bdSTimur Tabi 	info.var.sync = fsl_diu_mode_db->sync;
325ba8e76bdSTimur Tabi 	info.var.vmode = fsl_diu_mode_db->vmode;
3268c6b2504STimur Tabi 	info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
327ba8e76bdSTimur Tabi 
328ba8e76bdSTimur Tabi 	/* Memory allocation for framebuffer */
3298c6b2504STimur Tabi 	info.screen_size =
330ba8e76bdSTimur Tabi 		info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
331ba8e76bdSTimur Tabi 	ad = allocate_fb(info.var.xres, info.var.yres,
332ba8e76bdSTimur Tabi 			 info.var.bits_per_pixel / 8, &info.screen_base);
333ba8e76bdSTimur Tabi 	if (!ad) {
334ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
335ba8e76bdSTimur Tabi 		return -1;
336ba8e76bdSTimur Tabi 	}
33714f88c43SAnatolij Gustschin 
33814f88c43SAnatolij Gustschin 	ad->pix_fmt = pixel_format;
33914f88c43SAnatolij Gustschin 
34014f88c43SAnatolij Gustschin 	/* Disable chroma keying function */
34114f88c43SAnatolij Gustschin 	ad->ckmax_r = 0;
34214f88c43SAnatolij Gustschin 	ad->ckmax_g = 0;
34314f88c43SAnatolij Gustschin 	ad->ckmax_b = 0;
34414f88c43SAnatolij Gustschin 
34514f88c43SAnatolij Gustschin 	ad->ckmin_r = 255;
34614f88c43SAnatolij Gustschin 	ad->ckmin_g = 255;
34714f88c43SAnatolij Gustschin 	ad->ckmin_b = 255;
34814f88c43SAnatolij Gustschin 
349ba8e76bdSTimur Tabi 	/* Initialize the gamma table */
350ba8e76bdSTimur Tabi 	if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
351ba8e76bdSTimur Tabi 		printf("DIU:   Out of memory\n");
352ba8e76bdSTimur Tabi 		return -1;
353ba8e76bdSTimur Tabi 	}
354ba8e76bdSTimur Tabi 	gamma_table_base = gamma.vaddr;
35514f88c43SAnatolij Gustschin 	for (i = 0; i <= 2; i++)
356ba8e76bdSTimur Tabi 		for (j = 0; j < 256; j++)
35714f88c43SAnatolij Gustschin 			*gamma_table_base++ = j;
35814f88c43SAnatolij Gustschin 
35914f88c43SAnatolij Gustschin 	if (gamma_fix == 1) {	/* fix the gamma */
360ba8e76bdSTimur Tabi 		gamma_table_base = gamma.vaddr;
36114f88c43SAnatolij Gustschin 		for (i = 0; i < 256 * 3; i++) {
36214f88c43SAnatolij Gustschin 			gamma_table_base[i] = (gamma_table_base[i] << 2)
36314f88c43SAnatolij Gustschin 				| ((gamma_table_base[i] >> 6) & 0x03);
36414f88c43SAnatolij Gustschin 		}
36514f88c43SAnatolij Gustschin 	}
36614f88c43SAnatolij Gustschin 
367ba8e76bdSTimur Tabi 	/* Initialize the cursor */
368ba8e76bdSTimur Tabi 	if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
369ba8e76bdSTimur Tabi 		printf("DIU:   Can't alloc cursor data\n");
370ba8e76bdSTimur Tabi 		return -1;
371ba8e76bdSTimur Tabi 	}
37214f88c43SAnatolij Gustschin 
37314f88c43SAnatolij Gustschin 	/* Program DIU registers */
374ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 0);	/* Temporarily disable the DIU */
37514f88c43SAnatolij Gustschin 
376ba8e76bdSTimur Tabi 	out_be32(&hw->gamma, gamma.paddr);
377ba8e76bdSTimur Tabi 	out_be32(&hw->cursor, cursor.paddr);
37814f88c43SAnatolij Gustschin 	out_be32(&hw->bgnd, 0x007F7F7F);
379ba8e76bdSTimur Tabi 	out_be32(&hw->bgnd_wb, 0);
380ba8e76bdSTimur Tabi 	out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
381ba8e76bdSTimur Tabi 	out_be32(&hw->wb_size, 0);
382ba8e76bdSTimur Tabi 	out_be32(&hw->wb_mem_addr, 0);
383ba8e76bdSTimur Tabi 	out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
384ba8e76bdSTimur Tabi 			info.var.hsync_len << 11 |
385ba8e76bdSTimur Tabi 			info.var.right_margin);
38614f88c43SAnatolij Gustschin 
387ba8e76bdSTimur Tabi 	out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
388ba8e76bdSTimur Tabi 			info.var.vsync_len << 11 |
389ba8e76bdSTimur Tabi 			info.var.lower_margin);
39014f88c43SAnatolij Gustschin 
391ba8e76bdSTimur Tabi 	out_be32(&hw->syn_pol, 0);
392ba8e76bdSTimur Tabi 	out_be32(&hw->thresholds, 0x00037800);
393ba8e76bdSTimur Tabi 	out_be32(&hw->int_status, 0);
394ba8e76bdSTimur Tabi 	out_be32(&hw->int_mask, 0);
39514f88c43SAnatolij Gustschin 	out_be32(&hw->plut, 0x01F5F666);
39614f88c43SAnatolij Gustschin 	/* Pixel Clock configuration */
397ba8e76bdSTimur Tabi 	diu_set_pixel_clock(info.var.pixclock);
39814f88c43SAnatolij Gustschin 
399ba8e76bdSTimur Tabi 	/* Set the frame buffers */
400ba8e76bdSTimur Tabi 	out_be32(&hw->desc[0], virt_to_phys(ad));
401ba8e76bdSTimur Tabi 	out_be32(&hw->desc[1], virt_to_phys(dummy_ad));
402ba8e76bdSTimur Tabi 	out_be32(&hw->desc[2], virt_to_phys(dummy_ad));
40314f88c43SAnatolij Gustschin 
404ba8e76bdSTimur Tabi 	/* Enable the DIU, set display to all three planes */
405ba8e76bdSTimur Tabi 	out_be32(&hw->diu_mode, 1);
40614f88c43SAnatolij Gustschin 
40714f88c43SAnatolij Gustschin 	return 0;
40814f88c43SAnatolij Gustschin }
40914f88c43SAnatolij Gustschin 
41014f88c43SAnatolij Gustschin void *video_hw_init(void)
41114f88c43SAnatolij Gustschin {
412ba8e76bdSTimur Tabi 	static GraphicDevice ctfb;
413ba8e76bdSTimur Tabi 	const char *options;
414ba8e76bdSTimur Tabi 	unsigned int depth = 0, freq = 0;
41514f88c43SAnatolij Gustschin 
416ba8e76bdSTimur Tabi 	if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
417ba8e76bdSTimur Tabi 				  &options))
418ba8e76bdSTimur Tabi 		return NULL;
419ba8e76bdSTimur Tabi 
420ba8e76bdSTimur Tabi 	/* Find the monitor port, which is a required option */
421ba8e76bdSTimur Tabi 	if (!options)
422ba8e76bdSTimur Tabi 		return NULL;
423ba8e76bdSTimur Tabi 	if (strncmp(options, "monitor=", 8) != 0)
424ba8e76bdSTimur Tabi 		return NULL;
425ba8e76bdSTimur Tabi 
426ba8e76bdSTimur Tabi 	if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
42714f88c43SAnatolij Gustschin 		return NULL;
42814f88c43SAnatolij Gustschin 
42914f88c43SAnatolij Gustschin 	/* fill in Graphic device struct */
43014f88c43SAnatolij Gustschin 	sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
431ba8e76bdSTimur Tabi 		ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
43214f88c43SAnatolij Gustschin 
433ba8e76bdSTimur Tabi 	ctfb.frameAdrs = (unsigned int)info.screen_base;
43414f88c43SAnatolij Gustschin 	ctfb.plnSizeX = ctfb.winSizeX;
43514f88c43SAnatolij Gustschin 	ctfb.plnSizeY = ctfb.winSizeY;
43614f88c43SAnatolij Gustschin 
43714f88c43SAnatolij Gustschin 	ctfb.gdfBytesPP = 4;
43814f88c43SAnatolij Gustschin 	ctfb.gdfIndex = GDF_32BIT_X888RGB;
43914f88c43SAnatolij Gustschin 
44014f88c43SAnatolij Gustschin 	ctfb.isaBase = 0;
44114f88c43SAnatolij Gustschin 	ctfb.pciBase = 0;
442ba8e76bdSTimur Tabi 	ctfb.memSize = info.screen_size;
44314f88c43SAnatolij Gustschin 
44414f88c43SAnatolij Gustschin 	/* Cursor Start Address */
44514f88c43SAnatolij Gustschin 	ctfb.dprBase = 0;
44614f88c43SAnatolij Gustschin 	ctfb.vprBase = 0;
44714f88c43SAnatolij Gustschin 	ctfb.cprBase = 0;
44814f88c43SAnatolij Gustschin 
44914f88c43SAnatolij Gustschin 	return &ctfb;
45014f88c43SAnatolij Gustschin }
451