18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
23 #include <linux/slab.h>
31 #include <linux/wait.h>
45 #define to_vt8500lcd_info(__info) container_of(__info, \
46 struct vt8500lcd_info, fb)
53 unsigned long control0;
58 if (info->
var.bits_per_pixel <= 8) {
60 info->
var.red.offset = 0;
61 info->
var.red.length = info->
var.bits_per_pixel;
62 info->
var.red.msb_right = 0;
64 info->
var.green.offset = 0;
65 info->
var.green.length = info->
var.bits_per_pixel;
66 info->
var.green.msb_right = 0;
68 info->
var.blue.offset = 0;
69 info->
var.blue.length = info->
var.bits_per_pixel;
70 info->
var.blue.msb_right = 0;
72 info->
var.transp.offset = 0;
73 info->
var.transp.length = 0;
74 info->
var.transp.msb_right = 0;
77 info->
fix.line_length = info->
var.xres_virtual /
78 (8/info->
var.bits_per_pixel);
81 info->
var.transp.offset = 0;
82 info->
var.transp.length = 0;
83 info->
var.transp.msb_right = 0;
85 if (info->
var.bits_per_pixel == 16) {
87 info->
var.red.offset = 11;
88 info->
var.red.length = 5;
89 info->
var.red.msb_right = 0;
90 info->
var.green.offset = 5;
91 info->
var.green.length = 6;
92 info->
var.green.msb_right = 0;
93 info->
var.blue.offset = 0;
94 info->
var.blue.length = 5;
95 info->
var.blue.msb_right = 0;
98 info->
var.red.offset = info->
var.bits_per_pixel
100 info->
var.red.length = info->
var.bits_per_pixel / 3;
101 info->
var.red.msb_right = 0;
102 info->
var.green.offset = info->
var.bits_per_pixel / 3;
103 info->
var.green.length = info->
var.bits_per_pixel / 3;
104 info->
var.green.msb_right = 0;
105 info->
var.blue.offset = 0;
106 info->
var.blue.length = info->
var.bits_per_pixel / 3;
107 info->
var.blue.msb_right = 0;
111 info->
fix.line_length = info->
var.bits_per_pixel > 16 ?
112 info->
var.xres_virtual << 2 :
113 info->
var.xres_virtual << 1;
116 for (i = 0; i < 8; i++) {
117 if (bpp_values[i] == info->
var.bits_per_pixel) {
127 writel((((info->
var.hsync_len - 1) & 0x3f) << 26)
128 | ((info->
var.left_margin & 0xff) << 18)
129 | (((info->
var.xres - 1) & 0x3ff) << 8)
130 | (info->
var.right_margin & 0xff), fbi->
regbase + 0x4);
131 writel((((info->
var.vsync_len - 1) & 0x3f) << 26)
132 | ((info->
var.upper_margin & 0xff) << 18)
133 | (((info->
var.yres - 1) & 0x3ff) << 8)
134 | (info->
var.lower_margin & 0xff), fbi->
regbase + 0x8);
135 writel((((info->
var.yres - 1) & 0x400) << 2)
136 | ((info->
var.xres - 1) & 0x400), fbi->
regbase + 0x10);
147 return chan << bf->
offset;
150 static int vt8500lcd_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
159 if (info->
var.grayscale)
161 (19595 * red + 38470 * green + 7471 *
blue) >> 16;
163 switch (fbi->
fb.fix.visual) {
168 val = chan_to_field(red, &fbi->
fb.var.red);
169 val |= chan_to_field(green, &fbi->
fb.var.green);
170 val |= chan_to_field(blue, &fbi->
fb.var.blue);
180 | ((green >> 5) & 0x7e0)
181 | ((blue >> 11) & 0x1f),
189 static int vt8500lcd_ioctl(
struct fb_info *info,
unsigned int cmd,
214 unsigned pixlen = info->
fix.line_length / info->
var.xres_virtual;
215 unsigned off = pixlen * var->
xoffset
220 | (((info->
var.xres_virtual - info->
var.xres) * pixlen / 4) << 20)
221 | (off >> 2), fbi->
regbase + 0x20);
231 static int vt8500lcd_blank(
int blank,
struct fb_info *info)
242 for (i = 0; i < 256; i++)
243 vt8500lcd_setcolreg(i, 0, 0, 0, 0, info);
252 static struct fb_ops vt8500lcd_ops = {
254 .fb_set_par = vt8500lcd_set_par,
255 .fb_setcolreg = vt8500lcd_setcolreg,
260 .fb_ioctl = vt8500lcd_ioctl,
261 .fb_pan_display = vt8500lcd_pan_display,
262 .fb_blank = vt8500lcd_blank,
287 unsigned long fb_mem_len;
296 dev_err(&pdev->
dev,
"Failed to initialize framebuffer device\n");
301 strcpy(fbi->
fb.fix.id,
"VT8500 LCD");
304 fbi->
fb.fix.xpanstep = 0;
305 fbi->
fb.fix.ypanstep = 1;
306 fbi->
fb.fix.ywrapstep = 0;
309 fbi->
fb.var.nonstd = 0;
311 fbi->
fb.var.height = -1;
312 fbi->
fb.var.width = -1;
315 fbi->
fb.fbops = &vt8500lcd_ops;
326 fbi->
fb.pseudo_palette =
addr;
330 dev_err(&pdev->
dev,
"no I/O memory resource defined\n");
337 dev_err(&pdev->
dev,
"failed to request I/O memory\n");
344 dev_err(&pdev->
dev,
"failed to map I/O memory\n");
346 goto failed_free_res;
351 pr_err(
"%s: No display description in Device Tree\n", __func__);
353 goto failed_free_res;
361 ret |= of_property_read_u32(np,
"hactive", &of_mode.xres);
362 ret |= of_property_read_u32(np,
"vactive", &of_mode.yres);
363 ret |= of_property_read_u32(np,
"hback-porch", &of_mode.left_margin);
364 ret |= of_property_read_u32(np,
"hfront-porch", &of_mode.right_margin);
365 ret |= of_property_read_u32(np,
"hsync-len", &of_mode.hsync_len);
366 ret |= of_property_read_u32(np,
"vback-porch", &of_mode.upper_margin);
367 ret |= of_property_read_u32(np,
"vfront-porch", &of_mode.lower_margin);
368 ret |= of_property_read_u32(np,
"vsync-len", &of_mode.vsync_len);
369 ret |= of_property_read_u32(np,
"bpp", &bpp);
371 pr_err(
"%s: Unable to read display properties\n", __func__);
372 goto failed_free_res;
377 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
381 pr_err(
"%s: Failed to allocate framebuffer\n", __func__);
385 fbi->
fb.fix.smem_start = fb_mem_phys;
386 fbi->
fb.fix.smem_len = fb_mem_len;
387 fbi->
fb.screen_base = fb_mem_virt;
395 dev_err(&pdev->
dev,
"Failed to allocate palette buffer\n");
404 goto failed_free_palette;
407 ret =
request_irq(irq, vt8500lcd_handle_irq, 0,
"LCD", fbi);
409 dev_err(&pdev->
dev,
"request_irq failed: %d\n", ret);
411 goto failed_free_palette;
417 dev_err(&pdev->
dev,
"Failed to allocate color map\n");
419 goto failed_free_irq;
424 fbi->
fb.var.xres_virtual = of_mode.xres;
425 fbi->
fb.var.yres_virtual = of_mode.yres * 2;
426 fbi->
fb.var.bits_per_pixel =
bpp;
428 ret = vt8500lcd_set_par(&fbi->
fb);
430 dev_err(&pdev->
dev,
"Failed to set parameters\n");
431 goto failed_free_cmap;
437 platform_set_drvdata(pdev, fbi);
442 "Failed to register framebuffer device: %d\n", ret);
443 goto failed_free_cmap;
454 if (fbi->
fb.cmap.len)
466 platform_set_drvdata(pdev,
NULL);
482 if (fbi->
fb.cmap.len)
502 { .compatible =
"via,vt8500-fb", },
507 .probe = vt8500lcd_probe,
511 .name =
"vt8500-lcd",