[PATCH] tps65217: Allow placement elsewhere than parent mfd device
From: Pantelis Antoniou <hidden>
Date: 2012-10-30 18:12:51
Also in:
linux-devicetree, linux-omap, lkml
Subsystem:
backlight class/subsystem, framebuffer layer, the rest · Maintainers:
Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Linus Torvalds
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 <redacted> --- drivers/video/backlight/tps65217_bl.c | 103 ++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 11 deletions(-)
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), }, };
--
1.7.12