aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Schocher <hs@denx.de>2011-01-26 02:21:30 -0500
committerPaul Mundt <lethal@linux-sh.org>2011-03-22 04:17:14 -0400
commit4295f9bf74a885da390abc49a3b42a011c1bb890 (patch)
tree6ac387cbdcacd8708611acbaab72dad1b783c90e
parente6a049807105decf5aa7f0c510f5e5ec96c3548e (diff)
video, sm501: add OF binding to support SM501
- add binding to OF, compatible name "smi,sm501" Signed-off-by: Heiko Schocher <hs@denx.de> cc: linux-fbdev@vger.kernel.org cc: devicetree-discuss@ozlabs.org cc: Ben Dooks <ben@simtec.co.uk> cc: Vincent Sanders <vince@simtec.co.uk> cc: Samuel Ortiz <sameo@linux.intel.com> cc: linux-kernel@vger.kernel.org cc: Randy Dunlap <rdunlap@xenotime.net> cc: Paul Mundt <lethal@linux-sh.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--Documentation/powerpc/dts-bindings/sm501.txt34
-rw-r--r--drivers/mfd/sm501.c9
-rw-r--r--drivers/video/sm501fb.c42
3 files changed, 81 insertions, 4 deletions
diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 000000000000..7d319fba9b5b
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,34 @@
1* SM SM501
2
3The SM SM501 is a LCD controller, with proper hardware, it can also
4drive DVI monitors.
5
6Required properties:
7- compatible : should be "smi,sm501".
8- reg : contain two entries:
9 - First entry: System Configuration register
10 - Second entry: IO space (Display Controller register)
11- interrupts : SMI interrupt to the cpu should be described here.
12- interrupt-parent : the phandle for the interrupt controller that
13 services interrupts for this device.
14
15Optional properties:
16- mode : select a video mode:
17 <xres>x<yres>[-<bpp>][@<refresh>]
18- edid : verbatim EDID data block describing attached display.
19 Data from the detailed timing descriptor will be used to
20 program the display controller.
21- little-endian: availiable on big endian systems, to
22 set different foreign endian.
23- big-endian: availiable on little endian systems, to
24 set different foreign endian.
25
26Example for MPC5200:
27 display@1,0 {
28 compatible = "smi,sm501";
29 reg = <1 0x00000000 0x00800000
30 1 0x03e00000 0x00200000>;
31 interrupts = <1 1 3>;
32 mode = "640x480-32@60";
33 edid = [edid-data];
34 };
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 558d5f3f6d02..df3702c1756d 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1377,7 +1377,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
1377 sm501_register_gpio(sm); 1377 sm501_register_gpio(sm);
1378 } 1378 }
1379 1379
1380 if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) { 1380 if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
1381 if (!sm501_gpio_isregistered(sm)) 1381 if (!sm501_gpio_isregistered(sm))
1382 dev_err(sm->dev, "no gpio available for i2c gpio.\n"); 1382 dev_err(sm->dev, "no gpio available for i2c gpio.\n");
1383 else 1383 else
@@ -1422,6 +1422,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
1422 1422
1423 sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1); 1423 sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
1424 sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); 1424 sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
1425
1425 if (sm->io_res == NULL || sm->mem_res == NULL) { 1426 if (sm->io_res == NULL || sm->mem_res == NULL) {
1426 dev_err(&dev->dev, "failed to get IO resource\n"); 1427 dev_err(&dev->dev, "failed to get IO resource\n");
1427 ret = -ENOENT; 1428 ret = -ENOENT;
@@ -1735,10 +1736,16 @@ static struct pci_driver sm501_pci_driver = {
1735 1736
1736MODULE_ALIAS("platform:sm501"); 1737MODULE_ALIAS("platform:sm501");
1737 1738
1739static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
1740 { .compatible = "smi,sm501", },
1741 { /* end */ }
1742};
1743
1738static struct platform_driver sm501_plat_driver = { 1744static struct platform_driver sm501_plat_driver = {
1739 .driver = { 1745 .driver = {
1740 .name = "sm501", 1746 .name = "sm501",
1741 .owner = THIS_MODULE, 1747 .owner = THIS_MODULE,
1748 .of_match_table = of_sm501_match_tbl,
1742 }, 1749 },
1743 .probe = sm501_plat_probe, 1750 .probe = sm501_plat_probe,
1744 .remove = sm501_plat_remove, 1751 .remove = sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index f31252ce8892..46d1a64fe80d 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -1729,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
1729 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | 1729 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1730 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; 1730 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
1731 1731
1732#if defined(CONFIG_OF)
1733#ifdef __BIG_ENDIAN
1734 if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
1735 fb->flags |= FBINFO_FOREIGN_ENDIAN;
1736#else
1737 if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
1738 fb->flags |= FBINFO_FOREIGN_ENDIAN;
1739#endif
1740#endif
1732 /* fixed data */ 1741 /* fixed data */
1733 1742
1734 fb->fix.type = FB_TYPE_PACKED_PIXELS; 1743 fb->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -1765,14 +1774,17 @@ static int sm501fb_init_fb(struct fb_info *fb,
1765 fb->var.xres_virtual = fb->var.xres; 1774 fb->var.xres_virtual = fb->var.xres;
1766 fb->var.yres_virtual = fb->var.yres; 1775 fb->var.yres_virtual = fb->var.yres;
1767 } else { 1776 } else {
1768 if (info->edid_data) 1777 if (info->edid_data) {
1769 ret = fb_find_mode(&fb->var, fb, fb_mode, 1778 ret = fb_find_mode(&fb->var, fb, fb_mode,
1770 fb->monspecs.modedb, 1779 fb->monspecs.modedb,
1771 fb->monspecs.modedb_len, 1780 fb->monspecs.modedb_len,
1772 &sm501_default_mode, default_bpp); 1781 &sm501_default_mode, default_bpp);
1773 else 1782 /* edid_data is no longer needed, free it */
1783 kfree(info->edid_data);
1784 } else {
1774 ret = fb_find_mode(&fb->var, fb, 1785 ret = fb_find_mode(&fb->var, fb,
1775 NULL, NULL, 0, NULL, 8); 1786 NULL, NULL, 0, NULL, 8);
1787 }
1776 1788
1777 switch (ret) { 1789 switch (ret) {
1778 case 1: 1790 case 1:
@@ -1933,8 +1945,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
1933 } 1945 }
1934 1946
1935 if (info->pdata == NULL) { 1947 if (info->pdata == NULL) {
1936 dev_info(dev, "using default configuration data\n"); 1948 int found = 0;
1949#if defined(CONFIG_OF)
1950 struct device_node *np = pdev->dev.parent->of_node;
1951 const u8 *prop;
1952 const char *cp;
1953 int len;
1954
1937 info->pdata = &sm501fb_def_pdata; 1955 info->pdata = &sm501fb_def_pdata;
1956 if (np) {
1957 /* Get EDID */
1958 cp = of_get_property(np, "mode", &len);
1959 if (cp)
1960 strcpy(fb_mode, cp);
1961 prop = of_get_property(np, "edid", &len);
1962 if (prop && len == EDID_LENGTH) {
1963 info->edid_data = kmemdup(prop, EDID_LENGTH,
1964 GFP_KERNEL);
1965 if (info->edid_data)
1966 found = 1;
1967 }
1968 }
1969#endif
1970 if (!found) {
1971 dev_info(dev, "using default configuration data\n");
1972 info->pdata = &sm501fb_def_pdata;
1973 }
1938 } 1974 }
1939 1975
1940 /* probe for the presence of each panel */ 1976 /* probe for the presence of each panel */