Commit 98bea620 authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Mauro Carvalho Chehab

[media] si4713: add device tree support

Add device tree support by changing the device registration order.
In the device tree the si4713 node is a normal I2C device, which
will be probed as such. Thus the V4L device must be probed from
the I2C device and not the other way around.
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent c3a5baf4
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <media/v4l2-fh.h> #include <media/v4l2-fh.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h> #include <media/v4l2-event.h>
#include <media/radio-si4713.h> #include "si4713.h"
/* module parameters */ /* module parameters */
static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */
...@@ -153,7 +153,6 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) ...@@ -153,7 +153,6 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
{ {
struct radio_si4713_platform_data *pdata = pdev->dev.platform_data; struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
struct radio_si4713_device *rsdev; struct radio_si4713_device *rsdev;
struct i2c_adapter *adapter;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int rval = 0; int rval = 0;
...@@ -177,20 +176,11 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) ...@@ -177,20 +176,11 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
goto exit; goto exit;
} }
adapter = i2c_get_adapter(pdata->i2c_bus); sd = i2c_get_clientdata(pdata->subdev);
if (!adapter) { rval = v4l2_device_register_subdev(&rsdev->v4l2_dev, sd);
dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", if (rval) {
pdata->i2c_bus);
rval = -ENODEV;
goto unregister_v4l2_dev;
}
sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
pdata->subdev_board_info, NULL);
if (!sd) {
dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
rval = -ENODEV; goto unregister_v4l2_dev;
goto put_adapter;
} }
rsdev->radio_dev = radio_si4713_vdev_template; rsdev->radio_dev = radio_si4713_vdev_template;
...@@ -202,14 +192,12 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) ...@@ -202,14 +192,12 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) { if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
dev_err(&pdev->dev, "Could not register video device.\n"); dev_err(&pdev->dev, "Could not register video device.\n");
rval = -EIO; rval = -EIO;
goto put_adapter; goto unregister_v4l2_dev;
} }
dev_info(&pdev->dev, "New device successfully probed\n"); dev_info(&pdev->dev, "New device successfully probed\n");
goto exit; goto exit;
put_adapter:
i2c_put_adapter(adapter);
unregister_v4l2_dev: unregister_v4l2_dev:
v4l2_device_unregister(&rsdev->v4l2_dev); v4l2_device_unregister(&rsdev->v4l2_dev);
exit: exit:
...@@ -220,14 +208,10 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) ...@@ -220,14 +208,10 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
static int radio_si4713_pdriver_remove(struct platform_device *pdev) static int radio_si4713_pdriver_remove(struct platform_device *pdev)
{ {
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
struct v4l2_subdev, list);
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct radio_si4713_device *rsdev; struct radio_si4713_device *rsdev;
rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev); rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
video_unregister_device(&rsdev->radio_dev); video_unregister_device(&rsdev->radio_dev);
i2c_put_adapter(client->adapter);
v4l2_device_unregister(&rsdev->v4l2_dev); v4l2_device_unregister(&rsdev->v4l2_dev);
return 0; return 0;
......
...@@ -1447,6 +1447,10 @@ static int si4713_probe(struct i2c_client *client, ...@@ -1447,6 +1447,10 @@ static int si4713_probe(struct i2c_client *client,
{ {
struct si4713_device *sdev; struct si4713_device *sdev;
struct v4l2_ctrl_handler *hdl; struct v4l2_ctrl_handler *hdl;
struct si4713_platform_data *pdata = client->dev.platform_data;
struct device_node *np = client->dev.of_node;
struct radio_si4713_platform_data si4713_pdev_pdata;
struct platform_device *si4713_pdev;
int rval; int rval;
sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL); sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
...@@ -1607,8 +1611,30 @@ static int si4713_probe(struct i2c_client *client, ...@@ -1607,8 +1611,30 @@ static int si4713_probe(struct i2c_client *client,
goto free_ctrls; goto free_ctrls;
} }
if (!np && (!pdata || !pdata->is_platform_device))
return 0;
si4713_pdev = platform_device_alloc("radio-si4713", -1);
if (!si4713_pdev)
goto put_main_pdev;
si4713_pdev_pdata.subdev = client;
rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
sizeof(si4713_pdev_pdata));
if (rval)
goto put_main_pdev;
rval = platform_device_add(si4713_pdev);
if (rval)
goto put_main_pdev;
sdev->pd = si4713_pdev;
return 0; return 0;
put_main_pdev:
platform_device_put(si4713_pdev);
v4l2_device_unregister_subdev(&sdev->sd);
free_ctrls: free_ctrls:
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
exit: exit:
...@@ -1621,6 +1647,8 @@ static int si4713_remove(struct i2c_client *client) ...@@ -1621,6 +1647,8 @@ static int si4713_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct si4713_device *sdev = to_si4713_device(sd); struct si4713_device *sdev = to_si4713_device(sd);
platform_device_unregister(sdev->pd);
if (sdev->power_state) if (sdev->power_state)
si4713_set_power_state(sdev, POWER_DOWN); si4713_set_power_state(sdev, POWER_DOWN);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#ifndef SI4713_I2C_H #ifndef SI4713_I2C_H
#define SI4713_I2C_H #define SI4713_I2C_H
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
...@@ -238,6 +239,7 @@ struct si4713_device { ...@@ -238,6 +239,7 @@ struct si4713_device {
struct regulator *vdd; struct regulator *vdd;
struct regulator *vio; struct regulator *vio;
struct gpio_desc *gpio_reset; struct gpio_desc *gpio_reset;
struct platform_device *pd;
u32 power_state; u32 power_state;
u32 rds_enabled; u32 rds_enabled;
u32 frequency; u32 frequency;
...@@ -245,4 +247,8 @@ struct si4713_device { ...@@ -245,4 +247,8 @@ struct si4713_device {
u32 stereo; u32 stereo;
u32 tune_rnl; u32 tune_rnl;
}; };
struct radio_si4713_platform_data {
struct i2c_client *subdev;
};
#endif /* ifndef SI4713_I2C_H */ #endif /* ifndef SI4713_I2C_H */
/*
* include/media/radio-si4713.h
*
* Board related data definitions for Si4713 radio transmitter chip.
*
* Copyright (c) 2009 Nokia Corporation
* Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef RADIO_SI4713_H
#define RADIO_SI4713_H
#include <linux/i2c.h>
#define SI4713_NAME "radio-si4713"
/*
* Platform dependent definition
*/
struct radio_si4713_platform_data {
int i2c_bus;
struct i2c_board_info *subdev_board_info;
};
#endif /* ifndef RADIO_SI4713_H*/
...@@ -26,6 +26,7 @@ struct si4713_platform_data { ...@@ -26,6 +26,7 @@ struct si4713_platform_data {
const char * const *supply_names; const char * const *supply_names;
unsigned supplies; unsigned supplies;
int gpio_reset; /* < 0 if not used */ int gpio_reset; /* < 0 if not used */
bool is_platform_device;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment