mirror of https://github.com/hak5/openwrt-owl.git
203 lines
6.0 KiB
Diff
203 lines
6.0 KiB
Diff
|
From 884d3962ef4787c8cf0b8a7a673531c623d1dff8 Mon Sep 17 00:00:00 2001
|
||
|
From: Darren Etheridge <detheridge@ti.com>
|
||
|
Date: Fri, 2 Aug 2013 15:35:36 -0500
|
||
|
Subject: [PATCH 334/752] video: da8xx-fb: adding dt support
|
||
|
|
||
|
Enhancing driver to enable probe triggered by a corresponding dt entry.
|
||
|
|
||
|
Add da8xx-fb.txt documentation to devicetree section.
|
||
|
|
||
|
Obtain fb_videomode details for the connected lcd panel using the
|
||
|
display timing details present in DT.
|
||
|
|
||
|
Ensure that platform data is present before checking whether platform
|
||
|
callback is present (the one used to control backlight). So far this
|
||
|
was not an issue as driver was purely non-DT triggered, but now DT
|
||
|
support has been added this check must be performed.
|
||
|
|
||
|
v2: squashing multiple commits from Afzal Mohammed (afzal@ti.com)
|
||
|
v3: remove superfluous cast
|
||
|
v4: expose both ti,am3352-lcdc and ti,da830-lcdc for .compatible
|
||
|
as driver can use enhanced features of all version of the
|
||
|
silicon block.
|
||
|
v5: addressed review comments from Prabhakar Lad
|
||
|
v6: Changed the .compatible naming to match the existing drm bindings
|
||
|
for am33xx devices
|
||
|
v7: clarify which compatible to use in the documentation for DA850
|
||
|
|
||
|
Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
|
||
|
Signed-off-by: Darren Etheridge <detheridge@ti.com>
|
||
|
---
|
||
|
.../devicetree/bindings/video/da8xx-fb.txt | 42 +++++++++++++
|
||
|
drivers/video/fbdev/da8xx-fb.c | 66 +++++++++++++++++++-
|
||
|
2 files changed, 105 insertions(+), 3 deletions(-)
|
||
|
create mode 100644 Documentation/devicetree/bindings/video/da8xx-fb.txt
|
||
|
|
||
|
--- /dev/null
|
||
|
+++ b/Documentation/devicetree/bindings/video/da8xx-fb.txt
|
||
|
@@ -0,0 +1,42 @@
|
||
|
+TI LCD Controller on DA830/DA850/AM335x SoC's
|
||
|
+
|
||
|
+Required properties:
|
||
|
+- compatible:
|
||
|
+ DA830, DA850 - "ti,da8xx-tilcdc"
|
||
|
+ AM335x SoC's - "ti,am33xx-tilcdc"
|
||
|
+- reg: Address range of lcdc register set
|
||
|
+- interrupts: lcdc interrupt
|
||
|
+- display-timings: typical videomode of lcd panel, represented as child.
|
||
|
+ Refer Documentation/devicetree/bindings/video/display-timing.txt for
|
||
|
+ display timing binding details. If multiple videomodes are mentioned
|
||
|
+ in display timings node, typical videomode has to be mentioned as the
|
||
|
+ native mode or it has to be first child (driver cares only for native
|
||
|
+ videomode).
|
||
|
+
|
||
|
+Recommended properties:
|
||
|
+- ti,hwmods: Name of the hwmod associated to the LCDC
|
||
|
+
|
||
|
+Example for am335x SoC's:
|
||
|
+
|
||
|
+lcdc@4830e000 {
|
||
|
+ compatible = "ti,am33xx-tilcdc";
|
||
|
+ reg = <0x4830e000 0x1000>;
|
||
|
+ interrupts = <36>;
|
||
|
+ ti,hwmods = "lcdc";
|
||
|
+ status = "okay";
|
||
|
+ display-timings {
|
||
|
+ 800x480p62 {
|
||
|
+ clock-frequency = <30000000>;
|
||
|
+ hactive = <800>;
|
||
|
+ vactive = <480>;
|
||
|
+ hfront-porch = <39>;
|
||
|
+ hback-porch = <39>;
|
||
|
+ hsync-len = <47>;
|
||
|
+ vback-porch = <29>;
|
||
|
+ vfront-porch = <13>;
|
||
|
+ vsync-len = <2>;
|
||
|
+ hsync-active = <1>;
|
||
|
+ vsync-active = <1>;
|
||
|
+ };
|
||
|
+ };
|
||
|
+};
|
||
|
--- a/drivers/video/fbdev/da8xx-fb.c
|
||
|
+++ b/drivers/video/fbdev/da8xx-fb.c
|
||
|
@@ -36,6 +36,7 @@
|
||
|
#include <linux/slab.h>
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/lcm.h>
|
||
|
+#include <video/of_display_timing.h>
|
||
|
#include <video/da8xx-fb.h>
|
||
|
#include <asm/div64.h>
|
||
|
|
||
|
@@ -1317,12 +1318,54 @@ static struct fb_ops da8xx_fb_ops = {
|
||
|
.fb_blank = cfb_blank,
|
||
|
};
|
||
|
|
||
|
+static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev)
|
||
|
+{
|
||
|
+ struct lcd_ctrl_config *cfg;
|
||
|
+
|
||
|
+ cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL);
|
||
|
+ if (!cfg)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ /* default values */
|
||
|
+
|
||
|
+ if (lcd_revision == LCD_VERSION_1)
|
||
|
+ cfg->bpp = 16;
|
||
|
+ else
|
||
|
+ cfg->bpp = 32;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * For panels so far used with this LCDC, below statement is sufficient.
|
||
|
+ * For new panels, if required, struct lcd_ctrl_cfg fields to be updated
|
||
|
+ * with additional/modified values. Those values would have to be then
|
||
|
+ * obtained from dt(requiring new dt bindings).
|
||
|
+ */
|
||
|
+
|
||
|
+ cfg->panel_shade = COLOR_ACTIVE;
|
||
|
+
|
||
|
+ return cfg;
|
||
|
+}
|
||
|
+
|
||
|
static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
|
||
|
{
|
||
|
struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
|
||
|
struct fb_videomode *lcdc_info;
|
||
|
+ struct device_node *np = dev->dev.of_node;
|
||
|
int i;
|
||
|
|
||
|
+ if (np) {
|
||
|
+ lcdc_info = devm_kzalloc(&dev->dev,
|
||
|
+ sizeof(struct fb_videomode),
|
||
|
+ GFP_KERNEL);
|
||
|
+ if (!lcdc_info)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) {
|
||
|
+ dev_err(&dev->dev, "timings not available in DT\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ return lcdc_info;
|
||
|
+ }
|
||
|
+
|
||
|
for (i = 0, lcdc_info = known_lcd_panels;
|
||
|
i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
|
||
|
if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
|
||
|
@@ -1351,7 +1394,7 @@ static int fb_probe(struct platform_devi
|
||
|
int ret;
|
||
|
unsigned long ulcm;
|
||
|
|
||
|
- if (fb_pdata == NULL) {
|
||
|
+ if (fb_pdata == NULL && !device->dev.of_node) {
|
||
|
dev_err(&device->dev, "Can not get platform data\n");
|
||
|
return -ENOENT;
|
||
|
}
|
||
|
@@ -1391,7 +1434,10 @@ static int fb_probe(struct platform_devi
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
- lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
|
||
|
+ if (device->dev.of_node)
|
||
|
+ lcd_cfg = da8xx_fb_create_cfg(device);
|
||
|
+ else
|
||
|
+ lcd_cfg = fb_pdata->controller_data;
|
||
|
|
||
|
if (!lcd_cfg) {
|
||
|
ret = -EINVAL;
|
||
|
@@ -1410,7 +1456,7 @@ static int fb_probe(struct platform_devi
|
||
|
par->dev = &device->dev;
|
||
|
par->lcdc_clk = tmp_lcdc_clk;
|
||
|
par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
|
||
|
- if (fb_pdata->panel_power_ctrl) {
|
||
|
+ if (fb_pdata && fb_pdata->panel_power_ctrl) {
|
||
|
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
|
||
|
par->panel_power_ctrl(1);
|
||
|
}
|
||
|
@@ -1654,12 +1700,26 @@ static int fb_resume(struct device *dev)
|
||
|
|
||
|
static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume);
|
||
|
|
||
|
+#if IS_ENABLED(CONFIG_OF)
|
||
|
+static const struct of_device_id da8xx_fb_of_match[] = {
|
||
|
+ /*
|
||
|
+ * this driver supports version 1 and version 2 of the
|
||
|
+ * Texas Instruments lcd controller (lcdc) hardware block
|
||
|
+ */
|
||
|
+ {.compatible = "ti,da8xx-tilcdc", },
|
||
|
+ {.compatible = "ti,am33xx-tilcdc", },
|
||
|
+ {},
|
||
|
+};
|
||
|
+MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
|
||
|
+#endif
|
||
|
+
|
||
|
static struct platform_driver da8xx_fb_driver = {
|
||
|
.probe = fb_probe,
|
||
|
.remove = fb_remove,
|
||
|
.driver = {
|
||
|
.name = DRIVER_NAME,
|
||
|
.owner = THIS_MODULE,
|
||
|
+ .of_match_table = of_match_ptr(da8xx_fb_of_match),
|
||
|
.pm = &fb_pm_ops,
|
||
|
},
|
||
|
};
|