14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/module.h>
17 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/slab.h>
33 #include <asm/div64.h>
36 #include <mach/regs-lcd.h>
37 #include <mach/regs-gpio.h>
47 #ifdef CONFIG_FB_S3C2410_DEBUG
53 #define dprintk(msg...) \
70 static void s3c2410fb_set_lcdaddr(
struct fb_info *
info)
72 unsigned long saddr1, saddr2, saddr3;
76 saddr1 = info->
fix.smem_start >> 1;
77 saddr2 = info->
fix.smem_start;
78 saddr2 += info->
fix.line_length * info->
var.yres;
84 dprintk(
"LCDSADDR1 = 0x%08lx\n", saddr1);
85 dprintk(
"LCDSADDR2 = 0x%08lx\n", saddr2);
86 dprintk(
"LCDSADDR3 = 0x%08lx\n", saddr3);
97 static unsigned int s3c2410fb_calc_pixclk(
struct s3c2410fb_info *fbi,
101 unsigned long long div;
108 div = (
unsigned long long)clk * pixclk;
112 dprintk(
"pixclk %ld, divisor is %ld\n", pixclk, (
long)div);
133 dprintk(
"check_var(var=%p, info=%p)\n", var, info);
137 if (var->
yres == default_display->
yres &&
138 var->
xres == default_display->
xres &&
140 display = default_display;
143 if (type == mach_info->
displays[i].type &&
152 dprintk(
"wrong resolution or depth %dx%d at %d bpp\n",
193 var->
green.length = 3;
194 var->
green.offset = 2;
195 var->
blue.length = 2;
196 var->
blue.offset = 0;
208 var->
green.length = 4;
209 var->
green.offset = 4;
210 var->
blue.length = 4;
211 var->
blue.offset = 0;
218 var->
red.offset = 11;
219 var->
green.offset = 5;
220 var->
blue.offset = 0;
222 var->
green.length = 6;
223 var->
blue.length = 5;
226 var->
red.offset = 11;
227 var->
green.offset = 6;
228 var->
blue.offset = 1;
230 var->
green.length = 5;
231 var->
blue.length = 5;
237 var->
red.offset = 16;
238 var->
green.length = 8;
239 var->
green.offset = 8;
240 var->
blue.length = 8;
241 var->
blue.offset = 0;
251 static void s3c2410fb_calculate_stn_lcd_regs(
const struct fb_info *info,
257 int hs = var->
xres >> 2;
259 unsigned wlh = (var->
hsync_len >> 4) - 1;
289 dprintk(
"setting horz: lft=%d, rt=%d, sync=%d\n",
311 static void s3c2410fb_calculate_tft_lcd_regs(
const struct fb_info *info,
350 dprintk(
"setting vert: up=%d, low=%d, sync=%d\n",
353 dprintk(
"setting horz: lft=%d, rt=%d, sync=%d\n",
373 static void s3c2410fb_activate_var(
struct fb_info *info)
383 dprintk(
"%s: var->xres = %d\n", __func__, var->
xres);
384 dprintk(
"%s: var->yres = %d\n", __func__, var->
yres);
388 s3c2410fb_calculate_tft_lcd_regs(info, &fbi->
regs);
393 s3c2410fb_calculate_stn_lcd_regs(info, &fbi->
regs);
402 dprintk(
"new register set:\n");
403 dprintk(
"lcdcon[1] = 0x%08lx\n", fbi->
regs.lcdcon1);
404 dprintk(
"lcdcon[2] = 0x%08lx\n", fbi->
regs.lcdcon2);
405 dprintk(
"lcdcon[3] = 0x%08lx\n", fbi->
regs.lcdcon3);
406 dprintk(
"lcdcon[4] = 0x%08lx\n", fbi->
regs.lcdcon4);
407 dprintk(
"lcdcon[5] = 0x%08lx\n", fbi->
regs.lcdcon5);
417 s3c2410fb_set_lcdaddr(info);
428 static int s3c2410fb_set_par(
struct fb_info *info)
450 s3c2410fb_activate_var(info);
455 unsigned int regno,
unsigned int val)
478 static inline unsigned int chan_to_field(
unsigned int chan,
483 return chan << bf->
offset;
486 static int s3c2410fb_setcolreg(
unsigned regno,
497 switch (info->
fix.visual) {
504 val = chan_to_field(red, &info->
var.red);
505 val |= chan_to_field(green, &info->
var.green);
506 val |= chan_to_field(blue, &info->
var.blue);
516 val = (red >> 0) & 0xf800;
517 val |= (green >> 5) & 0x07e0;
518 val |= (blue >> 11) & 0x001f;
521 schedule_palette_update(fbi, regno, val);
567 static int s3c2410fb_blank(
int blank_mode,
struct fb_info *info)
572 dprintk(
"blank(mode=%d, info=%p)\n", blank_mode, info);
577 s3c2410fb_lcd_enable(fbi, 0);
579 s3c2410fb_lcd_enable(fbi, 1);
584 dprintk(
"setting TPAL to output 0x000000\n");
591 static int s3c2410fb_debug_show(
struct device *
dev,
597 static int s3c2410fb_debug_store(
struct device *
dev,
599 const char *
buf,
size_t len)
607 dev_dbg(dev,
"s3c2410fb: Debug On");
608 }
else if (
strnicmp(buf,
"off", 3) == 0 ||
611 dev_dbg(dev,
"s3c2410fb: Debug Off");
619 static DEVICE_ATTR(
debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store);
621 static struct fb_ops s3c2410fb_ops = {
623 .fb_check_var = s3c2410fb_check_var,
624 .fb_set_par = s3c2410fb_set_par,
625 .fb_blank = s3c2410fb_blank,
626 .fb_setcolreg = s3c2410fb_setcolreg,
646 dprintk(
"map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
653 dprintk(
"map_video_memory: clear %p:%08x\n",
657 info->
fix.smem_start = map_dma;
659 dprintk(
"map_video_memory: dma=%08lx cpu=%p size=%08x\n",
666 static inline void s3c2410fb_unmap_video_memory(
struct fb_info *info)
674 static inline void modify_gpio(
void __iomem *
reg,
675 unsigned long set,
unsigned long mask)
679 tmp =
readl(reg) & ~mask;
686 static int s3c2410fb_init_registers(
struct fb_info *info)
695 if (is_s3c2412(fbi)) {
734 for (i = 0; i < 256; i++) {
761 s3c2410fb_write_palette(fbi);
770 #ifdef CONFIG_CPU_FREQ
772 static int s3c2410fb_cpufreq_transition(
struct notifier_block *nb,
773 unsigned long val,
void *
data)
788 s3c2410fb_activate_var(fbinfo);
794 static inline int s3c2410fb_cpufreq_register(
struct s3c2410fb_info *info)
796 info->freq_transition.notifier_call = s3c2410fb_cpufreq_transition;
802 static inline void s3c2410fb_cpufreq_deregister(
struct s3c2410fb_info *info)
809 static inline int s3c2410fb_cpufreq_register(
struct s3c2410fb_info *info)
814 static inline void s3c2410fb_cpufreq_deregister(
struct s3c2410fb_info *info)
836 mach_info = pdev->
dev.platform_data;
837 if (mach_info ==
NULL) {
839 "no platform data for lcd, cannot attach\n");
844 dev_err(&pdev->
dev,
"default is %d but only %d displays\n",
861 platform_set_drvdata(pdev, fbinfo);
869 dev_err(&pdev->
dev,
"failed to get memory registers\n");
874 size = resource_size(res);
877 dev_err(&pdev->
dev,
"failed to get memory region\n");
884 dev_err(&pdev->
dev,
"ioremap() of registers failed\n");
903 fbinfo->
fix.type_aux = 0;
904 fbinfo->
fix.xpanstep = 0;
905 fbinfo->
fix.ypanstep = 0;
906 fbinfo->
fix.ywrapstep = 0;
909 fbinfo->
var.nonstd = 0;
911 fbinfo->
var.accel_flags = 0;
914 fbinfo->
fbops = &s3c2410fb_ops;
918 for (i = 0; i < 256; i++)
923 dev_err(&pdev->
dev,
"cannot get irq %d - err %d\n", irq, ret);
929 if (IS_ERR(info->
clk)) {
930 dev_err(&pdev->
dev,
"failed to get lcd clock source\n");
931 ret = PTR_ERR(info->
clk);
936 dprintk(
"got and enabled clock\n");
944 unsigned long smem_len = mach_info->
displays[
i].xres;
949 if (fbinfo->
fix.smem_len < smem_len)
950 fbinfo->
fix.smem_len = smem_len;
954 ret = s3c2410fb_map_video_memory(fbinfo);
956 dev_err(&pdev->
dev,
"Failed to allocate video RAM: %d\n", ret);
963 fbinfo->
var.xres = display->
xres;
964 fbinfo->
var.yres = display->
yres;
965 fbinfo->
var.bits_per_pixel = display->
bpp;
967 s3c2410fb_init_registers(fbinfo);
969 s3c2410fb_check_var(&fbinfo->
var, fbinfo);
971 ret = s3c2410fb_cpufreq_register(info);
973 dev_err(&pdev->
dev,
"Failed to register cpufreq\n");
974 goto free_video_memory;
979 dev_err(&pdev->
dev,
"Failed to register framebuffer device: %d\n",
987 dev_err(&pdev->
dev,
"failed to add debug attribute\n");
989 dev_info(&pdev->
dev,
"fb%d: %s frame buffer device\n",
995 s3c2410fb_cpufreq_deregister(info);
997 s3c2410fb_unmap_video_memory(fbinfo);
1008 platform_set_drvdata(pdev,
NULL);
1029 struct fb_info *fbinfo = platform_get_drvdata(pdev);
1034 s3c2410fb_cpufreq_deregister(info);
1036 s3c2410fb_lcd_enable(info, 0);
1039 s3c2410fb_unmap_video_memory(fbinfo);
1054 platform_set_drvdata(pdev,
NULL);
1065 struct fb_info *fbinfo = platform_get_drvdata(dev);
1068 s3c2410fb_lcd_enable(info, 0);
1082 struct fb_info *fbinfo = platform_get_drvdata(dev);
1088 s3c2410fb_init_registers(fbinfo);
1091 s3c2410fb_activate_var(fbinfo);
1098 #define s3c2410fb_suspend NULL
1099 #define s3c2410fb_resume NULL
1103 .probe = s3c2410fb_probe,
1108 .name =
"s3c2410-lcd",
1114 .probe = s3c2412fb_probe,
1119 .name =
"s3c2412-lcd",
1134 static void __exit s3c2410fb_cleanup(
void)