Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH v3 00/12] video: da8xx-fb: am335x DT support
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette

Hi,

This series adds DT support to da8xx-fb driver (device found on
DaVinci and AM335x SoC's). It does certain cleanup's in the process.

This series as compared to previous version handles configuration of
the LCDC clock rate by modelling as a clock divider of CCF. This would
take effect only if CCF is selected, if not, no change to  existing
method.

This makes use of Steffen Trumtrar's v16 of display timing DT support.

Testing has been done on AM335x SoC based boards like AM335x EVM. It
has also been verified that display on DA850 EVM (non-DT boot) works
as earlier.

This series is based on v3.8-rc3,
 and is dependent on,
1. Series v16 "of: add display helper" by,
        Steffen Trumtrar <s.trumtrar@pengutronix.de>
2. Patch "da8xx: Allow use by am33xx based devices" by,
        Pantelis Antoniou <panto@antoniou-consulting.com>
3. Series v3 "video: da8xx-fb: runtime timing configuration" by,
        me (Afzal Mohammed <afzal@ti.com>)

To test this series on AM335x based boards,
1. Series v2 "ARM: dts: AM33XX: lcdc support" by,
        me (Afzal Mohammed <afzal@ti.com>),
2. Series "HWMOD fixes for AM33xx PWM submodules and device tree nodes" by,
        Philip, Avinash <avinashphilip@ti.com>
3. Series "clk: divider: prepare for minimum divider" by,
        me (Afzal Mohammed <afzal@ti.com>),
4. Series "ARM: AM335x: LCDC platform support" by,
        me (Afzal Mohammed <afzal@ti.com>),
would be needed.

All above dependencies along with those required for testing is available
@ git://gitorious.org/x0148406-public/linux-kernel.git tags/da8xx-fb-dt-v3

Regards
Afzal

v3: model CCF clock divider with parent propogation if CCF selected
v2: 2 new patches - one to configure clock rate properly (12/12)and
    other to make io operations safe (1/12)

Afzal Mohammed (11):
  video: da8xx-fb: make io operations safe
  video: da8xx-fb: enable sync lost intr for v2 ip
  video: da8xx-fb: use devres
  video: da8xx-fb: ensure non-null cfg in pdata
  video: da8xx-fb: reorganize panel detection
  video: da8xx-fb: minimal dt support
  video: da8xx-fb: invoke platform callback safely
  video: da8xx-fb: obtain fb_videomode info from dt
  video: da8xx-fb: ensure pdata only for non-dt
  video: da8xx-fb: setup struct lcd_ctrl_config for dt
  video: da8xx-fb: CCF clock divider handling

Manjunathappa, Prakash (1):
  video: da8xx-fb: fix 24bpp raster configuration

 .../devicetree/bindings/video/fb-da8xx.txt         |  37 ++++
 drivers/video/da8xx-fb.c                           | 217 ++++++++++++++++-----
 2 files changed, 201 insertions(+), 53 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/fb-da8xx.txt

-- 
1.7.12


^ permalink raw reply

* [PATCH v3 02/12] video: da8xx-fb: fix 24bpp raster configuration
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette,
	Manjunathappa, Prakash
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

From: "Manjunathappa, Prakash" <prakash.pm@ti.com>

Set only LCD_V2_TFT_24BPP_MODE bit for 24bpp and LCD_V2_TFT_24BPP_UNPACK
bit along with LCD_V2_TFT_24BPP_MODE for 32bpp configuration.

Patch is tested on am335x-evm for 24bpp and da850-evm for 16bpp
configurations.

Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 35a33ca..7f92f37 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -550,10 +550,10 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
 	case 4:
 	case 16:
 		break;
-	case 24:
-		reg |= LCD_V2_TFT_24BPP_MODE;
 	case 32:
 		reg |= LCD_V2_TFT_24BPP_UNPACK;
+	case 24:
+		reg |= LCD_V2_TFT_24BPP_MODE;
 		break;
 
 	case 8:
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 06/12] video: da8xx-fb: reorganize panel detection
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Move panel detection to a separate function, this helps in readability
as well as makes DT support cleaner.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 42 ++++++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 3b146bc..b6ea5e9 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1253,6 +1253,27 @@ static struct fb_ops da8xx_fb_ops = {
 	.fb_blank = cfb_blank,
 };
 
+static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
+{
+	struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+	struct fb_videomode *lcdc_info;
+	int i;
+
+	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)
+			break;
+	}
+
+	if (i = ARRAY_SIZE(known_lcd_panels)) {
+		dev_err(&dev->dev, "no panel found\n");
+		return NULL;
+	}
+	dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
+
+	return lcdc_info;
+}
+
 static int fb_probe(struct platform_device *device)
 {
 	struct da8xx_lcdc_platform_data *fb_pdata @@ -1262,7 +1283,7 @@ static int fb_probe(struct platform_device *device)
 	struct fb_info *da8xx_fb_info;
 	struct clk *fb_clk = NULL;
 	struct da8xx_fb_par *par;
-	int ret, i;
+	int ret;
 	unsigned long ulcm;
 
 	if (fb_pdata = NULL) {
@@ -1270,6 +1291,10 @@ static int fb_probe(struct platform_device *device)
 		return -ENOENT;
 	}
 
+	lcdc_info = da8xx_fb_get_videomode(device);
+	if (lcdc_info = NULL)
+		return -ENODEV;
+
 	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
 	da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
 	if (!da8xx_fb_reg_base) {
@@ -1303,21 +1328,6 @@ static int fb_probe(struct platform_device *device)
 		break;
 	}
 
-	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)
-			break;
-	}
-
-	if (i = ARRAY_SIZE(known_lcd_panels)) {
-		dev_err(&device->dev, "GLCD: No valid panel found\n");
-		ret = -ENODEV;
-		goto err_pm_runtime_disable;
-	} else
-		dev_info(&device->dev, "GLCD: Found %s panel\n",
-					fb_pdata->type);
-
 	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
 
 	if (!lcd_cfg) {
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 07/12] video: da8xx-fb: minimal dt support
From: Afzal Mohammed @ 2013-01-22 16:53 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Driver is provided a means to have the probe triggered by DT.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 Documentation/devicetree/bindings/video/fb-da8xx.txt | 16 ++++++++++++++++
 drivers/video/da8xx-fb.c                             |  7 +++++++
 2 files changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/fb-da8xx.txt

diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
new file mode 100644
index 0000000..581e014
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
@@ -0,0 +1,16 @@
+TI LCD Controller on DA830/DA850/AM335x SoC's
+
+Required properties:
+- compatible:
+	DA830 - "ti,da830-lcdc"
+	AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
+- reg: Address range of lcdc register set
+- interrupts: lcdc interrupt
+
+Example:
+
+lcdc@4830e000 {
+	compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
+	reg =  <0x4830e000 0x1000>;
+	interrupts = <36>;
+};
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index b6ea5e9..08ee8eb 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1595,6 +1595,12 @@ static int fb_resume(struct platform_device *dev)
 #define fb_resume NULL
 #endif
 
+static const struct of_device_id da8xx_fb_of_match[] = {
+	{.compatible = "ti,da830-lcdc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
+
 static struct platform_driver da8xx_fb_driver = {
 	.probe = fb_probe,
 	.remove = fb_remove,
@@ -1603,6 +1609,7 @@ static struct platform_driver da8xx_fb_driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(da8xx_fb_of_match),
 		   },
 };
 
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 11/12] video: da8xx-fb: setup struct lcd_ctrl_config for dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

strcut lcd_ctrl_config information required for driver is currently
obtained via platform data. To handle DT probing, create
lcd_ctrl_config and populate it with default values, these values are
sufficient for the panels so far used with this controller to work.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 1c1a616..5455682 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1254,6 +1254,35 @@ 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) {
+		dev_err(&dev->dev, "memory allocation failed\n");
+		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->dev.platform_data;
@@ -1345,7 +1374,10 @@ static int fb_probe(struct platform_device *device)
 		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 = (struct lcd_ctrl_config *)fb_pdata->controller_data;
 
 	if (!lcd_cfg) {
 		ret = -EINVAL;
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 12/12] video: da8xx-fb: CCF clock divider handling
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Common clock framework provides a basic clock divider. Make use of it
to handle clock configuration in the LCDC IP, wherever applicable;
out of two platforms having this IP, only am335x is converted to use
CCF, DaVinci is not yet converted. Hence wrap the modification such
that it will come into effect only if CCF is selected, otherwise,
prgram dividers as earlier. Once DaVinci is converted to use CCF,
this ifdef'ery can be removed.

Divider clock instantiated is made as a one that allows the rate
propogation to it's parent, that provides more options w.r.t pixel
clock rates that could be configured.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---

v3: model CCF clock divider with parent propogation if CCF selected
v2: new patch

 drivers/video/da8xx-fb.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 5455682..3c9db1d 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/lcm.h>
+#include <linux/clk-provider.h>
 #include <video/of_display_timing.h>
 #include <video/da8xx-fb.h>
 #include <asm/div64.h>
@@ -133,6 +134,10 @@
 #define WSI_TIMEOUT	50
 #define PALETTE_SIZE	256
 
+#define	LCD_CLK_SHIFT	8
+#define	LCD_CLK_WIDTH	8
+#define	LCD_CLK_MIN_DIV	2
+
 static void __iomem *da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
 static unsigned int lcd_revision;
@@ -181,6 +186,9 @@ struct da8xx_fb_par {
 	u32 pseudo_palette[16];
 	struct fb_videomode	mode;
 	struct lcd_ctrl_config	cfg;
+#ifdef CONFIG_COMMON_CLK
+	struct clk		*child_clk;
+#endif
 };
 
 static struct fb_var_screeninfo da8xx_fb_var;
@@ -689,6 +697,19 @@ static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
 	return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
 }
 
+#ifdef	CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+					  unsigned pixclock)
+{
+	unsigned long rate;
+
+	rate = PICOS2KHZ(pixclock) * 1000;
+	rate = clk_round_rate(par->child_clk, rate);
+	rate = KHZ2PICOS(rate / 1000);
+
+	return rate;
+}
+#else
 static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
 					  unsigned pixclock)
 {
@@ -697,25 +718,49 @@ static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
 	div = da8xx_fb_calc_clk_divider(par, pixclock);
 	return KHZ2PICOS(par->lcd_fck_rate / (1000 * div));
 }
+#endif
 
 static inline void da8xx_fb_config_clk_divider(unsigned div)
 {
 	/* Configure the LCD clock divisor. */
 	lcdc_write(LCD_CLK_DIVISOR(div) |
 			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
 
+static inline void da8xx_fb_clkc_enable(void)
+{
 	if (lcd_revision = LCD_VERSION_2)
 		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
 				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
 }
 
-static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+#ifdef	CONFIG_COMMON_CLK
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+						    struct fb_videomode *mode)
+{
+	int ret;
+
+	ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(par->dev, "unable to setup pixel clock of %u ps",
+			mode->pixclock);
+		return ret;
+	}
+	da8xx_fb_clkc_enable();
+	return 0;
+}
+#else
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
 						    struct fb_videomode *mode)
 {
 	unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
 
 	da8xx_fb_config_clk_divider(div);
+	da8xx_fb_clkc_enable();
+
+	return 0;
 }
+#endif
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 		struct fb_videomode *panel)
@@ -723,7 +768,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	u32 bpp;
 	int ret = 0;
 
-	da8xx_fb_calc_config_clk_divider(par, panel);
+	ret = da8xx_fb_calc_config_clk_divider(par, panel);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (panel->sync & FB_SYNC_CLK_INVERT)
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -1406,6 +1453,22 @@ static int fb_probe(struct platform_device *device)
 
 	da8xx_fb_lcd_reset();
 
+#ifdef	CONFIG_COMMON_CLK
+	lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(0x2), LCD_CTRL_REG);
+	par->child_clk = clk_register_divider(NULL, "da8xx_fb_clk",
+					      __clk_get_name(fb_clk),
+					      CLK_SET_RATE_PARENT,
+					      da8xx_fb_reg_base + LCD_CTRL_REG,
+					      LCD_CLK_SHIFT, LCD_CLK_WIDTH,
+					      LCD_CLK_MIN_DIV,
+					      CLK_DIVIDER_ONE_BASED, NULL);
+	if (IS_ERR(par->child_clk)) {
+		dev_err(&device->dev, "error registering clk\n");
+		ret = -ENODEV;
+		goto err_release_fb;
+	}
+#endif
+
 	/* allocate frame buffer */
 	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
 	ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 10/12] video: da8xx-fb: ensure pdata only for non-dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

This driver is DT probe-able, hence ensure presence of platform data
only for non-DT boot.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0c68712..1c1a616 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1303,7 +1303,7 @@ static int fb_probe(struct platform_device *device)
 	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;
 	}
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 09/12] video: da8xx-fb: obtain fb_videomode info from dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Obtain fb_videomode details for the connected lcd panel using the
display timing details present in DT.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 .../devicetree/bindings/video/fb-da8xx.txt          | 21 +++++++++++++++++++++
 drivers/video/da8xx-fb.c                            | 17 +++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
index 581e014..0741f78 100644
--- a/Documentation/devicetree/bindings/video/fb-da8xx.txt
+++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
@@ -6,6 +6,12 @@ Required properties:
 	AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
 - 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).
 
 Example:
 
@@ -13,4 +19,19 @@ lcdc@4830e000 {
 	compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
 	reg =  <0x4830e000 0x1000>;
 	interrupts = <36>;
+	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>;
+		};
+	};
 };
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0beed20..0c68712 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/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>
 
@@ -1257,8 +1258,24 @@ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
 {
 	struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
 	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) {
+			dev_err(&dev->dev, "memory allocation failed\n");
+			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)
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 08/12] video: da8xx-fb: invoke platform callback safely
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

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.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 08ee8eb..0beed20 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1347,7 +1347,7 @@ static int fb_probe(struct platform_device *device)
 	par->dev = &device->dev;
 	par->lcdc_clk = fb_clk;
 	par->lcd_fck_rate = clk_get_rate(fb_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);
 	}
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 05/12] video: da8xx-fb: ensure non-null cfg in pdata
From: Afzal Mohammed @ 2013-01-22 16:55 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Ensure that platform data contains pointer for lcd_ctrl_config.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 7a32e83..3b146bc 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1320,6 +1320,11 @@ static int fb_probe(struct platform_device *device)
 
 	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
 
+	if (!lcd_cfg) {
+		ret = -EINVAL;
+		goto err_pm_runtime_disable;
+	}
+
 	da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
 					&device->dev);
 	if (!da8xx_fb_info) {
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 04/12] video: da8xx-fb: use devres
From: Afzal Mohammed @ 2013-01-22 16:55 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Replace existing resource handling in the driver with managed device
resource.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 35 ++++++-----------------------------
 1 file changed, 6 insertions(+), 29 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index ca69e01..7a32e83 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1036,12 +1036,9 @@ static int fb_remove(struct platform_device *dev)
 				  par->p_palette_base);
 		dma_free_coherent(NULL, par->vram_size, par->vram_virt,
 				  par->vram_phys);
-		free_irq(par->irq, par);
 		pm_runtime_put_sync(&dev->dev);
 		pm_runtime_disable(&dev->dev);
 		framebuffer_release(info);
-		iounmap(da8xx_fb_reg_base);
-		release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
 
 	}
 	return 0;
@@ -1265,7 +1262,6 @@ static int fb_probe(struct platform_device *device)
 	struct fb_info *da8xx_fb_info;
 	struct clk *fb_clk = NULL;
 	struct da8xx_fb_par *par;
-	resource_size_t len;
 	int ret, i;
 	unsigned long ulcm;
 
@@ -1275,29 +1271,16 @@ static int fb_probe(struct platform_device *device)
 	}
 
 	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
-	if (!lcdc_regs) {
-		dev_err(&device->dev,
-			"Can not get memory resource for LCD controller\n");
-		return -ENOENT;
-	}
-
-	len = resource_size(lcdc_regs);
-
-	lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
-	if (!lcdc_regs)
-		return -EBUSY;
-
-	da8xx_fb_reg_base = ioremap(lcdc_regs->start, len);
+	da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
 	if (!da8xx_fb_reg_base) {
-		ret = -EBUSY;
-		goto err_request_mem;
+		dev_err(&device->dev, "memory resource setup failed\n");
+		return -EADDRNOTAVAIL;
 	}
 
-	fb_clk = clk_get(&device->dev, "fck");
+	fb_clk = devm_clk_get(&device->dev, "fck");
 	if (IS_ERR(fb_clk)) {
 		dev_err(&device->dev, "Can not get device clock\n");
-		ret = -ENODEV;
-		goto err_ioremap;
+		return -ENODEV;
 	}
 
 	pm_runtime_enable(&device->dev);
@@ -1458,7 +1441,7 @@ static int fb_probe(struct platform_device *device)
 		lcdc_irq_handler = lcdc_irq_handler_rev02;
 	}
 
-	ret = request_irq(par->irq, lcdc_irq_handler, 0,
+	ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
 			DRIVER_NAME, par);
 	if (ret)
 		goto irq_freq;
@@ -1488,12 +1471,6 @@ err_pm_runtime_disable:
 	pm_runtime_put_sync(&device->dev);
 	pm_runtime_disable(&device->dev);
 
-err_ioremap:
-	iounmap(da8xx_fb_reg_base);
-
-err_request_mem:
-	release_mem_region(lcdc_regs->start, len);
-
 	return ret;
 }
 
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 01/12] video: da8xx-fb: make io operations safe
From: Afzal Mohammed @ 2013-01-22 16:56 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

Replace __raw_readl/__raw_writel with readl/writel; this driver is
reused on ARMv7 (AM335x SoC).

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---

v2: new patch

 drivers/video/da8xx-fb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 720604c..35a33ca 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -141,12 +141,12 @@ static int frame_done_flag;
 
 static inline unsigned int lcdc_read(unsigned int addr)
 {
-	return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
+	return (unsigned int)readl(da8xx_fb_reg_base + (addr));
 }
 
 static inline void lcdc_write(unsigned int val, unsigned int addr)
 {
-	__raw_writel(val, da8xx_fb_reg_base + (addr));
+	writel(val, da8xx_fb_reg_base + (addr));
 }
 
 struct da8xx_fb_par {
-- 
1.7.12


^ permalink raw reply related

* [PATCH v3 03/12] video: da8xx-fb: enable sync lost intr for v2 ip
From: Afzal Mohammed @ 2013-01-22 16:56 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>

interrupt handler is checking for sync lost interrupt, but it was not
enabled, enable it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 7f92f37..ca69e01 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -318,7 +318,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
 			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
 				LCD_V2_END_OF_FRAME0_INT_ENA |
 				LCD_V2_END_OF_FRAME1_INT_ENA |
-				LCD_FRAME_DONE;
+				LCD_FRAME_DONE | LCD_SYNC_LOST;
 			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
 		}
 		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
-- 
1.7.12


^ permalink raw reply related

* Re: [PATCH v3 00/12] video: da8xx-fb: am335x DT support
From: Koen Kooi @ 2013-01-22 17:03 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: linux-fbdev, linux-omap, linux-kernel, Florian Tobias Schandinat,
	Tomi Valkeinen, Grant Likely, Rob Herring, Rob Landley,
	Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>


Op 22 jan. 2013, om 17:51 heeft Afzal Mohammed <afzal@ti.com> het volgende geschreven:

> Hi,
> 
> This series adds DT support to da8xx-fb driver (device found on
> DaVinci and AM335x SoC's). It does certain cleanup's in the process.
> 
> This series as compared to previous version handles configuration of
> the LCDC clock rate by modelling as a clock divider of CCF. This would
> take effect only if CCF is selected, if not, no change to  existing
> method.
> 
> This makes use of Steffen Trumtrar's v16 of display timing DT support.

Wouldn't it be better to delete da8xx-fb.* and switch to Rob Clarks DRM based driver for this IP block?

regards,

Koen

^ permalink raw reply

* Re: [PATCH v3 00/12] video: da8xx-fb: am335x DT support
From: Rob Clark @ 2013-01-22 18:45 UTC (permalink / raw)
  To: Koen Kooi
  Cc: Afzal Mohammed, linux-fbdev, linux-omap, linux-kernel,
	Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <02F0A27B-B16B-42F8-A0BC-29726732226D@dominion.thruhere.net>

On Tue, Jan 22, 2013 at 11:03 AM, Koen Kooi <koen@dominion.thruhere.net> wrote:
>
> Op 22 jan. 2013, om 17:51 heeft Afzal Mohammed <afzal@ti.com> het volgende geschreven:
>
>> Hi,
>>
>> This series adds DT support to da8xx-fb driver (device found on
>> DaVinci and AM335x SoC's). It does certain cleanup's in the process.
>>
>> This series as compared to previous version handles configuration of
>> the LCDC clock rate by modelling as a clock divider of CCF. This would
>> take effect only if CCF is selected, if not, no change to  existing
>> method.
>>
>> This makes use of Steffen Trumtrar's v16 of display timing DT support.
>
> Wouldn't it be better to delete da8xx-fb.* and switch to Rob Clarks DRM based driver for this IP block?

we probably can't delete da8xx-fb, but I think it would be ok to only
use it for legacy platforms not yet ported to DT.

BR,
-R

> regards,
>
> Koen--
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v16 RESEND 0/7] of: add display helper
From: Rob Clark @ 2013-01-22 21:50 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: devicetree-discuss, David Airlie, Rob Herring, linux-fbdev,
	dri-devel, Laurent Pinchart, Thierry Reding,
	Guennady Liakhovetski, linux-media, Tomi Valkeinen,
	Stephen Warren, Florian Tobias Schandinat, Leela Krishna Amudala,
	Mohammed, Afzal, kernel
In-Reply-To: <1358766482-6275-1-git-send-email-s.trumtrar@pengutronix.de>

On Mon, Jan 21, 2013 at 5:07 AM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:
> Hi!
>
> There was still no maintainer, that commented, ack'd, nack'd, apply'd the
> series. So, this is just a resend.
> The patches were tested with:
>
>         - v15 on Tegra by Thierry
>         - sh-mobile-lcdcfb by Laurent
>         - MX53QSB by Marek
>         - Exynos: smdk5250 by Leela
>         - AM335X EVM & AM335X EVM-SK by Afzal
>         - imx6q: sabrelite, sabresd by Philipp and me
>         - imx53: tqma53/mba53 by me


btw, you can add my tested-by for this series..  I've been using them
for the tilcdc lcd-panel output driver support.

BR,
-R


>
>
> Changes since v15:
>         - move include/linux/{videomode,display_timing}.h to include/video
>         - move include/linux/of_{videomode,display_timing}.h to include/video
>         - reimplement flags: add VESA flags and data flags
>         - let pixelclock in struct videomode be unsigned long
>         - rename of_display_timings_exists to of_display_timings_exist
>         - revise logging/error messages: replace __func__ with np->full_name
>         - rename pixelclk-inverted to pixelclk-active
>         - revise comments in code
>
> Changes since v14:
>         - fix "const struct *" warning
>                 (reported by: Leela Krishna Amudala <l.krishna@samsung.com>)
>         - return -EINVAL when htotal or vtotal are zero
>         - remove unreachable code in of_get_display_timings
>         - include headers in .c files and not implicit in .h
>         - sort includes alphabetically
>         - fix lower/uppercase in binding documentation
>         - rebase onto v3.7-rc7
>
> Changes since v13:
>         - fix "const struct *" warning
>                 (reported by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>)
>         - prevent division by zero in fb_videomode_from_videomode
>
> Changes since v12:
>         - rename struct display_timing to via_display_timing in via subsystem
>         - fix refreshrate calculation
>         - fix "const struct *" warnings
>                 (reported by: Manjunathappa, Prakash <prakash.pm@ti.com>)
>         - some CodingStyle fixes
>         - rewrite parts of commit messages and display-timings.txt
>         - let display_timing_get_value get all values instead of just typical
>
> Changes since v11:
>         - make pointers const where applicable
>         - add reviewed-by Laurent Pinchart
>
> Changes since v10:
>         - fix function name (drm_)display_mode_from_videomode
>         - add acked-by, reviewed-by, tested-by
>
> Changes since v9:
>         - don't leak memory when previous timings were correct
>         - CodingStyle fixes
>         - move blank lines around
>
> Changes since v8:
>         - fix memory leaks
>         - change API to be more consistent (foo_from_bar(struct bar, struct foo))
>         - include headers were necessary
>         - misc minor bugfixes
>
> Changes since v7:
>         - move of_xxx to drivers/video
>         - remove non-binding documentation from display-timings.txt
>         - squash display_timings and videomode in one patch
>         - misc minor fixes
>
> Changes since v6:
>         - get rid of some empty lines etc.
>         - move functions to their subsystems
>         - split of_ from non-of_ functions
>         - add at least some kerneldoc to some functions
>
> Changes since v5:
>         - removed all display stuff and just describe timings
>
> Changes since v4:
>         - refactored functions
>
> Changes since v3:
>         - print error messages
>         - free alloced memory
>         - general cleanup
>
> Changes since v2:
>         - use hardware-near property-names
>         - provide a videomode structure
>         - allow ranges for all properties (<min,typ,max>)
>         - functions to get display_mode or fb_videomode
>
>
> Regards,
> Steffen
>
>
> Steffen Trumtrar (7):
>   viafb: rename display_timing to via_display_timing
>   video: add display_timing and videomode
>   video: add of helper for display timings/videomode
>   fbmon: add videomode helpers
>   fbmon: add of_videomode helpers
>   drm_modes: add videomode helpers
>   drm_modes: add of_videomode helpers
>
>  .../devicetree/bindings/video/display-timing.txt   |  109 +++++++++
>  drivers/gpu/drm/drm_modes.c                        |   70 ++++++
>  drivers/video/Kconfig                              |   21 ++
>  drivers/video/Makefile                             |    4 +
>  drivers/video/display_timing.c                     |   24 ++
>  drivers/video/fbmon.c                              |   94 ++++++++
>  drivers/video/of_display_timing.c                  |  239 ++++++++++++++++++++
>  drivers/video/of_videomode.c                       |   54 +++++
>  drivers/video/via/hw.c                             |    6 +-
>  drivers/video/via/hw.h                             |    2 +-
>  drivers/video/via/lcd.c                            |    2 +-
>  drivers/video/via/share.h                          |    2 +-
>  drivers/video/via/via_modesetting.c                |    8 +-
>  drivers/video/via/via_modesetting.h                |    6 +-
>  drivers/video/videomode.c                          |   39 ++++
>  include/drm/drmP.h                                 |    9 +
>  include/linux/fb.h                                 |    8 +
>  include/video/display_timing.h                     |  124 ++++++++++
>  include/video/of_display_timing.h                  |   20 ++
>  include/video/of_videomode.h                       |   18 ++
>  include/video/videomode.h                          |   48 ++++
>  21 files changed, 894 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/video/display-timing.txt
>  create mode 100644 drivers/video/display_timing.c
>  create mode 100644 drivers/video/of_display_timing.c
>  create mode 100644 drivers/video/of_videomode.c
>  create mode 100644 drivers/video/videomode.c
>  create mode 100644 include/video/display_timing.h
>  create mode 100644 include/video/of_display_timing.h
>  create mode 100644 include/video/of_videomode.h
>  create mode 100644 include/video/videomode.h
>
> --
> 1.7.10.4
>

^ permalink raw reply

* Re: [PATCH 1/3] fb: backlight: Add the Himax HX-8357B LCD controller
From: Jingoo Han @ 2013-01-23  1:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358871791-14214-2-git-send-email-maxime.ripard@free-electrons.com>

On Wednesday, January 23, 2013 1:23 AM, Maxime Ripard wrote
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/video/backlight/Kconfig  |    7 +
>  drivers/video/backlight/Makefile |    1 +
>  drivers/video/backlight/hx8357.c |  482 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 490 insertions(+)
>  create mode 100644 drivers/video/backlight/hx8357.c
> 
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index 765a945..c39bed0 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -126,6 +126,13 @@ config LCD_AMS369FG06
>  	  If you have an AMS369FG06 AMOLED Panel, say Y to enable its
>  	  LCD control driver.
> 
> +config LCD_HX8357
> +	tristate "Himax HX-8357 LCD Driver"
> +	depends on SPI
> +	help
> +	  If you have a HX-8357 LCD panel, say Y to enable its LCD control
> +	  driver.
> +
>  endif # LCD_CLASS_DEVICE
> 
>  #
> diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
> index e7ce729..b69d391 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_LCD_TOSA)		   += tosa_lcd.o
>  obj-$(CONFIG_LCD_S6E63M0)	+= s6e63m0.o
>  obj-$(CONFIG_LCD_LD9040)	+= ld9040.o
>  obj-$(CONFIG_LCD_AMS369FG06)	+= ams369fg06.o
> +obj-$(CONFIG_LCD_HX8357)	+= hx8357.o
> 
>  obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
>  obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
> diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
> new file mode 100644
> index 0000000..ee4d607
> --- /dev/null
> +++ b/drivers/video/backlight/hx8357.c
> @@ -0,0 +1,482 @@
> +/*
> + * Driver for the Himax HX-8357 LCD Controller
> + *
> + * Copyright 2012 Free Electrons
> + *
> + * Licensed under the GPLv2 or later.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/lcd.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>
> +#include <linux/spi/spi.h>
> +
> +#define HX8357_NUM_IM_PINS	3
> +
> +#define HX8357_SWRESET			0x01
> +#define HX8357_GET_RED_CHANNEL		0x06
> +#define HX8357_GET_GREEN_CHANNEL	0x07
> +#define HX8357_GET_BLUE_CHANNEL		0x08
> +#define HX8357_GET_POWER_MODE		0x0a
> +#define HX8357_GET_MADCTL		0x0b
> +#define HX8357_GET_PIXEL_FORMAT		0x0c
> +#define HX8357_GET_DISPLAY_MODE		0x0d
> +#define HX8357_GET_SIGNAL_MODE		0x0e
> +#define HX8357_GET_DIAGNOSTIC_RESULT	0x0f
> +#define HX8357_ENTER_SLEEP_MODE		0x10
> +#define HX8357_EXIT_SLEEP_MODE		0x11
> +#define HX8357_ENTER_PARTIAL_MODE	0x12
> +#define HX8357_ENTER_NORMAL_MODE	0x13
> +#define HX8357_EXIT_INVERSION_MODE	0x20
> +#define HX8357_ENTER_INVERSION_MODE	0x21
> +#define HX8357_SET_DISPLAY_OFF		0x28
> +#define HX8357_SET_DISPLAY_ON		0x29
> +#define HX8357_SET_COLUMN_ADDRESS	0x2a
> +#define HX8357_SET_PAGE_ADDRESS		0x2b
> +#define HX8357_WRITE_MEMORY_START	0x2c
> +#define HX8357_READ_MEMORY_START	0x2e
> +#define HX8357_SET_PARTIAL_AREA		0x30
> +#define HX8357_SET_SCROLL_AREA		0x33
> +#define HX8357_SET_TEAR_OFF		0x34
> +#define HX8357_SET_TEAR_ON		0x35
> +#define HX8357_SET_ADDRESS_MODE		0x36
> +#define HX8357_SET_SCROLL_START		0x37
> +#define HX8357_EXIT_IDLE_MODE		0x38
> +#define HX8357_ENTER_IDLE_MOD		0x39

Please change MOD to MODE as below :-)

  HX8357_ENTER_IDLE_MODE

> +#define HX8357_SET_PIXEL_FORMAT		0x3a
> +#define HX8357_SET_PIXEL_FORMAT_DBI_3BIT	(0x1)
> +#define HX8357_SET_PIXEL_FORMAT_DBI_16BIT	(0x5)
> +#define HX8357_SET_PIXEL_FORMAT_DBI_18BIT	(0x6)
> +#define HX8357_SET_PIXEL_FORMAT_DPI_3BIT	(0x1 << 4)
> +#define HX8357_SET_PIXEL_FORMAT_DPI_16BIT	(0x5 << 4)
> +#define HX8357_SET_PIXEL_FORMAT_DPI_18BIT	(0x6 << 4)
> +#define HX8357_WRITE_MEMORY_CONTINUE	0x3c
> +#define HX8357_READ_MEMORY_CONTINUE	0x3e
> +#define HX8357_SET_TEAR_SCAN_LINES	0x44
> +#define HX8357_GET_SCAN_LINES		0x45
> +#define HX8357_READ_DDB_START		0xa1
> +#define HX8357_SET_DISPLAY_MODE		0xb4
> +#define HX8357_SET_DISPLAY_MODE_RGB_THROUGH	(0x3)
> +#define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE	(1 << 4)
> +#define HX8357_SET_PANEL_DRIVING	0xc0
> +#define HX8357_SET_DISPLAY_FRAME	0xc5
> +#define HX8357_SET_RGB			0xc6
> +#define HX8357_SET_RGB_ENABLE_HIGH		(1 << 1)
> +#define HX8357_SET_GAMMA		0xc8
> +#define HX8357_SET_POWER		0xd0
> +#define HX8357_SET_VCOM			0xd1
> +#define HX8357_SET_POWER_NORMAL		0xd2
> +#define HX8357_SET_PANEL_RELATED	0xe9
> +
> +struct hx8357_data {
> +	unsigned		im_pins[HX8357_NUM_IM_PINS];
> +	unsigned		reset;
> +	struct spi_device	*spi;
> +	int			state;
> +};
> +
> +static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
> +				void *txbuf, u16 txlen,
> +				void *rxbuf, u16 rxlen)
> +{
> +	struct hx8357_data *lcd = lcd_get_data(lcdev);
> +	struct spi_message msg;
> +	struct spi_transfer xfer[2];
> +	u16 *local_txbuf = NULL;
> +	int ret = 0;
> +
> +	memset(xfer, 0, sizeof(xfer));
> +	spi_message_init(&msg);
> +
> +	if (txlen) {
> +		int i;
> +
> +		local_txbuf = kcalloc(sizeof(*local_txbuf), txlen, GFP_KERNEL);
> +
> +		if (!local_txbuf) {
> +			dev_err(&lcdev->dev, "Couldn't allocate data buffer.\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < txlen; i++) {
> +			local_txbuf[i] = ((u8 *)txbuf)[i];
> +			if (i > 0)
> +				local_txbuf[i] |= 1 << 8;
> +		}
> +
> +		xfer[0].len = 2 * txlen;
> +		xfer[0].bits_per_word = 9;
> +		xfer[0].tx_buf = local_txbuf;
> +		spi_message_add_tail(&xfer[0], &msg);
> +	}
> +
> +	if (rxlen) {
> +		xfer[1].len = rxlen;
> +		xfer[1].bits_per_word = 8;
> +		xfer[1].rx_buf = rxbuf;
> +		spi_message_add_tail(&xfer[1], &msg);
> +	}
> +
> +	ret = spi_sync(lcd->spi, &msg);
> +	if (ret < 0)
> +		dev_err(&lcdev->dev, "Couldn't send SPI data.\n");
> +
> +	if (txlen)
> +		kfree(local_txbuf);
> +
> +	return ret;
> +}
> +
> +static inline int hx8357_spi_write_array(struct lcd_device *lcdev,
> +					u8 *value, u8 len)
> +{
> +	return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0);
> +}
> +
> +static inline int hx8357_spi_write_byte(struct lcd_device *lcdev,
> +					u8 value)
> +{
> +	return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0);
> +}
> +
> +static int hx8357_enter_standby(struct lcd_device *lcdev)
> +{
> +	int ret;
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(10000, 12000);
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE);
> +	if (ret < 0)
> +		return ret;
> +
> +	msleep(120);
> +
> +	return 0;
> +}
> +
> +static int hx8357_exit_standby(struct lcd_device *lcdev)
> +{
> +	int ret;
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
> +	if (ret < 0)
> +		return ret;
> +
> +	msleep(120);
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int hx8357_lcd_init(struct lcd_device *lcdev)
> +{
> +	struct hx8357_data *lcd = lcd_get_data(lcdev);
> +	u8 buf[16];
> +	int ret;
> +
> +	/*
> +	 * Set the interface selection pins to SPI mode, with three
> +	 * wires
> +	 */
> +	gpio_set_value_cansleep(lcd->im_pins[0], 1);
> +	gpio_set_value_cansleep(lcd->im_pins[1], 0);
> +	gpio_set_value_cansleep(lcd->im_pins[2], 1);
> +
> +	/* Reset the screen */
> +	gpio_set_value(lcd->reset, 1);
> +	usleep_range(10000, 12000);
> +	gpio_set_value(lcd->reset, 0);
> +	usleep_range(10000, 12000);
> +	gpio_set_value(lcd->reset, 1);
> +	msleep(120);
> +
> +	buf[0] = HX8357_SET_POWER;
> +	buf[1] = 0x44;
> +	buf[2] = 0x41;
> +	buf[3] = 0x06;
> +	ret = hx8357_spi_write_array(lcdev, buf, 4);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_VCOM;
> +	buf[1] = 0x40;
> +	buf[2] = 0x10;
> +	ret = hx8357_spi_write_array(lcdev, buf, 3);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_POWER_NORMAL;
> +	buf[1] = 0x05;
> +	buf[2] = 0x12;
> +	ret = hx8357_spi_write_array(lcdev, buf, 3);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_PANEL_DRIVING;
> +	buf[1] = 0x14;
> +	buf[2] = 0x3b;
> +	buf[3] = 0x00;
> +	buf[4] = 0x02;
> +	buf[5] = 0x11;
> +	ret = hx8357_spi_write_array(lcdev, buf, 6);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_DISPLAY_FRAME;
> +	buf[1] = 0x0c;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_PANEL_RELATED;
> +	buf[1] = 0x01;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = 0xea;
> +	buf[1] = 0x03;
> +	buf[2] = 0x00;
> +	buf[3] = 0x00;
> +	ret = hx8357_spi_write_array(lcdev, buf, 4);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = 0xeb;
> +	buf[1] = 0x40;
> +	buf[2] = 0x54;
> +	buf[3] = 0x26;
> +	buf[4] = 0xdb;
> +	ret = hx8357_spi_write_array(lcdev, buf, 5);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_GAMMA;
> +	buf[1] = 0x00;
> +	buf[2] = 0x15;
> +	buf[3] = 0x00;
> +	buf[4] = 0x22;
> +	buf[5] = 0x00;
> +	buf[6] = 0x08;
> +	buf[7] = 0x77;
> +	buf[8] = 0x26;
> +	buf[9] = 0x77;
> +	buf[10] = 0x22;
> +	buf[11] = 0x04;
> +	buf[12] = 0x00;
> +	ret = hx8357_spi_write_array(lcdev, buf, 13);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_ADDRESS_MODE;
> +	buf[1] = 0xc0;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_PIXEL_FORMAT;
> +	buf[1] = HX8357_SET_PIXEL_FORMAT_DPI_18BIT |
> +		HX8357_SET_PIXEL_FORMAT_DBI_18BIT;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_COLUMN_ADDRESS;
> +	buf[1] = 0x00;
> +	buf[2] = 0x00;
> +	buf[3] = 0x01;
> +	buf[4] = 0x3f;
> +	ret = hx8357_spi_write_array(lcdev, buf, 5);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_PAGE_ADDRESS;
> +	buf[1] = 0x00;
> +	buf[2] = 0x00;
> +	buf[3] = 0x01;
> +	buf[4] = 0xdf;
> +	ret = hx8357_spi_write_array(lcdev, buf, 5);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_RGB;
> +	buf[1] = 0x02;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = HX8357_SET_DISPLAY_MODE;
> +	buf[1] = HX8357_SET_DISPLAY_MODE_RGB_THROUGH |
> +		HX8357_SET_DISPLAY_MODE_RGB_INTERFACE;
> +	ret = hx8357_spi_write_array(lcdev, buf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
> +	if (ret < 0)
> +		return ret;
> +
> +	msleep(120);
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(5000, 7000);
> +
> +	ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)
> +
> +static int hx8357_set_power(struct lcd_device *lcdev, int power)
> +{
> +	struct hx8357_data *lcd = lcd_get_data(lcdev);
> +	int ret = 0;
> +
> +	if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state))
> +		ret = hx8357_exit_standby(lcdev);
> +	else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state))
> +		ret = hx8357_enter_standby(lcdev);
> +
> +	if (ret = 0)
> +		lcd->state = power;
> +	else
> +		dev_warn(&lcdev->dev, "failed to set power mode %d\n", power);
> +
> +	return ret;
> +}
> +
> +static int hx8357_get_power(struct lcd_device *lcdev)
> +{
> +	struct hx8357_data *lcd = lcd_get_data(lcdev);
> +
> +	return lcd->state;
> +}
> +
> +static struct lcd_ops hx8357_ops = {
> +	.set_power	= hx8357_set_power,
> +	.get_power	= hx8357_get_power,
> +};
> +
> +static int __devinit hx8357_probe(struct spi_device *spi)

Please remove '__devexit', because it is useless.
Also, it makes build error.

(http://comments.gmane.org/gmane.linux.kernel/1395773)

> +{
> +	struct lcd_device *lcdev;
> +	struct hx8357_data *lcd;
> +	int i, ret;
> +
> +	lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
> +	if (!lcd) {
> +		dev_err(&spi->dev, "Couldn't allocate lcd internal structure!\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = spi_setup(spi);
> +	if (ret < 0) {
> +		dev_err(&spi->dev, "SPI setup failed.\n");
> +		return ret;
> +	}
> +
> +	lcd->spi = spi;
> +
> +	lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
> +	if (!gpio_is_valid(lcd->reset)) {
> +		dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = devm_gpio_request_one(&spi->dev, lcd->reset,
> +				    GPIOF_OUT_INIT_HIGH,
> +				    "hx8357-reset");
> +	if (ret) {
> +		dev_err(&spi->dev,
> +			"failed to request gpio %d: %d\n",
> +			lcd->reset, ret);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
> +		lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
> +						"im-gpios", i);
> +		if (lcd->im_pins[i] = -EPROBE_DEFER) {
> +			dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
> +			return -EPROBE_DEFER;
> +		}
> +		if (!gpio_is_valid(lcd->im_pins[i])) {
> +			dev_err(&spi->dev, "Missing dt property: im-gpios\n");
> +			return -EINVAL;
> +		}
> +
> +		ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
> +					GPIOF_DIR_OUT, "im_pins");

Please replace GPIOF_DIR_OUT with GPIOF_OUT_INIT_LOW.
If you want to set Low value, please use GPIOF_OUT_INIT_LOW.


> +		if (ret) {
> +			dev_err(&spi->dev, "failed to request gpio %d: %d\n",
> +				lcd->im_pins[i], ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
> +	if (IS_ERR(lcdev)) {
> +		ret = PTR_ERR(lcdev);
> +		return ret;
> +	}
> +	spi_set_drvdata(spi, lcdev);
> +
> +	ret = hx8357_lcd_init(lcdev);
> +	if (ret) {
> +		dev_err(&spi->dev, "Couldn't initialize panel\n");
> +		goto init_error;
> +	}
> +
> +	dev_info(&spi->dev, "Panel probed\n");
> +
> +	return 0;
> +
> +init_error:
> +	lcd_device_unregister(lcdev);
> +	return ret;
> +}
> +
> +static int __devexit hx8357_remove(struct spi_device *spi)

Please remove '__devexit'.

> +{
> +	struct lcd_device *lcdev = spi_get_drvdata(spi);
> +
> +	lcd_device_unregister(lcdev);
> +	return 0;
> +}
> +
> +static const struct of_device_id hx8357_dt_ids[] = {
> +	{ .compatible = "himax,hx8357" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
> +
> +static struct spi_driver hx8357_driver = {
> +	.probe  = hx8357_probe,
> +	.remove = __devexit_p(hx8357_remove),

Please remove '__devexit_p'.

> +	.driver = {
> +		.name = "hx8357",
> +		.of_match_table = of_match_ptr(hx8357_dt_ids),
> +	},
> +};
> +
> +module_spi_driver(hx8357_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
> +MODULE_DESCRIPTION("Himax HX-8357 LCD Driver");
> +MODULE_LICENSE("GPL");
> --
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* Re: [PATCH v16 RESEND 0/7] of: add display helper
From: Steffen Trumtrar @ 2013-01-23  9:12 UTC (permalink / raw)
  To: Rob Clark
  Cc: devicetree-discuss, David Airlie, Rob Herring, linux-fbdev,
	dri-devel, Laurent Pinchart, Thierry Reding,
	Guennady Liakhovetski, linux-media, Tomi Valkeinen,
	Stephen Warren, Florian Tobias Schandinat, Leela Krishna Amudala,
	Mohammed, Afzal, kernel
In-Reply-To: <CAF6AEGvFNA1gc_5XWqL_baEnn8DTn0R-xqui034rg3Eo-V_6Qw@mail.gmail.com>

On Tue, Jan 22, 2013 at 03:50:48PM -0600, Rob Clark wrote:
> On Mon, Jan 21, 2013 at 5:07 AM, Steffen Trumtrar
> <s.trumtrar@pengutronix.de> wrote:
> > Hi!
> >
> > There was still no maintainer, that commented, ack'd, nack'd, apply'd the
> > series. So, this is just a resend.
> > The patches were tested with:
> >
> >         - v15 on Tegra by Thierry
> >         - sh-mobile-lcdcfb by Laurent
> >         - MX53QSB by Marek
> >         - Exynos: smdk5250 by Leela
> >         - AM335X EVM & AM335X EVM-SK by Afzal
> >         - imx6q: sabrelite, sabresd by Philipp and me
> >         - imx53: tqma53/mba53 by me
> 
> 
> btw, you can add my tested-by for this series..  I've been using them
> for the tilcdc lcd-panel output driver support.
> 

Thanks. The more drivers the merrier ;-)

Steffen

> >
> >
> > Changes since v15:
> >         - move include/linux/{videomode,display_timing}.h to include/video
> >         - move include/linux/of_{videomode,display_timing}.h to include/video
> >         - reimplement flags: add VESA flags and data flags
> >         - let pixelclock in struct videomode be unsigned long
> >         - rename of_display_timings_exists to of_display_timings_exist
> >         - revise logging/error messages: replace __func__ with np->full_name
> >         - rename pixelclk-inverted to pixelclk-active
> >         - revise comments in code
> >
> > Changes since v14:
> >         - fix "const struct *" warning
> >                 (reported by: Leela Krishna Amudala <l.krishna@samsung.com>)
> >         - return -EINVAL when htotal or vtotal are zero
> >         - remove unreachable code in of_get_display_timings
> >         - include headers in .c files and not implicit in .h
> >         - sort includes alphabetically
> >         - fix lower/uppercase in binding documentation
> >         - rebase onto v3.7-rc7
> >
> > Changes since v13:
> >         - fix "const struct *" warning
> >                 (reported by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>)
> >         - prevent division by zero in fb_videomode_from_videomode
> >
> > Changes since v12:
> >         - rename struct display_timing to via_display_timing in via subsystem
> >         - fix refreshrate calculation
> >         - fix "const struct *" warnings
> >                 (reported by: Manjunathappa, Prakash <prakash.pm@ti.com>)
> >         - some CodingStyle fixes
> >         - rewrite parts of commit messages and display-timings.txt
> >         - let display_timing_get_value get all values instead of just typical
> >
> > Changes since v11:
> >         - make pointers const where applicable
> >         - add reviewed-by Laurent Pinchart
> >
> > Changes since v10:
> >         - fix function name (drm_)display_mode_from_videomode
> >         - add acked-by, reviewed-by, tested-by
> >
> > Changes since v9:
> >         - don't leak memory when previous timings were correct
> >         - CodingStyle fixes
> >         - move blank lines around
> >
> > Changes since v8:
> >         - fix memory leaks
> >         - change API to be more consistent (foo_from_bar(struct bar, struct foo))
> >         - include headers were necessary
> >         - misc minor bugfixes
> >
> > Changes since v7:
> >         - move of_xxx to drivers/video
> >         - remove non-binding documentation from display-timings.txt
> >         - squash display_timings and videomode in one patch
> >         - misc minor fixes
> >
> > Changes since v6:
> >         - get rid of some empty lines etc.
> >         - move functions to their subsystems
> >         - split of_ from non-of_ functions
> >         - add at least some kerneldoc to some functions
> >
> > Changes since v5:
> >         - removed all display stuff and just describe timings
> >
> > Changes since v4:
> >         - refactored functions
> >
> > Changes since v3:
> >         - print error messages
> >         - free alloced memory
> >         - general cleanup
> >
> > Changes since v2:
> >         - use hardware-near property-names
> >         - provide a videomode structure
> >         - allow ranges for all properties (<min,typ,max>)
> >         - functions to get display_mode or fb_videomode
> >
> >
> > Regards,
> > Steffen
> >
> >
> > Steffen Trumtrar (7):
> >   viafb: rename display_timing to via_display_timing
> >   video: add display_timing and videomode
> >   video: add of helper for display timings/videomode
> >   fbmon: add videomode helpers
> >   fbmon: add of_videomode helpers
> >   drm_modes: add videomode helpers
> >   drm_modes: add of_videomode helpers
> >
> >  .../devicetree/bindings/video/display-timing.txt   |  109 +++++++++
> >  drivers/gpu/drm/drm_modes.c                        |   70 ++++++
> >  drivers/video/Kconfig                              |   21 ++
> >  drivers/video/Makefile                             |    4 +
> >  drivers/video/display_timing.c                     |   24 ++
> >  drivers/video/fbmon.c                              |   94 ++++++++
> >  drivers/video/of_display_timing.c                  |  239 ++++++++++++++++++++
> >  drivers/video/of_videomode.c                       |   54 +++++
> >  drivers/video/via/hw.c                             |    6 +-
> >  drivers/video/via/hw.h                             |    2 +-
> >  drivers/video/via/lcd.c                            |    2 +-
> >  drivers/video/via/share.h                          |    2 +-
> >  drivers/video/via/via_modesetting.c                |    8 +-
> >  drivers/video/via/via_modesetting.h                |    6 +-
> >  drivers/video/videomode.c                          |   39 ++++
> >  include/drm/drmP.h                                 |    9 +
> >  include/linux/fb.h                                 |    8 +
> >  include/video/display_timing.h                     |  124 ++++++++++
> >  include/video/of_display_timing.h                  |   20 ++
> >  include/video/of_videomode.h                       |   18 ++
> >  include/video/videomode.h                          |   48 ++++
> >  21 files changed, 894 insertions(+), 13 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/video/display-timing.txt
> >  create mode 100644 drivers/video/display_timing.c
> >  create mode 100644 drivers/video/of_display_timing.c
> >  create mode 100644 drivers/video/of_videomode.c
> >  create mode 100644 drivers/video/videomode.c
> >  create mode 100644 include/video/display_timing.h
> >  create mode 100644 include/video/of_display_timing.h
> >  create mode 100644 include/video/of_videomode.h
> >  create mode 100644 include/video/videomode.h
> >
> > --
> > 1.7.10.4
> >
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Alex Courbot @ 2013-01-23  9:45 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, linux-fbdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
	Mark Zhang, gnurou@gmail.com
In-Reply-To: <20130122070630.GA14728@avionic-0098.adnet.avionic-design.de>

> I'm confused. Why would you want to call into pwm_bl directly? If we're
> going to split this up into separate platform devices, why not look up a
> given backlight device and use the backlight API on that? The pieces of
> the puzzle are all there: you can use of_find_backlight_by_node() to
> obtain a backlight device from a device tree node, so I'd expect the DT
> to look something like this:
> 
> 	backlight: backlight {
> 		compatible = "pwm-backlight";
> 		...
> 	};

This would still prevent any power control from the backlight driver. I.e. if 
someone sets the brightness to 0 through sysfs, we cannot power the backlight 
off as pwm-backlight cannot control more than the PWM without platform 
callbacks. Backlight could only be powered off as a result of a fb blank event.

> 	panel: panel {
> 		compatible = "...";
> 		...
> 		backlight = <&backlight>;
> 		...
> 	};

So all the power control of both the panel and backlight would be performed 
from this device's driver. How would it plug into tegra-drm? I would see 
tegra_panel as a new member of the tegra_output structure, with one callback 
invoked from tegra_encoder_dpms(). Does that look sane?

> After that you can wire it up with host1x using something like:
> 
> 	host1x {
> 		dc@54200000 {
> 			rgb {
> 				status = "okay";
> 
> 				nvidia,panel = <&panel>;
> 			};
> 		};
> 	};

Indeed. So if we do that, the DRM DPMS functions would take care of the 
panel/backlight powering and the backlight driver will control the PWM after 
this, through the FB notifier. This is a little bit different from the "official" 
power sequence, but I just tested controlling the PWM at the very end of the 
sequence and it works just as well. If you think this looks better I don't 
mind doing it that way, it is actually a good excuse for me to dive into the 
DRM code.

Anyway, this will only be a temporary solution, CDF is the only way to do this 
right.

Alex.


^ permalink raw reply

* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Leela Krishna Amudala @ 2013-01-23 10:27 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Thierry Reding, Stephen Warren,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mark Zhang,
	gnurou-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1358591420-7790-3-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Hello Alex,

On Sat, Jan 19, 2013 at 4:00 PM, Alexandre Courbot <acourbot@nvidia.com> wrote:
>
> Add a PWM-backlight subdriver for Tegra boards, with support for
> Ventana.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  arch/arm/boot/dts/tegra20-ventana.dts  |  18 +++-
>  arch/arm/configs/tegra_defconfig       |   1 +
>  drivers/video/backlight/Kconfig        |   7 ++
>  drivers/video/backlight/pwm_bl.c       |   3 +
>  drivers/video/backlight/pwm_bl_tegra.c | 159
> +++++++++++++++++++++++++++++++++
>  5 files changed, 186 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/video/backlight/pwm_bl_tegra.c
>
> diff --git a/arch/arm/boot/dts/tegra20-ventana.dts
> b/arch/arm/boot/dts/tegra20-ventana.dts
> index adc4754..a77b529 100644
> --- a/arch/arm/boot/dts/tegra20-ventana.dts
> +++ b/arch/arm/boot/dts/tegra20-ventana.dts
> @@ -516,6 +516,20 @@
>                 bus-width = <8>;
>         };
>
> +       backlight {
> +               compatible = "pwm-backlight-ventana";
> +               brightness-levels = <0 16 32 48 64 80 96 112 128 144 160
> 176 192 208 224 240 255>;
> +               default-brightness-level = <12>;
> +
> +               pwms = <&pwm 2 5000000>;
> +               pwm-names = "backlight";
> +
> +               power-supply = <&vdd_bl_reg>;
> +               panel-supply = <&vdd_pnl_reg>;
> +               bl-gpio = <&gpio 28 0>;
> +               bl-panel = <&gpio 10 0>;
> +       };
> +
>         regulators {
>                 compatible = "simple-bus";
>                 #address-cells = <1>;
> @@ -549,7 +563,7 @@
>                         enable-active-high;
>                 };
>
> -               regulator@3 {
> +               vdd_pnl_reg: regulator@3 {
>                         compatible = "regulator-fixed";
>                         reg = <3>;
>                         regulator-name = "vdd_pnl";
> @@ -559,7 +573,7 @@
>                         enable-active-high;
>                 };
>
> -               regulator@4 {
> +               vdd_bl_reg: regulator@4 {
>                         compatible = "regulator-fixed";
>                         reg = <4>;
>                         regulator-name = "vdd_bl";
> diff --git a/arch/arm/configs/tegra_defconfig
> b/arch/arm/configs/tegra_defconfig
> index a7827fd..1c46602 100644
> --- a/arch/arm/configs/tegra_defconfig
> +++ b/arch/arm/configs/tegra_defconfig
> @@ -150,6 +150,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
>  CONFIG_BACKLIGHT_CLASS_DEVICE=y
>  # CONFIG_BACKLIGHT_GENERIC is not set
>  CONFIG_BACKLIGHT_PWM=y
> +CONFIG_BACKLIGHT_PWM_TEGRA=y
>  CONFIG_FRAMEBUFFER_CONSOLE=y
>  CONFIG_LOGO=y
>  CONFIG_SOUND=y
> diff --git a/drivers/video/backlight/Kconfig
> b/drivers/video/backlight/Kconfig
> index 765a945..377a409 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -244,6 +244,13 @@ config BACKLIGHT_PWM
>           If you have a LCD backlight adjustable by PWM, say Y to enable
>           this driver.
>
> +config BACKLIGHT_PWM_TEGRA
> +       bool "PWM Backlight Driver for Tegra boards"
> +       depends on BACKLIGHT_PWM && ARCH_TEGRA
> +       help
> +         Support backlight power sequencing for Tegra boards.
> +         Supported boards: Ventana.
> +
>  config BACKLIGHT_DA903X
>         tristate "Backlight Driver for DA9030/DA9034 using WLED"
>         depends on PMIC_DA903X
> diff --git a/drivers/video/backlight/pwm_bl.c
> b/drivers/video/backlight/pwm_bl.c
> index b65a797..1a4a9a3 100644
> --- a/drivers/video/backlight/pwm_bl.c
> +++ b/drivers/video/backlight/pwm_bl.c
> @@ -217,6 +217,9 @@ static int pwm_backlight_parse_dt(struct device *dev,
>
>  static struct of_device_id pwm_backlight_of_match[] = {
>         { .compatible = "pwm-backlight" },
> +#ifdef CONFIG_BACKLIGHT_PWM_TEGRA
> +       { .compatible = "pwm-backlight-ventana" },
> +#endif
>         { }
>  };
>
> diff --git a/drivers/video/backlight/pwm_bl_tegra.c
> b/drivers/video/backlight/pwm_bl_tegra.c
> new file mode 100644
> index 0000000..8f2195b
> --- /dev/null
> +++ b/drivers/video/backlight/pwm_bl_tegra.c
> @@ -0,0 +1,159 @@
> +/*
> + * pwm-backlight subdriver for Tegra.
> + *
> + * Copyright (c) 2013 NVIDIA CORPORATION.  All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/pwm_backlight.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/list.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +
> +struct ventana_bl_data {
> +       struct regulator *vdd_power;
> +       struct regulator *vdd_panel;
> +       int bl_gpio;
> +       int panel_gpio;
> +       bool is_on;
> +};
> +
> +static int init_ventana(struct device *dev)
> +{
> +       struct ventana_bl_data *data;
> +       int ret;
> +
> +       data = devm_kzalloc(dev, sizeof(struct ventana_bl_data),
> GFP_KERNEL);
> +       if (!data)
> +               return -ENOMEM;
> +
> +       data->vdd_power = devm_regulator_get(dev, "power");
> +       if (IS_ERR(data->vdd_power)) {
> +               dev_err(dev, "cannot get power regulator!\n");
> +               return PTR_ERR(data->vdd_power);
> +       }
> +
> +       data->vdd_panel = devm_regulator_get(dev, "panel");
> +       if (IS_ERR(data->vdd_panel)) {
> +               dev_err(dev, "cannot get panel regulator!\n");
> +               return PTR_ERR(data->vdd_panel);
> +       }
> +
> +       ret = of_get_named_gpio(dev->of_node, "bl-gpio", 0);
> +       if (ret < 0) {
> +               dev_err(dev, "cannot find backlight GPIO!\n");
> +               return ret;
> +       }
> +       data->bl_gpio = ret;
> +
> +       ret = of_get_named_gpio(dev->of_node, "bl-panel", 0);
> +       if (ret < 0) {
> +               dev_err(dev, "cannot find panel GPIO!\n");
> +               return ret;
> +       }
> +       data->panel_gpio = ret;
> +
> +       ret = devm_gpio_request_one(dev, data->bl_gpio,
> +                                   GPIOF_DIR_OUT | GPIOF_OUT_INIT_LOW,
> +                                   "backlight");
> +       if (ret < 0) {
> +               dev_err(dev, "cannot request backlight GPIO!\n");
> +               return ret;
> +       }
> +
> +       ret = devm_gpio_request_one(dev, data->panel_gpio,
> +                                   GPIOF_DIR_OUT | GPIOF_OUT_INIT_LOW,
> +                                   "panel");
> +       if (ret < 0) {
> +               dev_err(dev, "cannot request panel GPIO!\n");
> +               return ret;
> +       }
> +
> +       pwm_backlight_set_subdriver_data(dev, data);

Here you are passing ventana_bl_data pointer as input and in the
pwm_backlight_get_subdriver_data() function you are assigning the
received driver data to backlight_device pointer. As both are two
different structures with different structure fields in it. There can
be a chance for a crash.

Please correct me if I'm wrong.

Best Wishes,
Leela Krishna Amudala.

> +
> +       return 0;
> +}
> +
> +static void exit_ventana(struct device *dev)
> +{
> +       struct ventana_bl_data *data > pwm_backlight_get_subdriver_data(dev);
> +
> +       devm_gpio_free(dev, data->panel_gpio);
> +       devm_gpio_free(dev, data->bl_gpio);
> +       devm_regulator_put(data->vdd_panel);
> +       devm_regulator_put(data->vdd_power);
> +       devm_kfree(dev, data);
> +}
> +
> +static int notify_ventana(struct device *dev, int brightness)
> +{
> +       struct ventana_bl_data *data > pwm_backlight_get_subdriver_data(dev);
> +       if (brightness && !data->is_on) {
> +               regulator_enable(data->vdd_panel);
> +               gpio_set_value(data->panel_gpio, 1);
> +               usleep_range(200000, 200000);
> +               regulator_enable(data->vdd_power);
> +               usleep_range(10000, 10000);
> +       } else if (!brightness && data->is_on) {
> +               gpio_set_value(data->bl_gpio, 0);
> +       }
> +
> +       return brightness;
> +}
> +
> +static void notify_after_ventana(struct device *dev, int brightness)
> +{
> +       struct ventana_bl_data *data > pwm_backlight_get_subdriver_data(dev);
> +       if (brightness && !data->is_on) {
> +               gpio_set_value(data->bl_gpio, 1);
> +               data->is_on = true;
> +       } else if (!brightness && data->is_on) {
> +               usleep_range(10000, 10000);
> +               regulator_disable(data->vdd_power);
> +               usleep_range(200000, 200000);
> +               gpio_set_value(data->panel_gpio, 0);
> +               regulator_disable(data->vdd_panel);
> +               data->is_on = false;
> +       }
> +}
> +
> +static struct pwm_backlight_subdriver pwm_backlight_ventana_subdriver = {
> +       .name = "pwm-backlight-ventana",
> +       .init = init_ventana,
> +       .exit = exit_ventana,
> +       .notify = notify_ventana,
> +       .notify_after = notify_after_ventana,
> +};
> +
> +static int __init pwm_backlight_tegra_init(void)
> +{
> +       pwm_backlight_add_subdriver(&pwm_backlight_ventana_subdriver);
> +       return 0;
> +}
> +
> +static void __exit pwm_backlight_tegra_exit(void)
> +{
> +       pwm_backlight_remove_subdriver(&pwm_backlight_ventana_subdriver);
> +}
> +
> +module_init(pwm_backlight_tegra_init);
> +module_exit(pwm_backlight_tegra_exit);
> +
> +MODULE_DESCRIPTION("Backlight Driver for Tegra boards");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:pwm-tegra-backlight");
> +
> +
> --
> 1.8.1.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Alex Courbot @ 2013-01-23 10:29 UTC (permalink / raw)
  To: Leela Krishna Amudala
  Cc: Thierry Reding, Stephen Warren,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mark Zhang,
	gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
In-Reply-To: <CAL1wa8d2BS3RxdsdUyCqF20ZKe46jUZcfUKitnpP9Lgb9aB5hw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Wednesday 23 January 2013 18:15:30 Leela Krishna Amudala wrote:
> > +       pwm_backlight_set_subdriver_data(dev, data);
> 
> Here you are passing ventana_bl_data pointer as input and in the
> pwm_backlight_get_subdriver_data() function you are assigning the
> received driver data to backlight_device pointer. As both are two
> different structures with different structure fields in it. There can
> be a chance for a crash.

That's because the following happens later in pwm_backlight_probe():

	pb->subdriver_data = dev_get_drvdata(&pdev->dev);
	...
	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
				       &pwm_backlight_ops, &props);
	...
	platform_set_drvdata(pdev, bl);

So from then on the result of dev_get_drvdata() is indeed an instance of 
backlight_device from which we can retrieve the subdriver data. I'm not really 
proud of this. But fortunately it seems like we are going to do things 
differently.

Alex.


^ permalink raw reply

* [PATCH v4 08/12] video: da8xx-fb: invoke platform callback safely
From: Afzal Mohammed @ 2013-01-23 11:49 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, devicetree-discuss, linux-doc,
	linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Mike Turquette
In-Reply-To: <cover.1358937685.git.afzal@ti.com>

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.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 08ee8eb..0beed20 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1347,7 +1347,7 @@ static int fb_probe(struct platform_device *device)
 	par->dev = &device->dev;
 	par->lcdc_clk = fb_clk;
 	par->lcd_fck_rate = clk_get_rate(fb_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);
 	}
-- 
1.7.12


^ permalink raw reply related

* [PATCH v4 12/12] video: da8xx-fb: CCF clock divider handling
From: Afzal Mohammed @ 2013-01-23 11:49 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, devicetree-discuss, linux-doc,
	linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Mike Turquette
In-Reply-To: <cover.1358937685.git.afzal@ti.com>

Common clock framework provides a basic clock divider. Make use of it
to handle clock configuration in the LCDC IP, wherever applicable;
out of two platforms having this IP, only am335x is converted to use
CCF, DaVinci is not yet converted. Hence wrap the modification such
that it will come into effect only if CCF is selected, otherwise,
prgram dividers as earlier. Once DaVinci is converted to use CCF,
this ifdef'ery can be removed.

Divider clock instantiated is made as a one that allows the rate
propogation to it's parent, that provides more options w.r.t pixel
clock rates that could be configured.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---

v4: use new registration for clock divider having minimum divider
    requirement and have ifdef'ery in a better way
v3: model CCF clock divider with parent propogation if CCF selected
v2: new patch

 drivers/video/da8xx-fb.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 5455682..6723683 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/lcm.h>
+#include <linux/clk-provider.h>
 #include <video/of_display_timing.h>
 #include <video/da8xx-fb.h>
 #include <asm/div64.h>
@@ -133,6 +134,10 @@
 #define WSI_TIMEOUT	50
 #define PALETTE_SIZE	256
 
+#define	LCD_CLK_SHIFT	8
+#define	LCD_CLK_WIDTH	8
+#define	LCD_CLK_MIN_DIV	2
+
 static void __iomem *da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
 static unsigned int lcd_revision;
@@ -181,6 +186,9 @@ struct da8xx_fb_par {
 	u32 pseudo_palette[16];
 	struct fb_videomode	mode;
 	struct lcd_ctrl_config	cfg;
+#ifdef CONFIG_COMMON_CLK
+	struct clk		*child_clk;
+#endif
 };
 
 static struct fb_var_screeninfo da8xx_fb_var;
@@ -683,12 +691,27 @@ static void da8xx_fb_lcd_reset(void)
 	}
 }
 
+#ifndef	CONFIG_COMMON_CLK
 static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
 						 unsigned pixclock)
 {
 	return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
 }
+#endif
 
+#ifdef	CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+					  unsigned pixclock)
+{
+	unsigned long rate;
+
+	rate = PICOS2KHZ(pixclock) * 1000;
+	rate = clk_round_rate(par->child_clk, rate);
+	rate = KHZ2PICOS(rate / 1000);
+
+	return rate;
+}
+#else
 static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
 					  unsigned pixclock)
 {
@@ -703,19 +726,43 @@ static inline void da8xx_fb_config_clk_divider(unsigned div)
 	/* Configure the LCD clock divisor. */
 	lcdc_write(LCD_CLK_DIVISOR(div) |
 			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
+#endif
 
+static inline void da8xx_fb_clkc_enable(void)
+{
 	if (lcd_revision = LCD_VERSION_2)
 		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
 				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
 }
 
-static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+#ifdef	CONFIG_COMMON_CLK
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+						    struct fb_videomode *mode)
+{
+	int ret;
+
+	ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(par->dev, "unable to setup pixel clock of %u ps",
+			mode->pixclock);
+		return ret;
+	}
+	da8xx_fb_clkc_enable();
+	return 0;
+}
+#else
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
 						    struct fb_videomode *mode)
 {
 	unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
 
 	da8xx_fb_config_clk_divider(div);
+	da8xx_fb_clkc_enable();
+
+	return 0;
 }
+#endif
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 		struct fb_videomode *panel)
@@ -723,7 +770,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	u32 bpp;
 	int ret = 0;
 
-	da8xx_fb_calc_config_clk_divider(par, panel);
+	ret = da8xx_fb_calc_config_clk_divider(par, panel);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (panel->sync & FB_SYNC_CLK_INVERT)
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -1406,6 +1455,25 @@ static int fb_probe(struct platform_device *device)
 
 	da8xx_fb_lcd_reset();
 
+#ifdef	CONFIG_COMMON_CLK
+	/* set sane divisor value to begin along with the mode */
+	lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(LCD_CLK_MIN_DIV),
+		   LCD_CTRL_REG);
+
+	par->child_clk = clk_register_min_divider(NULL, "da8xx_fb_clk",
+					      __clk_get_name(fb_clk),
+					      CLK_SET_RATE_PARENT,
+					      da8xx_fb_reg_base + LCD_CTRL_REG,
+					      LCD_CLK_SHIFT, LCD_CLK_WIDTH,
+					      LCD_CLK_MIN_DIV,
+					      CLK_DIVIDER_ONE_BASED, NULL);
+	if (IS_ERR(par->child_clk)) {
+		dev_err(&device->dev, "error registering clk\n");
+		ret = -ENODEV;
+		goto err_release_fb;
+	}
+#endif
+
 	/* allocate frame buffer */
 	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
 	ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
-- 
1.7.12


^ permalink raw reply related

* [PATCH v4 11/12] video: da8xx-fb: setup struct lcd_ctrl_config for dt
From: Afzal Mohammed @ 2013-01-23 11:49 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, devicetree-discuss, linux-doc,
	linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Mike Turquette
In-Reply-To: <cover.1358937685.git.afzal@ti.com>

strcut lcd_ctrl_config information required for driver is currently
obtained via platform data. To handle DT probing, create
lcd_ctrl_config and populate it with default values, these values are
sufficient for the panels so far used with this controller to work.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 1c1a616..5455682 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1254,6 +1254,35 @@ 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) {
+		dev_err(&dev->dev, "memory allocation failed\n");
+		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->dev.platform_data;
@@ -1345,7 +1374,10 @@ static int fb_probe(struct platform_device *device)
 		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 = (struct lcd_ctrl_config *)fb_pdata->controller_data;
 
 	if (!lcd_cfg) {
 		ret = -EINVAL;
-- 
1.7.12


^ permalink raw reply related

* [PATCH v4 10/12] video: da8xx-fb: ensure pdata only for non-dt
From: Afzal Mohammed @ 2013-01-23 11:49 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, devicetree-discuss, linux-doc,
	linux-kernel
  Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
	Rob Herring, Rob Landley, Mike Turquette
In-Reply-To: <cover.1358937685.git.afzal@ti.com>

This driver is DT probe-able, hence ensure presence of platform data
only for non-DT boot.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/video/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0c68712..1c1a616 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1303,7 +1303,7 @@ static int fb_probe(struct platform_device *device)
 	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;
 	}
-- 
1.7.12


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox