11 #include <linux/kernel.h>
21 #include <linux/module.h>
23 #include <mach/board.h>
29 #define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
30 #define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
33 #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
34 #define ATMEL_LCDC_DMA_BURST_LEN 8
35 #define ATMEL_LCDC_FIFO_SIZE 512
37 #if defined(CONFIG_ARCH_AT91)
38 #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
39 | FBINFO_PARTIAL_PAN_OK \
40 | FBINFO_HWACCEL_YPAN)
48 #elif defined(CONFIG_AVR32)
49 #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
50 | FBINFO_PARTIAL_PAN_OK \
51 | FBINFO_HWACCEL_XPAN \
52 | FBINFO_HWACCEL_YPAN)
61 pixeloff = (var->
xoffset * info->
var.bits_per_pixel) & 0x1f;
63 dma2dcfg = (info->
var.xres_virtual - info->
var.xres)
64 * info->
var.bits_per_pixel / 8;
79 #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
85 int power = sinfo->bl_power;
92 if (bl->
props.fb_blank != sinfo->bl_power)
93 power = bl->
props.fb_blank;
94 else if (bl->
props.power != sinfo->bl_power)
95 power = bl->
props.power;
105 brightness ? contrast_ctr : 0);
109 bl->
props.fb_blank = bl->
props.power = sinfo->bl_power = power;
123 .get_brightness = atmel_bl_get_brightness,
133 if (sinfo->backlight)
138 props.max_brightness = 0xff;
140 &atmel_lcdc_bl_ops, &
props);
142 dev_err(&sinfo->
pdev->dev,
"error %ld on backlight register\n",
146 sinfo->backlight =
bl;
150 bl->
props.brightness = atmel_bl_get_brightness(bl);
155 if (sinfo->backlight)
163 dev_warn(&sinfo->
pdev->dev,
"backlight control is not available\n");
183 init_backlight(sinfo);
196 static unsigned long compute_hozval(
unsigned long xres,
unsigned long lcdcon2)
236 atmel_lcdfb_stop_nowait(sinfo);
251 static void atmel_lcdfb_update_dma(
struct fb_info *info,
259 + var->
xoffset * info->
var.bits_per_pixel / 8);
266 atmel_lcdfb_update_dma2d(sinfo, var, info);
269 static inline void atmel_lcdfb_free_video_memory(
struct atmel_lcdfb_info *sinfo)
288 unsigned int smem_len;
348 unsigned long clk_value_khz;
352 dev_dbg(dev,
"%s:\n", __func__);
356 if (!atmel_lcdfb_choose_mode(var, info)) {
357 dev_err(dev,
"needed value not specified\n");
365 dev_dbg(dev,
" clk: %lu KHz\n", clk_value_khz);
383 var->
red.msb_right = var->
green.msb_right = var->
blue.msb_right = 0;
384 var->
transp.msb_right = 0;
388 if (info->
fix.smem_len) {
391 if (smem_len > info->
fix.smem_len)
420 var->
red.offset = var->
green.offset = var->
blue.offset = 0;
427 var->
red.offset = 11;
428 var->
blue.offset = 0;
432 var->
blue.offset = 11;
434 var->
green.offset = 5;
435 var->
green.length = 6;
436 var->
red.length = var->
blue.length = 5;
445 var->
red.offset = 16;
446 var->
blue.offset = 0;
450 var->
blue.offset = 16;
452 var->
green.offset = 8;
453 var->
red.length = var->
green.length = var->
blue.length = 8;
456 dev_err(dev,
"color depth %d not supported\n",
471 atmel_lcdfb_stop(sinfo);
472 atmel_lcdfb_start(sinfo);
489 static int atmel_lcdfb_set_par(
struct fb_info *info)
492 unsigned long hozval_linesz;
494 unsigned long clk_value_khz;
495 unsigned long bits_per_line;
496 unsigned long pix_factor = 2;
501 dev_dbg(info->
device,
" * resolution: %ux%u (%ux%u virtual)\n",
502 info->
var.xres, info->
var.yres,
503 info->
var.xres_virtual, info->
var.yres_virtual);
505 atmel_lcdfb_stop_nowait(sinfo);
507 if (info->
var.bits_per_pixel == 1)
509 else if (info->
var.bits_per_pixel <= 8)
514 bits_per_line = info->
var.xres_virtual * info->
var.bits_per_pixel;
519 atmel_lcdfb_update_dma(info, &info->
var);
522 value = (info->
var.yres * info->
var.xres * info->
var.bits_per_pixel) / 32;
536 if (value < pix_factor) {
537 dev_notice(info->
device,
"Bypassing pixel clock divider\n");
540 value = (value / pix_factor) - 1;
546 KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
560 switch (info->
var.bits_per_pixel) {
569 default:
BUG();
break;
577 value |= info->
var.lower_margin;
584 value |= (info->
var.left_margin - 1);
589 hozval_linesz = compute_hozval(info->
var.xres,
594 value |= info->
var.yres - 1;
614 atmel_lcdfb_start(sinfo);
621 static inline unsigned int chan_to_field(
unsigned int chan,
const struct fb_bitfield *
bf)
625 return chan << bf->
offset;
653 static int atmel_lcdfb_setcolreg(
unsigned int regno,
unsigned int red,
662 if (info->
var.grayscale)
663 red = green = blue = (19595 * red + 38470 * green
664 + 7471 *
blue) >> 16;
666 switch (info->
fix.visual) {
671 val = chan_to_field(red, &info->
var.red);
672 val |= chan_to_field(green, &info->
var.green);
673 val |= chan_to_field(blue, &info->
var.blue);
685 val = ((red >> 11) & 0x001f);
686 val |= ((green >> 6) & 0x03e0);
687 val |= ((blue >> 1) & 0x7c00);
697 val = ((blue >> 11) & 0x001f);
698 val |= ((red >> 0) & 0xf800);
700 val = ((red >> 11) & 0x001f);
701 val |= ((blue >> 0) & 0xf800);
704 val |= ((green >> 5) & 0x07e0);
714 val = (regno == 0) ? 0x00 : 0x1F;
730 atmel_lcdfb_update_dma(info, var);
735 static int atmel_lcdfb_blank(
int blank_mode,
struct fb_info *info)
739 switch (blank_mode) {
742 atmel_lcdfb_start(sinfo);
748 atmel_lcdfb_stop(sinfo);
758 static struct fb_ops atmel_lcdfb_ops = {
760 .fb_check_var = atmel_lcdfb_check_var,
761 .fb_set_par = atmel_lcdfb_set_par,
762 .fb_setcolreg = atmel_lcdfb_setcolreg,
763 .fb_blank = atmel_lcdfb_blank,
764 .fb_pan_display = atmel_lcdfb_pan_display,
794 atmel_lcdfb_reset(sinfo);
805 "%luKiB frame buffer at %08lx (mapped at %p)\n",
806 (
unsigned long)info->
fix.smem_len / 1024,
807 (
unsigned long)info->
fix.smem_start,
844 dev_dbg(dev,
"%s BEGIN\n", __func__);
849 dev_err(dev,
"cannot allocate memory\n");
868 dev_err(dev,
"cannot get default configuration\n");
875 info->
flags = ATMEL_LCDFB_FBINFO_DEFAULT;
877 info->
fbops = &atmel_lcdfb_ops;
880 info->
fix = atmel_lcdfb_fix;
896 atmel_lcdfb_start_clock(sinfo);
902 dev_err(dev,
"no suitable video mode found\n");
909 dev_err(dev,
"resources unusable\n");
916 dev_err(dev,
"unable to get irq\n");
926 info->
fix.smem_len = resource_size(map);
928 info->
fix.smem_len, pdev->
name)) {
945 ret = atmel_lcdfb_alloc_video_memory(sinfo);
947 dev_err(dev,
"cannot allocate framebuffer: %d\n", ret);
954 info->
fix.mmio_len = resource_size(regs);
957 info->
fix.mmio_len, pdev->
name)) {
964 dev_err(dev,
"cannot map LCDC registers\n");
970 init_contrast(sinfo);
975 dev_err(dev,
"request_irq failed: %d\n", ret);
983 ret = atmel_lcdfb_init_fbinfo(sinfo);
985 dev_err(dev,
"init fbinfo failed: %d\n", ret);
986 goto unregister_irqs;
993 atmel_lcdfb_check_var(&info->
var, info);
997 dev_warn(dev,
"unable to set display parameters\n");
1008 dev_err(dev,
"failed to register framebuffer device: %d\n", ret);
1020 dev_info(dev,
"fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
1033 exit_backlight(sinfo);
1041 atmel_lcdfb_free_video_memory(sinfo);
1047 atmel_lcdfb_stop_clock(sinfo);
1055 dev_dbg(dev,
"%s FAILED\n", __func__);
1065 if (!info || !info->
par)
1070 exit_backlight(sinfo);
1074 atmel_lcdfb_stop_clock(sinfo);
1086 atmel_lcdfb_free_video_memory(sinfo);
1099 struct fb_info *info = platform_get_drvdata(pdev);
1113 atmel_lcdfb_stop(sinfo);
1114 atmel_lcdfb_stop_clock(sinfo);
1121 struct fb_info *info = platform_get_drvdata(pdev);
1124 atmel_lcdfb_start_clock(sinfo);
1125 atmel_lcdfb_start(sinfo);
1138 #define atmel_lcdfb_suspend NULL
1139 #define atmel_lcdfb_resume NULL
1143 .remove =
__exit_p(atmel_lcdfb_remove),
1148 .name =
"atmel_lcdfb",
1153 static int __init atmel_lcdfb_init(
void)
1158 static void __exit atmel_lcdfb_exit(
void)