diff mbox

tps65217: Allow placement elsewhere than parent mfd device

Message ID 1351699024-4356-1-git-send-email-panto@antoniou-consulting.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pantelis Antoniou Oct. 31, 2012, 3:57 p.m. UTC
The current code expect the configuration of the backlight to stay
constant after initialization. This patch allows to move it around.

Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 drivers/video/backlight/tps65217_bl.c | 103 ++++++++++++++++++++++++++++++----
 1 file changed, 92 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 7088163..69c1dfe 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -24,8 +24,11 @@ 
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/of_i2c.h>
 
 struct tps65217_bl {
+	struct i2c_client *i2c_client;
 	struct tps65217 *tps;
 	struct device *dev;
 	struct backlight_device *bl;
@@ -98,8 +101,6 @@  static int tps65217_bl_update_status(struct backlight_device *bl)
 			return rc;
 		}
 
-		dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
-
 		if (!tps65217_bl->is_enabled)
 			rc = tps65217_bl_enable(tps65217_bl);
 	} else {
@@ -187,14 +188,69 @@  static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
 
 #ifdef CONFIG_OF
 static struct tps65217_bl_pdata *
-tps65217_bl_parse_dt(struct platform_device *pdev)
+tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
+		int *brightnessp)
 {
-	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
-	struct device_node *node = of_node_get(tps->dev->of_node);
+	struct i2c_client *i2c_client;
+	struct tps65217 *tps;
+	struct device_node *node, *rnode, *pnode;
 	struct tps65217_bl_pdata *pdata, *err;
+	u32 tps_handle;
 	u32 val;
 
-	node = of_find_node_by_name(node, "backlight");
+	tps = NULL;
+	node = NULL;
+	*brightnessp = 0;
+
+	/* our node (compatible) */
+	pnode = pdev->dev.of_node;
+	if (pnode != NULL &&
+		of_property_read_u32(pnode, "tps", &tps_handle) == 0) {
+		/* we are not instantiated from the mfd */
+		node = of_find_node_by_phandle(tps_handle);
+		if (node == NULL) {
+			dev_err(&pdev->dev, "failed to find the tps node\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		i2c_client = of_find_i2c_device_by_node(node);
+		if (i2c_client == NULL) {
+			dev_err(&pdev->dev, "failed to find the i2c device "
+					"of tps node\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		/* yeah this is gross; the whole concept is */
+		tps = i2c_get_clientdata(i2c_client);
+		if (tps == NULL) {
+			dev_err(&pdev->dev, "failed to get tps structure\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		/* read default brightness */
+		val = 0;
+		of_property_read_u32(pnode, "brightness", &val);
+		if (val >= 100)
+			val = 100;
+
+		*brightnessp = val;
+
+		/* no need for this anymore */
+		of_node_put(node);
+
+		dev_info(&pdev->dev, "got tps=%p from handle 0x%x\n", tps, tps_handle);
+	}
+
+	if (tps == NULL)
+		tps = dev_get_drvdata(pdev->dev.parent);
+
+	rnode = of_node_get(tps->dev->of_node);
+
+	node = of_find_node_by_name(rnode, "backlight");
+	of_node_put(rnode);
+	rnode = NULL;
+
 	if (!node)
 		return ERR_PTR(-ENODEV);
 
@@ -247,6 +303,7 @@  tps65217_bl_parse_dt(struct platform_device *pdev)
 
 	of_node_put(node);
 
+	*tpsp = tps;
 	return pdata;
 
 err:
@@ -254,9 +311,16 @@  err:
 
 	return err;
 }
+
+static struct of_device_id tps65217_backlight_of_match[] = {
+	{ .compatible = "tps65217-backlight" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tps65217_backlight_of_match);
 #else
 static struct tps65217_bl_pdata *
-tps65217_bl_parse_dt(struct platform_device *pdev)
+tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
+		int *brightnessp)
 {
 	return NULL;
 }
@@ -265,13 +329,16 @@  tps65217_bl_parse_dt(struct platform_device *pdev)
 static int tps65217_bl_probe(struct platform_device *pdev)
 {
 	int rc;
-	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct tps65217 *tps;
 	struct tps65217_bl *tps65217_bl;
 	struct tps65217_bl_pdata *pdata;
 	struct backlight_properties bl_props;
+	int brightness = 0;
 
-	if (tps->dev->of_node) {
-		pdata = tps65217_bl_parse_dt(pdev);
+	tps = NULL;
+
+	if (pdev->dev.of_node) {
+		pdata = tps65217_bl_parse_dt(pdev, &tps, &brightness);
 		if (IS_ERR(pdata))
 			return PTR_ERR(pdata);
 	} else {
@@ -281,6 +348,14 @@  static int tps65217_bl_probe(struct platform_device *pdev)
 		}
 
 		pdata = pdev->dev.platform_data;
+
+		/* get the parent device */
+		tps = dev_get_drvdata(pdev->dev.parent);
+	}
+
+	if (tps == NULL) {
+		dev_err(&pdev->dev, "failed to find tps\n");
+		return -EINVAL;
 	}
 
 	tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
@@ -311,9 +386,14 @@  static int tps65217_bl_probe(struct platform_device *pdev)
 		return PTR_ERR(tps65217_bl->bl);
 	}
 
-	tps65217_bl->bl->props.brightness = 0;
+	tps65217_bl->bl->props.brightness = brightness;
 	platform_set_drvdata(pdev, tps65217_bl);
 
+	/* update with initial settings */
+	tps65217_bl_update_status(tps65217_bl->bl);
+
+	dev_info(&pdev->dev, "OK.\n");
+
 	return 0;
 }
 
@@ -332,6 +412,7 @@  static struct platform_driver tps65217_bl_driver = {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "tps65217-bl",
+		.of_match_table	= of_match_ptr(tps65217_backlight_of_match),
 	},
 };