13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
17 #include <linux/slab.h>
23 #include <linux/list.h>
29 #include <asm/sizes.h>
31 #define to_clcd(info) container_of(info, struct clcd_fb, fb)
34 static const char *clcd_name =
"CLCD FB";
40 static inline void clcdfb_sleep(
unsigned int ms)
49 static inline void clcdfb_set_start(
struct clcd_fb *
fb)
51 unsigned long ustart = fb->
fb.fix.smem_start;
54 ustart += fb->
fb.var.yoffset * fb->
fb.fix.line_length;
55 lstart = ustart + fb->
fb.var.yres * fb->
fb.fix.line_length / 2;
61 static void clcdfb_disable(
struct clcd_fb *
fb)
65 if (fb->
board->disable)
66 fb->
board->disable(fb);
116 if (fb->
board->enable)
117 fb->
board->enable(fb);
142 var->
red.msb_right = 0;
143 var->
green.msb_right = 0;
144 var->
blue.msb_right = 0;
161 var->
green.offset = 0;
163 var->
blue.offset = 0;
188 if (caps & CLCD_CAP_565) {
189 var->
green.length = 6;
191 }
else if (caps & CLCD_CAP_5551) {
192 var->
green.length = 5;
195 var->
green.length = 4;
200 if (var->
green.length >= 5) {
202 var->
blue.length = 5;
205 var->
blue.length = 4;
217 var->
green.length = 8;
218 var->
blue.length = 8;
245 var->
blue.offset = 0;
250 var->
green.offset = var->
red.offset + var->
red.length;
263 if (fb->
board->check)
264 ret = fb->
board->check(fb, var);
272 ret = clcdfb_set_bitfields(fb, var);
277 static int clcdfb_set_par(
struct fb_info *info)
282 fb->
fb.fix.line_length = fb->
fb.var.xres_virtual *
283 fb->
fb.var.bits_per_pixel / 8;
285 if (fb->
fb.var.bits_per_pixel <= 8)
299 clcdfb_set_start(fb);
305 clcdfb_enable(fb,
regs.cntl);
309 "CLCD: Registers set to\n"
310 " %08x %08x %08x %08x\n"
311 " %08x %08x %08x %08x\n",
333 clcdfb_setcolreg(
unsigned int regno,
unsigned int red,
unsigned int green,
339 fb->
cmap[regno] = convert_bitfield(transp, &fb->
fb.var.transp) |
340 convert_bitfield(blue, &fb->
fb.var.blue) |
341 convert_bitfield(green, &fb->
fb.var.green) |
342 convert_bitfield(red, &fb->
fb.var.red);
348 newval = (red >> 11) & 0x001f;
349 newval |= (green >> 6) & 0x03e0;
350 newval |= (blue >> 1) & 0x7c00;
383 static int clcdfb_blank(
int blank_mode,
struct fb_info *info)
387 if (blank_mode != 0) {
395 static int clcdfb_mmap(
struct fb_info *info,
402 len = info->
fix.smem_len;
404 if (off <= len && vma->vm_end - vma->
vm_start <= len - off &&
406 ret = fb->
board->mmap(fb, vma);
411 static struct fb_ops clcdfb_ops = {
413 .fb_check_var = clcdfb_check_var,
414 .fb_set_par = clcdfb_set_par,
415 .fb_setcolreg = clcdfb_setcolreg,
416 .fb_blank = clcdfb_blank,
420 .fb_mmap = clcdfb_mmap,
423 static int clcdfb_register(
struct clcd_fb *fb)
435 #ifdef CONFIG_ARCH_VERSATILE
445 if (IS_ERR(fb->
clk)) {
446 ret = PTR_ERR(fb->
clk);
454 fb->
fb.device = &fb->
dev->dev;
456 fb->
fb.fix.mmio_start = fb->
dev->res.start;
457 fb->
fb.fix.mmio_len = resource_size(&fb->
dev->res);
466 fb->
fb.fbops = &clcdfb_ops;
468 fb->
fb.pseudo_palette = fb->
cmap;
470 strncpy(fb->
fb.fix.id, clcd_name,
sizeof(fb->
fb.fix.id));
472 fb->
fb.fix.type_aux = 0;
473 fb->
fb.fix.xpanstep = 0;
474 fb->
fb.fix.ypanstep = 0;
475 fb->
fb.fix.ywrapstep = 0;
478 fb->
fb.var.xres = fb->
panel->mode.xres;
479 fb->
fb.var.yres = fb->
panel->mode.yres;
480 fb->
fb.var.xres_virtual = fb->
panel->mode.xres;
481 fb->
fb.var.yres_virtual = fb->
panel->mode.yres;
482 fb->
fb.var.bits_per_pixel = fb->
panel->bpp;
483 fb->
fb.var.grayscale = fb->
panel->grayscale;
484 fb->
fb.var.pixclock = fb->
panel->mode.pixclock;
485 fb->
fb.var.left_margin = fb->
panel->mode.left_margin;
486 fb->
fb.var.right_margin = fb->
panel->mode.right_margin;
487 fb->
fb.var.upper_margin = fb->
panel->mode.upper_margin;
488 fb->
fb.var.lower_margin = fb->
panel->mode.lower_margin;
489 fb->
fb.var.hsync_len = fb->
panel->mode.hsync_len;
490 fb->
fb.var.vsync_len = fb->
panel->mode.vsync_len;
491 fb->
fb.var.sync = fb->
panel->mode.sync;
492 fb->
fb.var.vmode = fb->
panel->mode.vmode;
494 fb->
fb.var.nonstd = 0;
495 fb->
fb.var.height = fb->
panel->height;
496 fb->
fb.var.width = fb->
panel->width;
497 fb->
fb.var.accel_flags = 0;
499 fb->
fb.monspecs.hfmin = 0;
500 fb->
fb.monspecs.hfmax = 100000;
501 fb->
fb.monspecs.vfmin = 0;
502 fb->
fb.monspecs.vfmax = 400;
503 fb->
fb.monspecs.dclkmin = 1000000;
504 fb->
fb.monspecs.dclkmax = 100000000;
509 clcdfb_set_bitfields(fb, &fb->
fb.var);
525 dev_info(&fb->
dev->dev,
"%s hardware, %s display\n",
570 dev_info(&fb->
dev->dev,
"PL%03x rev%u at 0x%08llx\n",
572 (
unsigned long long)dev->
res.start);
574 ret = fb->
board->setup(fb);
578 ret = clcdfb_register(fb);
584 fb->
board->remove(fb);
607 fb->
board->remove(fb);
616 static struct amba_id clcdfb_id_table[] = {
628 .name =
"clcd-pl11x",
630 .probe = clcdfb_probe,
631 .remove = clcdfb_remove,
632 .id_table = clcdfb_id_table,
635 static int __init amba_clcdfb_init(
void)
645 static void __exit amba_clcdfb_exit(
void)