forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[media] media: i2c/adp1653: Devicetree support for adp1653
Add device tree support for adp1653 flash LED driver. Signed-off-by: Pavel Machek <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
- Loading branch information
1 parent
b2dbde5
commit 074c57a
Showing
2 changed files
with
95 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
* Contributors: | ||
* Sakari Ailus <[email protected]> | ||
* Tuukka Toivonen <[email protected]> | ||
* Pavel Machek <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
|
@@ -34,6 +35,8 @@ | |
#include <linux/module.h> | ||
#include <linux/i2c.h> | ||
#include <linux/slab.h> | ||
#include <linux/of.h> | ||
#include <linux/gpio/consumer.h> | ||
#include <media/adp1653.h> | ||
#include <media/v4l2-device.h> | ||
|
||
|
@@ -308,16 +311,28 @@ __adp1653_set_power(struct adp1653_flash *flash, int on) | |
{ | ||
int ret; | ||
|
||
ret = flash->platform_data->power(&flash->subdev, on); | ||
if (ret < 0) | ||
return ret; | ||
if (flash->platform_data->power) { | ||
ret = flash->platform_data->power(&flash->subdev, on); | ||
if (ret < 0) | ||
return ret; | ||
} else { | ||
gpiod_set_value(flash->platform_data->enable_gpio, on); | ||
if (on) | ||
/* Some delay is apparently required. */ | ||
udelay(20); | ||
} | ||
|
||
if (!on) | ||
return 0; | ||
|
||
ret = adp1653_init_device(flash); | ||
if (ret < 0) | ||
if (ret >= 0) | ||
return ret; | ||
|
||
if (flash->platform_data->power) | ||
flash->platform_data->power(&flash->subdev, 0); | ||
else | ||
gpiod_set_value(flash->platform_data->enable_gpio, 0); | ||
|
||
return ret; | ||
} | ||
|
@@ -407,21 +422,85 @@ static int adp1653_resume(struct device *dev) | |
|
||
#endif /* CONFIG_PM */ | ||
|
||
static int adp1653_of_init(struct i2c_client *client, | ||
struct adp1653_flash *flash, | ||
struct device_node *node) | ||
{ | ||
struct adp1653_platform_data *pd; | ||
struct device_node *child; | ||
|
||
pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL); | ||
if (!pd) | ||
return -ENOMEM; | ||
flash->platform_data = pd; | ||
|
||
child = of_get_child_by_name(node, "flash"); | ||
if (!child) | ||
return -EINVAL; | ||
|
||
if (of_property_read_u32(child, "flash-timeout-us", | ||
&pd->max_flash_timeout)) | ||
goto err; | ||
|
||
if (of_property_read_u32(child, "flash-max-microamp", | ||
&pd->max_flash_intensity)) | ||
goto err; | ||
|
||
pd->max_flash_intensity /= 1000; | ||
|
||
if (of_property_read_u32(child, "led-max-microamp", | ||
&pd->max_torch_intensity)) | ||
goto err; | ||
|
||
pd->max_torch_intensity /= 1000; | ||
of_node_put(child); | ||
|
||
child = of_get_child_by_name(node, "indicator"); | ||
if (!child) | ||
return -EINVAL; | ||
|
||
if (of_property_read_u32(child, "led-max-microamp", | ||
&pd->max_indicator_intensity)) | ||
goto err; | ||
|
||
of_node_put(child); | ||
|
||
pd->enable_gpio = devm_gpiod_get(&client->dev, "enable"); | ||
if (!pd->enable_gpio) { | ||
dev_err(&client->dev, "Error getting GPIO\n"); | ||
return -EINVAL; | ||
} | ||
|
||
return 0; | ||
err: | ||
dev_err(&client->dev, "Required property not found\n"); | ||
of_node_put(child); | ||
return -EINVAL; | ||
} | ||
|
||
|
||
static int adp1653_probe(struct i2c_client *client, | ||
const struct i2c_device_id *devid) | ||
{ | ||
struct adp1653_flash *flash; | ||
int ret; | ||
|
||
/* we couldn't work without platform data */ | ||
if (client->dev.platform_data == NULL) | ||
return -ENODEV; | ||
|
||
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); | ||
if (flash == NULL) | ||
return -ENOMEM; | ||
|
||
flash->platform_data = client->dev.platform_data; | ||
if (client->dev.of_node) { | ||
ret = adp1653_of_init(client, flash, client->dev.of_node); | ||
if (ret) | ||
return ret; | ||
} else { | ||
if (!client->dev.platform_data) { | ||
dev_err(&client->dev, | ||
"Neither DT not platform data provided\n"); | ||
return EINVAL; | ||
} | ||
flash->platform_data = client->dev.platform_data; | ||
} | ||
|
||
mutex_init(&flash->power_lock); | ||
|
||
|
@@ -442,6 +521,7 @@ static int adp1653_probe(struct i2c_client *client, | |
return 0; | ||
|
||
free_and_quit: | ||
dev_err(&client->dev, "adp1653: failed to register device\n"); | ||
v4l2_ctrl_handler_free(&flash->ctrls); | ||
return ret; | ||
} | ||
|
@@ -464,7 +544,7 @@ static const struct i2c_device_id adp1653_id_table[] = { | |
}; | ||
MODULE_DEVICE_TABLE(i2c, adp1653_id_table); | ||
|
||
static struct dev_pm_ops adp1653_pm_ops = { | ||
static const struct dev_pm_ops adp1653_pm_ops = { | ||
.suspend = adp1653_suspend, | ||
.resume = adp1653_resume, | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters