1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun * Authors: York Sun <yorksun@freescale.com>
4*4882a593Smuzhiyun * Timur Tabi <timur@freescale.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * FSL DIU Framebuffer driver
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <malloc.h>
13*4882a593Smuzhiyun #include <asm/io.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include "videomodes.h"
16*4882a593Smuzhiyun #include <video_fb.h>
17*4882a593Smuzhiyun #include <fsl_diu_fb.h>
18*4882a593Smuzhiyun #include <linux/list.h>
19*4882a593Smuzhiyun #include <linux/fb.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
22*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_800_480 = {
23*4882a593Smuzhiyun .name = "800x480-60",
24*4882a593Smuzhiyun .refresh = 60,
25*4882a593Smuzhiyun .xres = 800,
26*4882a593Smuzhiyun .yres = 480,
27*4882a593Smuzhiyun .pixclock = 31250,
28*4882a593Smuzhiyun .left_margin = 86,
29*4882a593Smuzhiyun .right_margin = 42,
30*4882a593Smuzhiyun .upper_margin = 33,
31*4882a593Smuzhiyun .lower_margin = 10,
32*4882a593Smuzhiyun .hsync_len = 128,
33*4882a593Smuzhiyun .vsync_len = 2,
34*4882a593Smuzhiyun .sync = 0,
35*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* For the SHARP LQ084S3LG01, used on the P1022DS board */
39*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_800_600 = {
40*4882a593Smuzhiyun .name = "800x600-60",
41*4882a593Smuzhiyun .refresh = 60,
42*4882a593Smuzhiyun .xres = 800,
43*4882a593Smuzhiyun .yres = 600,
44*4882a593Smuzhiyun .pixclock = 25000,
45*4882a593Smuzhiyun .left_margin = 88,
46*4882a593Smuzhiyun .right_margin = 40,
47*4882a593Smuzhiyun .upper_margin = 23,
48*4882a593Smuzhiyun .lower_margin = 1,
49*4882a593Smuzhiyun .hsync_len = 128,
50*4882a593Smuzhiyun .vsync_len = 4,
51*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
52*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun * These parameters give default parameters
57*4882a593Smuzhiyun * for video output 1024x768,
58*4882a593Smuzhiyun * FIXME - change timing to proper amounts
59*4882a593Smuzhiyun * hsync 31.5kHz, vsync 60Hz
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_1024_768 = {
62*4882a593Smuzhiyun .name = "1024x768-60",
63*4882a593Smuzhiyun .refresh = 60,
64*4882a593Smuzhiyun .xres = 1024,
65*4882a593Smuzhiyun .yres = 768,
66*4882a593Smuzhiyun .pixclock = 15385,
67*4882a593Smuzhiyun .left_margin = 160,
68*4882a593Smuzhiyun .right_margin = 24,
69*4882a593Smuzhiyun .upper_margin = 29,
70*4882a593Smuzhiyun .lower_margin = 3,
71*4882a593Smuzhiyun .hsync_len = 136,
72*4882a593Smuzhiyun .vsync_len = 6,
73*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
74*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_1280_1024 = {
78*4882a593Smuzhiyun .name = "1280x1024-60",
79*4882a593Smuzhiyun .refresh = 60,
80*4882a593Smuzhiyun .xres = 1280,
81*4882a593Smuzhiyun .yres = 1024,
82*4882a593Smuzhiyun .pixclock = 9375,
83*4882a593Smuzhiyun .left_margin = 38,
84*4882a593Smuzhiyun .right_margin = 128,
85*4882a593Smuzhiyun .upper_margin = 2,
86*4882a593Smuzhiyun .lower_margin = 7,
87*4882a593Smuzhiyun .hsync_len = 216,
88*4882a593Smuzhiyun .vsync_len = 37,
89*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
90*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_1280_720 = {
94*4882a593Smuzhiyun .name = "1280x720-60",
95*4882a593Smuzhiyun .refresh = 60,
96*4882a593Smuzhiyun .xres = 1280,
97*4882a593Smuzhiyun .yres = 720,
98*4882a593Smuzhiyun .pixclock = 13426,
99*4882a593Smuzhiyun .left_margin = 192,
100*4882a593Smuzhiyun .right_margin = 64,
101*4882a593Smuzhiyun .upper_margin = 22,
102*4882a593Smuzhiyun .lower_margin = 1,
103*4882a593Smuzhiyun .hsync_len = 136,
104*4882a593Smuzhiyun .vsync_len = 3,
105*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
106*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
107*4882a593Smuzhiyun };
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun static struct fb_videomode fsl_diu_mode_1920_1080 = {
110*4882a593Smuzhiyun .name = "1920x1080-60",
111*4882a593Smuzhiyun .refresh = 60,
112*4882a593Smuzhiyun .xres = 1920,
113*4882a593Smuzhiyun .yres = 1080,
114*4882a593Smuzhiyun .pixclock = 5787,
115*4882a593Smuzhiyun .left_margin = 328,
116*4882a593Smuzhiyun .right_margin = 120,
117*4882a593Smuzhiyun .upper_margin = 34,
118*4882a593Smuzhiyun .lower_margin = 1,
119*4882a593Smuzhiyun .hsync_len = 208,
120*4882a593Smuzhiyun .vsync_len = 3,
121*4882a593Smuzhiyun .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
122*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * These are the fields of area descriptor(in DDR memory) for every plane
127*4882a593Smuzhiyun */
128*4882a593Smuzhiyun struct diu_ad {
129*4882a593Smuzhiyun /* Word 0(32-bit) in DDR memory */
130*4882a593Smuzhiyun __le32 pix_fmt; /* hard coding pixel format */
131*4882a593Smuzhiyun /* Word 1(32-bit) in DDR memory */
132*4882a593Smuzhiyun __le32 addr;
133*4882a593Smuzhiyun /* Word 2(32-bit) in DDR memory */
134*4882a593Smuzhiyun __le32 src_size_g_alpha;
135*4882a593Smuzhiyun /* Word 3(32-bit) in DDR memory */
136*4882a593Smuzhiyun __le32 aoi_size;
137*4882a593Smuzhiyun /* Word 4(32-bit) in DDR memory */
138*4882a593Smuzhiyun __le32 offset_xyi;
139*4882a593Smuzhiyun /* Word 5(32-bit) in DDR memory */
140*4882a593Smuzhiyun __le32 offset_xyd;
141*4882a593Smuzhiyun /* Word 6(32-bit) in DDR memory */
142*4882a593Smuzhiyun __le32 ckmax_r:8;
143*4882a593Smuzhiyun __le32 ckmax_g:8;
144*4882a593Smuzhiyun __le32 ckmax_b:8;
145*4882a593Smuzhiyun __le32 res9:8;
146*4882a593Smuzhiyun /* Word 7(32-bit) in DDR memory */
147*4882a593Smuzhiyun __le32 ckmin_r:8;
148*4882a593Smuzhiyun __le32 ckmin_g:8;
149*4882a593Smuzhiyun __le32 ckmin_b:8;
150*4882a593Smuzhiyun __le32 res10:8;
151*4882a593Smuzhiyun /* Word 8(32-bit) in DDR memory */
152*4882a593Smuzhiyun __le32 next_ad;
153*4882a593Smuzhiyun /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
154*4882a593Smuzhiyun __le32 res[3];
155*4882a593Smuzhiyun } __attribute__ ((packed));
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /*
158*4882a593Smuzhiyun * DIU register map
159*4882a593Smuzhiyun */
160*4882a593Smuzhiyun struct diu {
161*4882a593Smuzhiyun __be32 desc[3];
162*4882a593Smuzhiyun __be32 gamma;
163*4882a593Smuzhiyun __be32 pallete;
164*4882a593Smuzhiyun __be32 cursor;
165*4882a593Smuzhiyun __be32 curs_pos;
166*4882a593Smuzhiyun __be32 diu_mode;
167*4882a593Smuzhiyun __be32 bgnd;
168*4882a593Smuzhiyun __be32 bgnd_wb;
169*4882a593Smuzhiyun __be32 disp_size;
170*4882a593Smuzhiyun __be32 wb_size;
171*4882a593Smuzhiyun __be32 wb_mem_addr;
172*4882a593Smuzhiyun __be32 hsyn_para;
173*4882a593Smuzhiyun __be32 vsyn_para;
174*4882a593Smuzhiyun __be32 syn_pol;
175*4882a593Smuzhiyun __be32 thresholds;
176*4882a593Smuzhiyun __be32 int_status;
177*4882a593Smuzhiyun __be32 int_mask;
178*4882a593Smuzhiyun __be32 colorbar[8];
179*4882a593Smuzhiyun __be32 filling;
180*4882a593Smuzhiyun __be32 plut;
181*4882a593Smuzhiyun } __attribute__ ((packed));
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun struct diu_addr {
184*4882a593Smuzhiyun void *vaddr; /* Virtual address */
185*4882a593Smuzhiyun u32 paddr; /* 32-bit physical address */
186*4882a593Smuzhiyun unsigned int offset; /* Alignment offset */
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static struct fb_info info;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /*
192*4882a593Smuzhiyun * Align to 64-bit(8-byte), 32-byte, etc.
193*4882a593Smuzhiyun */
allocate_buf(struct diu_addr * buf,u32 size,u32 bytes_align)194*4882a593Smuzhiyun static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun u32 offset, ssize;
197*4882a593Smuzhiyun u32 mask;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun ssize = size + bytes_align;
200*4882a593Smuzhiyun buf->vaddr = malloc(ssize);
201*4882a593Smuzhiyun if (!buf->vaddr)
202*4882a593Smuzhiyun return -1;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun memset(buf->vaddr, 0, ssize);
205*4882a593Smuzhiyun mask = bytes_align - 1;
206*4882a593Smuzhiyun offset = (u32)buf->vaddr & mask;
207*4882a593Smuzhiyun if (offset) {
208*4882a593Smuzhiyun buf->offset = bytes_align - offset;
209*4882a593Smuzhiyun buf->vaddr += offset;
210*4882a593Smuzhiyun } else
211*4882a593Smuzhiyun buf->offset = 0;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun buf->paddr = virt_to_phys(buf->vaddr);
214*4882a593Smuzhiyun return 0;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /*
218*4882a593Smuzhiyun * Allocate a framebuffer and an Area Descriptor that points to it. Both
219*4882a593Smuzhiyun * are created in the same memory block. The Area Descriptor is updated to
220*4882a593Smuzhiyun * point to the framebuffer memory. Memory is aligned as needed.
221*4882a593Smuzhiyun */
allocate_fb(unsigned int xres,unsigned int yres,unsigned int depth,char ** fb)222*4882a593Smuzhiyun static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
223*4882a593Smuzhiyun unsigned int depth, char **fb)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun unsigned long size = xres * yres * depth;
226*4882a593Smuzhiyun struct diu_addr addr;
227*4882a593Smuzhiyun struct diu_ad *ad;
228*4882a593Smuzhiyun size_t ad_size = roundup(sizeof(struct diu_ad), 32);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /*
231*4882a593Smuzhiyun * Allocate a memory block that holds the Area Descriptor and the
232*4882a593Smuzhiyun * frame buffer right behind it. To keep the code simple, everything
233*4882a593Smuzhiyun * is aligned on a 32-byte address.
234*4882a593Smuzhiyun */
235*4882a593Smuzhiyun if (allocate_buf(&addr, ad_size + size, 32) < 0)
236*4882a593Smuzhiyun return NULL;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun ad = addr.vaddr;
239*4882a593Smuzhiyun ad->addr = cpu_to_le32(addr.paddr + ad_size);
240*4882a593Smuzhiyun ad->aoi_size = cpu_to_le32((yres << 16) | xres);
241*4882a593Smuzhiyun ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
242*4882a593Smuzhiyun ad->offset_xyi = 0;
243*4882a593Smuzhiyun ad->offset_xyd = 0;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (fb)
246*4882a593Smuzhiyun *fb = addr.vaddr + ad_size;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun return ad;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
fsl_diu_init(u16 xres,u16 yres,u32 pixel_format,int gamma_fix)251*4882a593Smuzhiyun int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun struct fb_videomode *fsl_diu_mode_db;
254*4882a593Smuzhiyun struct diu_ad *ad;
255*4882a593Smuzhiyun struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
256*4882a593Smuzhiyun u8 *gamma_table_base;
257*4882a593Smuzhiyun unsigned int i, j;
258*4882a593Smuzhiyun struct diu_addr gamma;
259*4882a593Smuzhiyun struct diu_addr cursor;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* Convert the X,Y resolution pair into a single number */
262*4882a593Smuzhiyun #define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun switch (RESOLUTION(xres, yres)) {
265*4882a593Smuzhiyun case RESOLUTION(800, 480):
266*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_800_480;
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun case RESOLUTION(800, 600):
269*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_800_600;
270*4882a593Smuzhiyun break;
271*4882a593Smuzhiyun case RESOLUTION(1024, 768):
272*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_1024_768;
273*4882a593Smuzhiyun break;
274*4882a593Smuzhiyun case RESOLUTION(1280, 1024):
275*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
276*4882a593Smuzhiyun break;
277*4882a593Smuzhiyun case RESOLUTION(1280, 720):
278*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_1280_720;
279*4882a593Smuzhiyun break;
280*4882a593Smuzhiyun case RESOLUTION(1920, 1080):
281*4882a593Smuzhiyun fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
282*4882a593Smuzhiyun break;
283*4882a593Smuzhiyun default:
284*4882a593Smuzhiyun printf("DIU: Unsupported resolution %ux%u\n", xres, yres);
285*4882a593Smuzhiyun return -1;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /* read mode info */
289*4882a593Smuzhiyun info.var.xres = fsl_diu_mode_db->xres;
290*4882a593Smuzhiyun info.var.yres = fsl_diu_mode_db->yres;
291*4882a593Smuzhiyun info.var.bits_per_pixel = 32;
292*4882a593Smuzhiyun info.var.pixclock = fsl_diu_mode_db->pixclock;
293*4882a593Smuzhiyun info.var.left_margin = fsl_diu_mode_db->left_margin;
294*4882a593Smuzhiyun info.var.right_margin = fsl_diu_mode_db->right_margin;
295*4882a593Smuzhiyun info.var.upper_margin = fsl_diu_mode_db->upper_margin;
296*4882a593Smuzhiyun info.var.lower_margin = fsl_diu_mode_db->lower_margin;
297*4882a593Smuzhiyun info.var.hsync_len = fsl_diu_mode_db->hsync_len;
298*4882a593Smuzhiyun info.var.vsync_len = fsl_diu_mode_db->vsync_len;
299*4882a593Smuzhiyun info.var.sync = fsl_diu_mode_db->sync;
300*4882a593Smuzhiyun info.var.vmode = fsl_diu_mode_db->vmode;
301*4882a593Smuzhiyun info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Memory allocation for framebuffer */
304*4882a593Smuzhiyun info.screen_size =
305*4882a593Smuzhiyun info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
306*4882a593Smuzhiyun ad = allocate_fb(info.var.xres, info.var.yres,
307*4882a593Smuzhiyun info.var.bits_per_pixel / 8, &info.screen_base);
308*4882a593Smuzhiyun if (!ad) {
309*4882a593Smuzhiyun printf("DIU: Out of memory\n");
310*4882a593Smuzhiyun return -1;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun ad->pix_fmt = pixel_format;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Disable chroma keying function */
316*4882a593Smuzhiyun ad->ckmax_r = 0;
317*4882a593Smuzhiyun ad->ckmax_g = 0;
318*4882a593Smuzhiyun ad->ckmax_b = 0;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun ad->ckmin_r = 255;
321*4882a593Smuzhiyun ad->ckmin_g = 255;
322*4882a593Smuzhiyun ad->ckmin_b = 255;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* Initialize the gamma table */
325*4882a593Smuzhiyun if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
326*4882a593Smuzhiyun printf("DIU: Out of memory\n");
327*4882a593Smuzhiyun return -1;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun gamma_table_base = gamma.vaddr;
330*4882a593Smuzhiyun for (i = 0; i <= 2; i++)
331*4882a593Smuzhiyun for (j = 0; j < 256; j++)
332*4882a593Smuzhiyun *gamma_table_base++ = j;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (gamma_fix == 1) { /* fix the gamma */
335*4882a593Smuzhiyun gamma_table_base = gamma.vaddr;
336*4882a593Smuzhiyun for (i = 0; i < 256 * 3; i++) {
337*4882a593Smuzhiyun gamma_table_base[i] = (gamma_table_base[i] << 2)
338*4882a593Smuzhiyun | ((gamma_table_base[i] >> 6) & 0x03);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Initialize the cursor */
343*4882a593Smuzhiyun if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
344*4882a593Smuzhiyun printf("DIU: Can't alloc cursor data\n");
345*4882a593Smuzhiyun return -1;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /* Program DIU registers */
349*4882a593Smuzhiyun out_be32(&hw->diu_mode, 0); /* Temporarily disable the DIU */
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun out_be32(&hw->gamma, gamma.paddr);
352*4882a593Smuzhiyun out_be32(&hw->cursor, cursor.paddr);
353*4882a593Smuzhiyun out_be32(&hw->bgnd, 0x007F7F7F);
354*4882a593Smuzhiyun out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
355*4882a593Smuzhiyun out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
356*4882a593Smuzhiyun info.var.hsync_len << 11 |
357*4882a593Smuzhiyun info.var.right_margin);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
360*4882a593Smuzhiyun info.var.vsync_len << 11 |
361*4882a593Smuzhiyun info.var.lower_margin);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* Pixel Clock configuration */
364*4882a593Smuzhiyun diu_set_pixel_clock(info.var.pixclock);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /* Set the frame buffers */
367*4882a593Smuzhiyun out_be32(&hw->desc[0], virt_to_phys(ad));
368*4882a593Smuzhiyun out_be32(&hw->desc[1], 0);
369*4882a593Smuzhiyun out_be32(&hw->desc[2], 0);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /* Enable the DIU, set display to all three planes */
372*4882a593Smuzhiyun out_be32(&hw->diu_mode, 1);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun return 0;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
video_hw_init(void)377*4882a593Smuzhiyun void *video_hw_init(void)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun static GraphicDevice ctfb;
380*4882a593Smuzhiyun const char *options;
381*4882a593Smuzhiyun unsigned int depth = 0, freq = 0;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
384*4882a593Smuzhiyun &options))
385*4882a593Smuzhiyun return NULL;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* Find the monitor port, which is a required option */
388*4882a593Smuzhiyun if (!options)
389*4882a593Smuzhiyun return NULL;
390*4882a593Smuzhiyun if (strncmp(options, "monitor=", 8) != 0)
391*4882a593Smuzhiyun return NULL;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
394*4882a593Smuzhiyun return NULL;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* fill in Graphic device struct */
397*4882a593Smuzhiyun sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
398*4882a593Smuzhiyun ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun ctfb.frameAdrs = (unsigned int)info.screen_base;
401*4882a593Smuzhiyun ctfb.plnSizeX = ctfb.winSizeX;
402*4882a593Smuzhiyun ctfb.plnSizeY = ctfb.winSizeY;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun ctfb.gdfBytesPP = 4;
405*4882a593Smuzhiyun ctfb.gdfIndex = GDF_32BIT_X888RGB;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun ctfb.isaBase = 0;
408*4882a593Smuzhiyun ctfb.pciBase = 0;
409*4882a593Smuzhiyun ctfb.memSize = info.screen_size;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun /* Cursor Start Address */
412*4882a593Smuzhiyun ctfb.dprBase = 0;
413*4882a593Smuzhiyun ctfb.vprBase = 0;
414*4882a593Smuzhiyun ctfb.cprBase = 0;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return &ctfb;
417*4882a593Smuzhiyun }
418