Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Sean Paul @ 2014-12-03  1:39 UTC (permalink / raw)
  To: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: jg1.han-Sze3O3UU22JBDgjK7y7TUQ, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	Sean Paul, Stéphane Marchesin

This patch refactors the dt parsing code to avoid setting platform_data,
instead just setting lp->pdata directly. This facilitates easier
probe deferral since the current scheme would require us to clear out
dev->platform_data before deferring.

Cc: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 25fb8e3..257b3ba 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
 };
 
 #ifdef CONFIG_OF
-static int lp855x_parse_dt(struct device *dev, struct device_node *node)
+static int lp855x_parse_dt(struct lp855x *lp)
 {
+	struct device *dev = lp->dev;
+	struct device_node *node = dev->of_node;
 	struct lp855x_platform_data *pdata;
 	int rom_length;
 
@@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
 		pdata->rom_data = &rom[0];
 	}
 
-	dev->platform_data = pdata;
+	lp->pdata = pdata;
 
 	return 0;
 }
 #else
-static int lp855x_parse_dt(struct device *dev, struct device_node *node)
+static int lp855x_parse_dt(struct lp855x *lp)
 {
 	return -EINVAL;
 }
@@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
 	struct lp855x *lp;
-	struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
-	struct device_node *node = cl->dev.of_node;
 	int ret;
 
-	if (!pdata) {
-		ret = lp855x_parse_dt(&cl->dev, node);
-		if (ret < 0)
-			return ret;
-
-		pdata = dev_get_platdata(&cl->dev);
-	}
-
 	if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
 		return -EIO;
 
@@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	if (!lp)
 		return -ENOMEM;
 
-	if (pdata->period_ns > 0)
-		lp->mode = PWM_BASED;
-	else
-		lp->mode = REGISTER_BASED;
-
 	lp->client = cl;
 	lp->dev = &cl->dev;
-	lp->pdata = pdata;
 	lp->chipname = id->name;
 	lp->chip_id = id->driver_data;
+	lp->pdata = dev_get_platdata(&cl->dev);
+
+	if (!lp->pdata) {
+		ret = lp855x_parse_dt(lp);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (lp->pdata->period_ns > 0)
+		lp->mode = PWM_BASED;
+	else
+		lp->mode = REGISTER_BASED;
+
 	i2c_set_clientdata(cl, lp);
 
 	ret = lp855x_configure(lp);
-- 
2.1.1


^ permalink raw reply related

* [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Sean Paul @ 2014-12-03  1:39 UTC (permalink / raw)
  To: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: jg1.han-Sze3O3UU22JBDgjK7y7TUQ, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	Sean Paul, Stéphane Marchesin, Aaron Durbin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

This patch adds a supply regulator to the lp855x platform data to facilitate
powering on/off the 3V rail attached to the controller.

Cc: Stéphane Marchesin <marcheu@chromium.org>
Cc: Aaron Durbin <adurbin@chromium.org>
Acked-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Add NULL check in lp855x_remove


 .../devicetree/bindings/video/backlight/lp855x.txt     |  2 ++
 drivers/video/backlight/lp855x_bl.c                    | 18 ++++++++++++++++++
 include/linux/platform_data/lp855x.h                   |  2 ++
 3 files changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
index 96e83a5..0a3ecbc 100644
--- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
+++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
@@ -12,6 +12,7 @@ Optional properties:
   - pwm-period: PWM period value. Set only PWM input mode used (u32)
   - rom-addr: Register address of ROM area to be updated (u8)
   - rom-val: Register value to be updated (u8)
+  - power-supply: Regulator which controls the 3V rail
 
 Example:
 
@@ -56,6 +57,7 @@ Example:
 	backlight@2c {
 		compatible = "ti,lp8557";
 		reg = <0x2c>;
+		power-supply = <&backlight_vdd>;
 
 		dev-ctrl = /bits/ 8 <0x41>;
 		init-brt = /bits/ 8 <0x0a>;
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 257b3ba..a26d3bb 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -17,6 +17,7 @@
 #include <linux/of.h>
 #include <linux/platform_data/lp855x.h>
 #include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
 
 /* LP8550/1/2/3/6 Registers */
 #define LP855X_BRIGHTNESS_CTRL		0x00
@@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
 		pdata->rom_data = &rom[0];
 	}
 
+	pdata->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(pdata->supply)) {
+		if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		pdata->supply = NULL;
+	}
+
 	lp->pdata = pdata;
 
 	return 0;
@@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	else
 		lp->mode = REGISTER_BASED;
 
+	if (lp->pdata->supply) {
+		ret = regulator_enable(lp->pdata->supply);
+		if (ret < 0) {
+			dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
+			return ret;
+		}
+	}
+
 	i2c_set_clientdata(cl, lp);
 
 	ret = lp855x_configure(lp);
@@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
 
 	lp->bl->props.brightness = 0;
 	backlight_update_status(lp->bl);
+	if (lp->pdata->supply)
+		regulator_disable(lp->pdata->supply);
 	sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
 
 	return 0;
diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
index 1b2ba24..9c7fd1e 100644
--- a/include/linux/platform_data/lp855x.h
+++ b/include/linux/platform_data/lp855x.h
@@ -136,6 +136,7 @@ struct lp855x_rom_data {
 		Only valid when mode is PWM_BASED.
  * @size_program : total size of lp855x_rom_data
  * @rom_data : list of new eeprom/eprom registers
+ * @supply : regulator that supplies 3V input
  */
 struct lp855x_platform_data {
 	const char *name;
@@ -144,6 +145,7 @@ struct lp855x_platform_data {
 	unsigned int period_ns;
 	int size_program;
 	struct lp855x_rom_data *rom_data;
+	struct regulator *supply;
 };
 
 #endif
-- 
2.2.0.rc0.207.ga3a616c


^ permalink raw reply related

* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Bryan Wu @ 2014-12-03  1:49 UTC (permalink / raw)
  To: Sean Paul
  Cc: 김우겸, FBDEV list,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jingoo Han,
	Lee Jones, Stéphane Marchesin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Tue, Dec 2, 2014 at 5:39 PM, Sean Paul <seanpaul@chromium.org> wrote:
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
>

Looks good to me,
Acked-by: Bryan Wu <cooloney@gmail.com>

Please also wait for Milo to ack. Lee, can you take this patch?

Thanks,
-Bryan

> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
>  1 file changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 25fb8e3..257b3ba 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
>  };
>
>  #ifdef CONFIG_OF
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
> +       struct device *dev = lp->dev;
> +       struct device_node *node = dev->of_node;
>         struct lp855x_platform_data *pdata;
>         int rom_length;
>
> @@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>                 pdata->rom_data = &rom[0];
>         }
>
> -       dev->platform_data = pdata;
> +       lp->pdata = pdata;
>
>         return 0;
>  }
>  #else
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
>         return -EINVAL;
>  }
> @@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>  static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  {
>         struct lp855x *lp;
> -       struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
> -       struct device_node *node = cl->dev.of_node;
>         int ret;
>
> -       if (!pdata) {
> -               ret = lp855x_parse_dt(&cl->dev, node);
> -               if (ret < 0)
> -                       return ret;
> -
> -               pdata = dev_get_platdata(&cl->dev);
> -       }
> -
>         if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
>                 return -EIO;
>
> @@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>         if (!lp)
>                 return -ENOMEM;
>
> -       if (pdata->period_ns > 0)
> -               lp->mode = PWM_BASED;
> -       else
> -               lp->mode = REGISTER_BASED;
> -
>         lp->client = cl;
>         lp->dev = &cl->dev;
> -       lp->pdata = pdata;
>         lp->chipname = id->name;
>         lp->chip_id = id->driver_data;
> +       lp->pdata = dev_get_platdata(&cl->dev);
> +
> +       if (!lp->pdata) {
> +               ret = lp855x_parse_dt(lp);
> +               if (ret < 0)
> +                       return ret;
> +       }
> +
> +       if (lp->pdata->period_ns > 0)
> +               lp->mode = PWM_BASED;
> +       else
> +               lp->mode = REGISTER_BASED;
> +
>         i2c_set_clientdata(cl, lp);
>
>         ret = lp855x_configure(lp);
> --
> 2.1.1
>

^ permalink raw reply

* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Kim, Milo @ 2014-12-03  1:56 UTC (permalink / raw)
  To: Sean Paul
  Cc: cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A, Stéphane Marchesin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On 12/3/2014 10:39 AM, Sean Paul wrote:
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
>
> Cc: Stéphane Marchesin<marcheu@chromium.org>
> Signed-off-by: Sean Paul<seanpaul@chromium.org>

Acked-by: Milo Kim <milo.kim@ti.com>

^ permalink raw reply

* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Kim, Milo @ 2014-12-03  1:57 UTC (permalink / raw)
  To: Sean Paul
  Cc: cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A, Stéphane Marchesin,
	Aaron Durbin
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On 12/3/2014 10:39 AM, Sean Paul wrote:
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
>
> Cc: Stéphane Marchesin<marcheu@chromium.org>
> Cc: Aaron Durbin<adurbin@chromium.org>
> Acked-by: Milo Kim<milo.kim@ti.com>
> Signed-off-by: Sean Paul<seanpaul@chromium.org>

Acked-by: Milo Kim <milo.kim@ti.com>

^ permalink raw reply

* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Jingoo Han @ 2014-12-03  2:06 UTC (permalink / raw)
  To: 'Sean Paul'
  Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	'Stéphane Marchesin', 'Aaron Durbin',
	'Jingoo Han'
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Wednesday, December 03, 2014 10:39 AM, Sean Paul wrote:
> 
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
> 
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Cc: Aaron Durbin <adurbin@chromium.org>
> Acked-by: Milo Kim <milo.kim@ti.com>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Acked-by: Jingoo Han <jg1.han@samsung.com>

Best regards,
Jingoo Han

> ---
> 
> Changes in v2:
> 	- Add NULL check in lp855x_remove
> 
> 
>  .../devicetree/bindings/video/backlight/lp855x.txt     |  2 ++
>  drivers/video/backlight/lp855x_bl.c                    | 18 ++++++++++++++++++
>  include/linux/platform_data/lp855x.h                   |  2 ++
>  3 files changed, 22 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> index 96e83a5..0a3ecbc 100644
> --- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> @@ -12,6 +12,7 @@ Optional properties:
>    - pwm-period: PWM period value. Set only PWM input mode used (u32)
>    - rom-addr: Register address of ROM area to be updated (u8)
>    - rom-val: Register value to be updated (u8)
> +  - power-supply: Regulator which controls the 3V rail
> 
>  Example:
> 
> @@ -56,6 +57,7 @@ Example:
>  	backlight@2c {
>  		compatible = "ti,lp8557";
>  		reg = <0x2c>;
> +		power-supply = <&backlight_vdd>;
> 
>  		dev-ctrl = /bits/ 8 <0x41>;
>  		init-brt = /bits/ 8 <0x0a>;
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 257b3ba..a26d3bb 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -17,6 +17,7 @@
>  #include <linux/of.h>
>  #include <linux/platform_data/lp855x.h>
>  #include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
> 
>  /* LP8550/1/2/3/6 Registers */
>  #define LP855X_BRIGHTNESS_CTRL		0x00
> @@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
>  		pdata->rom_data = &rom[0];
>  	}
> 
> +	pdata->supply = devm_regulator_get(dev, "power");
> +	if (IS_ERR(pdata->supply)) {
> +		if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		pdata->supply = NULL;
> +	}
> +
>  	lp->pdata = pdata;
> 
>  	return 0;
> @@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  	else
>  		lp->mode = REGISTER_BASED;
> 
> +	if (lp->pdata->supply) {
> +		ret = regulator_enable(lp->pdata->supply);
> +		if (ret < 0) {
> +			dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
> +			return ret;
> +		}
> +	}
> +
>  	i2c_set_clientdata(cl, lp);
> 
>  	ret = lp855x_configure(lp);
> @@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
> 
>  	lp->bl->props.brightness = 0;
>  	backlight_update_status(lp->bl);
> +	if (lp->pdata->supply)
> +		regulator_disable(lp->pdata->supply);
>  	sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
> 
>  	return 0;
> diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
> index 1b2ba24..9c7fd1e 100644
> --- a/include/linux/platform_data/lp855x.h
> +++ b/include/linux/platform_data/lp855x.h
> @@ -136,6 +136,7 @@ struct lp855x_rom_data {
>  		Only valid when mode is PWM_BASED.
>   * @size_program : total size of lp855x_rom_data
>   * @rom_data : list of new eeprom/eprom registers
> + * @supply : regulator that supplies 3V input
>   */
>  struct lp855x_platform_data {
>  	const char *name;
> @@ -144,6 +145,7 @@ struct lp855x_platform_data {
>  	unsigned int period_ns;
>  	int size_program;
>  	struct lp855x_rom_data *rom_data;
> +	struct regulator *supply;
>  };
> 
>  #endif
> --
> 2.2.0.rc0.207.ga3a616c


^ permalink raw reply

* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Jingoo Han @ 2014-12-03  2:08 UTC (permalink / raw)
  To: 'Sean Paul'
  Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	'Stéphane Marchesin', 'Jingoo Han'
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Wednesday, December 03, 2014 10:39 AM, Sean Paul wrote:
> 
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
> 
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Acked-by: Jingoo Han <jg1.han@samsung.com>

Best regards,
Jingoo Han

> ---
>  drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
>  1 file changed, 18 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 25fb8e3..257b3ba 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
>  };
> 
>  #ifdef CONFIG_OF
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
> +	struct device *dev = lp->dev;
> +	struct device_node *node = dev->of_node;
>  	struct lp855x_platform_data *pdata;
>  	int rom_length;
> 
> @@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>  		pdata->rom_data = &rom[0];
>  	}
> 
> -	dev->platform_data = pdata;
> +	lp->pdata = pdata;
> 
>  	return 0;
>  }
>  #else
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
>  	return -EINVAL;
>  }
> @@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>  static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  {
>  	struct lp855x *lp;
> -	struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
> -	struct device_node *node = cl->dev.of_node;
>  	int ret;
> 
> -	if (!pdata) {
> -		ret = lp855x_parse_dt(&cl->dev, node);
> -		if (ret < 0)
> -			return ret;
> -
> -		pdata = dev_get_platdata(&cl->dev);
> -	}
> -
>  	if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
>  		return -EIO;
> 
> @@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  	if (!lp)
>  		return -ENOMEM;
> 
> -	if (pdata->period_ns > 0)
> -		lp->mode = PWM_BASED;
> -	else
> -		lp->mode = REGISTER_BASED;
> -
>  	lp->client = cl;
>  	lp->dev = &cl->dev;
> -	lp->pdata = pdata;
>  	lp->chipname = id->name;
>  	lp->chip_id = id->driver_data;
> +	lp->pdata = dev_get_platdata(&cl->dev);
> +
> +	if (!lp->pdata) {
> +		ret = lp855x_parse_dt(lp);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (lp->pdata->period_ns > 0)
> +		lp->mode = PWM_BASED;
> +	else
> +		lp->mode = REGISTER_BASED;
> +
>  	i2c_set_clientdata(cl, lp);
> 
>  	ret = lp855x_configure(lp);
> --
> 2.1.1


^ permalink raw reply

* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Bryan Wu @ 2014-12-03  2:13 UTC (permalink / raw)
  To: Sean Paul
  Cc: 김우겸, FBDEV list,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jingoo Han,
	Lee Jones, Stéphane Marchesin, Aaron Durbin
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Tue, Dec 2, 2014 at 5:39 PM, Sean Paul <seanpaul@chromium.org> wrote:
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
>
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Cc: Aaron Durbin <adurbin@chromium.org>
> Acked-by: Milo Kim <milo.kim@ti.com>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Acked-by: Bryan Wu <cooloney@gmail.com>

Thanks,
-Bryan

> ---
>
> Changes in v2:
>         - Add NULL check in lp855x_remove
>
>
>  .../devicetree/bindings/video/backlight/lp855x.txt     |  2 ++
>  drivers/video/backlight/lp855x_bl.c                    | 18 ++++++++++++++++++
>  include/linux/platform_data/lp855x.h                   |  2 ++
>  3 files changed, 22 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> index 96e83a5..0a3ecbc 100644
> --- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> @@ -12,6 +12,7 @@ Optional properties:
>    - pwm-period: PWM period value. Set only PWM input mode used (u32)
>    - rom-addr: Register address of ROM area to be updated (u8)
>    - rom-val: Register value to be updated (u8)
> +  - power-supply: Regulator which controls the 3V rail
>
>  Example:
>
> @@ -56,6 +57,7 @@ Example:
>         backlight@2c {
>                 compatible = "ti,lp8557";
>                 reg = <0x2c>;
> +               power-supply = <&backlight_vdd>;
>
>                 dev-ctrl = /bits/ 8 <0x41>;
>                 init-brt = /bits/ 8 <0x0a>;
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 257b3ba..a26d3bb 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -17,6 +17,7 @@
>  #include <linux/of.h>
>  #include <linux/platform_data/lp855x.h>
>  #include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
>
>  /* LP8550/1/2/3/6 Registers */
>  #define LP855X_BRIGHTNESS_CTRL         0x00
> @@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
>                 pdata->rom_data = &rom[0];
>         }
>
> +       pdata->supply = devm_regulator_get(dev, "power");
> +       if (IS_ERR(pdata->supply)) {
> +               if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
> +                       return -EPROBE_DEFER;
> +               pdata->supply = NULL;
> +       }
> +
>         lp->pdata = pdata;
>
>         return 0;
> @@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>         else
>                 lp->mode = REGISTER_BASED;
>
> +       if (lp->pdata->supply) {
> +               ret = regulator_enable(lp->pdata->supply);
> +               if (ret < 0) {
> +                       dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
> +                       return ret;
> +               }
> +       }
> +
>         i2c_set_clientdata(cl, lp);
>
>         ret = lp855x_configure(lp);
> @@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
>
>         lp->bl->props.brightness = 0;
>         backlight_update_status(lp->bl);
> +       if (lp->pdata->supply)
> +               regulator_disable(lp->pdata->supply);
>         sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
>
>         return 0;
> diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
> index 1b2ba24..9c7fd1e 100644
> --- a/include/linux/platform_data/lp855x.h
> +++ b/include/linux/platform_data/lp855x.h
> @@ -136,6 +136,7 @@ struct lp855x_rom_data {
>                 Only valid when mode is PWM_BASED.
>   * @size_program : total size of lp855x_rom_data
>   * @rom_data : list of new eeprom/eprom registers
> + * @supply : regulator that supplies 3V input
>   */
>  struct lp855x_platform_data {
>         const char *name;
> @@ -144,6 +145,7 @@ struct lp855x_platform_data {
>         unsigned int period_ns;
>         int size_program;
>         struct lp855x_rom_data *rom_data;
> +       struct regulator *supply;
>  };
>
>  #endif
> --
> 2.2.0.rc0.207.ga3a616c
>

^ permalink raw reply

* [PATCH v10 0/6] Add Skyworks SKY81452 device drivers
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
	cooloney-Re5JQEeQqe8AvxtiuMwx3w, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, trivial-DgEjT+Ai2ygdnm+yROfE0A
  Cc: akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	jic23-DgEjT+Ai2ygdnm+yROfE0A,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	ktsai-GubuWUlQtMwciDkP5Hr2oA, hs-ynQEQJNshbs,
	stwiss.opensource-WBD+wuPFNBhBDgjK7y7TUQ,
	matti.vaittinen-OYasijW0DpE, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	jason-NLaQJdtUoK4Be96aLqz0jA, heiko-4mtYJXux2i+zQB+pC5nmwQ,
	shawn.guo-KZfg59tc24xl57MIdRCFDg, florian.vaussard-p8DiymsW2f8,
	andrew-g2DYL2Zd6BY, antonynpavlov-Re5JQEeQqe8AvxtiuMwx3w,
	hytszk-Re5JQEeQqe8AvxtiuMwx3w, plagnioj-sclMFOaUSTBWk0Htik3J/w,
	tomi.valkeinen-l0cyMroinI0, jack.yoo-tjhQNA90jdKqndwCJWfcng,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

This patch set includes regulator and backlight driver for SKY81452.
Also it includes documents for device tree and module.
sky81452-regulator was already applied. So this series doesn't
include it.

v10:
Removed trivial get_brightness implementations for sky81452-backlight

v9:
Removed the change to remove MODULE_VERSION() for sky81452-regulator

v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO
Made up the example for backlight DT
Changed the DT parsing of regulator using regulator_node and of_match

v7:
Modified licensing text to GPLv2
Splitted Kconfig renaming from DT patch

v6:
Added new line character at the end of line of dev_err()

v5:
Changed DT for regulator : 'lout' node should be defined under 'regulator'
Removed compatible string from sky81452-regulator driver
Modified sky81452-regulator to return EINVAL when of_node is NULL
Move sky81452-backlight.h to include/linux/platform_data

v4:
Removed MODULE_VERSION()
Modified license to GPLv2
Removed calling to backlight_device_unregister() in sky81452-backlight

v3:
Cleaned-up DBG messages
Cleaned-up DT
Fixed the backlight name from 'sky81452-bl' to 'sky81452-backlight'
Assigned mfd_cell.of_compatible for binding device node
Modified error messages
Modified sky81452-regulator to return ENODATA when of_node is NULL

v2:
Split the patches for each sub-system
Added 'reg' attribute for I2C address in device tree documents
Added 'compatible' attribute in child drivers
Renamed CONFIG_SKY81452 to CONFIG_MFD_SKY81452
Changed the dependency from I2C=y to I2C, for CONFIG_MFD_SKY81452
Added message for exception or errors.
Added vendor prefix for Skyworks Solutions, Inc.
Add SKY81452 to the Trivial Devices list

Gyungoh Yoo (6):
  mfd: Add support for Skyworks SKY81452 driver
  backlight: Add support Skyworks SKY81452 backlight driver
  devicetree: mfd: Add new SKY81452 mfd binding
  devicetree: backlight: Add new SKY81452 backlight binding
  devicetree: Add vendor prefix for Skyworks Solutions, Inc.
  devicetree: i2c: Add SKY81452 to the Trivial Devices list

 .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
 Documentation/devicetree/bindings/mfd/sky81452.txt |  36 +++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../video/backlight/sky81452-backlight.txt         |  29 ++
 drivers/mfd/Kconfig                                |  12 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/sky81452.c                             | 108 +++++++
 drivers/video/backlight/Kconfig                    |  10 +
 drivers/video/backlight/Makefile                   |   1 +
 drivers/video/backlight/sky81452-backlight.c       | 334 +++++++++++++++++++++
 include/linux/mfd/sky81452.h                       |  31 ++
 include/linux/platform_data/sky81452-backlight.h   |  46 +++
 12 files changed, 610 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/sky81452.txt
 create mode 100644 Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
 create mode 100644 drivers/mfd/sky81452.c
 create mode 100644 drivers/video/backlight/sky81452-backlight.c
 create mode 100644 include/linux/mfd/sky81452.h
 create mode 100644 include/linux/platform_data/sky81452-backlight.h

-- 
1.9.1


^ permalink raw reply

* [PATCH v10 1/6] mfd: Add support for Skyworks SKY81452 driver
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
Changes v10:
Nothing

Changes v9:
Nothing

Changes v8:
Nothing

Changes v7:
Modified licensing text to GPLv2

Changes v6:
Added new line character at the end of line of dev_err()

Changes v5:
Move sky81452-backlight.h to include/linux/platform_data

Changes v4:
Removed MODULE_VERSION()
Modified license to GPLv2

Changes v3:
Fixed the backlight name from 'sky81452-bl' to 'sky81452-backlight'
Assigned mfd_cell.of_compatible for binding device node
Modified error messages

Changes v2:
Renamed CONFIG_SKY81452 to CONFIG_MFD_SKY81452
Changed the dependency from I2C=y to I2C, for CONFIG_MFD_SKY81452
Added message for exception or errors

 drivers/mfd/Kconfig          |  12 +++++
 drivers/mfd/Makefile         |   1 +
 drivers/mfd/sky81452.c       | 108 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/sky81452.h |  31 +++++++++++++
 4 files changed, 152 insertions(+)
 create mode 100644 drivers/mfd/sky81452.c
 create mode 100644 include/linux/mfd/sky81452.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1456ea7..a54244c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -693,6 +693,18 @@ config MFD_SM501_GPIO
 	 lines on the SM501. The platform data is used to supply the
 	 base number for the first GPIO line to register.
 
+config MFD_SKY81452
+	tristate "Skyworks Solutions SKY81452"
+	select MFD_CORE
+	select REGMAP_I2C
+	depends on I2C
+	help
+	  This is the core driver for the Skyworks SKY81452 backlight and
+	  voltage regulator device.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sky81452.
+
 config MFD_SMSC
        bool "SMSC ECE1099 series chips"
        depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8bd54b1..d9683ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -174,6 +174,7 @@ obj-$(CONFIG_MFD_STW481X)	+= stw481x.o
 obj-$(CONFIG_MFD_IPAQ_MICRO)	+= ipaq-micro.o
 obj-$(CONFIG_MFD_MENF21BMC)	+= menf21bmc.o
 obj-$(CONFIG_MFD_HI6421_PMIC)	+= hi6421-pmic-core.o
+obj-$(CONFIG_MFD_SKY81452)		+= sky81452.o
 
 intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c
new file mode 100644
index 0000000..b0c9b04
--- /dev/null
+++ b/drivers/mfd/sky81452.c
@@ -0,0 +1,108 @@
+/*
+ * sky81452.c	SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/sky81452.h>
+
+static const struct regmap_config sky81452_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int sky81452_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	const struct sky81452_platform_data *pdata = dev_get_platdata(dev);
+	struct mfd_cell cells[2];
+	struct regmap *regmap;
+	int ret;
+
+	if (!pdata) {
+		pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+	}
+
+	regmap = devm_regmap_init_i2c(client, &sky81452_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to initialize.err=%ld\n", PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	i2c_set_clientdata(client, regmap);
+
+	memset(cells, 0, sizeof(cells));
+	cells[0].name = "sky81452-backlight";
+	cells[0].of_compatible = "skyworks,sky81452-backlight";
+	cells[0].platform_data = pdata->bl_pdata;
+	cells[0].pdata_size = sizeof(*pdata->bl_pdata);
+	cells[1].name = "sky81452-regulator";
+	cells[1].platform_data = pdata->regulator_init_data;
+	cells[1].pdata_size = sizeof(*pdata->regulator_init_data);
+
+	ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL);
+	if (ret)
+		dev_err(dev, "failed to add child devices. err=%d\n", ret);
+
+	return ret;
+}
+
+static int sky81452_remove(struct i2c_client *client)
+{
+	mfd_remove_devices(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id sky81452_ids[] = {
+	{ "sky81452" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sky81452_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_of_match[] = {
+	{ .compatible = "skyworks,sky81452", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sky81452_of_match);
+#endif
+
+static struct i2c_driver sky81452_driver = {
+	.driver = {
+		.name = "sky81452",
+		.of_match_table = of_match_ptr(sky81452_of_match),
+	},
+	.probe = sky81452_probe,
+	.remove = sky81452_remove,
+	.id_table = sky81452_ids,
+};
+
+module_i2c_driver(sky81452_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 MFD driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/sky81452.h b/include/linux/mfd/sky81452.h
new file mode 100644
index 0000000..b0925fa
--- /dev/null
+++ b/include/linux/mfd/sky81452.h
@@ -0,0 +1,31 @@
+/*
+ * sky81452.h	SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_H
+#define _SKY81452_H
+
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/regulator/machine.h>
+
+struct sky81452_platform_data {
+	struct sky81452_bl_platform_data *bl_pdata;
+	struct regulator_init_data *regulator_init_data;
+};
+
+#endif
-- 
1.9.1


^ permalink raw reply related

* [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Removed trivial get_brightness implementations

Changes v9:
Nothing

Changes v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO

Changes v7:
Modified licensing text to GPLv2

Changes v6:
Added new line character at the end of line of dev_err()

Changes v5:
Move sky81452-backlight.h to include/linux/platform_data

Changes v4:
Reordering header files for readability
Removed calling to backlight_device_unregister()
Removed MODULE_VERSION()
Modified license to GPLv2

Changes v3:
Modified DBG messages

Changes v2:
Added 'compatible' attribute in the driver
Added message for exception or errors

 drivers/video/backlight/Kconfig                  |  10 +
 drivers/video/backlight/Makefile                 |   1 +
 drivers/video/backlight/sky81452-backlight.c     | 334 +++++++++++++++++++++++
 include/linux/platform_data/sky81452-backlight.h |  46 ++++
 4 files changed, 391 insertions(+)
 create mode 100644 drivers/video/backlight/sky81452-backlight.c
 create mode 100644 include/linux/platform_data/sky81452-backlight.h

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 8d03924..2586fdd 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -409,6 +409,16 @@ config BACKLIGHT_PANDORA
 	  If you have a Pandora console, say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_SKY81452
+	tristate "Backlight driver for SKY81452"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
+	help
+	  If you have a Skyworks SKY81452, say Y to enable the
+	  backlight driver.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called sky81452-backlight
+
 config BACKLIGHT_TPS65217
 	tristate "TPS65217 Backlight"
 	depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index fcd50b73..d67073f 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA)		+= pandora_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_PWM)		+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)		+= kb3886_bl.o
+obj-$(CONFIG_BACKLIGHT_SKY81452)	+= sky81452-backlight.o
 obj-$(CONFIG_BACKLIGHT_TOSA)		+= tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217)	+= tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)		+= wm831x_bl.o
diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c
new file mode 100644
index 0000000..8105597
--- /dev/null
+++ b/drivers/video/backlight/sky81452-backlight.c
@@ -0,0 +1,334 @@
+/*
+ * sky81452-backlight.c	SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/slab.h>
+
+/* registers */
+#define SKY81452_REG0	0x00
+#define SKY81452_REG1	0x01
+#define SKY81452_REG2	0x02
+#define SKY81452_REG4	0x04
+#define SKY81452_REG5	0x05
+
+/* bit mask */
+#define SKY81452_CS	0xFF
+#define SKY81452_EN	0x3F
+#define SKY81452_IGPW	0x20
+#define SKY81452_PWMMD	0x10
+#define SKY81452_PHASE	0x08
+#define SKY81452_ILIM	0x04
+#define SKY81452_VSHRT	0x03
+#define SKY81452_OCP	0x80
+#define SKY81452_OTMP	0x40
+#define SKY81452_SHRT	0x3F
+#define SKY81452_OPN	0x3F
+
+#define SKY81452_DEFAULT_NAME "lcd-backlight"
+#define SKY81452_MAX_BRIGHTNESS	(SKY81452_CS + 1)
+
+#define CTZ(b) __builtin_ctz(b)
+
+static int sky81452_bl_update_status(struct backlight_device *bd)
+{
+	const struct sky81452_bl_platform_data *pdata +			dev_get_platdata(bd->dev.parent);
+	const unsigned int brightness = (unsigned int)bd->props.brightness;
+	struct regmap *regmap = bl_get_data(bd);
+	int ret;
+
+	if (brightness > 0) {
+		ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
+		if (IS_ERR_VALUE(ret))
+			return ret;
+
+		return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+					pdata->enable << CTZ(SKY81452_EN));
+	}
+
+	return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
+}
+
+static const struct backlight_ops sky81452_bl_ops = {
+	.update_status = sky81452_bl_update_status,
+};
+
+static ssize_t sky81452_bl_store_enable(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+	unsigned long value;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &value);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+					value << CTZ(SKY81452_EN));
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	return count;
+}
+
+static ssize_t sky81452_bl_show_open_short(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+	unsigned int reg, value = 0;
+	char tmp[3];
+	int i, ret;
+
+	reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
+	ret = regmap_read(regmap, reg, &value);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	if (value & SKY81452_SHRT) {
+		*buf = 0;
+		for (i = 0; i < 6; i++) {
+			if (value & 0x01) {
+				sprintf(tmp, "%d ", i + 1);
+				strcat(buf, tmp);
+			}
+			value >>= 1;
+		}
+		strcat(buf, "\n");
+	} else {
+		strcpy(buf, "none\n");
+	}
+
+	return strlen(buf);
+}
+
+static ssize_t sky81452_bl_show_fault(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+	unsigned int value = 0;
+	int ret;
+
+	ret = regmap_read(regmap, SKY81452_REG4, &value);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	*buf = 0;
+
+	if (value & SKY81452_OCP)
+		strcat(buf, "over-current ");
+
+	if (value & SKY81452_OTMP)
+		strcat(buf, "over-temperature");
+
+	strcat(buf, "\n");
+	return strlen(buf);
+}
+
+static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
+static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
+
+static struct attribute *sky81452_bl_attribute[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_open.attr,
+	&dev_attr_short.attr,
+	&dev_attr_fault.attr,
+	NULL
+};
+
+static const struct attribute_group sky81452_bl_attr_group = {
+	.attrs = sky81452_bl_attribute,
+};
+
+#ifdef CONFIG_OF
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+							struct device *dev)
+{
+	struct device_node *np = of_node_get(dev->of_node);
+	struct sky81452_bl_platform_data *pdata;
+	int ret;
+
+	if (!np) {
+		dev_err(dev, "backlight node not found.\n");
+		return ERR_PTR(-ENODATA);
+	}
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		of_node_put(np);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_property_read_string(np, "name", &pdata->name);
+	pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
+	pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
+	pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
+	pdata->gpio_enable = of_get_gpio(np, 0);
+
+	ret = of_property_read_u32(np, "skyworks,en-channels", &pdata->enable);
+	if (IS_ERR_VALUE(ret))
+		pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
+
+	ret = of_property_read_u32(np, "skyworks,short-detection-threshold",
+			&pdata->short_detection_threshold);
+	if (IS_ERR_VALUE(ret))
+		pdata->short_detection_threshold = 7;
+
+	ret = of_property_read_u32(np, "skyworks,current-limit",
+			&pdata->boost_current_limit);
+	if (IS_ERR_VALUE(ret))
+		pdata->boost_current_limit = 2750;
+
+	of_node_put(np);
+	return pdata;
+}
+#else
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+							struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int sky81452_bl_init_device(struct regmap *regmap,
+		struct sky81452_bl_platform_data *pdata)
+{
+	unsigned int value;
+
+	value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
+	value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
+	value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
+
+	if (pdata->boost_current_limit = 2300)
+		value |= SKY81452_ILIM;
+	else if (pdata->boost_current_limit != 2750)
+		return -EINVAL;
+
+	if (pdata->short_detection_threshold < 4 ||
+				pdata->short_detection_threshold > 7)
+		return -EINVAL;
+	value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
+
+	return regmap_write(regmap, SKY81452_REG2, value);
+}
+
+static int sky81452_bl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *regmap = dev_get_drvdata(dev->parent);
+	struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	const char *name;
+	int ret;
+
+	if (!pdata) {
+		pdata = sky81452_bl_parse_dt(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
+
+	if (gpio_is_valid(pdata->gpio_enable)) {
+		ret = devm_gpio_request_one(dev, pdata->gpio_enable,
+					GPIOF_OUT_INIT_HIGH, "sky81452-en");
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(dev, "failed to request GPIO. err=%d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = sky81452_bl_init_device(regmap, pdata);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(dev, "failed to initialize. err=%d\n", ret);
+		return ret;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.max_brightness = SKY81452_MAX_BRIGHTNESS,
+	name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
+	bd = devm_backlight_device_register(dev, name, dev, regmap,
+						&sky81452_bl_ops, &props);
+	if (IS_ERR(bd)) {
+		dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
+		return PTR_ERR(bd);
+	}
+
+	platform_set_drvdata(pdev, bd);
+
+	ret  = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(dev, "failed to create attribute. err=%d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int sky81452_bl_remove(struct platform_device *pdev)
+{
+	const struct sky81452_bl_platform_data *pdata +						dev_get_platdata(&pdev->dev);
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
+	sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+
+	bd->props.power = FB_BLANK_UNBLANK;
+	bd->props.brightness = 0;
+	backlight_update_status(bd);
+
+	if (gpio_is_valid(pdata->gpio_enable))
+		gpio_set_value_cansleep(pdata->gpio_enable, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_bl_of_match[] = {
+	{ .compatible = "skyworks,sky81452-backlight", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
+#endif
+
+static struct platform_driver sky81452_bl_driver = {
+	.driver = {
+		.name = "sky81452-backlight",
+		.of_match_table = of_match_ptr(sky81452_bl_of_match),
+	},
+	.probe = sky81452_bl_probe,
+	.remove = sky81452_bl_remove,
+};
+
+module_platform_driver(sky81452_bl_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h
new file mode 100644
index 0000000..1231e9b
--- /dev/null
+++ b/include/linux/platform_data/sky81452-backlight.h
@@ -0,0 +1,46 @@
+/*
+ * sky81452.h	SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_BACKLIGHT_H
+#define _SKY81452_BACKLIGHT_H
+
+/**
+ * struct sky81452_platform_data
+ * @name:	backlight driver name.
+		If it is not defined, default name is lcd-backlight.
+ * @gpio_enable:GPIO number which control EN pin
+ * @enable:	Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
+ * @ignore_pwm:	true if DPWMI should be ignored.
+ * @dpwm_mode:	true is DPWM dimming mode, otherwise Analog dimming mode.
+ * @phase_shift:true is phase shift mode.
+ * @short_detecion_threshold:	It should be one of 4, 5, 6 and 7V.
+ * @boost_current_limit:	It should be one of 2300, 2750mA.
+ */
+struct sky81452_bl_platform_data {
+	const char *name;
+	int gpio_enable;
+	unsigned int enable;
+	bool ignore_pwm;
+	bool dpwm_mode;
+	bool phase_shift;
+	unsigned int short_detection_threshold;
+	unsigned int boost_current_limit;
+};
+
+#endif
-- 
1.9.1


^ permalink raw reply related

* [PATCH v10 3/6] devicetree: mfd: Add new SKY81452 mfd binding
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing

Changes v9:
Nothing

Changes v8:
Made up the example for backlight DT

Changes v7:
Nothing

Changes v6:
Nothing

Changes v5:
Changed DT for regulator : 'lout' node should be defined under 'regulator'
Removed compatible string from sky81452-regulator driver

Changes v4:
Nothing

Changes v3:
Nothing

Changes v2:
Added reg attribute for I2C slave address

 Documentation/devicetree/bindings/mfd/sky81452.txt | 36 ++++++++++++++++++++++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/sky81452.txt

diff --git a/Documentation/devicetree/bindings/mfd/sky81452.txt b/Documentation/devicetree/bindings/mfd/sky81452.txt
new file mode 100644
index 0000000..ab71473
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/sky81452.txt
@@ -0,0 +1,36 @@
+SKY81452 bindings
+
+Required properties:
+- compatible	: Must be "skyworks,sky81452"
+- reg		: I2C slave address
+
+Required child nodes:
+- backlight	: container node for backlight following the binding
+		in video/backlight/sky81452-backlight.txt
+- regulator	: container node for regulators following the binding
+		in regulator/sky81452-regulator.txt
+
+Example:
+
+	sky81452@2c {
+		compatible = "skyworks,sky81452";
+		reg = <0x2c>;
+
+		backlight {
+			compatible = "skyworks,sky81452-backlight";
+			name = "pwm-backlight";
+			skyworks,en-channels = <0x3f>;
+			skyworks,ignore-pwm;
+			skyworks,phase-shift;
+			skyworks,ovp-level = <20>;
+			skyworks,current-limit = <2300>;
+		};
+
+		regulator {
+			lout {
+				regulator-name = "sky81452-lout";
+				regulator-min-microvolt = <4500000>;
+				regulator-max-microvolt = <8000000>;
+			};
+		};
+	};
-- 
1.9.1


^ permalink raw reply related

* [PATCH v10 4/6] devicetree: backlight: Add new SKY81452 backlight binding
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
---
Changes v10:
Nothing

Changes v9:
Nothing

Changes v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO
Made up the example for backlight DT

Changes v7:
Nothing

Changes v6:
Nothing

Changes v5:
Nothing

Changes v4:
Nothing

Changes v3:
Nothing

Changes v2:
Added reg attribute for I2C slave address

 .../video/backlight/sky81452-backlight.txt         | 29 ++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt

diff --git a/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt b/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
new file mode 100644
index 0000000..8daebf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
@@ -0,0 +1,29 @@
+SKY81452-backlight bindings
+
+Required properties:
+- compatible		: Must be "skyworks,sky81452-backlight"
+
+Optional properties:
+- name			: Name of backlight device. Default is 'lcd-backlight'.
+- gpios			: GPIO to use to EN pin.
+			See Documentation/devicetree/bindings/gpio/gpio.txt
+- skyworks,en-channels	: Enable mask for current sink channel 1 to 6.
+- skyworks,ignore-pwm	: Ignore both PWM input
+- skyworks,dpwm-mode	: Enable DPWM dimming mode, otherwise Analog dimming.
+- skyworks,phase-shift	: Enable phase shift mode
+- skyworks,ovp-level	: Over-voltage protection level.
+			Should be between 14 or 28V.
+- skyworks,short-detection-threshold	: It should be one of 4, 5, 6 and 7V.
+- skyworks,current-limit	: It should be 2300mA or 2750mA.
+
+Example:
+
+	backlight {
+		compatible = "skyworks,sky81452-backlight";
+		name = "pwm-backlight";
+		skyworks,en-channels = <0x3f>;
+		skyworks,ignore-pwm;
+		skyworks,phase-shift;
+		skyworks,ovp-level = <20>;
+		skyworks,current-limit = <2300>;
+	};
-- 
1.9.1


^ permalink raw reply related

* [PATCH v10 5/6] devicetree: Add vendor prefix for Skyworks Solutions, Inc.
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing

Changes v9:
Nothing

Changes v8:
Nothing

Changes v7:
Nothing

Changes v6:
Nothing

Changes v5:
Nothing

Changes v4:
Nothing

Changes v3:
Nothing

Changes v2:
Added vendor prefix for Skyworks Solutions, Inc.

 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a344ec2..68143f0 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -140,6 +140,7 @@ sii	Seiko Instruments, Inc.
 silergy	Silergy Corp.
 sirf	SiRF Technology, Inc.
 sitronix	Sitronix Technology Corporation
+skyworks	Skyworks Solutions, Inc.
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
-- 
1.9.1


^ permalink raw reply related

* [PATCH v10 6/6] devicetree: i2c: Add SKY81452 to the Trivial Devices list
From: gyungoh @ 2014-12-03  7:05 UTC (permalink / raw)
  To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>

From: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing

Changes v9:
Nothing

Changes v8:
Nothing

Changes v7:
Nothing

Changes v6:
Nothing

Changes v5:
Nothing

Changes v4:
Nothing

Changes v3:
Nothing

Changes v2:
Add SKY81452 to the Trivial Devices list

 Documentation/devicetree/bindings/i2c/trivial-devices.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index fbde415..122fa1e 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -77,6 +77,7 @@ ramtron,24c64		i2c serial eeprom  (24cxx)
 ricoh,rs5c372a		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 samsung,24ad0xd1	S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
 sii,s35390a		2-wire CMOS real-time clock
+skyworks,sky81452	Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 st-micro,24c256		i2c serial eeprom  (24cxx)
 stm,m41t00		Serial Access TIMEKEEPER
 stm,m41t62		Serial real-time clock (RTC) with alarm
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: Jingoo Han @ 2014-12-03  7:13 UTC (permalink / raw)
  To: gyungoh, sameo, lee.jones, grant.likely, robh+dt, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
  Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree,
	'Jingoo Han'
In-Reply-To: <1417590332-4912-3-git-send-email-jack.yoo@skyworksinc.com>

On Wednesday, December 03, 2014 4:05 PM, Gyungoh Yoo wrote:
> 
> From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
> 
> Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>

Acked-by: Jingoo Han <jg1.han@samsung.com>

Best regards,
Jingoo Han

> ---
> Changes v10:
> Removed trivial get_brightness implementations
> 
> Changes v9:
> Nothing
> 
> Changes v8:
> Renamed property names for backlight with vendor prefix
> Modified gpio-enable property to generic property for GPIO
> 
> Changes v7:
> Modified licensing text to GPLv2
> 
> Changes v6:
> Added new line character at the end of line of dev_err()
> 
> Changes v5:
> Move sky81452-backlight.h to include/linux/platform_data
> 
> Changes v4:
> Reordering header files for readability
> Removed calling to backlight_device_unregister()
> Removed MODULE_VERSION()
> Modified license to GPLv2
> 
> Changes v3:
> Modified DBG messages
> 
> Changes v2:
> Added 'compatible' attribute in the driver
> Added message for exception or errors
> 
>  drivers/video/backlight/Kconfig                  |  10 +
>  drivers/video/backlight/Makefile                 |   1 +
>  drivers/video/backlight/sky81452-backlight.c     | 334 +++++++++++++++++++++++
>  include/linux/platform_data/sky81452-backlight.h |  46 ++++
>  4 files changed, 391 insertions(+)
>  create mode 100644 drivers/video/backlight/sky81452-backlight.c
>  create mode 100644 include/linux/platform_data/sky81452-backlight.h
> 
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index 8d03924..2586fdd 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -409,6 +409,16 @@ config BACKLIGHT_PANDORA
>  	  If you have a Pandora console, say Y to enable the
>  	  backlight driver.
> 
> +config BACKLIGHT_SKY81452
> +	tristate "Backlight driver for SKY81452"
> +	depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
> +	help
> +	  If you have a Skyworks SKY81452, say Y to enable the
> +	  backlight driver.
> +
> +	  To compile this driver as a module, choose M here: the module will
> +	  be called sky81452-backlight
> +
>  config BACKLIGHT_TPS65217
>  	tristate "TPS65217 Backlight"
>  	depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
> diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
> index fcd50b73..d67073f 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA)		+= pandora_bl.o
>  obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
>  obj-$(CONFIG_BACKLIGHT_PWM)		+= pwm_bl.o
>  obj-$(CONFIG_BACKLIGHT_SAHARA)		+= kb3886_bl.o
> +obj-$(CONFIG_BACKLIGHT_SKY81452)	+= sky81452-backlight.o
>  obj-$(CONFIG_BACKLIGHT_TOSA)		+= tosa_bl.o
>  obj-$(CONFIG_BACKLIGHT_TPS65217)	+= tps65217_bl.o
>  obj-$(CONFIG_BACKLIGHT_WM831X)		+= wm831x_bl.o
> diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-
> backlight.c
> new file mode 100644
> index 0000000..8105597
> --- /dev/null
> +++ b/drivers/video/backlight/sky81452-backlight.c
> @@ -0,0 +1,334 @@
> +/*
> + * sky81452-backlight.c	SKY81452 backlight driver
> + *
> + * Copyright 2014 Skyworks Solutions Inc.
> + * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/err.h>
> +#include <linux/gpio.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/platform_data/sky81452-backlight.h>
> +#include <linux/slab.h>
> +
> +/* registers */
> +#define SKY81452_REG0	0x00
> +#define SKY81452_REG1	0x01
> +#define SKY81452_REG2	0x02
> +#define SKY81452_REG4	0x04
> +#define SKY81452_REG5	0x05
> +
> +/* bit mask */
> +#define SKY81452_CS	0xFF
> +#define SKY81452_EN	0x3F
> +#define SKY81452_IGPW	0x20
> +#define SKY81452_PWMMD	0x10
> +#define SKY81452_PHASE	0x08
> +#define SKY81452_ILIM	0x04
> +#define SKY81452_VSHRT	0x03
> +#define SKY81452_OCP	0x80
> +#define SKY81452_OTMP	0x40
> +#define SKY81452_SHRT	0x3F
> +#define SKY81452_OPN	0x3F
> +
> +#define SKY81452_DEFAULT_NAME "lcd-backlight"
> +#define SKY81452_MAX_BRIGHTNESS	(SKY81452_CS + 1)
> +
> +#define CTZ(b) __builtin_ctz(b)
> +
> +static int sky81452_bl_update_status(struct backlight_device *bd)
> +{
> +	const struct sky81452_bl_platform_data *pdata > +			dev_get_platdata(bd->dev.parent);
> +	const unsigned int brightness = (unsigned int)bd->props.brightness;
> +	struct regmap *regmap = bl_get_data(bd);
> +	int ret;
> +
> +	if (brightness > 0) {
> +		ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
> +		if (IS_ERR_VALUE(ret))
> +			return ret;
> +
> +		return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> +					pdata->enable << CTZ(SKY81452_EN));
> +	}
> +
> +	return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
> +}
> +
> +static const struct backlight_ops sky81452_bl_ops = {
> +	.update_status = sky81452_bl_update_status,
> +};
> +
> +static ssize_t sky81452_bl_store_enable(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> +	unsigned long value;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 16, &value);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> +					value << CTZ(SKY81452_EN));
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	return count;
> +}
> +
> +static ssize_t sky81452_bl_show_open_short(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> +	unsigned int reg, value = 0;
> +	char tmp[3];
> +	int i, ret;
> +
> +	reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
> +	ret = regmap_read(regmap, reg, &value);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	if (value & SKY81452_SHRT) {
> +		*buf = 0;
> +		for (i = 0; i < 6; i++) {
> +			if (value & 0x01) {
> +				sprintf(tmp, "%d ", i + 1);
> +				strcat(buf, tmp);
> +			}
> +			value >>= 1;
> +		}
> +		strcat(buf, "\n");
> +	} else {
> +		strcpy(buf, "none\n");
> +	}
> +
> +	return strlen(buf);
> +}
> +
> +static ssize_t sky81452_bl_show_fault(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> +	unsigned int value = 0;
> +	int ret;
> +
> +	ret = regmap_read(regmap, SKY81452_REG4, &value);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	*buf = 0;
> +
> +	if (value & SKY81452_OCP)
> +		strcat(buf, "over-current ");
> +
> +	if (value & SKY81452_OTMP)
> +		strcat(buf, "over-temperature");
> +
> +	strcat(buf, "\n");
> +	return strlen(buf);
> +}
> +
> +static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
> +static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
> +static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
> +static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
> +
> +static struct attribute *sky81452_bl_attribute[] = {
> +	&dev_attr_enable.attr,
> +	&dev_attr_open.attr,
> +	&dev_attr_short.attr,
> +	&dev_attr_fault.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group sky81452_bl_attr_group = {
> +	.attrs = sky81452_bl_attribute,
> +};
> +
> +#ifdef CONFIG_OF
> +static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
> +							struct device *dev)
> +{
> +	struct device_node *np = of_node_get(dev->of_node);
> +	struct sky81452_bl_platform_data *pdata;
> +	int ret;
> +
> +	if (!np) {
> +		dev_err(dev, "backlight node not found.\n");
> +		return ERR_PTR(-ENODATA);
> +	}
> +
> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata) {
> +		of_node_put(np);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	of_property_read_string(np, "name", &pdata->name);
> +	pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
> +	pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
> +	pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
> +	pdata->gpio_enable = of_get_gpio(np, 0);
> +
> +	ret = of_property_read_u32(np, "skyworks,en-channels", &pdata->enable);
> +	if (IS_ERR_VALUE(ret))
> +		pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
> +
> +	ret = of_property_read_u32(np, "skyworks,short-detection-threshold",
> +			&pdata->short_detection_threshold);
> +	if (IS_ERR_VALUE(ret))
> +		pdata->short_detection_threshold = 7;
> +
> +	ret = of_property_read_u32(np, "skyworks,current-limit",
> +			&pdata->boost_current_limit);
> +	if (IS_ERR_VALUE(ret))
> +		pdata->boost_current_limit = 2750;
> +
> +	of_node_put(np);
> +	return pdata;
> +}
> +#else
> +static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
> +							struct device *dev)
> +{
> +	return ERR_PTR(-EINVAL);
> +}
> +#endif
> +
> +static int sky81452_bl_init_device(struct regmap *regmap,
> +		struct sky81452_bl_platform_data *pdata)
> +{
> +	unsigned int value;
> +
> +	value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
> +	value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
> +	value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
> +
> +	if (pdata->boost_current_limit = 2300)
> +		value |= SKY81452_ILIM;
> +	else if (pdata->boost_current_limit != 2750)
> +		return -EINVAL;
> +
> +	if (pdata->short_detection_threshold < 4 ||
> +				pdata->short_detection_threshold > 7)
> +		return -EINVAL;
> +	value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
> +
> +	return regmap_write(regmap, SKY81452_REG2, value);
> +}
> +
> +static int sky81452_bl_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct regmap *regmap = dev_get_drvdata(dev->parent);
> +	struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
> +	struct backlight_device *bd;
> +	struct backlight_properties props;
> +	const char *name;
> +	int ret;
> +
> +	if (!pdata) {
> +		pdata = sky81452_bl_parse_dt(dev);
> +		if (IS_ERR(pdata))
> +			return PTR_ERR(pdata);
> +	}
> +
> +	if (gpio_is_valid(pdata->gpio_enable)) {
> +		ret = devm_gpio_request_one(dev, pdata->gpio_enable,
> +					GPIOF_OUT_INIT_HIGH, "sky81452-en");
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(dev, "failed to request GPIO. err=%d\n", ret);
> +			return ret;
> +		}
> +	}
> +
> +	ret = sky81452_bl_init_device(regmap, pdata);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(dev, "failed to initialize. err=%d\n", ret);
> +		return ret;
> +	}
> +
> +	memset(&props, 0, sizeof(props));
> +	props.max_brightness = SKY81452_MAX_BRIGHTNESS,
> +	name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
> +	bd = devm_backlight_device_register(dev, name, dev, regmap,
> +						&sky81452_bl_ops, &props);
> +	if (IS_ERR(bd)) {
> +		dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
> +		return PTR_ERR(bd);
> +	}
> +
> +	platform_set_drvdata(pdev, bd);
> +
> +	ret  = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(dev, "failed to create attribute. err=%d\n", ret);
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
> +static int sky81452_bl_remove(struct platform_device *pdev)
> +{
> +	const struct sky81452_bl_platform_data *pdata > +						dev_get_platdata(&pdev->dev);
> +	struct backlight_device *bd = platform_get_drvdata(pdev);
> +
> +	sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
> +
> +	bd->props.power = FB_BLANK_UNBLANK;
> +	bd->props.brightness = 0;
> +	backlight_update_status(bd);
> +
> +	if (gpio_is_valid(pdata->gpio_enable))
> +		gpio_set_value_cansleep(pdata->gpio_enable, 0);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id sky81452_bl_of_match[] = {
> +	{ .compatible = "skyworks,sky81452-backlight", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
> +#endif
> +
> +static struct platform_driver sky81452_bl_driver = {
> +	.driver = {
> +		.name = "sky81452-backlight",
> +		.of_match_table = of_match_ptr(sky81452_bl_of_match),
> +	},
> +	.probe = sky81452_bl_probe,
> +	.remove = sky81452_bl_remove,
> +};
> +
> +module_platform_driver(sky81452_bl_driver);
> +
> +MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
> +MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-
> backlight.h
> new file mode 100644
> index 0000000..1231e9b
> --- /dev/null
> +++ b/include/linux/platform_data/sky81452-backlight.h
> @@ -0,0 +1,46 @@
> +/*
> + * sky81452.h	SKY81452 backlight driver
> + *
> + * Copyright 2014 Skyworks Solutions Inc.
> + * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _SKY81452_BACKLIGHT_H
> +#define _SKY81452_BACKLIGHT_H
> +
> +/**
> + * struct sky81452_platform_data
> + * @name:	backlight driver name.
> +		If it is not defined, default name is lcd-backlight.
> + * @gpio_enable:GPIO number which control EN pin
> + * @enable:	Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
> + * @ignore_pwm:	true if DPWMI should be ignored.
> + * @dpwm_mode:	true is DPWM dimming mode, otherwise Analog dimming mode.
> + * @phase_shift:true is phase shift mode.
> + * @short_detecion_threshold:	It should be one of 4, 5, 6 and 7V.
> + * @boost_current_limit:	It should be one of 2300, 2750mA.
> + */
> +struct sky81452_bl_platform_data {
> +	const char *name;
> +	int gpio_enable;
> +	unsigned int enable;
> +	bool ignore_pwm;
> +	bool dpwm_mode;
> +	bool phase_shift;
> +	unsigned int short_detection_threshold;
> +	unsigned int boost_current_limit;
> +};
> +
> +#endif
> --
> 1.9.1


^ permalink raw reply

* [PATCHv2 0/4] LS1021A: Add dcfb framebuffer driver support.
From: Xiubo Li @ 2014-12-03  9:15 UTC (permalink / raw)
  To: linux-arm-kernel

Framebuffer driver for the Freescale SoC Display Controller.


Change in V2:
- Use the native-mode timing as default.
- Add to_fsl_private().


Xiubo Li (4):
  video: fsl-dcfb: Add dcfb framebuffer driver for LS1021A platform
  video: fsl-dcfb: Add devicetree binding support
  ARM: ls1021a: dtsi: Add dt node support for dcfb.
  ARM: ls1021a: dts: Add and enable dt node for dcfb.

 .../devicetree/bindings/video/fsl,dcfb.txt         |  52 ++
 arch/arm/boot/dts/ls1021a-twr.dts                  |  26 +
 arch/arm/boot/dts/ls1021a.dtsi                     |  10 +
 drivers/video/fbdev/Kconfig                        |  19 +
 drivers/video/fbdev/Makefile                       |   1 +
 drivers/video/fbdev/fsl-dcfb.c                     | 814 +++++++++++++++++++++
 6 files changed, 922 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/fsl,dcfb.txt
 create mode 100644 drivers/video/fbdev/fsl-dcfb.c

-- 
2.1.0.27.g96db324


^ permalink raw reply

* [PATCHv2 1/4] video: fsl-dcfb: Add dcfb framebuffer driver for LS1021A platform
From: Xiubo Li @ 2014-12-03  9:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>

The Display Controller module is a system master that fetches graphics
stored in internal/external memory and displays them on a TFT LCD panel.
A wide range of panel sizes is supported and the timing of the interface
signals is configurable.

The dcfb has these features:
o Full RGB888 output to TFT LCD panel.
o Optional output to system memory dependent on implementation.
o Supports Programmable panel size upto a maximum of 2032x2047. The actual
  resolution supported depends upon the pixel clock and bus bandwidth
  available.
o Gamma correction with 8-bit resolution on each color component.
o Dedicated memory blocks to store a cursor and Color Look Up Tables(CLUTs).
o Temporal Dithering.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 drivers/video/fbdev/Kconfig    |  19 +
 drivers/video/fbdev/Makefile   |   1 +
 drivers/video/fbdev/fsl-dcfb.c | 814 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 834 insertions(+)
 create mode 100644 drivers/video/fbdev/fsl-dcfb.c

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 4916c97..460fe39 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1948,6 +1948,25 @@ config FB_MBX_DEBUG
 
          If unsure, say N.
 
+config FB_FSL_DCFB
+	tristate "Freescale Display Control Framebuffer Support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	select REGMAP_MMIO
+	---help---
+	  Framebuffer driver for the Freescale SoC Display Control.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want).
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+
 config FB_FSL_DIU
 	tristate "Freescale DIU framebuffer support"
 	depends on FB && FSL_SOC
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 1979aff..9015138 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_FB_SH7760)		  += sh7760fb.o
 obj-$(CONFIG_FB_IMX)              += imxfb.o
 obj-$(CONFIG_FB_S3C)		  += s3c-fb.o
 obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.o
+obj-$(CONFIG_FB_FSL_DCFB)	  += fsl-dcfb.o
 obj-$(CONFIG_FB_FSL_DIU)	  += fsl-diu-fb.o
 obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
diff --git a/drivers/video/fbdev/fsl-dcfb.c b/drivers/video/fbdev/fsl-dcfb.c
new file mode 100644
index 0000000..c3843bf
--- /dev/null
+++ b/drivers/video/fbdev/fsl-dcfb.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright 2012-2014 Freescale Semiconductor, Inc.
+ *
+ * Freescale Dispaly Controller Framebuffer Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+#define FSL_SCFG_CTRL		0x28
+#define FSL_SCFG_PIXEL_EN	BIT(31)
+
+#define FSL_DCFB_MODE		0x10
+#define FSL_DCFB_BGND		0x14
+#define FSL_DCFB_FIX_SIZE	0x18
+#define FSL_DCFB_HSYN		0x1c
+#define FSL_DCFB_VSYN		0x20
+#define FSL_DCFB_SP		0x24
+#define FSL_DCFB_TS		0x28
+#define FSL_DCFB_DIV_RATIO	0x54
+#define FSL_DCFB_UPDATE		0xcc
+#define FSL_DCFB_VAR_SIZE	0x200
+#define FSL_DCFB_POS		0x204
+#define FSL_DCFB_BASE		0x208
+#define FSL_DCFB_CTRL		0x20c
+#define FSL_DCFB_CKMAX		0x210
+#define FSL_DCFB_CKMIN		0x214
+#define FSL_DCFB_FCOLOR		0x21c
+#define FSL_DCFB_BCOLOR		0x220
+#define FSL_DCFB_SKIP		0x224
+#define FSL_DCFB_MAX		0x300
+
+#define FSL_DCFB_HSYN_BP(x)	((x) << 22)
+#define FSL_DCFB_HSYN_PW(x)	((x) << 11)
+#define FSL_DCFB_HSYN_FP(x)	(x)
+#define FSL_DCFB_VSYN_BP(x)	((x) << 22)
+#define FSL_DCFB_VSYN_PW(x)	((x) << 11)
+#define FSL_DCFB_VSYN_FP(x)	(x)
+
+#define FSL_DCFB_SP_VS		BIT(1)
+#define FSL_DCFB_SP_HS		BIT(0)
+
+#define FSL_DCFB_TS_LBV(x)	((x) << 16)
+#define FSL_DCFB_TS_OBH(x)	((x) << 8)
+#define FSL_DCFB_TS_OBL(x)	(x)
+
+#define FSL_DCFB_UPDATE_MODE	BIT(31)
+#define FSL_DCFB_UPDATE_READREG	BIT(30)
+
+#define FSL_DCFB_VAR_SIZE_H(x)	((x) << 16)
+#define FSL_DCFB_VAR_SIZE_W(x)	(x)
+
+#define FSL_DCFB_POSY(x)	((x) << 16)
+#define FSL_DCFB_POSX(x)	(x)
+
+#define FSL_DCFB_CTRL_EN	BIT(31)
+#define FSL_DCFB_CTRL_TILE_EN	BIT(30)
+#define FSL_DCFB_CTRL_DATA_SEL_CLUT	BIT(29)
+#define FSL_DCFB_CTRL_SAFETY_EN	BIT(28)
+#define FSL_DCFB_CTRL_TRANS(x)	((x) << 20)
+#define FSL_DCFB_CTRL_BPP(x)	((x) << 16)
+#define FSL_DCFB_CTRL_RLE_EN	BIT(15)
+#define FSL_DCFB_CTRL_LUOFFS(x)	((x) << 4)
+#define FSL_DCFB_CTRL_BB_ON	BIT(2)
+
+#define FSL_DCFB_CKMAX_R(x)	((x) << 16)
+#define FSL_DCFB_CKMAX_G(x)	((x) << 8)
+#define FSL_DCFB_CKMAX_B(x)	(x)
+
+#define FSL_DCFB_CKMIN_R(x)	((x) << 16)
+#define FSL_DCFB_CKMIN_G(x)	((x) << 8)
+#define FSL_DCFB_CKMIN_B(x)	(x)
+
+#define FSL_DCFB_TILE_SIZE_W(x)	((x) << 16)
+#define FSL_DCFB_TILE_SIZE_H(x)	(x)
+
+#define FSL_DCFB_FCOLOR_OFF(x)	(x)
+#define FSL_DCFB_BCOLOR_OFF(x)	(x)
+
+#define FSL_DCFB_MODE_BITER(x)	((x) << 20)
+#define FSL_DCFB_MODE_RASTER_EN	BIT(14)
+#define FSL_DCFB_MODE_MODE(x)	(x)
+#define FSL_DCFB_MODE_MODE_MASK	0x03
+
+#define FSL_DCFB_BGND_R(x)	((x) << 16)
+#define FSL_DCFB_BGND_G(x)	((x) << 8)
+#define FSL_DCFB_BGND_B(x)	(x)
+
+#define FSL_DCFB_FIX_SIZE_Y(x)	((x) << 16)
+#define FSL_DCFB_FIX_SIZE_X(x)	(x)
+
+enum fsl_dcfb_fmt {
+	FSL_DCFB_RGB565 = 4,
+	FSL_DCFB_RGB888,
+	FSL_DCFB_ARGB8888,
+};
+
+enum fsl_dcfb_mode {
+	FSL_DCFB_MOD_OFF = 0,
+	FSL_DCFB_MOD_NORMAL,
+	FSL_DCFB_MOD_TEST,
+	FSL_DCFB_MOD_COLORBAR,
+};
+
+struct fsl_dcfb_fb_private {
+	struct fb_info *fsl_dcfb_info;
+	struct device *dev;
+	struct regmap *regmap;
+	struct clk *clk;
+};
+
+struct fsl_dcfb_fb_info {
+	unsigned long pseudo_palette[16];
+	unsigned int count;
+	struct fsl_dcfb_fb_private *parent;
+};
+
+static inline struct fsl_dcfb_fb_private *to_fsl_private(struct fb_info *info)
+{
+	struct fsl_dcfb_fb_info *fsl_info = info->par;
+
+	return (struct fsl_dcfb_fb_private *)fsl_info->parent;
+}
+
+static int fsl_dcfb_get_bpp(unsigned int bits_per_pixel)
+{
+	int bpp;
+
+	switch (bits_per_pixel) {
+	case 16:
+		bpp = FSL_DCFB_RGB565;
+		break;
+	case 24:
+		bpp = FSL_DCFB_RGB888;
+		break;
+	case 32:
+		bpp = FSL_DCFB_ARGB8888;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return bpp;
+}
+
+static int fsl_dcfb_set_panel(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	int bpp;
+
+	regmap_write(dcfb->regmap, FSL_DCFB_VAR_SIZE,
+		     FSL_DCFB_VAR_SIZE_H(var->yres) |
+		     FSL_DCFB_VAR_SIZE_W(var->xres));
+	regmap_write(dcfb->regmap, FSL_DCFB_POS,
+		     FSL_DCFB_POSY(0) | FSL_DCFB_POSX(0));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_BASE, info->fix.smem_start);
+
+	bpp = fsl_dcfb_get_bpp(var->bits_per_pixel);
+	if (bpp < 0) {
+		dev_err(dcfb->dev, "unsupported color depth: %u\n",
+				var->bits_per_pixel);
+		return bpp;
+	}
+
+	regmap_write(dcfb->regmap, FSL_DCFB_CTRL, FSL_DCFB_CTRL_EN |
+		     FSL_DCFB_CTRL_TRANS(0xFF) | FSL_DCFB_CTRL_BPP(bpp));
+	regmap_write(dcfb->regmap, FSL_DCFB_CKMAX, FSL_DCFB_CKMAX_R(0xFF) |
+		     FSL_DCFB_CKMAX_G(0xFF) | FSL_DCFB_CKMAX_B(0xFF));
+	regmap_write(dcfb->regmap, FSL_DCFB_CKMIN, FSL_DCFB_CKMIN_R(0) |
+		     FSL_DCFB_CKMIN_G(0) | FSL_DCFB_CKMIN_B(0));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_FCOLOR, FSL_DCFB_FCOLOR_OFF(0));
+	regmap_write(dcfb->regmap, FSL_DCFB_BCOLOR, FSL_DCFB_BCOLOR_OFF(0));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+	return 0;
+}
+
+static int fsl_dcfb_reset_panel(struct fsl_dcfb_fb_private *dcfb)
+{
+	regmap_write(dcfb->regmap, FSL_DCFB_VAR_SIZE, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_POS, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_BASE, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_CTRL, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_CKMAX, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_CKMIN, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_FCOLOR, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_BCOLOR, 0x0);
+	regmap_write(dcfb->regmap, FSL_DCFB_SKIP, 0x0);
+
+	regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+	return 0;
+}
+
+static void fsl_dcfb_modeset(struct fsl_dcfb_fb_private *dcfb,
+			     enum fsl_dcfb_mode mode)
+{
+	regmap_update_bits(dcfb->regmap, FSL_DCFB_MODE,
+			   FSL_DCFB_MODE_MODE_MASK,
+			   FSL_DCFB_MODE_MODE(mode));
+}
+
+static int fsl_dcfb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xoffset + info->var.xres > info->var.xres_virtual)
+		var->xoffset = info->var.xres_virtual - info->var.xres;
+
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
+		var->yoffset = info->var.yres_virtual - info->var.yres;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 24:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 32:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		var->transp.msb_right = 0;
+		break;
+	default:
+		dev_err(dcfb->dev, "unsupported color depth: %u\n",
+			var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int fsl_dcfb_alloc_mem(struct fb_info *info)
+{
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	u32 smem_len = info->fix.line_length * info->var.yres_virtual;
+
+	info->fix.smem_len = smem_len;
+
+	info->screen_base = dma_alloc_writecombine(info->device,
+		info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start,
+		GFP_KERNEL);
+	if (!info->screen_base) {
+		dev_err(dcfb->dev, "unable to allocate fb memory\n");
+		return -ENOMEM;
+	}
+
+	memset(info->screen_base, 0, info->fix.smem_len);
+
+	return 0;
+}
+
+static void fsl_dcfb_free_mem(struct fb_info *info)
+{
+	if (!info->screen_base)
+		return;
+
+	dma_free_writecombine(info->device, info->fix.smem_len,
+		info->screen_base, info->fix.smem_start);
+
+	info->screen_base = NULL;
+	info->fix.smem_start = 0;
+	info->fix.smem_len = 0;
+}
+
+static int fsl_dcfb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	unsigned int div, len;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = fix->ypanstep = 1;
+
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	len = info->var.yres_virtual * info->fix.line_length;
+	if (len != info->fix.smem_len) {
+		if (info->fix.smem_start)
+			fsl_dcfb_free_mem(info);
+
+		if (fsl_dcfb_alloc_mem(info)) {
+			dev_err(dcfb->dev, "unable to allocate FB memory\n");
+			return -ENOMEM;
+		}
+	}
+
+	div = KHZ2PICOS(clk_get_rate(dcfb->clk) / 1000);
+	regmap_write(dcfb->regmap, FSL_DCFB_DIV_RATIO,
+		     info->var.pixclock / div);
+
+	regmap_write(dcfb->regmap, FSL_DCFB_FIX_SIZE,
+		     FSL_DCFB_FIX_SIZE_Y(var->yres) |
+		     FSL_DCFB_FIX_SIZE_X(var->xres / 16));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_HSYN,
+		     FSL_DCFB_HSYN_BP(var->left_margin) |
+		     FSL_DCFB_HSYN_PW(var->hsync_len) |
+		     FSL_DCFB_HSYN_FP(var->right_margin));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_VSYN,
+		     FSL_DCFB_VSYN_BP(var->upper_margin) |
+		     FSL_DCFB_VSYN_PW(var->vsync_len) |
+		     FSL_DCFB_VSYN_FP(var->lower_margin));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_SP,
+		     FSL_DCFB_SP_VS | FSL_DCFB_SP_HS);
+
+	regmap_write(dcfb->regmap, FSL_DCFB_BGND, FSL_DCFB_BGND_R(0) |
+		     FSL_DCFB_BGND_G(0) | FSL_DCFB_BGND_B(0));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_MODE,
+		     FSL_DCFB_MODE_BITER(1) | FSL_DCFB_MODE_RASTER_EN);
+
+	regmap_write(dcfb->regmap, FSL_DCFB_TS, FSL_DCFB_TS_LBV(0x03) |
+		     FSL_DCFB_TS_OBH(0x78) | FSL_DCFB_TS_OBL(0x0A));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+	fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_NORMAL);
+	fsl_dcfb_set_panel(info);
+
+	return 0;
+}
+
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
+static int fsl_dcfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+				      7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+			u32 value;
+
+			red = CNVT_TOHW(red, info->var.red.length);
+			green = CNVT_TOHW(green, info->var.green.length);
+			blue = CNVT_TOHW(blue, info->var.blue.length);
+			transp = CNVT_TOHW(transp, info->var.transp.length);
+
+			value = (red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset) |
+				(transp << info->var.transp.offset);
+
+			pal[regno] = value;
+			ret = 0;
+		}
+		break;
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+
+	return ret;
+}
+#undef CNVT_TOHW
+
+static int fsl_dcfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	unsigned long addr;
+	int offset;
+
+	if ((info->var.xoffset = var->xoffset) &&
+	    (info->var.yoffset = var->yoffset))
+		return 0;
+
+	if ((var->xoffset + info->var.xres) > info->var.xres_virtual
+	    || (var->yoffset + info->var.yres) > info->var.yres_virtual)
+		return -EINVAL;
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	offset = (info->var.yoffset * info->var.xres_virtual);
+	offset += info->var.xoffset;
+	addr = info->fix.smem_start +
+		(offset * (info->var.bits_per_pixel >> 3));
+
+	regmap_write(dcfb->regmap, FSL_DCFB_BASE, addr);
+	regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+	return 0;
+}
+
+static int fsl_dcfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+
+	switch (blank_mode) {
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		fsl_dcfb_reset_panel(dcfb);
+		break;
+	case FB_BLANK_POWERDOWN:
+		fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_OFF);
+		break;
+	case FB_BLANK_UNBLANK:
+		fsl_dcfb_set_panel(info);
+		break;
+	}
+
+	return 0;
+}
+
+static int fsl_dcfb_open(struct fb_info *info, int user)
+{
+	struct fsl_dcfb_fb_info *fsl_info = info->par;
+	int ret = 0;
+
+	fsl_info->count++;
+	if (fsl_info->count = 1) {
+		fsl_dcfb_check_var(&info->var, info);
+		ret = fsl_dcfb_set_par(info);
+		if (ret < 0)
+			fsl_info->count--;
+	}
+
+	return ret;
+}
+
+static int fsl_dcfb_release(struct fb_info *info, int user)
+{
+	struct fsl_dcfb_fb_info *fsl_info = info->par;
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	int ret = 0;
+
+	fsl_info->count--;
+	if (fsl_info->count = 0)
+		ret = fsl_dcfb_reset_panel(dcfb);
+
+	return ret;
+}
+
+static struct fb_ops fsl_dcfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = fsl_dcfb_check_var,
+	.fb_set_par = fsl_dcfb_set_par,
+	.fb_setcolreg = fsl_dcfb_setcolreg,
+	.fb_blank = fsl_dcfb_blank,
+	.fb_pan_display = fsl_dcfb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_open = fsl_dcfb_open,
+	.fb_release = fsl_dcfb_release,
+};
+
+static int fsl_dcfb_init_fbinfo(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+	struct device_node *np = dcfb->dev->of_node;
+	struct device_node *dnp, *tnp;
+	struct display_timings *timings;
+	struct fb_videomode fb_vm;
+	int i, ret;
+
+	INIT_LIST_HEAD(&info->modelist);
+
+	dnp = of_parse_phandle(np, "display", 0);
+	if (!dnp) {
+		dev_err(dcfb->dev, "failed to find \"display\" phandle.\n");
+		return -ENODEV;
+	}
+
+	ret = of_property_read_u32(dnp, "bits-per-pixel",
+				   &var->bits_per_pixel);
+	if (ret < 0) {
+		dev_err(dcfb->dev, "failed to get \"bits-per-pixel\" property.\n");
+		goto put_dnp;
+	}
+
+	timings = of_get_display_timings(dnp);
+	if (!timings) {
+		dev_err(dcfb->dev, "failed to get display timings\n");
+		return -ENODEV;
+		goto put_dnp;
+	}
+
+	tnp = of_find_node_by_name(dnp, "display-timings");
+	if (!tnp) {
+		dev_err(dcfb->dev, "failed to find \"display-timings\" node\n");
+		return -ENODEV;
+		goto put_dnp;
+	}
+
+	for (i = 0; i < of_get_child_count(tnp); i++) {
+		struct videomode vm;
+
+		ret = videomode_from_timings(timings, &vm, i);
+		if (ret < 0)
+			goto put_tnp;
+
+		ret = fb_videomode_from_videomode(&vm, &fb_vm);
+		if (ret < 0)
+			goto put_tnp;
+
+		fb_add_videomode(&fb_vm, &info->modelist);
+	}
+
+	ret = of_get_fb_videomode(dnp, &fb_vm, OF_USE_NATIVE_MODE);
+	if (ret)
+		goto put_dnp;
+
+	fb_videomode_to_var(&info->var, &fb_vm);
+	ret = fsl_dcfb_check_var(&info->var, info);
+
+put_tnp:
+	of_node_put(tnp);
+put_dnp:
+	of_node_put(dnp);
+
+	return ret;
+}
+
+static const struct regmap_config fsl_scfg_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.max_register = FSL_SCFG_CTRL,
+};
+
+static int scfg_config(struct fsl_dcfb_fb_private *dcfb, struct device_node *np)
+{
+	struct device_node *snp;
+	struct platform_device *pdev;
+	struct resource *res;
+	void __iomem *base;
+	struct regmap *regmap;
+	int ret = 0;
+
+	snp = of_parse_phandle(np, "scfg-controller", 0);
+	if (!snp)
+		return -ENODEV;
+
+	pdev = of_find_device_by_node(snp);
+	if (!pdev) {
+		ret = -ENODEV;
+		goto put_snp;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		goto put_snp;
+	}
+
+	base = ioremap(res->start, SZ_4K);
+	if (IS_ERR(base)) {
+		dev_err(&pdev->dev, "could not ioremap scfg resource\n");
+		ret = PTR_ERR(base);
+		goto put_snp;
+	}
+
+	regmap = regmap_init_mmio(&pdev->dev, base,
+				  &fsl_scfg_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		ret = PTR_ERR(regmap);
+		goto ioremap;
+	}
+
+	regmap_write(regmap, FSL_SCFG_CTRL, FSL_SCFG_PIXEL_EN);
+
+	regmap_exit(regmap);
+ioremap:
+	iounmap(base);
+put_snp:
+	of_node_put(snp);
+
+	return ret;
+}
+
+static int fsl_dcfb_dev_init(struct device_node *np,
+			     struct fsl_dcfb_fb_private *dcfb)
+{
+	int ret;
+
+	ret = scfg_config(dcfb, np);
+	if (ret) {
+		dev_err(dcfb->dev, "could not config scfg\n");
+		return -EINVAL;
+	}
+
+	return fsl_dcfb_reset_panel(dcfb);
+}
+
+static const struct regmap_config fsl_dcfb_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.max_register = FSL_DCFB_MAX,
+};
+
+static int fsl_dcfb_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct fsl_dcfb_fb_private *dcfb;
+	struct fsl_dcfb_fb_info *fsl_info;
+	struct fb_info *info;
+	struct resource *res;
+	void __iomem *base;
+	int ret = 0;
+
+	dcfb = devm_kzalloc(&pdev->dev,
+		sizeof(struct fsl_dcfb_fb_private), GFP_KERNEL);
+	if (!dcfb)
+		return -ENOMEM;
+
+	dcfb->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get memory IO resource\n");
+		return -ENODEV;
+	}
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		dev_err(&pdev->dev, "could not ioremap resource\n");
+		return PTR_ERR(base);
+	}
+
+	dcfb->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+				NULL, base, &fsl_dcfb_regmap_config);
+	if (IS_ERR(dcfb->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(dcfb->regmap);
+	}
+
+	dcfb->clk = devm_clk_get(&pdev->dev, "dcfb");
+	if (IS_ERR(dcfb->clk)) {
+		ret = PTR_ERR(dcfb->clk);
+		dev_err(&pdev->dev, "could not get clock\n");
+		return -EINVAL;
+	}
+	clk_prepare_enable(dcfb->clk);
+
+	fsl_dcfb_dev_init(np, dcfb);
+
+	dcfb->fsl_dcfb_info +		framebuffer_alloc(sizeof(struct fsl_dcfb_fb_info), &pdev->dev);
+	if (!dcfb->fsl_dcfb_info) {
+		ret = -ENOMEM;
+		goto err_clk;
+	}
+
+	dcfb->fsl_dcfb_info->fix.smem_start = 0;
+
+	fsl_info = dcfb->fsl_dcfb_info->par;
+	fsl_info->count = 0,
+	fsl_info->parent = dcfb;
+
+	info = dcfb->fsl_dcfb_info;
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->fbops = &fsl_dcfb_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->pseudo_palette = &fsl_info->pseudo_palette;
+
+	ret = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto err_mem;
+	}
+
+	ret = fsl_dcfb_init_fbinfo(info);
+	if (ret)
+		goto err_cmap;
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(dcfb->dev, "failed to register framebuffer device\n");
+		goto err_cmap;
+	}
+
+	dev_set_drvdata(&pdev->dev, dcfb);
+
+	goto out;
+
+err_cmap:
+	fb_dealloc_cmap(&info->cmap);
+err_mem:
+	framebuffer_release(dcfb->fsl_dcfb_info);
+err_clk:
+	clk_disable_unprepare(dcfb->clk);
+out:
+	return ret;
+}
+
+static int fsl_dcfb_remove(struct platform_device *pdev)
+{
+	struct fsl_dcfb_fb_private *dcfb = dev_get_drvdata(&pdev->dev);
+	struct fb_info *info = dcfb->fsl_dcfb_info;
+
+	fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_OFF);
+	fsl_dcfb_free_mem(info);
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(dcfb->fsl_dcfb_info);
+	clk_disable_unprepare(dcfb->clk);
+
+	return 0;
+}
+
+static struct of_device_id fsl_dcfb_dt_ids[] = {
+	{ .compatible = "fsl,ls1021a-dcfb", },
+	{}
+};
+
+static struct platform_driver fsl_dcfb_driver = {
+	.driver = {
+		.name = "fsl-dcfb",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_dcfb_dt_ids,
+	},
+	.probe = fsl_dcfb_probe,
+	.remove = fsl_dcfb_remove,
+};
+
+module_platform_driver(fsl_dcfb_driver);
+
+MODULE_DESCRIPTION("Freescale Simple Display Controller FB Driver");
+MODULE_ALIAS("platform:fsl-dcfb");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0.27.g96db324


^ permalink raw reply related

* [PATCHv2 2/4] video: fsl-dcfb: Add devicetree binding support
From: Xiubo Li @ 2014-12-03  9:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>

Add devicetree binding support for fsl-dcfb framebuffer driver. It
uses the generic display bindings and helper functions.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 .../devicetree/bindings/video/fsl,dcfb.txt         | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/fsl,dcfb.txt

diff --git a/Documentation/devicetree/bindings/video/fsl,dcfb.txt b/Documentation/devicetree/bindings/video/fsl,dcfb.txt
new file mode 100644
index 0000000..2f3d02b
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/fsl,dcfb.txt
@@ -0,0 +1,52 @@
+* Freescale Simple Display Controller FB Driver
+
+== For dcfb node =+Required properties:
+- compatible:		Should be one of "fsl,ls1021a-dcfb".
+- reg:			Address and length of the register set for dcfb.
+- clocks:		From common clock binding: handle to dcfb clock.
+- clock-names:		From common clock binding: Shall be "dcfb".
+- display:		The phandle to display node.
+
+Optional properties:
+- scfg-controller:	The phandle of scfg node.
+
+== For display sub-node =+Required properties:
+- bits-per-pixel:	<16> for RGB565,
+			<24> for RGB888,
+			<32> for RGB8888.
+
+Required timing node for dispplay sub-node:
+- display-timings:	Refer to binding doc display-timing.txt for details.
+
+Examples:
+dcfb: dcfb@2ce0000 {
+	compatible = "fsl,ls1021a-dcfb";
+	reg = <0x0 0x2ce0000 0x0 0x10000>;
+	clocks = <&platform_clk 0>;
+	clock-names = "dcfb";
+	scfg-controller = <&scfg>;
+	display = <&display>;
+
+	display: display@0 {
+		bits-per-pixel = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: nl4827hc19 {
+				clock-frequency = <10870000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hfront-porch = <2>;
+				vback-porch = <1>;
+				vfront-porch = <1>;
+				hsync-len = <41>;
+				vsync-len = <2>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+};
-- 
2.1.0.27.g96db324


^ permalink raw reply related

* [PATCHv2 3/4] ARM: ls1021a: dtsi: Add dt node support for dcfb.
From: Xiubo Li @ 2014-12-03  9:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>

On LS1021A SoC, the dcfb device is in BE mode.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..740a04e 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,16 @@
 				 <&platform_clk 1>;
 		};
 
+		dcfb: dcfb@2ce0000 {
+			compatible = "fsl,ls1021a-dcfb";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcfb";
+			scfg-controller = <&scfg>;
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio@2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324


^ permalink raw reply related

* [PATCHv2 4/4] ARM: ls1021a: dts: Add and enable dt node for dcfb.
From: Xiubo Li @ 2014-12-03  9:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>

On LS1021A TWR board, the TFT LCD panel is WQVGA "480x272", and
the bpp is 24.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/ls1021a-twr.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a2c591e..3602286 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -58,6 +58,32 @@
 	};
 };
 
+&dcfb {
+	display = <&display>;
+	status = "okay";
+
+	display: display@0 {
+		bits-per-pixel = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: nl4827hc19 {
+				clock-frequency = <10870000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vfront-porch = <2>;
+				hsync-len = <41>;
+				vsync-len = <4>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+};
+
 &dspi1 {
 	bus-num = <0>;
 	status = "okay";
-- 
2.1.0.27.g96db324


^ permalink raw reply related

* Re: [PATCHv2 0/4] LS1021A: Add dcfb framebuffer driver support.
From: Arnd Bergmann @ 2014-12-03  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>

On Wednesday 03 December 2014 17:15:58 Xiubo Li wrote:
> Framebuffer driver for the Freescale SoC Display Controller.
> 
> 
> Change in V2:
> - Use the native-mode timing as default.
> - Add to_fsl_private().

<standard reply>

We try to not have any new framebuffer drivers. Please consider making
this a DRM/KMS driver instead.

</standard reply>

	Arnd

^ permalink raw reply

* Re: [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: Oliver Neukum @ 2014-12-03 10:02 UTC (permalink / raw)
  To: gyungoh
  Cc: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
	pawel.moll, mark.rutland, ijc+devicetree, galak, trivial, akpm,
	jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
	matti.vaittinen, broonie, jason, heiko, shawn.guo,
	florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
	tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-3-git-send-email-jack.yoo@skyworksinc.com>

On Wed, 2014-12-03 at 16:05 +0900, gyungoh@gmail.com wrote:
> +static ssize_t sky81452_bl_store_enable(struct device *dev,
> +               struct device_attribute *attr, const char *buf, size_t
> count)
> +{
> +       struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> +       unsigned long value;
> +       int ret;
> +
> +       ret = kstrtoul(buf, 16, &value);
> +       if (IS_ERR_VALUE(ret))
> +               return ret;
> +
> +       ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> +                                       value << CTZ(SKY81452_EN));

No range checking for value?

> +       if (IS_ERR_VALUE(ret))
> +               return ret;
> +
> +       return count;
> +}

	Regards
		Oliver

-- 
Oliver Neukum <oneukum@suse.de>


^ permalink raw reply

* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Lee Jones @ 2014-12-03 10:15 UTC (permalink / raw)
  To: Sean Paul
  Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
	Stéphane Marchesin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Tue, 02 Dec 2014, Sean Paul wrote:

> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
> 
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
>  1 file changed, 18 insertions(+), 19 deletions(-)

Applied with Acks, thanks.

> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 25fb8e3..257b3ba 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
>  };
>  
>  #ifdef CONFIG_OF
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
> +	struct device *dev = lp->dev;
> +	struct device_node *node = dev->of_node;
>  	struct lp855x_platform_data *pdata;
>  	int rom_length;
>  
> @@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>  		pdata->rom_data = &rom[0];
>  	}
>  
> -	dev->platform_data = pdata;
> +	lp->pdata = pdata;
>  
>  	return 0;
>  }
>  #else
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
>  {
>  	return -EINVAL;
>  }
> @@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
>  static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  {
>  	struct lp855x *lp;
> -	struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
> -	struct device_node *node = cl->dev.of_node;
>  	int ret;
>  
> -	if (!pdata) {
> -		ret = lp855x_parse_dt(&cl->dev, node);
> -		if (ret < 0)
> -			return ret;
> -
> -		pdata = dev_get_platdata(&cl->dev);
> -	}
> -
>  	if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
>  		return -EIO;
>  
> @@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  	if (!lp)
>  		return -ENOMEM;
>  
> -	if (pdata->period_ns > 0)
> -		lp->mode = PWM_BASED;
> -	else
> -		lp->mode = REGISTER_BASED;
> -
>  	lp->client = cl;
>  	lp->dev = &cl->dev;
> -	lp->pdata = pdata;
>  	lp->chipname = id->name;
>  	lp->chip_id = id->driver_data;
> +	lp->pdata = dev_get_platdata(&cl->dev);
> +
> +	if (!lp->pdata) {
> +		ret = lp855x_parse_dt(lp);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (lp->pdata->period_ns > 0)
> +		lp->mode = PWM_BASED;
> +	else
> +		lp->mode = REGISTER_BASED;
> +
>  	i2c_set_clientdata(cl, lp);
>  
>  	ret = lp855x_configure(lp);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Lee Jones @ 2014-12-03 10:15 UTC (permalink / raw)
  To: Sean Paul
  Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
	Stéphane Marchesin, Aaron Durbin
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

On Tue, 02 Dec 2014, Sean Paul wrote:

> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
> 
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Cc: Aaron Durbin <adurbin@chromium.org>
> Acked-by: Milo Kim <milo.kim@ti.com>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Add NULL check in lp855x_remove
> 
> 
>  .../devicetree/bindings/video/backlight/lp855x.txt     |  2 ++
>  drivers/video/backlight/lp855x_bl.c                    | 18 ++++++++++++++++++
>  include/linux/platform_data/lp855x.h                   |  2 ++
>  3 files changed, 22 insertions(+)

Applied with Acks, thanks.

> diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> index 96e83a5..0a3ecbc 100644
> --- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> @@ -12,6 +12,7 @@ Optional properties:
>    - pwm-period: PWM period value. Set only PWM input mode used (u32)
>    - rom-addr: Register address of ROM area to be updated (u8)
>    - rom-val: Register value to be updated (u8)
> +  - power-supply: Regulator which controls the 3V rail
>  
>  Example:
>  
> @@ -56,6 +57,7 @@ Example:
>  	backlight@2c {
>  		compatible = "ti,lp8557";
>  		reg = <0x2c>;
> +		power-supply = <&backlight_vdd>;
>  
>  		dev-ctrl = /bits/ 8 <0x41>;
>  		init-brt = /bits/ 8 <0x0a>;
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 257b3ba..a26d3bb 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -17,6 +17,7 @@
>  #include <linux/of.h>
>  #include <linux/platform_data/lp855x.h>
>  #include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
>  
>  /* LP8550/1/2/3/6 Registers */
>  #define LP855X_BRIGHTNESS_CTRL		0x00
> @@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
>  		pdata->rom_data = &rom[0];
>  	}
>  
> +	pdata->supply = devm_regulator_get(dev, "power");
> +	if (IS_ERR(pdata->supply)) {
> +		if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		pdata->supply = NULL;
> +	}
> +
>  	lp->pdata = pdata;
>  
>  	return 0;
> @@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
>  	else
>  		lp->mode = REGISTER_BASED;
>  
> +	if (lp->pdata->supply) {
> +		ret = regulator_enable(lp->pdata->supply);
> +		if (ret < 0) {
> +			dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
> +			return ret;
> +		}
> +	}
> +
>  	i2c_set_clientdata(cl, lp);
>  
>  	ret = lp855x_configure(lp);
> @@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
>  
>  	lp->bl->props.brightness = 0;
>  	backlight_update_status(lp->bl);
> +	if (lp->pdata->supply)
> +		regulator_disable(lp->pdata->supply);
>  	sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
>  
>  	return 0;
> diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
> index 1b2ba24..9c7fd1e 100644
> --- a/include/linux/platform_data/lp855x.h
> +++ b/include/linux/platform_data/lp855x.h
> @@ -136,6 +136,7 @@ struct lp855x_rom_data {
>  		Only valid when mode is PWM_BASED.
>   * @size_program : total size of lp855x_rom_data
>   * @rom_data : list of new eeprom/eprom registers
> + * @supply : regulator that supplies 3V input
>   */
>  struct lp855x_platform_data {
>  	const char *name;
> @@ -144,6 +145,7 @@ struct lp855x_platform_data {
>  	unsigned int period_ns;
>  	int size_program;
>  	struct lp855x_rom_data *rom_data;
> +	struct regulator *supply;
>  };
>  
>  #endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply


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