Skip to contentSkip to conversation

backlight: Add TPS65217 WLED driver

PATCH Superseded Matthias Kaehlcke 3 participants 4 messages Aug 22, 2012 – Aug 24, 2012

Subsystems (4)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 backlight: Add TPS65217 WLED driver

The TPS65217 chip contains a boost converter and current sinks which can be used to drive LEDs for use as backlights. Expose this functionality via the backlight API.

Tested on an AM335x based custom board with a single WLED string, using different values for ISEL and FDIM (though it would be hard to tell the difference except for the value in WLEDCTRL1). Both instantiation through the device tree and by passing platform data have been tested. Testing has been done with an Androidized 3.2 kernel from the rowboat project

This patch is based on the mfd/for-next branch (20120822)

Changes since v2:

* adapted to the latest version of the tps65217 mfd driver
* register backlight as mfd subdevice
* allocate struct tps65217_bl after validation of the device tree/platform data

---
 drivers/mfd/tps65217.c                |    3 +
 drivers/video/backlight/Kconfig       |    7 +
 drivers/video/backlight/Makefile      |    1 +
 drivers/video/backlight/tps65217_bl.c |  352 +++++++++++++++++++++++++++++++++
 include/linux/mfd/tps65217.h          |   18 ++
 5 files changed, 381 insertions(+)
 create mode 100644 drivers/video/backlight/tps65217_bl.c
drivers/mfd/tps65217.c +3 -0
index 3bc2744..592059e 100644
@@ -34,6 +34,9 @@ static struct mfd_cell tps65217s[] = {
 	{
 		.name = "tps65217-pmic",
 	},
+	{
+		.name = "tps65217-bl",
+	},
 };
 
 /**
drivers/video/backlight/Kconfig +7 -0
index cf28276..63cee2e 100644
@@ -373,6 +373,13 @@ config BACKLIGHT_PANDORA
 	  If you have a Pandora console, say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_TPS65217
+	tristate "TPS65217 Backlight"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
+	help
+	  If you have a Texas Instruments TPS65217 say Y to enable the
+	  backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
drivers/video/backlight/Makefile +1 -0
index a2ac9cf..00223a6 100644
@@ -43,3 +43,4 @@ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
drivers/video/backlight/tps65217_bl.c new file +352 -0

352 lines not on this page · raw message

include/linux/mfd/tps65217.h +18 -0
index 7cd83d8..290762f 100644
@@ -213,6 +213,23 @@ enum tps65217_regulator_id {
 /* Number of total regulators available */
 #define TPS65217_NUM_REGULATOR		(TPS65217_NUM_DCDC + TPS65217_NUM_LDO)
 
+enum tps65217_bl_isel {
+	TPS65217_BL_ISET1 = 1,
+	TPS65217_BL_ISET2,
+};
+
+enum tps65217_bl_fdim {
+	TPS65217_BL_FDIM_100HZ,
+	TPS65217_BL_FDIM_200HZ,
+	TPS65217_BL_FDIM_500HZ,
+	TPS65217_BL_FDIM_1000HZ,
+};
+
+struct tps65217_bl_pdata {
+	enum tps65217_bl_isel isel;
+	enum tps65217_bl_fdim fdim;
+};
+
 /**
  * struct tps65217_board - packages regulator init data
  * @tps65217_regulator_data: regulator initialization values
@@ -222,6 +239,7 @@ enum tps65217_regulator_id {
 struct tps65217_board {
 	struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR];
 	struct device_node *of_node[TPS65217_NUM_REGULATOR];
+	struct tps65217_bl_pdata *bl_pdata;
 };
 
 /**
Signature · 1 line
1.7.10
#1 lore raw

Hi Kaehlcke,

Quoted 10 lines · Matthias Kaehlcke

The TPS65217 chip contains a boost converter and current sinks which can be used to drive LEDs for use as backlights. Expose this functionality via the backlight API.

Tested on an AM335x based custom board with a single WLED string, using different values for ISEL and FDIM (though it would be hard to tell the difference except for the value in WLEDCTRL1). Both instantiation through the device tree and by passing platform data have been tested. Testing has been done with an Androidized 3.2 kernel from the rowboat project

Quoted 7 lines

This patch is based on the mfd/for-next branch (20120822)

Changes since v2:

* adapted to the latest version of the tps65217 mfd driver
* register backlight as mfd subdevice
* allocate struct tps65217_bl after validation of the device tree/platform data

This patch should divide into 2 patches, one patch meant for MFD changes other for backlight.

Quoted 80 lines
---
 drivers/mfd/tps65217.c                |    3 +
 drivers/video/backlight/Kconfig       |    7 +
 drivers/video/backlight/Makefile      |    1 +
 drivers/video/backlight/tps65217_bl.c |  352 +++++++++++++++++++++++++++++++++
 include/linux/mfd/tps65217.h          |   18 ++
 5 files changed, 381 insertions(+)
 create mode 100644 drivers/video/backlight/tps65217_bl.c
drivers/mfd/tps65217.c +3 -0
index 3bc2744..592059e 100644
@@ -34,6 +34,9 @@ static struct mfd_cell tps65217s[] = {
 	{
 		.name = "tps65217-pmic",
 	},
+	{
+		.name = "tps65217-bl",
+	},
 };
 
 /**
drivers/video/backlight/Kconfig +7 -0
index cf28276..63cee2e 100644
@@ -373,6 +373,13 @@ config BACKLIGHT_PANDORA
 	  If you have a Pandora console, say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_TPS65217
+	tristate "TPS65217 Backlight"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
+	help
+	  If you have a Texas Instruments TPS65217 say Y to enable the
+	  backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
drivers/video/backlight/Makefile +1 -0
index a2ac9cf..00223a6 100644
@@ -43,3 +43,4 @@ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
drivers/video/backlight/tps65217_bl.c new file +22 -0
new file mode 100644
index 0000000..5842d5f
@@ -0,0 +1,352 @@
+/*
+ * tps65217_bl.c
+ *
+ * TPS65217 backlight driver
+ *
+ * Copyright (C) 2012 Matthias Kaehlcke
+ * Author: Matthias Kaehlcke <[email protected]>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>

drivers/video/backlight/tps65217_bl.c line 32

Quoted 10 lines
drivers/video/backlight/tps65217_bl.c new file +10 -0
+#include <linux/mfd/tps65217.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct tps65217_bl {
+	struct tps65217 *tps;
+	struct device *dev;
+	struct backlight_device *bl;
+	int on;

Can you use Boolean here? Change the name as well, something like bool is_enabled?

Quoted 179 lines
drivers/video/backlight/tps65217_bl.c new file +179 -0
+};
+
+static int tps65217_bl_enable(struct tps65217_bl *tps65217_bl)
+{
+	int rc;
+
+	rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+			TPS65217_WLEDCTRL1_ISINK_ENABLE,
+			TPS65217_WLEDCTRL1_ISINK_ENABLE, TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to enable backlight: %d\n", rc);
+		return rc;
+	}
+
+	tps65217_bl->on = 1;
+
+	dev_dbg(tps65217_bl->dev, "backlight enabled\n");
+
+	return 0;
+}
+
+static int tps65217_bl_disable(struct tps65217_bl *tps65217_bl)
+{
+	int rc;
+
+	rc = tps65217_clear_bits(tps65217_bl->tps,
+				TPS65217_REG_WLEDCTRL1,
+				TPS65217_WLEDCTRL1_ISINK_ENABLE,
+				TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to disable backlight: %d\n", rc);
+		return rc;
+	}
+
+	tps65217_bl->on = 0;
+
+	dev_dbg(tps65217_bl->dev, "backlight disabled\n");
+
+	return 0;
+}
+
+static int tps65217_bl_update_status(struct backlight_device *bl)
+{
+	struct tps65217_bl *tps65217_bl = bl_get_data(bl);
+	int rc;
+	int brightness = bl->props.brightness;
+
+	if (bl->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
+	if ((bl->props.power != FB_BLANK_UNBLANK) ||
+		(bl->props.fb_blank != FB_BLANK_UNBLANK))
+		/* framebuffer in low power mode or blanking active */
+		brightness = 0;
+
+	if (brightness > 0) {
+		rc = tps65217_reg_write(tps65217_bl->tps,
+					TPS65217_REG_WLEDCTRL2,
+					brightness - 1,
+					TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to set brightness level: %d\n", rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
+
+		if (!tps65217_bl->on)
+			rc = tps65217_bl_enable(tps65217_bl);
+	} else {
+		rc = tps65217_bl_disable(tps65217_bl);
+	}
+
+	return rc;
+}
+
+static int tps65217_bl_get_brightness(struct backlight_device *bl)
+{
+	return bl->props.brightness;
+}
+
+static const struct backlight_ops tps65217_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= tps65217_bl_update_status,
+	.get_brightness	= tps65217_bl_get_brightness
+};
+
+static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
+			struct tps65217_bl_pdata *pdata)
+{
+	int rc;
+
+	rc = tps65217_bl_disable(tps65217_bl);
+	if (rc)
+		return rc;
+
+	switch (pdata->isel) {
+	case TPS65217_BL_ISET1:
+		/* select ISET_1 current level */
+		rc = tps65217_clear_bits(tps65217_bl->tps,
+					TPS65217_REG_WLEDCTRL1,
+					TPS65217_WLEDCTRL1_ISEL,
+					TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to select ISET1 current level: %d)\n",
+				rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "selected ISET1 current level\n");
+
+		break;
+
+	case TPS65217_BL_ISET2:
+		/* select ISET2 current level */
+		rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+				TPS65217_WLEDCTRL1_ISEL,
+				TPS65217_WLEDCTRL1_ISEL, TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to select ISET2 current level: %d\n",
+				rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "selected ISET2 current level\n");
+
+		break;
+
+	default:
+		dev_err(tps65217_bl->dev,
+			"invalid value for current level: %d\n", pdata->isel);
+		return -EINVAL;
+	}
+
+	/* set PWM frequency */
+	rc = tps65217_set_bits(tps65217_bl->tps,
+			TPS65217_REG_WLEDCTRL1,
+			TPS65217_WLEDCTRL1_FDIM_MASK,
+			pdata->fdim,
+			TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to select PWM dimming frequency: %d\n",
+			rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct tps65217_bl_pdata *
+tps65217_bl_parse_dt(struct platform_device *pdev)
+{
+	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *node = of_node_get(tps->dev->of_node);
+	struct tps65217_bl_pdata *pdata, *err;
+	u32 val;
+
+	node = of_find_node_by_name(node, "backlight");
+	if (!node)
+		return ERR_PTR(-ENODEV);
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "failed to allocate platform data\n");
+		err = ERR_PTR(-ENOMEM);
+		goto err;
+	}
+
+	pdata->isel = TPS65217_BL_ISET1;
+	if (!of_property_read_u32(node, "isel", &val)) {
+		if (val < TPS65217_BL_ISET1 ||
+			val > TPS65217_BL_ISET2) {

drivers/video/backlight/tps65217_bl.c line 221

Quoted 10 lines
drivers/video/backlight/tps65217_bl.c new file +10 -0
+			dev_err(&pdev->dev,
+				"invalid 'isel' value in the device tree\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		pdata->isel = val;
+	}
+
+	pdata->fdim = TPS65217_BL_FDIM_200HZ;

Why 200 by default?

Regards
AnilKumar

#2 lore raw

Hi AnilKumar,

thanks for your comments

El Thu, Aug 23, 2012 at 07:53:49AM +0000 AnilKumar, Chimata ha dit:

Quoted 2 lines

This patch should divide into 2 patches, one patch meant for MFD changes other for backlight.

will do

Quoted 8 lines

drivers/video/backlight/tps65217_bl.c line 32

Quoted 5 lines
drivers/video/backlight/tps65217_bl.c new file +5 -0
+struct tps65217_bl {
+	struct tps65217 *tps;
+	struct device *dev;
+	struct backlight_device *bl;
+	int on;

Can you use Boolean here? Change the name as well, something like bool is_enabled?

ok

Quoted 3 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+	pdata->fdim = TPS65217_BL_FDIM_200HZ;

Why 200 by default?

it's the default value in the register after reset

best regards

Signature · 11 lines
Matthias Kaehlcke
Embedded Linux Developer
Amsterdam

                If you don't know where you are going,
               you will probably end up somewhere else
                         (Laurence J. Peter)
                                                                 .''`.
    using free software / Debian GNU/Linux | http://debian.org  : :'  :
                                                                `. `'`
gpg --keyserver pgp.mit.edu --recv-keys 47D8E5D4                  `-
Tested-by on v3 1/1
#3 lore raw
In reply to Matthias Kaehlcke

Op 22 aug. 2012, om 23:04 heeft Matthias Kaehlcke <[email protected]> het volgende geschreven:

Quoted 12 lines

The TPS65217 chip contains a boost converter and current sinks which can be used to drive LEDs for use as backlights. Expose this functionality via the backlight API.

Tested on an AM335x based custom board with a single WLED string, using different values for ISEL and FDIM (though it would be hard to tell the difference except for the value in WLEDCTRL1). Both instantiation through the device tree and by passing platform data have been tested. Testing has been done with an Androidized 3.2 kernel from the rowboat project

This patch is based on the mfd/for-next branch (20120822)

Quoted 7 lines

Changes since v2:

* adapted to the latest version of the tps65217 mfd driver
* register backlight as mfd subdevice
* allocate struct tps65217_bl after validation of the device tree/platform data

Work beautifully on a beaglebone + 3" LCD cape, although there's no FB driver yet: