|
|
@@ -0,0 +1,202 @@
|
|
|
+From 884d3962ef4787c8cf0b8a7a673531c623d1dff8 Mon Sep 17 00:00:00 2001
|
|
|
+From: Darren Etheridge <[email protected]>
|
|
|
+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 ([email protected])
|
|
|
+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 <[email protected]>
|
|
|
+Signed-off-by: Darren Etheridge <[email protected]>
|
|
|
+---
|
|
|
+ .../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,
|
|
|
+ },
|
|
|
+ };
|