aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-08-13 19:59:15 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-08-13 19:59:15 -0400
commit7d72e6fa56c4100b9669efe0044f77ed9eb785a1 (patch)
tree5e90bf4969809a1ab20b97432b85be20ccfaa1f4 /drivers/video
parentba00376b0b13f234d839541a7b36a5bf5c2a4036 (diff)
parent2be1f3a73dd02e38e181cf5abacb3d45a6a2d6b8 (diff)
Merge branch 'master' into for-linus
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig17
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/bw2.c4
-rw-r--r--drivers/video/cg14.c6
-rw-r--r--drivers/video/cg3.c4
-rw-r--r--drivers/video/cg6.c6
-rw-r--r--drivers/video/console/bitblit.c2
-rw-r--r--drivers/video/console/fbcon.c2
-rw-r--r--drivers/video/console/fbcon_ccw.c2
-rw-r--r--drivers/video/console/fbcon_cw.c2
-rw-r--r--drivers/video/console/fbcon_ud.c2
-rw-r--r--drivers/video/efifb.c8
-rw-r--r--drivers/video/fbmem.c6
-rw-r--r--drivers/video/ffb.c4
-rw-r--r--drivers/video/fsl-diu-fb.c8
-rw-r--r--drivers/video/igafb.c5
-rw-r--r--drivers/video/imxfb.c19
-rw-r--r--drivers/video/leo.c6
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c2
-rw-r--r--drivers/video/mb862xx/mb862xxfb.c4
-rw-r--r--drivers/video/msm/mddi.c4
-rw-r--r--drivers/video/msm/mdp.c1
-rw-r--r--drivers/video/p9100.c4
-rw-r--r--drivers/video/platinumfb.c4
-rw-r--r--drivers/video/s3c-fb.c811
-rw-r--r--drivers/video/sh_mipi_dsi.c505
-rw-r--r--drivers/video/sh_mobile_hdmi.c1028
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c196
-rw-r--r--drivers/video/sunxvr1000.c4
-rw-r--r--drivers/video/tcx.c6
-rw-r--r--drivers/video/uvesafb.c7
-rw-r--r--drivers/video/vt8623fb.c2
-rw-r--r--drivers/video/xilinxfb.c4
33 files changed, 2510 insertions, 177 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a9ca72f301bf..8b31fdfefc98 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1896,6 +1896,13 @@ config FB_W100
1896 1896
1897 If unsure, say N. 1897 If unsure, say N.
1898 1898
1899config SH_MIPI_DSI
1900 tristate
1901 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
1902
1903config SH_LCD_MIPI_DSI
1904 bool
1905
1899config FB_SH_MOBILE_LCDC 1906config FB_SH_MOBILE_LCDC
1900 tristate "SuperH Mobile LCDC framebuffer support" 1907 tristate "SuperH Mobile LCDC framebuffer support"
1901 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK 1908 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
@@ -1904,9 +1911,17 @@ config FB_SH_MOBILE_LCDC
1904 select FB_SYS_IMAGEBLIT 1911 select FB_SYS_IMAGEBLIT
1905 select FB_SYS_FOPS 1912 select FB_SYS_FOPS
1906 select FB_DEFERRED_IO 1913 select FB_DEFERRED_IO
1914 select SH_MIPI_DSI if SH_LCD_MIPI_DSI
1907 ---help--- 1915 ---help---
1908 Frame buffer driver for the on-chip SH-Mobile LCD controller. 1916 Frame buffer driver for the on-chip SH-Mobile LCD controller.
1909 1917
1918config FB_SH_MOBILE_HDMI
1919 tristate "SuperH Mobile HDMI controller support"
1920 depends on FB_SH_MOBILE_LCDC
1921 select FB_MODE_HELPERS
1922 ---help---
1923 Driver for the on-chip SH-Mobile HDMI controller.
1924
1910config FB_TMIO 1925config FB_TMIO
1911 tristate "Toshiba Mobile IO FrameBuffer support" 1926 tristate "Toshiba Mobile IO FrameBuffer support"
1912 depends on FB && MFD_CORE 1927 depends on FB && MFD_CORE
@@ -1931,7 +1946,7 @@ config FB_TMIO_ACCELL
1931 1946
1932config FB_S3C 1947config FB_S3C
1933 tristate "Samsung S3C framebuffer support" 1948 tristate "Samsung S3C framebuffer support"
1934 depends on FB && ARCH_S3C64XX 1949 depends on FB && S3C_DEV_FB
1935 select FB_CFB_FILLRECT 1950 select FB_CFB_FILLRECT
1936 select FB_CFB_COPYAREA 1951 select FB_CFB_COPYAREA
1937 select FB_CFB_IMAGEBLIT 1952 select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index f56a9cae2157..485e8ed1318c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
123obj-$(CONFIG_FB_PS3) += ps3fb.o 123obj-$(CONFIG_FB_PS3) += ps3fb.o
124obj-$(CONFIG_FB_SM501) += sm501fb.o 124obj-$(CONFIG_FB_SM501) += sm501fb.o
125obj-$(CONFIG_FB_XILINX) += xilinxfb.o 125obj-$(CONFIG_FB_XILINX) += xilinxfb.o
126obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
127obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
126obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o 128obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
127obj-$(CONFIG_FB_OMAP) += omap/ 129obj-$(CONFIG_FB_OMAP) += omap/
128obj-y += omap2/ 130obj-y += omap2/
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index c7796637bafd..4dc13467281d 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
273 return 0; 273 return 0;
274} 274}
275 275
276static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) 276static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match)
277{ 277{
278 struct device_node *dp = op->dev.of_node; 278 struct device_node *dp = op->dev.of_node;
279 struct fb_info *info; 279 struct fb_info *info;
@@ -350,7 +350,7 @@ out_err:
350 return err; 350 return err;
351} 351}
352 352
353static int __devexit bw2_remove(struct of_device *op) 353static int __devexit bw2_remove(struct platform_device *op)
354{ 354{
355 struct fb_info *info = dev_get_drvdata(&op->dev); 355 struct fb_info *info = dev_get_drvdata(&op->dev);
356 struct bw2_par *par = info->par; 356 struct bw2_par *par = info->par;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index d09fde8beb69..24249535ac86 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
446 { .size = 0 } 446 { .size = 0 }
447}; 447};
448 448
449static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, 449static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
450 struct cg14_par *par) 450 struct cg14_par *par)
451{ 451{
452 if (par->regs) 452 if (par->regs)
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
463 info->screen_base, info->fix.smem_len); 463 info->screen_base, info->fix.smem_len);
464} 464}
465 465
466static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) 466static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match)
467{ 467{
468 struct device_node *dp = op->dev.of_node; 468 struct device_node *dp = op->dev.of_node;
469 struct fb_info *info; 469 struct fb_info *info;
@@ -570,7 +570,7 @@ out_err:
570 return err; 570 return err;
571} 571}
572 572
573static int __devexit cg14_remove(struct of_device *op) 573static int __devexit cg14_remove(struct platform_device *op)
574{ 574{
575 struct fb_info *info = dev_get_drvdata(&op->dev); 575 struct fb_info *info = dev_get_drvdata(&op->dev);
576 struct cg14_par *par = info->par; 576 struct cg14_par *par = info->par;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 64aa29809fb9..09c0c3c42482 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
346 return 0; 346 return 0;
347} 347}
348 348
349static int __devinit cg3_probe(struct of_device *op, 349static int __devinit cg3_probe(struct platform_device *op,
350 const struct of_device_id *match) 350 const struct of_device_id *match)
351{ 351{
352 struct device_node *dp = op->dev.of_node; 352 struct device_node *dp = op->dev.of_node;
@@ -433,7 +433,7 @@ out_err:
433 return err; 433 return err;
434} 434}
435 435
436static int __devexit cg3_remove(struct of_device *op) 436static int __devexit cg3_remove(struct platform_device *op)
437{ 437{
438 struct fb_info *info = dev_get_drvdata(&op->dev); 438 struct fb_info *info = dev_get_drvdata(&op->dev);
439 struct cg3_par *par = info->par; 439 struct cg3_par *par = info->par;
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 2389a719dcc7..2b5a97058b08 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info)
718 sbus_writel(info->var.yres - 1, &fbc->clipmaxy); 718 sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
719} 719}
720 720
721static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, 721static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
722 struct cg6_par *par) 722 struct cg6_par *par)
723{ 723{
724 if (par->fbc) 724 if (par->fbc)
@@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
737 info->fix.smem_len); 737 info->fix.smem_len);
738} 738}
739 739
740static int __devinit cg6_probe(struct of_device *op, 740static int __devinit cg6_probe(struct platform_device *op,
741 const struct of_device_id *match) 741 const struct of_device_id *match)
742{ 742{
743 struct device_node *dp = op->dev.of_node; 743 struct device_node *dp = op->dev.of_node;
@@ -827,7 +827,7 @@ out_err:
827 return err; 827 return err;
828} 828}
829 829
830static int __devexit cg6_remove(struct of_device *op) 830static int __devexit cg6_remove(struct platform_device *op)
831{ 831{
832 struct fb_info *info = dev_get_drvdata(&op->dev); 832 struct fb_info *info = dev_get_drvdata(&op->dev);
833 struct cg6_par *par = info->par; 833 struct cg6_par *par = info->par;
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index af88651b0735..28b1a834906b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -22,7 +22,7 @@
22/* 22/*
23 * Accelerated handlers. 23 * Accelerated handlers.
24 */ 24 */
25static inline void update_attr(u8 *dst, u8 *src, int attribute, 25static void update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 26bf7cbfecc2..84f842331dfa 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -287,7 +287,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
287 !vt_force_oops_output(vc); 287 !vt_force_oops_output(vc);
288} 288}
289 289
290static inline int get_color(struct vc_data *vc, struct fb_info *info, 290static int get_color(struct vc_data *vc, struct fb_info *info,
291 u16 c, int is_fg) 291 u16 c, int is_fg)
292{ 292{
293 int depth = fb_get_color_depth(&info->var, &info->fix); 293 int depth = fb_get_color_depth(&info->var, &info->fix);
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index d135671d9961..41b32ae23dac 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -22,7 +22,7 @@
22 * Rotation 270 degrees 22 * Rotation 270 degrees
23 */ 23 */
24 24
25static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, 25static void ccw_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 126110f8454f..6a737827beb1 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -22,7 +22,7 @@
22 * Rotation 90 degrees 22 * Rotation 90 degrees
23 */ 23 */
24 24
25static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, 25static void cw_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 93a3e7381b50..ff0872c0498b 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -22,7 +22,7 @@
22 * Rotation 180 degrees 22 * Rotation 180 degrees
23 */ 23 */
24 24
25static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, 25static void ud_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 4a56f46af40a..815f84b07933 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -16,7 +16,7 @@
16 16
17#include <video/vga.h> 17#include <video/vga.h>
18 18
19static struct fb_var_screeninfo efifb_defined __initdata = { 19static struct fb_var_screeninfo efifb_defined __devinitdata = {
20 .activate = FB_ACTIVATE_NOW, 20 .activate = FB_ACTIVATE_NOW,
21 .height = -1, 21 .height = -1,
22 .width = -1, 22 .width = -1,
@@ -27,7 +27,7 @@ static struct fb_var_screeninfo efifb_defined __initdata = {
27 .vmode = FB_VMODE_NONINTERLACED, 27 .vmode = FB_VMODE_NONINTERLACED,
28}; 28};
29 29
30static struct fb_fix_screeninfo efifb_fix __initdata = { 30static struct fb_fix_screeninfo efifb_fix __devinitdata = {
31 .id = "EFI VGA", 31 .id = "EFI VGA",
32 .type = FB_TYPE_PACKED_PIXELS, 32 .type = FB_TYPE_PACKED_PIXELS,
33 .accel = FB_ACCEL_NONE, 33 .accel = FB_ACCEL_NONE,
@@ -59,7 +59,7 @@ static struct efifb_dmi_info {
59 int stride; 59 int stride;
60 int width; 60 int width;
61 int height; 61 int height;
62} dmi_list[] = { 62} dmi_list[] __initdata = {
63 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, 63 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
64 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ 64 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
65 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, 65 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
@@ -83,7 +83,7 @@ static int set_system(const struct dmi_system_id *id);
83 DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ 83 DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
84 &dmi_list[enumid] } 84 &dmi_list[enumid] }
85 85
86static struct dmi_system_id __initdata dmi_system_table[] = { 86static const struct dmi_system_id dmi_system_table[] __initconst = {
87 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), 87 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
88 /* At least one of these two will be right; maybe both? */ 88 /* At least one of these two will be right; maybe both? */
89 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), 89 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 731fce64df9d..b06647517c0e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1362,6 +1362,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1362 vma->vm_pgoff = off >> PAGE_SHIFT; 1362 vma->vm_pgoff = off >> PAGE_SHIFT;
1363 /* This is an IO map - tell maydump to skip this VMA */ 1363 /* This is an IO map - tell maydump to skip this VMA */
1364 vma->vm_flags |= VM_IO | VM_RESERVED; 1364 vma->vm_flags |= VM_IO | VM_RESERVED;
1365 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
1365 fb_pgprotect(file, vma, off); 1366 fb_pgprotect(file, vma, off);
1366 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1367 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1367 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1368 vma->vm_end - vma->vm_start, vma->vm_page_prot))
@@ -1786,7 +1787,7 @@ static int ofonly __read_mostly;
1786int fb_get_options(char *name, char **option) 1787int fb_get_options(char *name, char **option)
1787{ 1788{
1788 char *opt, *options = NULL; 1789 char *opt, *options = NULL;
1789 int opt_len, retval = 0; 1790 int retval = 0;
1790 int name_len = strlen(name), i; 1791 int name_len = strlen(name), i;
1791 1792
1792 if (name_len && ofonly && strncmp(name, "offb", 4)) 1793 if (name_len && ofonly && strncmp(name, "offb", 4))
@@ -1796,8 +1797,7 @@ int fb_get_options(char *name, char **option)
1796 for (i = 0; i < FB_MAX; i++) { 1797 for (i = 0; i < FB_MAX; i++) {
1797 if (video_options[i] == NULL) 1798 if (video_options[i] == NULL)
1798 continue; 1799 continue;
1799 opt_len = strlen(video_options[i]); 1800 if (!video_options[i][0])
1800 if (!opt_len)
1801 continue; 1801 continue;
1802 opt = video_options[i]; 1802 opt = video_options[i];
1803 if (!strncmp(name, opt, name_len) && 1803 if (!strncmp(name, opt, name_len) &&
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index f6ecfab296d3..6739b2af3bc0 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
893 info->fix.accel = FB_ACCEL_SUN_CREATOR; 893 info->fix.accel = FB_ACCEL_SUN_CREATOR;
894} 894}
895 895
896static int __devinit ffb_probe(struct of_device *op, 896static int __devinit ffb_probe(struct platform_device *op,
897 const struct of_device_id *match) 897 const struct of_device_id *match)
898{ 898{
899 struct device_node *dp = op->dev.of_node; 899 struct device_node *dp = op->dev.of_node;
@@ -1023,7 +1023,7 @@ out_err:
1023 return err; 1023 return err;
1024} 1024}
1025 1025
1026static int __devexit ffb_remove(struct of_device *op) 1026static int __devexit ffb_remove(struct platform_device *op)
1027{ 1027{
1028 struct fb_info *info = dev_get_drvdata(&op->dev); 1028 struct fb_info *info = dev_get_drvdata(&op->dev);
1029 struct ffb_par *par = info->par; 1029 struct ffb_par *par = info->par;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index e38ad2224540..8bbbf08fa3ce 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1393,7 +1393,7 @@ static void free_irq_local(int irq)
1393 * Power management hooks. Note that we won't be called from IRQ context, 1393 * Power management hooks. Note that we won't be called from IRQ context,
1394 * unlike the blank functions above, so we may sleep. 1394 * unlike the blank functions above, so we may sleep.
1395 */ 1395 */
1396static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) 1396static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
1397{ 1397{
1398 struct fsl_diu_data *machine_data; 1398 struct fsl_diu_data *machine_data;
1399 1399
@@ -1403,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state)
1403 return 0; 1403 return 0;
1404} 1404}
1405 1405
1406static int fsl_diu_resume(struct of_device *ofdev) 1406static int fsl_diu_resume(struct platform_device *ofdev)
1407{ 1407{
1408 struct fsl_diu_data *machine_data; 1408 struct fsl_diu_data *machine_data;
1409 1409
@@ -1487,7 +1487,7 @@ static ssize_t show_monitor(struct device *device,
1487 return diu_ops.show_monitor_port(machine_data->monitor_port, buf); 1487 return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
1488} 1488}
1489 1489
1490static int __devinit fsl_diu_probe(struct of_device *ofdev, 1490static int __devinit fsl_diu_probe(struct platform_device *ofdev,
1491 const struct of_device_id *match) 1491 const struct of_device_id *match)
1492{ 1492{
1493 struct device_node *np = ofdev->dev.of_node; 1493 struct device_node *np = ofdev->dev.of_node;
@@ -1667,7 +1667,7 @@ error2:
1667} 1667}
1668 1668
1669 1669
1670static int fsl_diu_remove(struct of_device *ofdev) 1670static int fsl_diu_remove(struct platform_device *ofdev)
1671{ 1671{
1672 struct fsl_diu_data *machine_data; 1672 struct fsl_diu_data *machine_data;
1673 int i; 1673 int i;
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 15d200109446..d885c770eb84 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -368,7 +368,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
368 return 1; 368 return 1;
369} 369}
370 370
371int __init igafb_init(void) 371static int __init igafb_init(void)
372{ 372{
373 struct fb_info *info; 373 struct fb_info *info;
374 struct pci_dev *pdev; 374 struct pci_dev *pdev;
@@ -531,6 +531,7 @@ int __init igafb_init(void)
531 iounmap(info->screen_base); 531 iounmap(info->screen_base);
532 kfree(par->mmap_map); 532 kfree(par->mmap_map);
533 kfree(info); 533 kfree(info);
534 return -ENODEV;
534 } 535 }
535 536
536#ifdef CONFIG_SPARC 537#ifdef CONFIG_SPARC
@@ -556,7 +557,7 @@ int __init igafb_init(void)
556 return 0; 557 return 0;
557} 558}
558 559
559int __init igafb_setup(char *options) 560static int __init igafb_setup(char *options)
560{ 561{
561 char *this_opt; 562 char *this_opt;
562 563
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 43f0639b1c10..5c363d026f64 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -40,6 +40,12 @@
40 */ 40 */
41#define DEBUG_VAR 1 41#define DEBUG_VAR 1
42 42
43#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
44 (defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \
45 defined(CONFIG_FB_IMX_MODULE))
46#define PWMR_BACKLIGHT_AVAILABLE
47#endif
48
43#define DRIVER_NAME "imx-fb" 49#define DRIVER_NAME "imx-fb"
44 50
45#define LCDC_SSA 0x00 51#define LCDC_SSA 0x00
@@ -175,7 +181,9 @@ struct imxfb_info {
175 181
176 struct imx_fb_videomode *mode; 182 struct imx_fb_videomode *mode;
177 int num_modes; 183 int num_modes;
184#ifdef PWMR_BACKLIGHT_AVAILABLE
178 struct backlight_device *bl; 185 struct backlight_device *bl;
186#endif
179 187
180 void (*lcd_power)(int); 188 void (*lcd_power)(int);
181 void (*backlight_power)(int); 189 void (*backlight_power)(int);
@@ -450,8 +458,7 @@ static int imxfb_set_par(struct fb_info *info)
450 return 0; 458 return 0;
451} 459}
452 460
453 461#ifdef PWMR_BACKLIGHT_AVAILABLE
454
455static int imxfb_bl_get_brightness(struct backlight_device *bl) 462static int imxfb_bl_get_brightness(struct backlight_device *bl)
456{ 463{
457 struct imxfb_info *fbi = bl_get_data(bl); 464 struct imxfb_info *fbi = bl_get_data(bl);
@@ -516,6 +523,7 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
516 if (fbi->bl) 523 if (fbi->bl)
517 backlight_device_unregister(fbi->bl); 524 backlight_device_unregister(fbi->bl);
518} 525}
526#endif
519 527
520static void imxfb_enable_controller(struct imxfb_info *fbi) 528static void imxfb_enable_controller(struct imxfb_info *fbi)
521{ 529{
@@ -647,6 +655,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
647 fbi->regs + LCDC_SIZE); 655 fbi->regs + LCDC_SIZE);
648 656
649 writel(fbi->pcr, fbi->regs + LCDC_PCR); 657 writel(fbi->pcr, fbi->regs + LCDC_PCR);
658#ifndef PWMR_BACKLIGHT_AVAILABLE
659 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
660#endif
650 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 661 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
651 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 662 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
652 663
@@ -847,7 +858,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
847 858
848 imxfb_enable_controller(fbi); 859 imxfb_enable_controller(fbi);
849 fbi->pdev = pdev; 860 fbi->pdev = pdev;
861#ifdef PWMR_BACKLIGHT_AVAILABLE
850 imxfb_init_backlight(fbi); 862 imxfb_init_backlight(fbi);
863#endif
851 864
852 return 0; 865 return 0;
853 866
@@ -885,7 +898,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
885 898
886 imxfb_disable_controller(fbi); 899 imxfb_disable_controller(fbi);
887 900
901#ifdef PWMR_BACKLIGHT_AVAILABLE
888 imxfb_exit_backlight(fbi); 902 imxfb_exit_backlight(fbi);
903#endif
889 unregister_framebuffer(info); 904 unregister_framebuffer(info);
890 905
891 pdata = pdev->dev.platform_data; 906 pdata = pdev->dev.platform_data;
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index ad677637ffbb..b599e5e36ced 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
529 var->transp.length = 0; 529 var->transp.length = 0;
530} 530}
531 531
532static void leo_unmap_regs(struct of_device *op, struct fb_info *info, 532static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
533 struct leo_par *par) 533 struct leo_par *par)
534{ 534{
535 if (par->lc_ss0_usr) 535 if (par->lc_ss0_usr)
@@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
547 of_iounmap(&op->resource[0], info->screen_base, 0x800000); 547 of_iounmap(&op->resource[0], info->screen_base, 0x800000);
548} 548}
549 549
550static int __devinit leo_probe(struct of_device *op, 550static int __devinit leo_probe(struct platform_device *op,
551 const struct of_device_id *match) 551 const struct of_device_id *match)
552{ 552{
553 struct device_node *dp = op->dev.of_node; 553 struct device_node *dp = op->dev.of_node;
@@ -637,7 +637,7 @@ out_err:
637 return err; 637 return err;
638} 638}
639 639
640static int __devexit leo_remove(struct of_device *op) 640static int __devexit leo_remove(struct platform_device *op)
641{ 641{
642 struct fb_info *info = dev_get_drvdata(&op->dev); 642 struct fb_info *info = dev_get_drvdata(&op->dev);
643 struct leo_par *par = info->par; 643 struct leo_par *par = info->par;
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 403b14445a78..0fb280ead3dc 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -191,7 +191,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
191 }; 191 };
192 192
193 i2c_new_probed_device(&m2info->maven.adapter, 193 i2c_new_probed_device(&m2info->maven.adapter,
194 &maven_info, addr_list); 194 &maven_info, addr_list, NULL);
195 } 195 }
196 } 196 }
197 return m2info; 197 return m2info;
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index 4e2b8cc3d460..b1c4374cf940 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
550 return 0; 550 return 0;
551} 551}
552 552
553static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, 553static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev,
554 const struct of_device_id *id) 554 const struct of_device_id *id)
555{ 555{
556 struct device_node *np = ofdev->dev.of_node; 556 struct device_node *np = ofdev->dev.of_node;
@@ -669,7 +669,7 @@ fbrel:
669 return ret; 669 return ret;
670} 670}
671 671
672static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) 672static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
673{ 673{
674 struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); 674 struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
675 struct mb862xxfb_par *par = fbi->par; 675 struct mb862xxfb_par *par = fbi->par;
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index c1ff271017a9..7c316c34dfca 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -187,10 +187,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
187 187
188static void mddi_handle_rev_data_avail(struct mddi_info *mddi) 188static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
189{ 189{
190 union mddi_rev *rev = mddi->rev_data;
191 uint32_t rev_data_count; 190 uint32_t rev_data_count;
192 uint32_t rev_crc_err_count; 191 uint32_t rev_crc_err_count;
193 int i;
194 struct reg_read_info *ri; 192 struct reg_read_info *ri;
195 size_t prev_offset; 193 size_t prev_offset;
196 uint16_t length; 194 uint16_t length;
@@ -670,7 +668,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
670 return 0; 668 return 0;
671} 669}
672 670
673static int __init mddi_probe(struct platform_device *pdev) 671static int __devinit mddi_probe(struct platform_device *pdev)
674{ 672{
675 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data; 673 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
676 struct mddi_info *mddi = &mddi_info[pdev->id]; 674 struct mddi_info *mddi = &mddi_info[pdev->id];
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 19c01c6208e8..3c28db03ad39 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -258,7 +258,6 @@ int get_img(struct mdp_img *img, struct fb_info *info,
258{ 258{
259 int put_needed, ret = 0; 259 int put_needed, ret = 0;
260 struct file *file; 260 struct file *file;
261 unsigned long vstart;
262 261
263 file = fget_light(img->memory_id, &put_needed); 262 file = fget_light(img->memory_id, &put_needed);
264 if (file == NULL) 263 if (file == NULL)
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 688b055abab2..b6c3fc2db632 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
249 info->fix.accel = FB_ACCEL_SUN_CGTHREE; 249 info->fix.accel = FB_ACCEL_SUN_CGTHREE;
250} 250}
251 251
252static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) 252static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match)
253{ 253{
254 struct device_node *dp = op->dev.of_node; 254 struct device_node *dp = op->dev.of_node;
255 struct fb_info *info; 255 struct fb_info *info;
@@ -326,7 +326,7 @@ out_err:
326 return err; 326 return err;
327} 327}
328 328
329static int __devexit p9100_remove(struct of_device *op) 329static int __devexit p9100_remove(struct platform_device *op)
330{ 330{
331 struct fb_info *info = dev_get_drvdata(&op->dev); 331 struct fb_info *info = dev_get_drvdata(&op->dev);
332 struct p9100_par *par = info->par; 332 struct p9100_par *par = info->par;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 72a1f4c04732..a50e1977b316 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options)
533#define invalidate_cache(addr) 533#define invalidate_cache(addr)
534#endif 534#endif
535 535
536static int __devinit platinumfb_probe(struct of_device* odev, 536static int __devinit platinumfb_probe(struct platform_device* odev,
537 const struct of_device_id *match) 537 const struct of_device_id *match)
538{ 538{
539 struct device_node *dp = odev->dev.of_node; 539 struct device_node *dp = odev->dev.of_node;
@@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev,
646 return rc; 646 return rc;
647} 647}
648 648
649static int __devexit platinumfb_remove(struct of_device* odev) 649static int __devexit platinumfb_remove(struct platform_device* odev)
650{ 650{
651 struct fb_info *info = dev_get_drvdata(&odev->dev); 651 struct fb_info *info = dev_get_drvdata(&odev->dev);
652 struct fb_info_platinum *pinfo = info->par; 652 struct fb_info_platinum *pinfo = info->par;
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 9682ecc60e12..f9aca9d13d1b 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1,7 +1,7 @@
1/* linux/drivers/video/s3c-fb.c 1/* linux/drivers/video/s3c-fb.c
2 * 2 *
3 * Copyright 2008 Openmoko Inc. 3 * Copyright 2008 Openmoko Inc.
4 * Copyright 2008 Simtec Electronics 4 * Copyright 2008-2010 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk> 5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/ 6 * http://armlinux.simtec.co.uk/
7 * 7 *
@@ -9,7 +9,7 @@
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software FoundatIon.
13*/ 13*/
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
@@ -21,9 +21,11 @@
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/fb.h> 22#include <linux/fb.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/uaccess.h>
25#include <linux/interrupt.h>
24 26
25#include <mach/map.h> 27#include <mach/map.h>
26#include <mach/regs-fb.h> 28#include <plat/regs-fb-v4.h>
27#include <plat/fb.h> 29#include <plat/fb.h>
28 30
29/* This driver will export a number of framebuffer interfaces depending 31/* This driver will export a number of framebuffer interfaces depending
@@ -36,9 +38,9 @@
36 * output timings and as the control for the output power-down state. 38 * output timings and as the control for the output power-down state.
37*/ 39*/
38 40
39/* note, some of the functions that get called are derived from including 41/* note, the previous use of <mach/regs-fb.h> to get platform specific data
40 * <mach/regs-fb.h> as they are specific to the architecture that the code 42 * has been replaced by using the platform device name to pick the correct
41 * is being built for. 43 * configuration data for the system.
42*/ 44*/
43 45
44#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE 46#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
@@ -48,13 +50,108 @@
48 __raw_writel(v, r); } while(0) 50 __raw_writel(v, r); } while(0)
49#endif /* FB_S3C_DEBUG_REGWRITE */ 51#endif /* FB_S3C_DEBUG_REGWRITE */
50 52
53/* irq_flags bits */
54#define S3C_FB_VSYNC_IRQ_EN 0
55
56#define VSYNC_TIMEOUT_MSEC 50
57
51struct s3c_fb; 58struct s3c_fb;
52 59
60#define VALID_BPP(x) (1 << ((x) - 1))
61
62#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
63#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
64#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
65#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
66#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
67
68/**
69 * struct s3c_fb_variant - fb variant information
70 * @is_2443: Set if S3C2443/S3C2416 style hardware.
71 * @nr_windows: The number of windows.
72 * @vidtcon: The base for the VIDTCONx registers
73 * @wincon: The base for the WINxCON registers.
74 * @winmap: The base for the WINxMAP registers.
75 * @keycon: The abse for the WxKEYCON registers.
76 * @buf_start: Offset of buffer start registers.
77 * @buf_size: Offset of buffer size registers.
78 * @buf_end: Offset of buffer end registers.
79 * @osd: The base for the OSD registers.
80 * @palette: Address of palette memory, or 0 if none.
81 * @has_prtcon: Set if has PRTCON register.
82 * @has_shadowcon: Set if has SHADOWCON register.
83 */
84struct s3c_fb_variant {
85 unsigned int is_2443:1;
86 unsigned short nr_windows;
87 unsigned short vidtcon;
88 unsigned short wincon;
89 unsigned short winmap;
90 unsigned short keycon;
91 unsigned short buf_start;
92 unsigned short buf_end;
93 unsigned short buf_size;
94 unsigned short osd;
95 unsigned short osd_stride;
96 unsigned short palette[S3C_FB_MAX_WIN];
97
98 unsigned int has_prtcon:1;
99 unsigned int has_shadowcon:1;
100};
101
102/**
103 * struct s3c_fb_win_variant
104 * @has_osd_c: Set if has OSD C register.
105 * @has_osd_d: Set if has OSD D register.
106 * @has_osd_alpha: Set if can change alpha transparency for a window.
107 * @palette_sz: Size of palette in entries.
108 * @palette_16bpp: Set if palette is 16bits wide.
109 * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
110 * register is located at the given offset from OSD_BASE.
111 * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
112 *
113 * valid_bpp bit x is set if (x+1)BPP is supported.
114 */
115struct s3c_fb_win_variant {
116 unsigned int has_osd_c:1;
117 unsigned int has_osd_d:1;
118 unsigned int has_osd_alpha:1;
119 unsigned int palette_16bpp:1;
120 unsigned short osd_size_off;
121 unsigned short palette_sz;
122 u32 valid_bpp;
123};
124
125/**
126 * struct s3c_fb_driverdata - per-device type driver data for init time.
127 * @variant: The variant information for this driver.
128 * @win: The window information for each window.
129 */
130struct s3c_fb_driverdata {
131 struct s3c_fb_variant variant;
132 struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
133};
134
135/**
136 * struct s3c_fb_palette - palette information
137 * @r: Red bitfield.
138 * @g: Green bitfield.
139 * @b: Blue bitfield.
140 * @a: Alpha bitfield.
141 */
142struct s3c_fb_palette {
143 struct fb_bitfield r;
144 struct fb_bitfield g;
145 struct fb_bitfield b;
146 struct fb_bitfield a;
147};
148
53/** 149/**
54 * struct s3c_fb_win - per window private data for each framebuffer. 150 * struct s3c_fb_win - per window private data for each framebuffer.
55 * @windata: The platform data supplied for the window configuration. 151 * @windata: The platform data supplied for the window configuration.
56 * @parent: The hardware that this window is part of. 152 * @parent: The hardware that this window is part of.
57 * @fbinfo: Pointer pack to the framebuffer info for this window. 153 * @fbinfo: Pointer pack to the framebuffer info for this window.
154 * @varint: The variant information for this window.
58 * @palette_buffer: Buffer/cache to hold palette entries. 155 * @palette_buffer: Buffer/cache to hold palette entries.
59 * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ 156 * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
60 * @index: The window number of this window. 157 * @index: The window number of this window.
@@ -65,6 +162,7 @@ struct s3c_fb_win {
65 struct s3c_fb *parent; 162 struct s3c_fb *parent;
66 struct fb_info *fbinfo; 163 struct fb_info *fbinfo;
67 struct s3c_fb_palette palette; 164 struct s3c_fb_palette palette;
165 struct s3c_fb_win_variant variant;
68 166
69 u32 *palette_buffer; 167 u32 *palette_buffer;
70 u32 pseudo_palette[16]; 168 u32 pseudo_palette[16];
@@ -72,37 +170,54 @@ struct s3c_fb_win {
72}; 170};
73 171
74/** 172/**
173 * struct s3c_fb_vsync - vsync information
174 * @wait: a queue for processes waiting for vsync
175 * @count: vsync interrupt count
176 */
177struct s3c_fb_vsync {
178 wait_queue_head_t wait;
179 unsigned int count;
180};
181
182/**
75 * struct s3c_fb - overall hardware state of the hardware 183 * struct s3c_fb - overall hardware state of the hardware
76 * @dev: The device that we bound to, for printing, etc. 184 * @dev: The device that we bound to, for printing, etc.
77 * @regs_res: The resource we claimed for the IO registers. 185 * @regs_res: The resource we claimed for the IO registers.
78 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 186 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
79 * @regs: The mapped hardware registers. 187 * @regs: The mapped hardware registers.
188 * @variant: Variant information for this hardware.
80 * @enabled: A bitmask of enabled hardware windows. 189 * @enabled: A bitmask of enabled hardware windows.
81 * @pdata: The platform configuration data passed with the device. 190 * @pdata: The platform configuration data passed with the device.
82 * @windows: The hardware windows that have been claimed. 191 * @windows: The hardware windows that have been claimed.
192 * @irq_no: IRQ line number
193 * @irq_flags: irq flags
194 * @vsync_info: VSYNC-related information (count, queues...)
83 */ 195 */
84struct s3c_fb { 196struct s3c_fb {
85 struct device *dev; 197 struct device *dev;
86 struct resource *regs_res; 198 struct resource *regs_res;
87 struct clk *bus_clk; 199 struct clk *bus_clk;
88 void __iomem *regs; 200 void __iomem *regs;
201 struct s3c_fb_variant variant;
89 202
90 unsigned char enabled; 203 unsigned char enabled;
91 204
92 struct s3c_fb_platdata *pdata; 205 struct s3c_fb_platdata *pdata;
93 struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; 206 struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
207
208 int irq_no;
209 unsigned long irq_flags;
210 struct s3c_fb_vsync vsync_info;
94}; 211};
95 212
96/** 213/**
97 * s3c_fb_win_has_palette() - determine if a mode has a palette 214 * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
98 * @win: The window number being queried. 215 * @win: The device window.
99 * @bpp: The number of bits per pixel to test. 216 * @bpp: The bit depth.
100 *
101 * Work out if the given window supports palletised data at the specified bpp.
102 */ 217 */
103static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp) 218static bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
104{ 219{
105 return s3c_fb_win_pal_size(win) <= (1 << bpp); 220 return win->variant.valid_bpp & VALID_BPP(bpp);
106} 221}
107 222
108/** 223/**
@@ -125,7 +240,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
125 var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); 240 var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres);
126 var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); 241 var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres);
127 242
128 if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) { 243 if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
129 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", 244 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
130 win->index, var->bits_per_pixel); 245 win->index, var->bits_per_pixel);
131 return -EINVAL; 246 return -EINVAL;
@@ -140,7 +255,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
140 case 2: 255 case 2:
141 case 4: 256 case 4:
142 case 8: 257 case 8:
143 if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) { 258 if (sfb->variant.palette[win->index] != 0) {
144 /* non palletised, A:1,R:2,G:3,B:2 mode */ 259 /* non palletised, A:1,R:2,G:3,B:2 mode */
145 var->red.offset = 4; 260 var->red.offset = 4;
146 var->green.offset = 2; 261 var->green.offset = 2;
@@ -255,6 +370,66 @@ static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
255} 370}
256 371
257/** 372/**
373 * vidosd_set_size() - set OSD size for a window
374 *
375 * @win: the window to set OSD size for
376 * @size: OSD size register value
377 */
378static void vidosd_set_size(struct s3c_fb_win *win, u32 size)
379{
380 struct s3c_fb *sfb = win->parent;
381
382 /* OSD can be set up if osd_size_off != 0 for this window */
383 if (win->variant.osd_size_off)
384 writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
385 + win->variant.osd_size_off);
386}
387
388/**
389 * vidosd_set_alpha() - set alpha transparency for a window
390 *
391 * @win: the window to set OSD size for
392 * @alpha: alpha register value
393 */
394static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
395{
396 struct s3c_fb *sfb = win->parent;
397
398 if (win->variant.has_osd_alpha)
399 writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
400}
401
402/**
403 * shadow_protect_win() - disable updating values from shadow registers at vsync
404 *
405 * @win: window to protect registers for
406 * @protect: 1 to protect (disable updates)
407 */
408static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
409{
410 struct s3c_fb *sfb = win->parent;
411 u32 reg;
412
413 if (protect) {
414 if (sfb->variant.has_prtcon) {
415 writel(PRTCON_PROTECT, sfb->regs + PRTCON);
416 } else if (sfb->variant.has_shadowcon) {
417 reg = readl(sfb->regs + SHADOWCON);
418 writel(reg | SHADOWCON_WINx_PROTECT(win->index),
419 sfb->regs + SHADOWCON);
420 }
421 } else {
422 if (sfb->variant.has_prtcon) {
423 writel(0, sfb->regs + PRTCON);
424 } else if (sfb->variant.has_shadowcon) {
425 reg = readl(sfb->regs + SHADOWCON);
426 writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
427 sfb->regs + SHADOWCON);
428 }
429 }
430}
431
432/**
258 * s3c_fb_set_par() - framebuffer request to set new framebuffer state. 433 * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
259 * @info: The framebuffer to change. 434 * @info: The framebuffer to change.
260 * 435 *
@@ -266,14 +441,17 @@ static int s3c_fb_set_par(struct fb_info *info)
266 struct s3c_fb_win *win = info->par; 441 struct s3c_fb_win *win = info->par;
267 struct s3c_fb *sfb = win->parent; 442 struct s3c_fb *sfb = win->parent;
268 void __iomem *regs = sfb->regs; 443 void __iomem *regs = sfb->regs;
444 void __iomem *buf = regs;
269 int win_no = win->index; 445 int win_no = win->index;
270 u32 osdc_data = 0; 446 u32 alpha = 0;
271 u32 data; 447 u32 data;
272 u32 pagewidth; 448 u32 pagewidth;
273 int clkdiv; 449 int clkdiv;
274 450
275 dev_dbg(sfb->dev, "setting framebuffer parameters\n"); 451 dev_dbg(sfb->dev, "setting framebuffer parameters\n");
276 452
453 shadow_protect_win(win, 1);
454
277 switch (var->bits_per_pixel) { 455 switch (var->bits_per_pixel) {
278 case 32: 456 case 32:
279 case 24: 457 case 24:
@@ -282,7 +460,7 @@ static int s3c_fb_set_par(struct fb_info *info)
282 info->fix.visual = FB_VISUAL_TRUECOLOR; 460 info->fix.visual = FB_VISUAL_TRUECOLOR;
283 break; 461 break;
284 case 8: 462 case 8:
285 if (s3c_fb_win_has_palette(win_no, 8)) 463 if (win->variant.palette_sz >= 256)
286 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 464 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
287 else 465 else
288 info->fix.visual = FB_VISUAL_TRUECOLOR; 466 info->fix.visual = FB_VISUAL_TRUECOLOR;
@@ -297,12 +475,15 @@ static int s3c_fb_set_par(struct fb_info *info)
297 475
298 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; 476 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
299 477
478 info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
479 info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
480
300 /* disable the window whilst we update it */ 481 /* disable the window whilst we update it */
301 writel(0, regs + WINCON(win_no)); 482 writel(0, regs + WINCON(win_no));
302 483
303 /* use window 0 as the basis for the lcd output timings */ 484 /* use platform specified window as the basis for the lcd timings */
304 485
305 if (win_no == 0) { 486 if (win_no == sfb->pdata->default_win) {
306 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); 487 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
307 488
308 data = sfb->pdata->vidcon0; 489 data = sfb->pdata->vidcon0;
@@ -315,6 +496,9 @@ static int s3c_fb_set_par(struct fb_info *info)
315 496
316 /* write the timing data to the panel */ 497 /* write the timing data to the panel */
317 498
499 if (sfb->variant.is_2443)
500 data |= (1 << 5);
501
318 data |= VIDCON0_ENVID | VIDCON0_ENVID_F; 502 data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
319 writel(data, regs + VIDCON0); 503 writel(data, regs + VIDCON0);
320 504
@@ -322,53 +506,54 @@ static int s3c_fb_set_par(struct fb_info *info)
322 VIDTCON0_VFPD(var->lower_margin - 1) | 506 VIDTCON0_VFPD(var->lower_margin - 1) |
323 VIDTCON0_VSPW(var->vsync_len - 1); 507 VIDTCON0_VSPW(var->vsync_len - 1);
324 508
325 writel(data, regs + VIDTCON0); 509 writel(data, regs + sfb->variant.vidtcon);
326 510
327 data = VIDTCON1_HBPD(var->left_margin - 1) | 511 data = VIDTCON1_HBPD(var->left_margin - 1) |
328 VIDTCON1_HFPD(var->right_margin - 1) | 512 VIDTCON1_HFPD(var->right_margin - 1) |
329 VIDTCON1_HSPW(var->hsync_len - 1); 513 VIDTCON1_HSPW(var->hsync_len - 1);
330 514
331 writel(data, regs + VIDTCON1); 515 /* VIDTCON1 */
516 writel(data, regs + sfb->variant.vidtcon + 4);
332 517
333 data = VIDTCON2_LINEVAL(var->yres - 1) | 518 data = VIDTCON2_LINEVAL(var->yres - 1) |
334 VIDTCON2_HOZVAL(var->xres - 1); 519 VIDTCON2_HOZVAL(var->xres - 1);
335 writel(data, regs + VIDTCON2); 520 writel(data, regs +sfb->variant.vidtcon + 8 );
336 } 521 }
337 522
338 /* write the buffer address */ 523 /* write the buffer address */
339 524
340 writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no)); 525 /* start and end registers stride is 8 */
526 buf = regs + win_no * 8;
527
528 writel(info->fix.smem_start, buf + sfb->variant.buf_start);
341 529
342 data = info->fix.smem_start + info->fix.line_length * var->yres; 530 data = info->fix.smem_start + info->fix.line_length * var->yres;
343 writel(data, regs + VIDW_BUF_END(win_no)); 531 writel(data, buf + sfb->variant.buf_end);
344 532
345 pagewidth = (var->xres * var->bits_per_pixel) >> 3; 533 pagewidth = (var->xres * var->bits_per_pixel) >> 3;
346 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | 534 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
347 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); 535 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth);
348 writel(data, regs + VIDW_BUF_SIZE(win_no)); 536 writel(data, regs + sfb->variant.buf_size + (win_no * 4));
349 537
350 /* write 'OSD' registers to control position of framebuffer */ 538 /* write 'OSD' registers to control position of framebuffer */
351 539
352 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); 540 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
353 writel(data, regs + VIDOSD_A(win_no)); 541 writel(data, regs + VIDOSD_A(win_no, sfb->variant));
354 542
355 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, 543 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
356 var->xres - 1)) | 544 var->xres - 1)) |
357 VIDOSDxB_BOTRIGHT_Y(var->yres - 1); 545 VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
358 546
359 writel(data, regs + VIDOSD_B(win_no)); 547 writel(data, regs + VIDOSD_B(win_no, sfb->variant));
360 548
361 data = var->xres * var->yres; 549 data = var->xres * var->yres;
362 550
363 osdc_data = VIDISD14C_ALPHA1_R(0xf) | 551 alpha = VIDISD14C_ALPHA1_R(0xf) |
364 VIDISD14C_ALPHA1_G(0xf) | 552 VIDISD14C_ALPHA1_G(0xf) |
365 VIDISD14C_ALPHA1_B(0xf); 553 VIDISD14C_ALPHA1_B(0xf);
366 554
367 if (s3c_fb_has_osd_d(win_no)) { 555 vidosd_set_alpha(win, alpha);
368 writel(data, regs + VIDOSD_D(win_no)); 556 vidosd_set_size(win, data);
369 writel(osdc_data, regs + VIDOSD_C(win_no));
370 } else
371 writel(data, regs + VIDOSD_C(win_no));
372 557
373 data = WINCONx_ENWIN; 558 data = WINCONx_ENWIN;
374 559
@@ -424,13 +609,15 @@ static int s3c_fb_set_par(struct fb_info *info)
424 else 609 else
425 data |= WINCON0_BPPMODE_24BPP_888; 610 data |= WINCON0_BPPMODE_24BPP_888;
426 611
612 data |= WINCONx_WSWP;
427 data |= WINCONx_BURSTLEN_16WORD; 613 data |= WINCONx_BURSTLEN_16WORD;
428 break; 614 break;
429 } 615 }
430 616
431 /* It has no color key control register for window0 */ 617 /* Enable the colour keying for the window below this one */
432 if (win_no > 0) { 618 if (win_no > 0) {
433 u32 keycon0_data = 0, keycon1_data = 0; 619 u32 keycon0_data = 0, keycon1_data = 0;
620 void __iomem *keycon = regs + sfb->variant.keycon;
434 621
435 keycon0_data = ~(WxKEYCON0_KEYBL_EN | 622 keycon0_data = ~(WxKEYCON0_KEYBL_EN |
436 WxKEYCON0_KEYEN_F | 623 WxKEYCON0_KEYEN_F |
@@ -438,12 +625,23 @@ static int s3c_fb_set_par(struct fb_info *info)
438 625
439 keycon1_data = WxKEYCON1_COLVAL(0xffffff); 626 keycon1_data = WxKEYCON1_COLVAL(0xffffff);
440 627
441 writel(keycon0_data, regs + WxKEYCONy(win_no-1, 0)); 628 keycon += (win_no - 1) * 8;
442 writel(keycon1_data, regs + WxKEYCONy(win_no-1, 1)); 629
630 writel(keycon0_data, keycon + WKEYCON0);
631 writel(keycon1_data, keycon + WKEYCON1);
632 }
633
634 writel(data, regs + sfb->variant.wincon + (win_no * 4));
635 writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
636
637 /* Enable DMA channel for this window */
638 if (sfb->variant.has_shadowcon) {
639 data = readl(sfb->regs + SHADOWCON);
640 data |= SHADOWCON_CHx_ENABLE(win_no);
641 writel(data, sfb->regs + SHADOWCON);
443 } 642 }
444 643
445 writel(data, regs + WINCON(win_no)); 644 shadow_protect_win(win, 0);
446 writel(0x0, regs + WINxMAP(win_no));
447 645
448 return 0; 646 return 0;
449} 647}
@@ -470,7 +668,7 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb,
470 void __iomem *palreg; 668 void __iomem *palreg;
471 u32 palcon; 669 u32 palcon;
472 670
473 palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg); 671 palreg = sfb->regs + sfb->variant.palette[win->index];
474 672
475 dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", 673 dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
476 __func__, win->index, reg, palreg, value); 674 __func__, win->index, reg, palreg, value);
@@ -480,10 +678,10 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb,
480 palcon = readl(sfb->regs + WPALCON); 678 palcon = readl(sfb->regs + WPALCON);
481 writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); 679 writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
482 680
483 if (s3c_fb_pal_is16(win->index)) 681 if (win->variant.palette_16bpp)
484 writew(value, palreg); 682 writew(value, palreg + (reg * 2));
485 else 683 else
486 writel(value, palreg); 684 writel(value, palreg + (reg * 4));
487 685
488 writel(palcon, sfb->regs + WPALCON); 686 writel(palcon, sfb->regs + WPALCON);
489} 687}
@@ -532,7 +730,7 @@ static int s3c_fb_setcolreg(unsigned regno,
532 break; 730 break;
533 731
534 case FB_VISUAL_PSEUDOCOLOR: 732 case FB_VISUAL_PSEUDOCOLOR:
535 if (regno < s3c_fb_win_pal_size(win->index)) { 733 if (regno < win->variant.palette_sz) {
536 val = chan_to_field(red, &win->palette.r); 734 val = chan_to_field(red, &win->palette.r);
537 val |= chan_to_field(green, &win->palette.g); 735 val |= chan_to_field(green, &win->palette.g);
538 val |= chan_to_field(blue, &win->palette.b); 736 val |= chan_to_field(blue, &win->palette.b);
@@ -591,7 +789,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
591 789
592 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); 790 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
593 791
594 wincon = readl(sfb->regs + WINCON(index)); 792 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
595 793
596 switch (blank_mode) { 794 switch (blank_mode) {
597 case FB_BLANK_POWERDOWN: 795 case FB_BLANK_POWERDOWN:
@@ -602,11 +800,11 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
602 case FB_BLANK_NORMAL: 800 case FB_BLANK_NORMAL:
603 /* disable the DMA and display 0x0 (black) */ 801 /* disable the DMA and display 0x0 (black) */
604 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), 802 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
605 sfb->regs + WINxMAP(index)); 803 sfb->regs + sfb->variant.winmap + (index * 4));
606 break; 804 break;
607 805
608 case FB_BLANK_UNBLANK: 806 case FB_BLANK_UNBLANK:
609 writel(0x0, sfb->regs + WINxMAP(index)); 807 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
610 wincon |= WINCONx_ENWIN; 808 wincon |= WINCONx_ENWIN;
611 sfb->enabled |= (1 << index); 809 sfb->enabled |= (1 << index);
612 break; 810 break;
@@ -617,7 +815,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
617 return 1; 815 return 1;
618 } 816 }
619 817
620 writel(wincon, sfb->regs + WINCON(index)); 818 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
621 819
622 /* Check the enabled state to see if we need to be running the 820 /* Check the enabled state to see if we need to be running the
623 * main LCD interface, as if there are no active windows then 821 * main LCD interface, as if there are no active windows then
@@ -636,12 +834,185 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
636 /* we're stuck with this until we can do something about overriding 834 /* we're stuck with this until we can do something about overriding
637 * the power control using the blanking event for a single fb. 835 * the power control using the blanking event for a single fb.
638 */ 836 */
639 if (index == 0) 837 if (index == sfb->pdata->default_win)
640 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); 838 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
641 839
642 return 0; 840 return 0;
643} 841}
644 842
843/**
844 * s3c_fb_pan_display() - Pan the display.
845 *
846 * Note that the offsets can be written to the device at any time, as their
847 * values are latched at each vsync automatically. This also means that only
848 * the last call to this function will have any effect on next vsync, but
849 * there is no need to sleep waiting for it to prevent tearing.
850 *
851 * @var: The screen information to verify.
852 * @info: The framebuffer device.
853 */
854static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
855 struct fb_info *info)
856{
857 struct s3c_fb_win *win = info->par;
858 struct s3c_fb *sfb = win->parent;
859 void __iomem *buf = sfb->regs + win->index * 8;
860 unsigned int start_boff, end_boff;
861
862 /* Offset in bytes to the start of the displayed area */
863 start_boff = var->yoffset * info->fix.line_length;
864 /* X offset depends on the current bpp */
865 if (info->var.bits_per_pixel >= 8) {
866 start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
867 } else {
868 switch (info->var.bits_per_pixel) {
869 case 4:
870 start_boff += var->xoffset >> 1;
871 break;
872 case 2:
873 start_boff += var->xoffset >> 2;
874 break;
875 case 1:
876 start_boff += var->xoffset >> 3;
877 break;
878 default:
879 dev_err(sfb->dev, "invalid bpp\n");
880 return -EINVAL;
881 }
882 }
883 /* Offset in bytes to the end of the displayed area */
884 end_boff = start_boff + var->yres * info->fix.line_length;
885
886 /* Temporarily turn off per-vsync update from shadow registers until
887 * both start and end addresses are updated to prevent corruption */
888 shadow_protect_win(win, 1);
889
890 writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
891 writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
892
893 shadow_protect_win(win, 0);
894
895 return 0;
896}
897
898/**
899 * s3c_fb_enable_irq() - enable framebuffer interrupts
900 * @sfb: main hardware state
901 */
902static void s3c_fb_enable_irq(struct s3c_fb *sfb)
903{
904 void __iomem *regs = sfb->regs;
905 u32 irq_ctrl_reg;
906
907 if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
908 /* IRQ disabled, enable it */
909 irq_ctrl_reg = readl(regs + VIDINTCON0);
910
911 irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
912 irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
913
914 irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
915 irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
916 irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
917 irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
918
919 writel(irq_ctrl_reg, regs + VIDINTCON0);
920 }
921}
922
923/**
924 * s3c_fb_disable_irq() - disable framebuffer interrupts
925 * @sfb: main hardware state
926 */
927static void s3c_fb_disable_irq(struct s3c_fb *sfb)
928{
929 void __iomem *regs = sfb->regs;
930 u32 irq_ctrl_reg;
931
932 if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
933 /* IRQ enabled, disable it */
934 irq_ctrl_reg = readl(regs + VIDINTCON0);
935
936 irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
937 irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
938
939 writel(irq_ctrl_reg, regs + VIDINTCON0);
940 }
941}
942
943static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
944{
945 struct s3c_fb *sfb = dev_id;
946 void __iomem *regs = sfb->regs;
947 u32 irq_sts_reg;
948
949 irq_sts_reg = readl(regs + VIDINTCON1);
950
951 if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
952
953 /* VSYNC interrupt, accept it */
954 writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
955
956 sfb->vsync_info.count++;
957 wake_up_interruptible(&sfb->vsync_info.wait);
958 }
959
960 /* We only support waiting for VSYNC for now, so it's safe
961 * to always disable irqs here.
962 */
963 s3c_fb_disable_irq(sfb);
964
965 return IRQ_HANDLED;
966}
967
968/**
969 * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
970 * @sfb: main hardware state
971 * @crtc: head index.
972 */
973static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
974{
975 unsigned long count;
976 int ret;
977
978 if (crtc != 0)
979 return -ENODEV;
980
981 count = sfb->vsync_info.count;
982 s3c_fb_enable_irq(sfb);
983 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
984 count != sfb->vsync_info.count,
985 msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
986 if (ret == 0)
987 return -ETIMEDOUT;
988
989 return 0;
990}
991
992static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
993 unsigned long arg)
994{
995 struct s3c_fb_win *win = info->par;
996 struct s3c_fb *sfb = win->parent;
997 int ret;
998 u32 crtc;
999
1000 switch (cmd) {
1001 case FBIO_WAITFORVSYNC:
1002 if (get_user(crtc, (u32 __user *)arg)) {
1003 ret = -EFAULT;
1004 break;
1005 }
1006
1007 ret = s3c_fb_wait_for_vsync(sfb, crtc);
1008 break;
1009 default:
1010 ret = -ENOTTY;
1011 }
1012
1013 return ret;
1014}
1015
645static struct fb_ops s3c_fb_ops = { 1016static struct fb_ops s3c_fb_ops = {
646 .owner = THIS_MODULE, 1017 .owner = THIS_MODULE,
647 .fb_check_var = s3c_fb_check_var, 1018 .fb_check_var = s3c_fb_check_var,
@@ -651,9 +1022,33 @@ static struct fb_ops s3c_fb_ops = {
651 .fb_fillrect = cfb_fillrect, 1022 .fb_fillrect = cfb_fillrect,
652 .fb_copyarea = cfb_copyarea, 1023 .fb_copyarea = cfb_copyarea,
653 .fb_imageblit = cfb_imageblit, 1024 .fb_imageblit = cfb_imageblit,
1025 .fb_pan_display = s3c_fb_pan_display,
1026 .fb_ioctl = s3c_fb_ioctl,
654}; 1027};
655 1028
656/** 1029/**
1030 * s3c_fb_missing_pixclock() - calculates pixel clock
1031 * @mode: The video mode to change.
1032 *
1033 * Calculate the pixel clock when none has been given through platform data.
1034 */
1035static void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode)
1036{
1037 u64 pixclk = 1000000000000ULL;
1038 u32 div;
1039
1040 div = mode->left_margin + mode->hsync_len + mode->right_margin +
1041 mode->xres;
1042 div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
1043 mode->yres;
1044 div *= mode->refresh ? : 60;
1045
1046 do_div(pixclk, div);
1047
1048 mode->pixclock = pixclk;
1049}
1050
1051/**
657 * s3c_fb_alloc_memory() - allocate display memory for framebuffer window 1052 * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
658 * @sfb: The base resources for the hardware. 1053 * @sfb: The base resources for the hardware.
659 * @win: The window to initialise memory for. 1054 * @win: The window to initialise memory for.
@@ -711,7 +1106,8 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
711{ 1106{
712 struct fb_info *fbi = win->fbinfo; 1107 struct fb_info *fbi = win->fbinfo;
713 1108
714 dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), 1109 if (fbi->screen_base)
1110 dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
715 fbi->screen_base, fbi->fix.smem_start); 1111 fbi->screen_base, fbi->fix.smem_start);
716} 1112}
717 1113
@@ -724,9 +1120,18 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
724 */ 1120 */
725static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) 1121static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
726{ 1122{
1123 u32 data;
1124
727 if (win->fbinfo) { 1125 if (win->fbinfo) {
1126 if (sfb->variant.has_shadowcon) {
1127 data = readl(sfb->regs + SHADOWCON);
1128 data &= ~SHADOWCON_CHx_ENABLE(win->index);
1129 data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
1130 writel(data, sfb->regs + SHADOWCON);
1131 }
728 unregister_framebuffer(win->fbinfo); 1132 unregister_framebuffer(win->fbinfo);
729 fb_dealloc_cmap(&win->fbinfo->cmap); 1133 if (win->fbinfo->cmap.len)
1134 fb_dealloc_cmap(&win->fbinfo->cmap);
730 s3c_fb_free_memory(sfb, win); 1135 s3c_fb_free_memory(sfb, win);
731 framebuffer_release(win->fbinfo); 1136 framebuffer_release(win->fbinfo);
732 } 1137 }
@@ -735,12 +1140,14 @@ static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
735/** 1140/**
736 * s3c_fb_probe_win() - register an hardware window 1141 * s3c_fb_probe_win() - register an hardware window
737 * @sfb: The base resources for the hardware 1142 * @sfb: The base resources for the hardware
1143 * @variant: The variant information for this window.
738 * @res: Pointer to where to place the resultant window. 1144 * @res: Pointer to where to place the resultant window.
739 * 1145 *
740 * Allocate and do the basic initialisation for one of the hardware's graphics 1146 * Allocate and do the basic initialisation for one of the hardware's graphics
741 * windows. 1147 * windows.
742 */ 1148 */
743static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, 1149static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
1150 struct s3c_fb_win_variant *variant,
744 struct s3c_fb_win **res) 1151 struct s3c_fb_win **res)
745{ 1152{
746 struct fb_var_screeninfo *var; 1153 struct fb_var_screeninfo *var;
@@ -751,9 +1158,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
751 int palette_size; 1158 int palette_size;
752 int ret; 1159 int ret;
753 1160
754 dev_dbg(sfb->dev, "probing window %d\n", win_no); 1161 dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
1162
1163 init_waitqueue_head(&sfb->vsync_info.wait);
755 1164
756 palette_size = s3c_fb_win_pal_size(win_no); 1165 palette_size = variant->palette_sz * 4;
757 1166
758 fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + 1167 fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
759 palette_size * sizeof(u32), sfb->dev); 1168 palette_size * sizeof(u32), sfb->dev);
@@ -770,7 +1179,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
770 WARN_ON(windata->win_mode.yres == 0); 1179 WARN_ON(windata->win_mode.yres == 0);
771 1180
772 win = fbinfo->par; 1181 win = fbinfo->par;
1182 *res = win;
773 var = &fbinfo->var; 1183 var = &fbinfo->var;
1184 win->variant = *variant;
774 win->fbinfo = fbinfo; 1185 win->fbinfo = fbinfo;
775 win->parent = sfb; 1186 win->parent = sfb;
776 win->windata = windata; 1187 win->windata = windata;
@@ -784,7 +1195,24 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
784 } 1195 }
785 1196
786 /* setup the r/b/g positions for the window's palette */ 1197 /* setup the r/b/g positions for the window's palette */
787 s3c_fb_init_palette(win_no, &win->palette); 1198 if (win->variant.palette_16bpp) {
1199 /* Set RGB 5:6:5 as default */
1200 win->palette.r.offset = 11;
1201 win->palette.r.length = 5;
1202 win->palette.g.offset = 5;
1203 win->palette.g.length = 6;
1204 win->palette.b.offset = 0;
1205 win->palette.b.length = 5;
1206
1207 } else {
1208 /* Set 8bpp or 8bpp and 1bit alpha */
1209 win->palette.r.offset = 16;
1210 win->palette.r.length = 8;
1211 win->palette.g.offset = 8;
1212 win->palette.g.length = 8;
1213 win->palette.b.offset = 0;
1214 win->palette.b.length = 8;
1215 }
788 1216
789 /* setup the initial video mode from the window */ 1217 /* setup the initial video mode from the window */
790 fb_videomode_to_var(&fbinfo->var, initmode); 1218 fb_videomode_to_var(&fbinfo->var, initmode);
@@ -808,7 +1236,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
808 1236
809 /* create initial colour map */ 1237 /* create initial colour map */
810 1238
811 ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1); 1239 ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
812 if (ret == 0) 1240 if (ret == 0)
813 fb_set_cmap(&fbinfo->cmap, fbinfo); 1241 fb_set_cmap(&fbinfo->cmap, fbinfo);
814 else 1242 else
@@ -826,7 +1254,6 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
826 return ret; 1254 return ret;
827 } 1255 }
828 1256
829 *res = win;
830 dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); 1257 dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
831 1258
832 return 0; 1259 return 0;
@@ -842,18 +1269,19 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
842static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) 1269static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
843{ 1270{
844 void __iomem *regs = sfb->regs; 1271 void __iomem *regs = sfb->regs;
845 1272 u32 reg;
846 writel(0, regs + WINCON(win)); 1273
847 writel(0xffffff, regs + WxKEYCONy(win, 0)); 1274 writel(0, regs + sfb->variant.wincon + (win * 4));
848 writel(0xffffff, regs + WxKEYCONy(win, 1)); 1275 writel(0, regs + VIDOSD_A(win, sfb->variant));
849 1276 writel(0, regs + VIDOSD_B(win, sfb->variant));
850 writel(0, regs + VIDOSD_A(win)); 1277 writel(0, regs + VIDOSD_C(win, sfb->variant));
851 writel(0, regs + VIDOSD_B(win)); 1278 reg = readl(regs + SHADOWCON);
852 writel(0, regs + VIDOSD_C(win)); 1279 writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON);
853} 1280}
854 1281
855static int __devinit s3c_fb_probe(struct platform_device *pdev) 1282static int __devinit s3c_fb_probe(struct platform_device *pdev)
856{ 1283{
1284 struct s3c_fb_driverdata *fbdrv;
857 struct device *dev = &pdev->dev; 1285 struct device *dev = &pdev->dev;
858 struct s3c_fb_platdata *pd; 1286 struct s3c_fb_platdata *pd;
859 struct s3c_fb *sfb; 1287 struct s3c_fb *sfb;
@@ -861,6 +1289,13 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
861 int win; 1289 int win;
862 int ret = 0; 1290 int ret = 0;
863 1291
1292 fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data;
1293
1294 if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
1295 dev_err(dev, "too many windows, cannot attach\n");
1296 return -EINVAL;
1297 }
1298
864 pd = pdev->dev.platform_data; 1299 pd = pdev->dev.platform_data;
865 if (!pd) { 1300 if (!pd) {
866 dev_err(dev, "no platform data specified\n"); 1301 dev_err(dev, "no platform data specified\n");
@@ -873,8 +1308,11 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
873 return -ENOMEM; 1308 return -ENOMEM;
874 } 1309 }
875 1310
1311 dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
1312
876 sfb->dev = dev; 1313 sfb->dev = dev;
877 sfb->pdata = pd; 1314 sfb->pdata = pd;
1315 sfb->variant = fbdrv->variant;
878 1316
879 sfb->bus_clk = clk_get(dev, "lcd"); 1317 sfb->bus_clk = clk_get(dev, "lcd");
880 if (IS_ERR(sfb->bus_clk)) { 1318 if (IS_ERR(sfb->bus_clk)) {
@@ -906,6 +1344,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
906 goto err_req_region; 1344 goto err_req_region;
907 } 1345 }
908 1346
1347 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1348 if (!res) {
1349 dev_err(dev, "failed to acquire irq resource\n");
1350 ret = -ENOENT;
1351 goto err_ioremap;
1352 }
1353 sfb->irq_no = res->start;
1354 ret = request_irq(sfb->irq_no, s3c_fb_irq,
1355 0, "s3c_fb", sfb);
1356 if (ret) {
1357 dev_err(dev, "irq request failed\n");
1358 goto err_ioremap;
1359 }
1360
909 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1361 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
910 1362
911 /* setup gpio and output polarity controls */ 1363 /* setup gpio and output polarity controls */
@@ -916,21 +1368,34 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
916 1368
917 /* zero all windows before we do anything */ 1369 /* zero all windows before we do anything */
918 1370
919 for (win = 0; win < S3C_FB_MAX_WIN; win++) 1371 for (win = 0; win < fbdrv->variant.nr_windows; win++)
920 s3c_fb_clear_win(sfb, win); 1372 s3c_fb_clear_win(sfb, win);
921 1373
1374 /* initialise colour key controls */
1375 for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
1376 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1377
1378 regs += (win * 8);
1379 writel(0xffffff, regs + WKEYCON0);
1380 writel(0xffffff, regs + WKEYCON1);
1381 }
1382
922 /* we have the register setup, start allocating framebuffers */ 1383 /* we have the register setup, start allocating framebuffers */
923 1384
924 for (win = 0; win < S3C_FB_MAX_WIN; win++) { 1385 for (win = 0; win < fbdrv->variant.nr_windows; win++) {
925 if (!pd->win[win]) 1386 if (!pd->win[win])
926 continue; 1387 continue;
927 1388
928 ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]); 1389 if (!pd->win[win]->win_mode.pixclock)
1390 s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
1391
1392 ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
1393 &sfb->windows[win]);
929 if (ret < 0) { 1394 if (ret < 0) {
930 dev_err(dev, "failed to create window %d\n", win); 1395 dev_err(dev, "failed to create window %d\n", win);
931 for (; win >= 0; win--) 1396 for (; win >= 0; win--)
932 s3c_fb_release_win(sfb, sfb->windows[win]); 1397 s3c_fb_release_win(sfb, sfb->windows[win]);
933 goto err_ioremap; 1398 goto err_irq;
934 } 1399 }
935 } 1400 }
936 1401
@@ -938,6 +1403,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
938 1403
939 return 0; 1404 return 0;
940 1405
1406err_irq:
1407 free_irq(sfb->irq_no, sfb);
1408
941err_ioremap: 1409err_ioremap:
942 iounmap(sfb->regs); 1410 iounmap(sfb->regs);
943 1411
@@ -970,6 +1438,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
970 if (sfb->windows[win]) 1438 if (sfb->windows[win])
971 s3c_fb_release_win(sfb, sfb->windows[win]); 1439 s3c_fb_release_win(sfb, sfb->windows[win]);
972 1440
1441 free_irq(sfb->irq_no, sfb);
1442
973 iounmap(sfb->regs); 1443 iounmap(sfb->regs);
974 1444
975 clk_disable(sfb->bus_clk); 1445 clk_disable(sfb->bus_clk);
@@ -1016,9 +1486,17 @@ static int s3c_fb_resume(struct platform_device *pdev)
1016 writel(pd->vidcon1, sfb->regs + VIDCON1); 1486 writel(pd->vidcon1, sfb->regs + VIDCON1);
1017 1487
1018 /* zero all windows before we do anything */ 1488 /* zero all windows before we do anything */
1019 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) 1489 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1020 s3c_fb_clear_win(sfb, win_no); 1490 s3c_fb_clear_win(sfb, win_no);
1021 1491
1492 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1493 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1494
1495 regs += (win_no * 8);
1496 writel(0xffffff, regs + WKEYCON0);
1497 writel(0xffffff, regs + WKEYCON1);
1498 }
1499
1022 /* restore framebuffers */ 1500 /* restore framebuffers */
1023 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { 1501 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1024 win = sfb->windows[win_no]; 1502 win = sfb->windows[win_no];
@@ -1036,11 +1514,208 @@ static int s3c_fb_resume(struct platform_device *pdev)
1036#define s3c_fb_resume NULL 1514#define s3c_fb_resume NULL
1037#endif 1515#endif
1038 1516
1517
1518#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
1519#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
1520
1521static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
1522 [0] = {
1523 .has_osd_c = 1,
1524 .osd_size_off = 0x8,
1525 .palette_sz = 256,
1526 .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1527 },
1528 [1] = {
1529 .has_osd_c = 1,
1530 .has_osd_d = 1,
1531 .osd_size_off = 0x12,
1532 .has_osd_alpha = 1,
1533 .palette_sz = 256,
1534 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1535 VALID_BPP(18) | VALID_BPP(19) |
1536 VALID_BPP(24) | VALID_BPP(25)),
1537 },
1538 [2] = {
1539 .has_osd_c = 1,
1540 .has_osd_d = 1,
1541 .osd_size_off = 0x12,
1542 .has_osd_alpha = 1,
1543 .palette_sz = 16,
1544 .palette_16bpp = 1,
1545 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1546 VALID_BPP(18) | VALID_BPP(19) |
1547 VALID_BPP(24) | VALID_BPP(25)),
1548 },
1549 [3] = {
1550 .has_osd_c = 1,
1551 .has_osd_alpha = 1,
1552 .palette_sz = 16,
1553 .palette_16bpp = 1,
1554 .valid_bpp = (VALID_BPP124 | VALID_BPP(16) |
1555 VALID_BPP(18) | VALID_BPP(19) |
1556 VALID_BPP(24) | VALID_BPP(25)),
1557 },
1558 [4] = {
1559 .has_osd_c = 1,
1560 .has_osd_alpha = 1,
1561 .palette_sz = 4,
1562 .palette_16bpp = 1,
1563 .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) |
1564 VALID_BPP(16) | VALID_BPP(18) |
1565 VALID_BPP(24) | VALID_BPP(25)),
1566 },
1567};
1568
1569static struct s3c_fb_driverdata s3c_fb_data_64xx = {
1570 .variant = {
1571 .nr_windows = 5,
1572 .vidtcon = VIDTCON0,
1573 .wincon = WINCON(0),
1574 .winmap = WINxMAP(0),
1575 .keycon = WKEYCON,
1576 .osd = VIDOSD_BASE,
1577 .osd_stride = 16,
1578 .buf_start = VIDW_BUF_START(0),
1579 .buf_size = VIDW_BUF_SIZE(0),
1580 .buf_end = VIDW_BUF_END(0),
1581
1582 .palette = {
1583 [0] = 0x400,
1584 [1] = 0x800,
1585 [2] = 0x300,
1586 [3] = 0x320,
1587 [4] = 0x340,
1588 },
1589
1590 .has_prtcon = 1,
1591 },
1592 .win[0] = &s3c_fb_data_64xx_wins[0],
1593 .win[1] = &s3c_fb_data_64xx_wins[1],
1594 .win[2] = &s3c_fb_data_64xx_wins[2],
1595 .win[3] = &s3c_fb_data_64xx_wins[3],
1596 .win[4] = &s3c_fb_data_64xx_wins[4],
1597};
1598
1599static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1600 .variant = {
1601 .nr_windows = 5,
1602 .vidtcon = VIDTCON0,
1603 .wincon = WINCON(0),
1604 .winmap = WINxMAP(0),
1605 .keycon = WKEYCON,
1606 .osd = VIDOSD_BASE,
1607 .osd_stride = 16,
1608 .buf_start = VIDW_BUF_START(0),
1609 .buf_size = VIDW_BUF_SIZE(0),
1610 .buf_end = VIDW_BUF_END(0),
1611
1612 .palette = {
1613 [0] = 0x2400,
1614 [1] = 0x2800,
1615 [2] = 0x2c00,
1616 [3] = 0x3000,
1617 [4] = 0x3400,
1618 },
1619
1620 .has_prtcon = 1,
1621 },
1622 .win[0] = &s3c_fb_data_64xx_wins[0],
1623 .win[1] = &s3c_fb_data_64xx_wins[1],
1624 .win[2] = &s3c_fb_data_64xx_wins[2],
1625 .win[3] = &s3c_fb_data_64xx_wins[3],
1626 .win[4] = &s3c_fb_data_64xx_wins[4],
1627};
1628
1629static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1630 .variant = {
1631 .nr_windows = 5,
1632 .vidtcon = VIDTCON0,
1633 .wincon = WINCON(0),
1634 .winmap = WINxMAP(0),
1635 .keycon = WKEYCON,
1636 .osd = VIDOSD_BASE,
1637 .osd_stride = 16,
1638 .buf_start = VIDW_BUF_START(0),
1639 .buf_size = VIDW_BUF_SIZE(0),
1640 .buf_end = VIDW_BUF_END(0),
1641
1642 .palette = {
1643 [0] = 0x2400,
1644 [1] = 0x2800,
1645 [2] = 0x2c00,
1646 [3] = 0x3000,
1647 [4] = 0x3400,
1648 },
1649
1650 .has_shadowcon = 1,
1651 },
1652 .win[0] = &s3c_fb_data_64xx_wins[0],
1653 .win[1] = &s3c_fb_data_64xx_wins[1],
1654 .win[2] = &s3c_fb_data_64xx_wins[2],
1655 .win[3] = &s3c_fb_data_64xx_wins[3],
1656 .win[4] = &s3c_fb_data_64xx_wins[4],
1657};
1658
1659/* S3C2443/S3C2416 style hardware */
1660static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1661 .variant = {
1662 .nr_windows = 2,
1663 .is_2443 = 1,
1664
1665 .vidtcon = 0x08,
1666 .wincon = 0x14,
1667 .winmap = 0xd0,
1668 .keycon = 0xb0,
1669 .osd = 0x28,
1670 .osd_stride = 12,
1671 .buf_start = 0x64,
1672 .buf_size = 0x94,
1673 .buf_end = 0x7c,
1674
1675 .palette = {
1676 [0] = 0x400,
1677 [1] = 0x800,
1678 },
1679 },
1680 .win[0] = &(struct s3c_fb_win_variant) {
1681 .palette_sz = 256,
1682 .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1683 },
1684 .win[1] = &(struct s3c_fb_win_variant) {
1685 .has_osd_c = 1,
1686 .has_osd_alpha = 1,
1687 .palette_sz = 256,
1688 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1689 VALID_BPP(18) | VALID_BPP(19) |
1690 VALID_BPP(24) | VALID_BPP(25) |
1691 VALID_BPP(28)),
1692 },
1693};
1694
1695static struct platform_device_id s3c_fb_driver_ids[] = {
1696 {
1697 .name = "s3c-fb",
1698 .driver_data = (unsigned long)&s3c_fb_data_64xx,
1699 }, {
1700 .name = "s5pc100-fb",
1701 .driver_data = (unsigned long)&s3c_fb_data_s5pc100,
1702 }, {
1703 .name = "s5pv210-fb",
1704 .driver_data = (unsigned long)&s3c_fb_data_s5pv210,
1705 }, {
1706 .name = "s3c2443-fb",
1707 .driver_data = (unsigned long)&s3c_fb_data_s3c2443,
1708 },
1709 {},
1710};
1711MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1712
1039static struct platform_driver s3c_fb_driver = { 1713static struct platform_driver s3c_fb_driver = {
1040 .probe = s3c_fb_probe, 1714 .probe = s3c_fb_probe,
1041 .remove = __devexit_p(s3c_fb_remove), 1715 .remove = __devexit_p(s3c_fb_remove),
1042 .suspend = s3c_fb_suspend, 1716 .suspend = s3c_fb_suspend,
1043 .resume = s3c_fb_resume, 1717 .resume = s3c_fb_resume,
1718 .id_table = s3c_fb_driver_ids,
1044 .driver = { 1719 .driver = {
1045 .name = "s3c-fb", 1720 .name = "s3c-fb",
1046 .owner = THIS_MODULE, 1721 .owner = THIS_MODULE,
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
new file mode 100644
index 000000000000..5699ce0c1780
--- /dev/null
+++ b/drivers/video/sh_mipi_dsi.c
@@ -0,0 +1,505 @@
1/*
2 * Renesas SH-mobile MIPI DSI support
3 *
4 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/string.h>
18#include <linux/types.h>
19
20#include <video/mipi_display.h>
21#include <video/sh_mipi_dsi.h>
22#include <video/sh_mobile_lcdc.h>
23
24#define CMTSRTCTR 0x80d0
25#define CMTSRTREQ 0x8070
26
27#define DSIINTE 0x0060
28
29/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
30#define MAX_SH_MIPI_DSI 2
31
32struct sh_mipi {
33 void __iomem *base;
34 struct clk *dsit_clk;
35 struct clk *dsip_clk;
36};
37
38static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
39
40/* Protect the above array */
41static DEFINE_MUTEX(array_lock);
42
43static struct sh_mipi *sh_mipi_by_handle(int handle)
44{
45 if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
46 return NULL;
47
48 return mipi_dsi[handle];
49}
50
51static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
52 u8 cmd, u8 param)
53{
54 u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
55 int cnt = 100;
56
57 /* transmit a short packet to LCD panel */
58 iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */
59 iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */
60
61 while ((ioread32(mipi->base + 0x8070) & 1) && --cnt)
62 udelay(1);
63
64 return cnt ? 0 : -ETIMEDOUT;
65}
66
67#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
68 -EINVAL : (c) - 1)
69
70static int sh_mipi_dcs(int handle, u8 cmd)
71{
72 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
73 if (!mipi)
74 return -ENODEV;
75 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
76}
77
78static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
79{
80 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
81 if (!mipi)
82 return -ENODEV;
83 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
84 param);
85}
86
87static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
88{
89 /*
90 * enable LCDC data tx, transition to LPS after completion of each HS
91 * packet
92 */
93 iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */
94}
95
96static void sh_mipi_shutdown(struct platform_device *pdev)
97{
98 struct sh_mipi *mipi = platform_get_drvdata(pdev);
99
100 sh_mipi_dsi_enable(mipi, false);
101}
102
103static void mipi_display_on(void *arg, struct fb_info *info)
104{
105 struct sh_mipi *mipi = arg;
106
107 sh_mipi_dsi_enable(mipi, true);
108}
109
110static void mipi_display_off(void *arg)
111{
112 struct sh_mipi *mipi = arg;
113
114 sh_mipi_dsi_enable(mipi, false);
115}
116
117static int __init sh_mipi_setup(struct sh_mipi *mipi,
118 struct sh_mipi_dsi_info *pdata)
119{
120 void __iomem *base = mipi->base;
121 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
122 u32 pctype, datatype, pixfmt;
123 u32 linelength;
124 bool yuv;
125
126 /* Select data format */
127 switch (pdata->data_format) {
128 case MIPI_RGB888:
129 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3;
133 yuv = false;
134 break;
135 case MIPI_RGB565:
136 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2;
140 yuv = false;
141 break;
142 case MIPI_RGB666_LP:
143 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3;
147 yuv = false;
148 break;
149 case MIPI_RGB666:
150 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
154 yuv = false;
155 break;
156 case MIPI_BGR888:
157 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3;
161 yuv = false;
162 break;
163 case MIPI_BGR565:
164 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2;
168 yuv = false;
169 break;
170 case MIPI_BGR666_LP:
171 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3;
175 yuv = false;
176 break;
177 case MIPI_BGR666:
178 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
182 yuv = false;
183 break;
184 case MIPI_YUYV:
185 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2;
189 yuv = true;
190 break;
191 case MIPI_UYVY:
192 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2;
196 yuv = true;
197 break;
198 case MIPI_YUV420_L:
199 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8;
203 yuv = true;
204 break;
205 case MIPI_YUV420:
206 pctype = 7;
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2;
211 yuv = true;
212 break;
213 default:
214 return -EINVAL;
215 }
216
217 if ((yuv && ch->interface_type != YUV422) ||
218 (!yuv && ch->interface_type != RGB24))
219 return -EINVAL;
220
221 /* reset DSI link */
222 iowrite32(0x00000001, base); /* SYSCTRL */
223 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
224 udelay(50);
225 iowrite32(0x00000000, base); /* SYSCTRL */
226
227 /* setup DSI link */
228
229 /*
230 * Default = ULPS enable |
231 * Contention detection enabled |
232 * EoT packet transmission enable |
233 * CRC check enable |
234 * ECC check enable
235 * additionally enable first two lanes
236 */
237 iowrite32(0x00003703, base + 0x04); /* SYSCONF */
238 /*
239 * T_wakeup = 0x7000
240 * T_hs-trail = 3
241 * T_hs-prepare = 3
242 * T_clk-trail = 3
243 * T_clk-prepare = 2
244 */
245 iowrite32(0x70003332, base + 0x08); /* TIMSET */
246 /* no responses requested */
247 iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */
248 /* request response to packets of type 0x28 */
249 iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */
250 /* High-speed transmission timeout, default 0xffffffff */
251 iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */
252 /* LP reception timeout, default 0xffffffff */
253 iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */
254 /* Turn-around timeout, default 0xffffffff */
255 iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */
256 /* Peripheral reset timeout, default 0xffffffff */
257 iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */
258 /* Enable timeout counters */
259 iowrite32(0x00000f00, base + 0x30); /* DSICTRL */
260 /* Interrupts not used, disable all */
261 iowrite32(0, base + DSIINTE);
262 /* DSI-Tx bias on */
263 iowrite32(0x00000001, base + 0x70); /* PHYCTRL */
264 udelay(200);
265 /* Deassert resets, power on, set multiplier */
266 iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */
267
268 /* setup l-bridge */
269
270 /*
271 * Enable transmission of all packets,
272 * transmit LPS after each HS packet completion
273 */
274 iowrite32(0x00000006, base + 0x8000); /* DTCTR */
275 /* VSYNC width = 2 (<< 17) */
276 iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */
277 /*
278 * Non-burst mode with sync pulses: VSE and HSE are output,
279 * HSA period allowed, no commands in LP
280 */
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0)
286 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
288
289 msleep(5);
290
291 /* setup LCD panel */
292
293 /* cf. drivers/video/omap/lcd_mipid.c */
294 sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
295 msleep(120);
296 /*
297 * [7] - Page Address Mode
298 * [6] - Column Address Mode
299 * [5] - Page / Column Address Mode
300 * [4] - Display Device Line Refresh Order
301 * [3] - RGB/BGR Order
302 * [2] - Display Data Latch Data Order
303 * [1] - Flip Horizontal
304 * [0] - Flip Vertical
305 */
306 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
307 /* cf. set_data_lines() */
308 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
309 pixfmt << 4);
310 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
311
312 return 0;
313}
314
315static int __init sh_mipi_probe(struct platform_device *pdev)
316{
317 struct sh_mipi *mipi;
318 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
319 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
320 unsigned long rate, f_current;
321 int idx = pdev->id, ret;
322 char dsip_clk[] = "dsi.p_clk";
323
324 if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
325 return -ENODEV;
326
327 mutex_lock(&array_lock);
328 if (idx < 0)
329 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
330 ;
331
332 if (idx == ARRAY_SIZE(mipi_dsi)) {
333 ret = -EBUSY;
334 goto efindslot;
335 }
336
337 mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
338 if (!mipi) {
339 ret = -ENOMEM;
340 goto ealloc;
341 }
342
343 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
344 dev_err(&pdev->dev, "MIPI register region already claimed\n");
345 ret = -EBUSY;
346 goto ereqreg;
347 }
348
349 mipi->base = ioremap(res->start, resource_size(res));
350 if (!mipi->base) {
351 ret = -ENOMEM;
352 goto emap;
353 }
354
355 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
356 if (IS_ERR(mipi->dsit_clk)) {
357 ret = PTR_ERR(mipi->dsit_clk);
358 goto eclktget;
359 }
360
361 f_current = clk_get_rate(mipi->dsit_clk);
362 /* 80MHz required by the datasheet */
363 rate = clk_round_rate(mipi->dsit_clk, 80000000);
364 if (rate > 0 && rate != f_current)
365 ret = clk_set_rate(mipi->dsit_clk, rate);
366 else
367 ret = rate;
368 if (ret < 0)
369 goto esettrate;
370
371 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
372
373 sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
374 mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
375 if (IS_ERR(mipi->dsip_clk)) {
376 ret = PTR_ERR(mipi->dsip_clk);
377 goto eclkpget;
378 }
379
380 f_current = clk_get_rate(mipi->dsip_clk);
381 /* Between 10 and 50MHz */
382 rate = clk_round_rate(mipi->dsip_clk, 24000000);
383 if (rate > 0 && rate != f_current)
384 ret = clk_set_rate(mipi->dsip_clk, rate);
385 else
386 ret = rate;
387 if (ret < 0)
388 goto esetprate;
389
390 dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
391
392 msleep(10);
393
394 ret = clk_enable(mipi->dsit_clk);
395 if (ret < 0)
396 goto eclkton;
397
398 ret = clk_enable(mipi->dsip_clk);
399 if (ret < 0)
400 goto eclkpon;
401
402 mipi_dsi[idx] = mipi;
403
404 ret = sh_mipi_setup(mipi, pdata);
405 if (ret < 0)
406 goto emipisetup;
407
408 mutex_unlock(&array_lock);
409 platform_set_drvdata(pdev, mipi);
410
411 /* Set up LCDC callbacks */
412 pdata->lcd_chan->board_cfg.board_data = mipi;
413 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
414 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
415
416 return 0;
417
418emipisetup:
419 mipi_dsi[idx] = NULL;
420 clk_disable(mipi->dsip_clk);
421eclkpon:
422 clk_disable(mipi->dsit_clk);
423eclkton:
424esetprate:
425 clk_put(mipi->dsip_clk);
426eclkpget:
427esettrate:
428 clk_put(mipi->dsit_clk);
429eclktget:
430 iounmap(mipi->base);
431emap:
432 release_mem_region(res->start, resource_size(res));
433ereqreg:
434 kfree(mipi);
435ealloc:
436efindslot:
437 mutex_unlock(&array_lock);
438
439 return ret;
440}
441
442static int __exit sh_mipi_remove(struct platform_device *pdev)
443{
444 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
445 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
446 struct sh_mipi *mipi = platform_get_drvdata(pdev);
447 int i, ret;
448
449 mutex_lock(&array_lock);
450
451 for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
452 ;
453
454 if (i == ARRAY_SIZE(mipi_dsi)) {
455 ret = -EINVAL;
456 } else {
457 ret = 0;
458 mipi_dsi[i] = NULL;
459 }
460
461 mutex_unlock(&array_lock);
462
463 if (ret < 0)
464 return ret;
465
466 pdata->lcd_chan->board_cfg.display_on = NULL;
467 pdata->lcd_chan->board_cfg.display_off = NULL;
468 pdata->lcd_chan->board_cfg.board_data = NULL;
469
470 clk_disable(mipi->dsip_clk);
471 clk_disable(mipi->dsit_clk);
472 clk_put(mipi->dsit_clk);
473 clk_put(mipi->dsip_clk);
474 iounmap(mipi->base);
475 if (res)
476 release_mem_region(res->start, resource_size(res));
477 platform_set_drvdata(pdev, NULL);
478 kfree(mipi);
479
480 return 0;
481}
482
483static struct platform_driver sh_mipi_driver = {
484 .remove = __exit_p(sh_mipi_remove),
485 .shutdown = sh_mipi_shutdown,
486 .driver = {
487 .name = "sh-mipi-dsi",
488 },
489};
490
491static int __init sh_mipi_init(void)
492{
493 return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
494}
495module_init(sh_mipi_init);
496
497static void __exit sh_mipi_exit(void)
498{
499 platform_driver_unregister(&sh_mipi_driver);
500}
501module_exit(sh_mipi_exit);
502
503MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
504MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
505MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
new file mode 100644
index 000000000000..2fde08cc66bf
--- /dev/null
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -0,0 +1,1028 @@
1/*
2 * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
3 * for SLISHDMI13T and SLIPHDMIT IP cores
4 *
5 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/console.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24#include <linux/workqueue.h>
25
26#include <video/sh_mobile_hdmi.h>
27#include <video/sh_mobile_lcdc.h>
28
29#define HDMI_SYSTEM_CTRL 0x00 /* System control */
30#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
31 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
32#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8 0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */
33#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0 0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */
34#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS 0x04 /* SPDIF audio sampling frequency,
35 bits 19..16 of Internal CTS */
36#define HDMI_INTERNAL_CTS_15_8 0x05 /* bits 15..8 of Internal CTS */
37#define HDMI_INTERNAL_CTS_7_0 0x06 /* bits 7..0 of Internal CTS */
38#define HDMI_EXTERNAL_CTS_19_16 0x07 /* External CTS */
39#define HDMI_EXTERNAL_CTS_15_8 0x08 /* External CTS */
40#define HDMI_EXTERNAL_CTS_7_0 0x09 /* External CTS */
41#define HDMI_AUDIO_SETTING_1 0x0A /* Audio setting.1 */
42#define HDMI_AUDIO_SETTING_2 0x0B /* Audio setting.2 */
43#define HDMI_I2S_AUDIO_SET 0x0C /* I2S audio setting */
44#define HDMI_DSD_AUDIO_SET 0x0D /* DSD audio setting */
45#define HDMI_DEBUG_MONITOR_1 0x0E /* Debug monitor.1 */
46#define HDMI_DEBUG_MONITOR_2 0x0F /* Debug monitor.2 */
47#define HDMI_I2S_INPUT_PIN_SWAP 0x10 /* I2S input pin swap */
48#define HDMI_AUDIO_STATUS_BITS_SETTING_1 0x11 /* Audio status bits setting.1 */
49#define HDMI_AUDIO_STATUS_BITS_SETTING_2 0x12 /* Audio status bits setting.2 */
50#define HDMI_CATEGORY_CODE 0x13 /* Category code */
51#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN 0x14 /* Source number/Audio word length */
52#define HDMI_AUDIO_VIDEO_SETTING_1 0x15 /* Audio/Video setting.1 */
53#define HDMI_VIDEO_SETTING_1 0x16 /* Video setting.1 */
54#define HDMI_DEEP_COLOR_MODES 0x17 /* Deep Color Modes */
55
56/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */
57#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS 0x18
58
59#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS 0x30 /* External video parameter settings */
60#define HDMI_EXTERNAL_H_TOTAL_7_0 0x31 /* External horizontal total (LSB) */
61#define HDMI_EXTERNAL_H_TOTAL_11_8 0x32 /* External horizontal total (MSB) */
62#define HDMI_EXTERNAL_H_BLANK_7_0 0x33 /* External horizontal blank (LSB) */
63#define HDMI_EXTERNAL_H_BLANK_9_8 0x34 /* External horizontal blank (MSB) */
64#define HDMI_EXTERNAL_H_DELAY_7_0 0x35 /* External horizontal delay (LSB) */
65#define HDMI_EXTERNAL_H_DELAY_9_8 0x36 /* External horizontal delay (MSB) */
66#define HDMI_EXTERNAL_H_DURATION_7_0 0x37 /* External horizontal duration (LSB) */
67#define HDMI_EXTERNAL_H_DURATION_9_8 0x38 /* External horizontal duration (MSB) */
68#define HDMI_EXTERNAL_V_TOTAL_7_0 0x39 /* External vertical total (LSB) */
69#define HDMI_EXTERNAL_V_TOTAL_9_8 0x3A /* External vertical total (MSB) */
70#define HDMI_AUDIO_VIDEO_SETTING_2 0x3B /* Audio/Video setting.2 */
71#define HDMI_EXTERNAL_V_BLANK 0x3D /* External vertical blank */
72#define HDMI_EXTERNAL_V_DELAY 0x3E /* External vertical delay */
73#define HDMI_EXTERNAL_V_DURATION 0x3F /* External vertical duration */
74#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL 0x40 /* Control packet manual send control */
75#define HDMI_CTRL_PKT_AUTO_SEND 0x41 /* Control packet auto send with VSYNC control */
76#define HDMI_AUTO_CHECKSUM_OPTION 0x42 /* Auto checksum option */
77#define HDMI_VIDEO_SETTING_2 0x45 /* Video setting.2 */
78#define HDMI_OUTPUT_OPTION 0x46 /* Output option */
79#define HDMI_SLIPHDMIT_PARAM_OPTION 0x51 /* SLIPHDMIT parameter option */
80#define HDMI_HSYNC_PMENT_AT_EMB_7_0 0x52 /* HSYNC placement at embedded sync (LSB) */
81#define HDMI_HSYNC_PMENT_AT_EMB_15_8 0x53 /* HSYNC placement at embedded sync (MSB) */
82#define HDMI_VSYNC_PMENT_AT_EMB_7_0 0x54 /* VSYNC placement at embedded sync (LSB) */
83#define HDMI_VSYNC_PMENT_AT_EMB_14_8 0x55 /* VSYNC placement at embedded sync (MSB) */
84#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1 0x56 /* SLIPHDMIT parameter settings.1 */
85#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2 0x57 /* SLIPHDMIT parameter settings.2 */
86#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3 0x58 /* SLIPHDMIT parameter settings.3 */
87#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5 0x59 /* SLIPHDMIT parameter settings.5 */
88#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6 0x5A /* SLIPHDMIT parameter settings.6 */
89#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7 0x5B /* SLIPHDMIT parameter settings.7 */
90#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8 0x5C /* SLIPHDMIT parameter settings.8 */
91#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9 0x5D /* SLIPHDMIT parameter settings.9 */
92#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10 0x5E /* SLIPHDMIT parameter settings.10 */
93#define HDMI_CTRL_PKT_BUF_INDEX 0x5F /* Control packet buffer index */
94#define HDMI_CTRL_PKT_BUF_ACCESS_HB0 0x60 /* Control packet data buffer access window - HB0 */
95#define HDMI_CTRL_PKT_BUF_ACCESS_HB1 0x61 /* Control packet data buffer access window - HB1 */
96#define HDMI_CTRL_PKT_BUF_ACCESS_HB2 0x62 /* Control packet data buffer access window - HB2 */
97#define HDMI_CTRL_PKT_BUF_ACCESS_PB0 0x63 /* Control packet data buffer access window - PB0 */
98#define HDMI_CTRL_PKT_BUF_ACCESS_PB1 0x64 /* Control packet data buffer access window - PB1 */
99#define HDMI_CTRL_PKT_BUF_ACCESS_PB2 0x65 /* Control packet data buffer access window - PB2 */
100#define HDMI_CTRL_PKT_BUF_ACCESS_PB3 0x66 /* Control packet data buffer access window - PB3 */
101#define HDMI_CTRL_PKT_BUF_ACCESS_PB4 0x67 /* Control packet data buffer access window - PB4 */
102#define HDMI_CTRL_PKT_BUF_ACCESS_PB5 0x68 /* Control packet data buffer access window - PB5 */
103#define HDMI_CTRL_PKT_BUF_ACCESS_PB6 0x69 /* Control packet data buffer access window - PB6 */
104#define HDMI_CTRL_PKT_BUF_ACCESS_PB7 0x6A /* Control packet data buffer access window - PB7 */
105#define HDMI_CTRL_PKT_BUF_ACCESS_PB8 0x6B /* Control packet data buffer access window - PB8 */
106#define HDMI_CTRL_PKT_BUF_ACCESS_PB9 0x6C /* Control packet data buffer access window - PB9 */
107#define HDMI_CTRL_PKT_BUF_ACCESS_PB10 0x6D /* Control packet data buffer access window - PB10 */
108#define HDMI_CTRL_PKT_BUF_ACCESS_PB11 0x6E /* Control packet data buffer access window - PB11 */
109#define HDMI_CTRL_PKT_BUF_ACCESS_PB12 0x6F /* Control packet data buffer access window - PB12 */
110#define HDMI_CTRL_PKT_BUF_ACCESS_PB13 0x70 /* Control packet data buffer access window - PB13 */
111#define HDMI_CTRL_PKT_BUF_ACCESS_PB14 0x71 /* Control packet data buffer access window - PB14 */
112#define HDMI_CTRL_PKT_BUF_ACCESS_PB15 0x72 /* Control packet data buffer access window - PB15 */
113#define HDMI_CTRL_PKT_BUF_ACCESS_PB16 0x73 /* Control packet data buffer access window - PB16 */
114#define HDMI_CTRL_PKT_BUF_ACCESS_PB17 0x74 /* Control packet data buffer access window - PB17 */
115#define HDMI_CTRL_PKT_BUF_ACCESS_PB18 0x75 /* Control packet data buffer access window - PB18 */
116#define HDMI_CTRL_PKT_BUF_ACCESS_PB19 0x76 /* Control packet data buffer access window - PB19 */
117#define HDMI_CTRL_PKT_BUF_ACCESS_PB20 0x77 /* Control packet data buffer access window - PB20 */
118#define HDMI_CTRL_PKT_BUF_ACCESS_PB21 0x78 /* Control packet data buffer access window - PB21 */
119#define HDMI_CTRL_PKT_BUF_ACCESS_PB22 0x79 /* Control packet data buffer access window - PB22 */
120#define HDMI_CTRL_PKT_BUF_ACCESS_PB23 0x7A /* Control packet data buffer access window - PB23 */
121#define HDMI_CTRL_PKT_BUF_ACCESS_PB24 0x7B /* Control packet data buffer access window - PB24 */
122#define HDMI_CTRL_PKT_BUF_ACCESS_PB25 0x7C /* Control packet data buffer access window - PB25 */
123#define HDMI_CTRL_PKT_BUF_ACCESS_PB26 0x7D /* Control packet data buffer access window - PB26 */
124#define HDMI_CTRL_PKT_BUF_ACCESS_PB27 0x7E /* Control packet data buffer access window - PB27 */
125#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW 0x80 /* EDID/KSV FIFO access window */
126#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0 0x81 /* DDC bus access frequency control (LSB) */
127#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8 0x82 /* DDC bus access frequency control (MSB) */
128#define HDMI_INTERRUPT_MASK_1 0x92 /* Interrupt mask.1 */
129#define HDMI_INTERRUPT_MASK_2 0x93 /* Interrupt mask.2 */
130#define HDMI_INTERRUPT_STATUS_1 0x94 /* Interrupt status.1 */
131#define HDMI_INTERRUPT_STATUS_2 0x95 /* Interrupt status.2 */
132#define HDMI_INTERRUPT_MASK_3 0x96 /* Interrupt mask.3 */
133#define HDMI_INTERRUPT_MASK_4 0x97 /* Interrupt mask.4 */
134#define HDMI_INTERRUPT_STATUS_3 0x98 /* Interrupt status.3 */
135#define HDMI_INTERRUPT_STATUS_4 0x99 /* Interrupt status.4 */
136#define HDMI_SOFTWARE_HDCP_CONTROL_1 0x9A /* Software HDCP control.1 */
137#define HDMI_FRAME_COUNTER 0x9C /* Frame counter */
138#define HDMI_FRAME_COUNTER_FOR_RI_CHECK 0x9D /* Frame counter for Ri check */
139#define HDMI_HDCP_CONTROL 0xAF /* HDCP control */
140#define HDMI_RI_FRAME_COUNT_REGISTER 0xB2 /* Ri frame count register */
141#define HDMI_DDC_BUS_CONTROL 0xB7 /* DDC bus control */
142#define HDMI_HDCP_STATUS 0xB8 /* HDCP status */
143#define HDMI_SHA0 0xB9 /* sha0 */
144#define HDMI_SHA1 0xBA /* sha1 */
145#define HDMI_SHA2 0xBB /* sha2 */
146#define HDMI_SHA3 0xBC /* sha3 */
147#define HDMI_SHA4 0xBD /* sha4 */
148#define HDMI_BCAPS_READ 0xBE /* BCAPS read / debug */
149#define HDMI_AKSV_BKSV_7_0_MONITOR 0xBF /* AKSV/BKSV[7:0] monitor */
150#define HDMI_AKSV_BKSV_15_8_MONITOR 0xC0 /* AKSV/BKSV[15:8] monitor */
151#define HDMI_AKSV_BKSV_23_16_MONITOR 0xC1 /* AKSV/BKSV[23:16] monitor */
152#define HDMI_AKSV_BKSV_31_24_MONITOR 0xC2 /* AKSV/BKSV[31:24] monitor */
153#define HDMI_AKSV_BKSV_39_32_MONITOR 0xC3 /* AKSV/BKSV[39:32] monitor */
154#define HDMI_EDID_SEGMENT_POINTER 0xC4 /* EDID segment pointer */
155#define HDMI_EDID_WORD_ADDRESS 0xC5 /* EDID word address */
156#define HDMI_EDID_DATA_FIFO_ADDRESS 0xC6 /* EDID data FIFO address */
157#define HDMI_NUM_OF_HDMI_DEVICES 0xC7 /* Number of HDMI devices */
158#define HDMI_HDCP_ERROR_CODE 0xC8 /* HDCP error code */
159#define HDMI_100MS_TIMER_SET 0xC9 /* 100ms timer setting */
160#define HDMI_5SEC_TIMER_SET 0xCA /* 5sec timer setting */
161#define HDMI_RI_READ_COUNT 0xCB /* Ri read count */
162#define HDMI_AN_SEED 0xCC /* An seed */
163#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED 0xCD /* Maximum number of receivers allowed */
164#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1 0xCE /* HDCP memory access control.1 */
165#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2 0xCF /* HDCP memory access control.2 */
166#define HDMI_HDCP_CONTROL_2 0xD0 /* HDCP Control 2 */
167#define HDMI_HDCP_KEY_MEMORY_CONTROL 0xD2 /* HDCP Key Memory Control */
168#define HDMI_COLOR_SPACE_CONV_CONFIG_1 0xD3 /* Color space conversion configuration.1 */
169#define HDMI_VIDEO_SETTING_3 0xD4 /* Video setting.3 */
170#define HDMI_RI_7_0 0xD5 /* Ri[7:0] */
171#define HDMI_RI_15_8 0xD6 /* Ri[15:8] */
172#define HDMI_PJ 0xD7 /* Pj */
173#define HDMI_SHA_RD 0xD8 /* sha_rd */
174#define HDMI_RI_7_0_SAVED 0xD9 /* Ri[7:0] saved */
175#define HDMI_RI_15_8_SAVED 0xDA /* Ri[15:8] saved */
176#define HDMI_PJ_SAVED 0xDB /* Pj saved */
177#define HDMI_NUM_OF_DEVICES 0xDC /* Number of devices */
178#define HDMI_HOT_PLUG_MSENS_STATUS 0xDF /* Hot plug/MSENS status */
179#define HDMI_BCAPS_WRITE 0xE0 /* bcaps */
180#define HDMI_BSTAT_7_0 0xE1 /* bstat[7:0] */
181#define HDMI_BSTAT_15_8 0xE2 /* bstat[15:8] */
182#define HDMI_BKSV_7_0 0xE3 /* bksv[7:0] */
183#define HDMI_BKSV_15_8 0xE4 /* bksv[15:8] */
184#define HDMI_BKSV_23_16 0xE5 /* bksv[23:16] */
185#define HDMI_BKSV_31_24 0xE6 /* bksv[31:24] */
186#define HDMI_BKSV_39_32 0xE7 /* bksv[39:32] */
187#define HDMI_AN_7_0 0xE8 /* An[7:0] */
188#define HDMI_AN_15_8 0xE9 /* An [15:8] */
189#define HDMI_AN_23_16 0xEA /* An [23:16] */
190#define HDMI_AN_31_24 0xEB /* An [31:24] */
191#define HDMI_AN_39_32 0xEC /* An [39:32] */
192#define HDMI_AN_47_40 0xED /* An [47:40] */
193#define HDMI_AN_55_48 0xEE /* An [55:48] */
194#define HDMI_AN_63_56 0xEF /* An [63:56] */
195#define HDMI_PRODUCT_ID 0xF0 /* Product ID */
196#define HDMI_REVISION_ID 0xF1 /* Revision ID */
197#define HDMI_TEST_MODE 0xFE /* Test mode */
198
199enum hotplug_state {
200 HDMI_HOTPLUG_DISCONNECTED,
201 HDMI_HOTPLUG_CONNECTED,
202 HDMI_HOTPLUG_EDID_DONE,
203};
204
205struct sh_hdmi {
206 void __iomem *base;
207 enum hotplug_state hp_state;
208 struct clk *hdmi_clk;
209 struct device *dev;
210 struct fb_info *info;
211 struct delayed_work edid_work;
212 struct fb_var_screeninfo var;
213};
214
215static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
216{
217 iowrite8(data, hdmi->base + reg);
218}
219
220static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
221{
222 return ioread8(hdmi->base + reg);
223}
224
225/* External video parameter settings */
226static void hdmi_external_video_param(struct sh_hdmi *hdmi)
227{
228 struct fb_var_screeninfo *var = &hdmi->var;
229 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
230 u8 sync = 0;
231
232 htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len;
233
234 hdelay = var->hsync_len + var->left_margin;
235 hblank = var->right_margin + hdelay;
236
237 /*
238 * Vertical timing looks a bit different in Figure 18,
239 * but let's try the same first by setting offset = 0
240 */
241 vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
242
243 vdelay = var->vsync_len + var->upper_margin;
244 vblank = var->lower_margin + vdelay;
245 voffset = min(var->upper_margin / 2, 6U);
246
247 /*
248 * [3]: VSYNC polarity: Positive
249 * [2]: HSYNC polarity: Positive
250 * [1]: Interlace/Progressive: Progressive
251 * [0]: External video settings enable: used.
252 */
253 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
254 sync |= 4;
255 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
256 sync |= 8;
257
258 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
259 htotal, hblank, hdelay, var->hsync_len,
260 vtotal, vblank, vdelay, var->vsync_len, sync);
261
262 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
263
264 hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0);
265 hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8);
266
267 hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0);
268 hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8);
269
270 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
271 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
272
273 hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
274 hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
275
276 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
277 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
278
279 hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK);
280
281 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
282
283 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
284
285 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */
286}
287
288/**
289 * sh_hdmi_video_config()
290 */
291static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
292{
293 /*
294 * [7:4]: Audio sampling frequency: 48kHz
295 * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green)
296 * [0]: Internal/External DE select: internal
297 */
298 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
299
300 /*
301 * [7:6]: Video output format: RGB 4:4:4
302 * [5:4]: Input video data width: 8 bit
303 * [3:1]: EAV/SAV location: channel 1
304 * [0]: Video input color space: RGB
305 */
306 hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1);
307
308 /*
309 * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is
310 * left at 0 by default, this configures 24bpp and sets the Color Depth
311 * (CD) field in the General Control Packet
312 */
313 hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES);
314}
315
316/**
317 * sh_hdmi_audio_config()
318 */
319static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
320{
321 /*
322 * [7:4] L/R data swap control
323 * [3:0] appropriate N[19:16]
324 */
325 hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT);
326 /* appropriate N[15:8] */
327 hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8);
328 /* appropriate N[7:0] */
329 hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0);
330
331 /* [7:4] 48 kHz SPDIF not used */
332 hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS);
333
334 /*
335 * [6:5] set required down sampling rate if required
336 * [4:3] set required audio source
337 */
338 hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1);
339
340 /* [3:0] set sending channel number for channel status */
341 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
342
343 /*
344 * [5:2] set valid I2S source input pin
345 * [1:0] set input I2S source mode
346 */
347 hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET);
348
349 /* [7:4] set valid DSD source input pin */
350 hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET);
351
352 /* [7:0] set appropriate I2S input pin swap settings if required */
353 hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP);
354
355 /*
356 * [7] set validity bit for channel status
357 * [3:0] set original sample frequency for channel status
358 */
359 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1);
360
361 /*
362 * [7] set value for channel status
363 * [6] set value for channel status
364 * [5] set copyright bit for channel status
365 * [4:2] set additional information for channel status
366 * [1:0] set clock accuracy for channel status
367 */
368 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2);
369
370 /* [7:0] set category code for channel status */
371 hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE);
372
373 /*
374 * [7:4] set source number for channel status
375 * [3:0] set word length for channel status
376 */
377 hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN);
378
379 /* [7:4] set sample frequency for channel status */
380 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
381}
382
383/**
384 * sh_hdmi_phy_config()
385 */
386static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
387{
388 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
389 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
390 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
391 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
392 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
393 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
394 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
395 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
396 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
397 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
398 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
399}
400
401/**
402 * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET
403 */
404static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
405{
406 /* AVI InfoFrame */
407 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
408
409 /* Packet Type = 0x82 */
410 hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
411
412 /* Version = 0x02 */
413 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
414
415 /* Length = 13 (0x0D) */
416 hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
417
418 /* N. A. Checksum */
419 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
420
421 /*
422 * Y = RGB
423 * A0 = No Data
424 * B = Bar Data not valid
425 * S = No Data
426 */
427 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
428
429 /*
430 * C = No Data
431 * M = 16:9 Picture Aspect Ratio
432 * R = Same as picture aspect ratio
433 */
434 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
435
436 /*
437 * ITC = No Data
438 * EC = xvYCC601
439 * Q = Default (depends on video format)
440 * SC = No Known non_uniform Scaling
441 */
442 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
443
444 /*
445 * VIC = 1280 x 720p: ignored if external config is used
446 * Send 2 for 720 x 480p, 16 for 1080p
447 */
448 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
449
450 /* PR = No Repetition */
451 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
452
453 /* Line Number of End of Top Bar (lower 8 bits) */
454 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
455
456 /* Line Number of End of Top Bar (upper 8 bits) */
457 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
458
459 /* Line Number of Start of Bottom Bar (lower 8 bits) */
460 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
461
462 /* Line Number of Start of Bottom Bar (upper 8 bits) */
463 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
464
465 /* Pixel Number of End of Left Bar (lower 8 bits) */
466 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
467
468 /* Pixel Number of End of Left Bar (upper 8 bits) */
469 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11);
470
471 /* Pixel Number of Start of Right Bar (lower 8 bits) */
472 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12);
473
474 /* Pixel Number of Start of Right Bar (upper 8 bits) */
475 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13);
476}
477
478/**
479 * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET
480 */
481static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
482{
483 /* Audio InfoFrame */
484 hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX);
485
486 /* Packet Type = 0x84 */
487 hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
488
489 /* Version Number = 0x01 */
490 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
491
492 /* 0 Length = 10 (0x0A) */
493 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
494
495 /* n. a. Checksum */
496 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
497
498 /* Audio Channel Count = Refer to Stream Header */
499 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
500
501 /* Refer to Stream Header */
502 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
503
504 /* Format depends on coding type (i.e. CT0...CT3) */
505 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
506
507 /* Speaker Channel Allocation = Front Right + Front Left */
508 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
509
510 /* Level Shift Value = 0 dB, Down - mix is permitted or no information */
511 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
512
513 /* Reserved (0) */
514 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
515 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
516 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
517 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
518 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
519}
520
521/**
522 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
523 */
524static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
525{
526 int i;
527
528 /* Gamut Metadata Packet */
529 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
530
531 /* Packet Type = 0x0A */
532 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
533 /* Gamut Packet is not used, so default value */
534 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
535 /* Gamut Packet is not used, so default value */
536 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
537
538 /* GBD bytes 0 through 27 */
539 for (i = 0; i <= 27; i++)
540 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
541 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
542}
543
544/**
545 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
546 */
547static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
548{
549 int i;
550
551 /* Audio Content Protection Packet (ACP) */
552 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
553
554 /* Packet Type = 0x04 */
555 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
556 /* ACP_Type */
557 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
558 /* Reserved (0) */
559 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
560
561 /* GBD bytes 0 through 27 */
562 for (i = 0; i <= 27; i++)
563 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
564 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
565}
566
567/**
568 * sh_hdmi_isrc1_setup() - ISRC1 Packet
569 */
570static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
571{
572 int i;
573
574 /* ISRC1 Packet */
575 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
576
577 /* Packet Type = 0x05 */
578 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
579 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
581 /* Reserved (0) */
582 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
583
584 /* PB0 UPC_EAN_ISRC_0-15 */
585 /* Bytes PB16-PB27 shall be set to a value of 0. */
586 for (i = 0; i <= 27; i++)
587 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
588 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
589}
590
591/**
592 * sh_hdmi_isrc2_setup() - ISRC2 Packet
593 */
594static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
595{
596 int i;
597
598 /* ISRC2 Packet */
599 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
600
601 /* HB0 Packet Type = 0x06 */
602 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
603 /* Reserved (0) */
604 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
605 /* Reserved (0) */
606 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
607
608 /* PB0 UPC_EAN_ISRC_16-31 */
609 /* Bytes PB16-PB27 shall be set to a value of 0. */
610 for (i = 0; i <= 27; i++)
611 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
612 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
613}
614
615/**
616 * sh_hdmi_configure() - Initialise HDMI for output
617 */
618static void sh_hdmi_configure(struct sh_hdmi *hdmi)
619{
620 /* Configure video format */
621 sh_hdmi_video_config(hdmi);
622
623 /* Configure audio format */
624 sh_hdmi_audio_config(hdmi);
625
626 /* Configure PHY */
627 sh_hdmi_phy_config(hdmi);
628
629 /* Auxiliary Video Information (AVI) InfoFrame */
630 sh_hdmi_avi_infoframe_setup(hdmi);
631
632 /* Audio InfoFrame */
633 sh_hdmi_audio_infoframe_setup(hdmi);
634
635 /* Gamut Metadata packet */
636 sh_hdmi_gamut_metadata_setup(hdmi);
637
638 /* Audio Content Protection (ACP) Packet */
639 sh_hdmi_acp_setup(hdmi);
640
641 /* ISRC1 Packet */
642 sh_hdmi_isrc1_setup(hdmi);
643
644 /* ISRC2 Packet */
645 sh_hdmi_isrc2_setup(hdmi);
646
647 /*
648 * Control packet auto send with VSYNC control: auto send
649 * General control, Gamut metadata, ISRC, and ACP packets
650 */
651 hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND);
652
653 /* FIXME */
654 msleep(10);
655
656 /* PS mode b->d, reset PLLA and PLLB */
657 hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
658
659 udelay(10);
660
661 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
662}
663
664static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
665{
666 struct fb_var_screeninfo *var = &hdmi->var;
667 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
668 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg;
669 unsigned long height = var->height, width = var->width;
670 int i;
671 u8 edid[128];
672
673 /* Read EDID */
674 pr_debug("Read back EDID code:");
675 for (i = 0; i < 128; i++) {
676 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
677#ifdef DEBUG
678 if ((i % 16) == 0) {
679 printk(KERN_CONT "\n");
680 printk(KERN_DEBUG "%02X | %02X", i, edid[i]);
681 } else {
682 printk(KERN_CONT " %02X", edid[i]);
683 }
684#endif
685 }
686#ifdef DEBUG
687 printk(KERN_CONT "\n");
688#endif
689 fb_parse_edid(edid, var);
690 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n",
691 var->left_margin, var->xres, var->right_margin, var->hsync_len,
692 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
693 PICOS2KHZ(var->pixclock));
694
695 /* FIXME: Use user-provided configuration instead of EDID */
696 var->width = width;
697 var->xres = lcd_cfg->xres;
698 var->xres_virtual = lcd_cfg->xres;
699 var->left_margin = lcd_cfg->left_margin;
700 var->right_margin = lcd_cfg->right_margin;
701 var->hsync_len = lcd_cfg->hsync_len;
702 var->height = height;
703 var->yres = lcd_cfg->yres;
704 var->yres_virtual = lcd_cfg->yres * 2;
705 var->upper_margin = lcd_cfg->upper_margin;
706 var->lower_margin = lcd_cfg->lower_margin;
707 var->vsync_len = lcd_cfg->vsync_len;
708 var->sync = lcd_cfg->sync;
709 var->pixclock = lcd_cfg->pixclock;
710
711 hdmi_external_video_param(hdmi);
712}
713
714static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
715{
716 struct sh_hdmi *hdmi = dev_id;
717 u8 status1, status2, mask1, mask2;
718
719 /* mode_b and PLLA and PLLB reset */
720 hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
721
722 /* How long shall reset be held? */
723 udelay(10);
724
725 /* mode_b and PLLA and PLLB reset release */
726 hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
727
728 status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
729 status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
730
731 mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1);
732 mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2);
733
734 /* Correct would be to ack only set bits, but the datasheet requires 0xff */
735 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1);
736 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
737
738 if (printk_ratelimit())
739 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
740 irq, status1, mask1, status2, mask2);
741
742 if (!((status1 & mask1) | (status2 & mask2))) {
743 return IRQ_NONE;
744 } else if (status1 & 0xc0) {
745 u8 msens;
746
747 /* Datasheet specifies 10ms... */
748 udelay(500);
749
750 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
751 pr_debug("MSENS 0x%x\n", msens);
752 /* Check, if hot plug & MSENS pin status are both high */
753 if ((msens & 0xC0) == 0xC0) {
754 /* Display plug in */
755 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
756
757 /* Set EDID word address */
758 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
759 /* Set EDID segment pointer */
760 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
761 /* Enable EDID interrupt */
762 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
763 } else if (!(status1 & 0x80)) {
764 /* Display unplug, beware multiple interrupts */
765 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED)
766 schedule_delayed_work(&hdmi->edid_work, 0);
767
768 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
769 /* display_off will switch back to mode_a */
770 }
771 } else if (status1 & 2) {
772 /* EDID error interrupt: retry */
773 /* Set EDID word address */
774 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
775 /* Set EDID segment pointer */
776 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
777 } else if (status1 & 4) {
778 /* Disable EDID interrupt */
779 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
780 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
781 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
782 }
783
784 return IRQ_HANDLED;
785}
786
787static void hdmi_display_on(void *arg, struct fb_info *info)
788{
789 struct sh_hdmi *hdmi = arg;
790 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
791
792 if (info->var.xres != 1280 || info->var.yres != 720) {
793 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n",
794 info->var.xres, info->var.yres);
795 return;
796 }
797
798 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
799 /*
800 * FIXME: not a good place to store fb_info. And we cannot nullify it
801 * even on monitor disconnect. What should the lifecycle be?
802 */
803 hdmi->info = info;
804 switch (hdmi->hp_state) {
805 case HDMI_HOTPLUG_EDID_DONE:
806 /* PS mode d->e. All functions are active */
807 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
808 pr_debug("HDMI running\n");
809 break;
810 case HDMI_HOTPLUG_DISCONNECTED:
811 info->state = FBINFO_STATE_SUSPENDED;
812 default:
813 hdmi->var = info->var;
814 }
815}
816
817static void hdmi_display_off(void *arg)
818{
819 struct sh_hdmi *hdmi = arg;
820 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
821
822 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev);
823 /* PS mode e->a */
824 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
825}
826
827/* Hotplug interrupt occurred, read EDID */
828static void edid_work_fn(struct work_struct *work)
829{
830 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
831 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
832
833 pr_debug("%s(%p): begin, hotplug status %d\n", __func__,
834 pdata->lcd_dev, hdmi->hp_state);
835
836 if (!pdata->lcd_dev)
837 return;
838
839 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
840 pm_runtime_get_sync(hdmi->dev);
841 /* A device has been plugged in */
842 sh_hdmi_read_edid(hdmi);
843 msleep(10);
844 sh_hdmi_configure(hdmi);
845 /* Switched to another (d) power-save mode */
846 msleep(10);
847
848 if (!hdmi->info)
849 return;
850
851 acquire_console_sem();
852
853 /* HDMI plug in */
854 hdmi->info->var = hdmi->var;
855 if (hdmi->info->state != FBINFO_STATE_RUNNING)
856 fb_set_suspend(hdmi->info, 0);
857 else
858 hdmi_display_on(hdmi, hdmi->info);
859
860 release_console_sem();
861 } else {
862 if (!hdmi->info)
863 return;
864
865 acquire_console_sem();
866
867 /* HDMI disconnect */
868 fb_set_suspend(hdmi->info, 1);
869
870 release_console_sem();
871 pm_runtime_put(hdmi->dev);
872 }
873
874 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev);
875}
876
877static int __init sh_hdmi_probe(struct platform_device *pdev)
878{
879 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
880 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
881 int irq = platform_get_irq(pdev, 0), ret;
882 struct sh_hdmi *hdmi;
883 long rate;
884
885 if (!res || !pdata || irq < 0)
886 return -ENODEV;
887
888 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
889 if (!hdmi) {
890 dev_err(&pdev->dev, "Cannot allocate device data\n");
891 return -ENOMEM;
892 }
893
894 hdmi->dev = &pdev->dev;
895
896 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
897 if (IS_ERR(hdmi->hdmi_clk)) {
898 ret = PTR_ERR(hdmi->hdmi_clk);
899 dev_err(&pdev->dev, "Unable to get clock: %d\n", ret);
900 goto egetclk;
901 }
902
903 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000;
904
905 rate = clk_round_rate(hdmi->hdmi_clk, rate);
906 if (rate < 0) {
907 ret = rate;
908 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
909 goto erate;
910 }
911
912 ret = clk_set_rate(hdmi->hdmi_clk, rate);
913 if (ret < 0) {
914 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
915 goto erate;
916 }
917
918 pr_debug("HDMI set frequency %lu\n", rate);
919
920 ret = clk_enable(hdmi->hdmi_clk);
921 if (ret < 0) {
922 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
923 goto eclkenable;
924 }
925
926 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
927
928 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
929 dev_err(&pdev->dev, "HDMI register region already claimed\n");
930 ret = -EBUSY;
931 goto ereqreg;
932 }
933
934 hdmi->base = ioremap(res->start, resource_size(res));
935 if (!hdmi->base) {
936 dev_err(&pdev->dev, "HDMI register region already claimed\n");
937 ret = -ENOMEM;
938 goto emap;
939 }
940
941 platform_set_drvdata(pdev, hdmi);
942
943#if 1
944 /* Product and revision IDs are 0 in sh-mobile version */
945 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
946 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
947#endif
948
949 /* Set up LCDC callbacks */
950 pdata->lcd_chan->board_cfg.board_data = hdmi;
951 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on;
952 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off;
953
954 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn);
955
956 pm_runtime_enable(&pdev->dev);
957 pm_runtime_resume(&pdev->dev);
958
959 ret = request_irq(irq, sh_hdmi_hotplug, 0,
960 dev_name(&pdev->dev), hdmi);
961 if (ret < 0) {
962 dev_err(&pdev->dev, "Unable to request irq: %d\n", ret);
963 goto ereqirq;
964 }
965
966 return 0;
967
968ereqirq:
969 pm_runtime_disable(&pdev->dev);
970 iounmap(hdmi->base);
971emap:
972 release_mem_region(res->start, resource_size(res));
973ereqreg:
974 clk_disable(hdmi->hdmi_clk);
975eclkenable:
976erate:
977 clk_put(hdmi->hdmi_clk);
978egetclk:
979 kfree(hdmi);
980
981 return ret;
982}
983
984static int __exit sh_hdmi_remove(struct platform_device *pdev)
985{
986 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
987 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
988 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
989 int irq = platform_get_irq(pdev, 0);
990
991 pdata->lcd_chan->board_cfg.display_on = NULL;
992 pdata->lcd_chan->board_cfg.display_off = NULL;
993 pdata->lcd_chan->board_cfg.board_data = NULL;
994
995 free_irq(irq, hdmi);
996 pm_runtime_disable(&pdev->dev);
997 cancel_delayed_work_sync(&hdmi->edid_work);
998 clk_disable(hdmi->hdmi_clk);
999 clk_put(hdmi->hdmi_clk);
1000 iounmap(hdmi->base);
1001 release_mem_region(res->start, resource_size(res));
1002 kfree(hdmi);
1003
1004 return 0;
1005}
1006
1007static struct platform_driver sh_hdmi_driver = {
1008 .remove = __exit_p(sh_hdmi_remove),
1009 .driver = {
1010 .name = "sh-mobile-hdmi",
1011 },
1012};
1013
1014static int __init sh_hdmi_init(void)
1015{
1016 return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
1017}
1018module_init(sh_hdmi_init);
1019
1020static void __exit sh_hdmi_exit(void)
1021{
1022 platform_driver_unregister(&sh_hdmi_driver);
1023}
1024module_exit(sh_hdmi_exit);
1025
1026MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1027MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
1028MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 12c451a711e9..d72075a9f01c 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -56,6 +56,7 @@ static int lcdc_shared_regs[] = {
56/* per-channel registers */ 56/* per-channel registers */
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, 58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
59 NR_CH_REGS }; 60 NR_CH_REGS };
60 61
61static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
@@ -74,6 +75,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
74 [LDVLNR] = 0x450, 75 [LDVLNR] = 0x450,
75 [LDVSYNR] = 0x454, 76 [LDVSYNR] = 0x454,
76 [LDPMR] = 0x460, 77 [LDPMR] = 0x460,
78 [LDHAJR] = 0x4a0,
77}; 79};
78 80
79static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { 81static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
@@ -137,6 +139,7 @@ struct sh_mobile_lcdc_priv {
137 struct clk *dot_clk; 139 struct clk *dot_clk;
138 unsigned long lddckr; 140 unsigned long lddckr;
139 struct sh_mobile_lcdc_chan ch[2]; 141 struct sh_mobile_lcdc_chan ch[2];
142 struct notifier_block notifier;
140 unsigned long saved_shared_regs[NR_SHARED_REGS]; 143 unsigned long saved_shared_regs[NR_SHARED_REGS];
141 int started; 144 int started;
142}; 145};
@@ -404,6 +407,56 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
404 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 407 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
405} 408}
406 409
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{
412 struct fb_var_screeninfo *var = &ch->info->var;
413 unsigned long h_total, hsync_pos;
414 u32 tmp;
415
416 tmp = ch->ldmt1r_value;
417 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
418 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
419 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
420 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
421 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
422 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
423 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
424 lcdc_write_chan(ch, LDMT1R, tmp);
425
426 /* setup SYS bus */
427 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429
430 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len +
432 var->left_margin + var->right_margin;
433 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp);
436
437 hsync_pos = var->xres + var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp);
441
442 /* vertical configuration */
443 tmp = var->yres + var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp);
447
448 tmp = var->yres + var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp);
451
452 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) |
454 ((h_total & 7) << 16) |
455 ((var->hsync_len & 7) << 8) |
456 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp);
458}
459
407static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
408{ 461{
409 struct sh_mobile_lcdc_chan *ch; 462 struct sh_mobile_lcdc_chan *ch;
@@ -470,49 +523,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
470 if (!ch->enabled) 523 if (!ch->enabled)
471 continue; 524 continue;
472 525
473 tmp = ch->ldmt1r_value; 526 sh_mobile_lcdc_geometry(ch);
474 tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
475 tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
476 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
477 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
478 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
479 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
480 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
481 lcdc_write_chan(ch, LDMT1R, tmp);
482
483 /* setup SYS bus */
484 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
485 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
486
487 /* horizontal configuration */
488 tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
489 tmp += lcd_cfg->left_margin;
490 tmp += lcd_cfg->right_margin;
491 tmp /= 8; /* HTCN */
492 tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
493 lcdc_write_chan(ch, LDHCNR, tmp);
494
495 tmp = lcd_cfg->xres;
496 tmp += lcd_cfg->right_margin;
497 tmp /= 8; /* HSYNP */
498 tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
499 lcdc_write_chan(ch, LDHSYNR, tmp);
500 527
501 /* power supply */ 528 /* power supply */
502 lcdc_write_chan(ch, LDPMR, 0); 529 lcdc_write_chan(ch, LDPMR, 0);
503 530
504 /* vertical configuration */
505 tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
506 tmp += lcd_cfg->upper_margin;
507 tmp += lcd_cfg->lower_margin; /* VTLN */
508 tmp |= lcd_cfg->yres << 16; /* VDLN */
509 lcdc_write_chan(ch, LDVLNR, tmp);
510
511 tmp = lcd_cfg->yres;
512 tmp += lcd_cfg->lower_margin; /* VSYNP */
513 tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
514 lcdc_write_chan(ch, LDVSYNR, tmp);
515
516 board_cfg = &ch->cfg.board_cfg; 531 board_cfg = &ch->cfg.board_cfg;
517 if (board_cfg->setup_sys) 532 if (board_cfg->setup_sys)
518 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 533 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
@@ -577,7 +592,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
577 592
578 board_cfg = &ch->cfg.board_cfg; 593 board_cfg = &ch->cfg.board_cfg;
579 if (board_cfg->display_on) 594 if (board_cfg->display_on)
580 board_cfg->display_on(board_cfg->board_data); 595 board_cfg->display_on(board_cfg->board_data, ch->info);
581 } 596 }
582 597
583 return 0; 598 return 0;
@@ -943,6 +958,62 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
943 .runtime_resume = sh_mobile_lcdc_runtime_resume, 958 .runtime_resume = sh_mobile_lcdc_runtime_resume,
944}; 959};
945 960
961static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data)
963{
964 struct fb_event *event = data;
965 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var;
969
970 if (&ch->lcdc->notifier != nb)
971 return 0;
972
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data);
975
976 switch(action) {
977 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off)
979 board_cfg->display_off(board_cfg->board_data);
980 pm_runtime_put(info->device);
981 break;
982 case FB_EVENT_RESUME:
983 var = &info->var;
984
985 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on)
987 board_cfg->display_on(board_cfg->board_data, ch->info);
988
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 }
1006
1007 pm_runtime_get_sync(info->device);
1008
1009 sh_mobile_lcdc_geometry(ch);
1010
1011 break;
1012 }
1013
1014 return 0;
1015}
1016
946static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1017static int sh_mobile_lcdc_remove(struct platform_device *pdev);
947 1018
948static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1019static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -1020,15 +1091,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020 goto err1; 1091 goto err1;
1021 } 1092 }
1022 1093
1094 priv->base = ioremap_nocache(res->start, resource_size(res));
1095 if (!priv->base)
1096 goto err1;
1097
1023 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); 1098 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
1024 if (error) { 1099 if (error) {
1025 dev_err(&pdev->dev, "unable to setup clocks\n"); 1100 dev_err(&pdev->dev, "unable to setup clocks\n");
1026 goto err1; 1101 goto err1;
1027 } 1102 }
1028 1103
1029 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
1030
1031 for (i = 0; i < j; i++) { 1104 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg;
1032 cfg = &priv->ch[i].cfg; 1107 cfg = &priv->ch[i].cfg;
1033 1108
1034 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
@@ -1039,22 +1114,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1039 } 1114 }
1040 1115
1041 info = priv->ch[i].info; 1116 info = priv->ch[i].info;
1117 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1042 info->fbops = &sh_mobile_lcdc_ops; 1119 info->fbops = &sh_mobile_lcdc_ops;
1043 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; 1120 var->xres = var->xres_virtual = lcd_cfg->xres;
1044 info->var.yres = cfg->lcd_cfg.yres; 1121 var->yres = lcd_cfg->yres;
1045 /* Default Y virtual resolution is 2x panel size */ 1122 /* Default Y virtual resolution is 2x panel size */
1046 info->var.yres_virtual = info->var.yres * 2; 1123 var->yres_virtual = var->yres * 2;
1047 info->var.width = cfg->lcd_size_cfg.width; 1124 var->width = cfg->lcd_size_cfg.width;
1048 info->var.height = cfg->lcd_size_cfg.height; 1125 var->height = cfg->lcd_size_cfg.height;
1049 info->var.activate = FB_ACTIVATE_NOW; 1126 var->activate = FB_ACTIVATE_NOW;
1050 error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); 1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1051 if (error) 1137 if (error)
1052 break; 1138 break;
1053 1139
1054 info->fix = sh_mobile_lcdc_fix; 1140 info->fix = sh_mobile_lcdc_fix;
1055 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); 1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1056 info->fix.smem_len = info->fix.line_length * 1142 info->fix.smem_len = info->fix.line_length *
1057 info->var.yres_virtual; 1143 var->yres_virtual;
1058 1144
1059 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1060 &priv->ch[i].dma_handle, GFP_KERNEL); 1146 &priv->ch[i].dma_handle, GFP_KERNEL);
@@ -1119,10 +1205,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1119 ch->cfg.bpp); 1205 ch->cfg.bpp);
1120 1206
1121 /* deferred io mode: disable clock to save power */ 1207 /* deferred io mode: disable clock to save power */
1122 if (info->fbdefio) 1208 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1123 sh_mobile_lcdc_clk_off(priv); 1209 sh_mobile_lcdc_clk_off(priv);
1124 } 1210 }
1125 1211
1212 /* Failure ignored */
1213 priv->notifier.notifier_call = sh_mobile_lcdc_notify;
1214 fb_register_client(&priv->notifier);
1215
1126 return 0; 1216 return 0;
1127err1: 1217err1:
1128 sh_mobile_lcdc_remove(pdev); 1218 sh_mobile_lcdc_remove(pdev);
@@ -1136,6 +1226,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1136 struct fb_info *info; 1226 struct fb_info *info;
1137 int i; 1227 int i;
1138 1228
1229 fb_unregister_client(&priv->notifier);
1230
1139 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1231 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1140 if (priv->ch[i].info && priv->ch[i].info->dev) 1232 if (priv->ch[i].info && priv->ch[i].info->dev)
1141 unregister_framebuffer(priv->ch[i].info); 1233 unregister_framebuffer(priv->ch[i].info);
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index 7288934c0d49..5dbe06af2226 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
111 return 0; 111 return 0;
112} 112}
113 113
114static int __devinit gfb_probe(struct of_device *op, 114static int __devinit gfb_probe(struct platform_device *op,
115 const struct of_device_id *match) 115 const struct of_device_id *match)
116{ 116{
117 struct device_node *dp = op->dev.of_node; 117 struct device_node *dp = op->dev.of_node;
@@ -172,7 +172,7 @@ err_out:
172 return err; 172 return err;
173} 173}
174 174
175static int __devexit gfb_remove(struct of_device *op) 175static int __devexit gfb_remove(struct platform_device *op)
176{ 176{
177 struct fb_info *info = dev_get_drvdata(&op->dev); 177 struct fb_info *info = dev_get_drvdata(&op->dev);
178 struct gfb_info *gp = info->par; 178 struct gfb_info *gp = info->par;
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index f375e0db6776..77ad27955cf0 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes)
342 info->fix.accel = FB_ACCEL_SUN_TCX; 342 info->fix.accel = FB_ACCEL_SUN_TCX;
343} 343}
344 344
345static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, 345static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
346 struct tcx_par *par) 346 struct tcx_par *par)
347{ 347{
348 if (par->tec) 348 if (par->tec)
@@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
362 info->screen_base, info->fix.smem_len); 362 info->screen_base, info->fix.smem_len);
363} 363}
364 364
365static int __devinit tcx_probe(struct of_device *op, 365static int __devinit tcx_probe(struct platform_device *op,
366 const struct of_device_id *match) 366 const struct of_device_id *match)
367{ 367{
368 struct device_node *dp = op->dev.of_node; 368 struct device_node *dp = op->dev.of_node;
@@ -486,7 +486,7 @@ out_err:
486 return err; 486 return err;
487} 487}
488 488
489static int __devexit tcx_remove(struct of_device *op) 489static int __devexit tcx_remove(struct platform_device *op)
490{ 490{
491 struct fb_info *info = dev_get_drvdata(&op->dev); 491 struct fb_info *info = dev_get_drvdata(&op->dev);
492 struct tcx_par *par = info->par; 492 struct tcx_par *par = info->par;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 7b8839ebf3c4..52ec0959d462 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void)
1977 1977
1978module_exit(uvesafb_exit); 1978module_exit(uvesafb_exit);
1979 1979
1980#define param_get_scroll NULL 1980static int param_set_scroll(const char *val, const struct kernel_param *kp)
1981static int param_set_scroll(const char *val, struct kernel_param *kp)
1982{ 1981{
1983 ypan = 0; 1982 ypan = 0;
1984 1983
@@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp)
1993 1992
1994 return 0; 1993 return 0;
1995} 1994}
1996 1995static struct kernel_param_ops param_ops_scroll = {
1996 .set = param_set_scroll,
1997};
1997#define param_check_scroll(name, p) __param_check(name, p, void) 1998#define param_check_scroll(name, p) __param_check(name, p, void)
1998 1999
1999module_param_named(scroll, ypan, scroll, 0); 2000module_param_named(scroll, ypan, scroll, 0);
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index d31dc96f838a..85d76ec4c63e 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
726 726
727 /* Prepare startup mode */ 727 /* Prepare startup mode */
728 728
729 kparam_block_sysfs_write(mode_option);
729 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 730 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
731 kparam_unblock_sysfs_write(mode_option);
730 if (! ((rc == 1) || (rc == 2))) { 732 if (! ((rc == 1) || (rc == 2))) {
731 rc = -EINVAL; 733 rc = -EINVAL;
732 dev_err(info->device, "mode %s not found\n", mode_option); 734 dev_err(info->device, "mode %s not found\n", mode_option);
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 29b5daacc217..0c9ce88e95e8 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev)
397 */ 397 */
398 398
399static int __devinit 399static int __devinit
400xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) 400xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
401{ 401{
402 const u32 *prop; 402 const u32 *prop;
403 u32 *p; 403 u32 *p;
@@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
477 return -ENODEV; 477 return -ENODEV;
478} 478}
479 479
480static int __devexit xilinxfb_of_remove(struct of_device *op) 480static int __devexit xilinxfb_of_remove(struct platform_device *op)
481{ 481{
482 return xilinxfb_release(&op->dev); 482 return xilinxfb_release(&op->dev);
483} 483}