From 98bea620c7ff301f9a7a6c31b2aca30964aa2fab Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 10 Nov 2014 17:34:41 -0300 Subject: [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: Sebastian Reichel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si4713/radio-platform-si4713.c | 28 +++++----------------- drivers/media/radio/si4713/si4713.c | 28 ++++++++++++++++++++++ drivers/media/radio/si4713/si4713.h | 6 +++++ 3 files changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers/media/radio') diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c index a47502a330f0..2de5439b9c79 100644 --- a/drivers/media/radio/si4713/radio-platform-si4713.c +++ b/drivers/media/radio/si4713/radio-platform-si4713.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include "si4713.h" /* module parameters */ 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) { struct radio_si4713_platform_data *pdata = pdev->dev.platform_data; struct radio_si4713_device *rsdev; - struct i2c_adapter *adapter; struct v4l2_subdev *sd; int rval = 0; @@ -177,20 +176,11 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) goto exit; } - adapter = i2c_get_adapter(pdata->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", - 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) { + sd = i2c_get_clientdata(pdata->subdev); + rval = v4l2_device_register_subdev(&rsdev->v4l2_dev, sd); + if (rval) { dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); - rval = -ENODEV; - goto put_adapter; + goto unregister_v4l2_dev; } rsdev->radio_dev = radio_si4713_vdev_template; @@ -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)) { dev_err(&pdev->dev, "Could not register video device.\n"); rval = -EIO; - goto put_adapter; + goto unregister_v4l2_dev; } dev_info(&pdev->dev, "New device successfully probed\n"); goto exit; -put_adapter: - i2c_put_adapter(adapter); unregister_v4l2_dev: v4l2_device_unregister(&rsdev->v4l2_dev); exit: @@ -220,14 +208,10 @@ exit: static int radio_si4713_pdriver_remove(struct platform_device *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; rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev); video_unregister_device(&rsdev->radio_dev); - i2c_put_adapter(client->adapter); v4l2_device_unregister(&rsdev->v4l2_dev); return 0; diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c index 449f6cda2938..c90004dac170 100644 --- a/drivers/media/radio/si4713/si4713.c +++ b/drivers/media/radio/si4713/si4713.c @@ -1447,6 +1447,10 @@ static int si4713_probe(struct i2c_client *client, { struct si4713_device *sdev; 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; sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL); @@ -1607,8 +1611,30 @@ static int si4713_probe(struct i2c_client *client, 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; +put_main_pdev: + platform_device_put(si4713_pdev); + v4l2_device_unregister_subdev(&sdev->sd); free_ctrls: v4l2_ctrl_handler_free(hdl); exit: @@ -1621,6 +1647,8 @@ static int si4713_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct si4713_device *sdev = to_si4713_device(sd); + platform_device_unregister(sdev->pd); + if (sdev->power_state) si4713_set_power_state(sdev, POWER_DOWN); diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h index 7c2479f42329..8a376e142188 100644 --- a/drivers/media/radio/si4713/si4713.h +++ b/drivers/media/radio/si4713/si4713.h @@ -15,6 +15,7 @@ #ifndef SI4713_I2C_H #define SI4713_I2C_H +#include #include #include #include @@ -238,6 +239,7 @@ struct si4713_device { struct regulator *vdd; struct regulator *vio; struct gpio_desc *gpio_reset; + struct platform_device *pd; u32 power_state; u32 rds_enabled; u32 frequency; @@ -245,4 +247,8 @@ struct si4713_device { u32 stereo; u32 tune_rnl; }; + +struct radio_si4713_platform_data { + struct i2c_client *subdev; +}; #endif /* ifndef SI4713_I2C_H */ -- cgit v1.2.3