media: ov2640: add device tree support
Subsystems (2)
v3 cover media: ov2640: add device tree support
This patch series add device tree support for ov2640. And also add the document for the devicetree properties.
v2->v3:
1. fix the gpiod_xxx api usage as we use reset pin as ACTIVE_LOW.
2. update the devicetree binding document.
v1 -> v2:
1. modified the dt bindings according to Laurent's suggestion.
2. add a fix patch for soc_camera. Otherwise the .reset() function won't work.
Josh Wu (5):
media: soc-camera: use icd->control instead of icd->pdev for reset()
media: ov2640: add async probe function
media: ov2640: add primary dt support
media: ov2640: add a master clock for sensor
media: ov2640: dt: add the device tree binding document
.../devicetree/bindings/media/i2c/ov2640.txt | 53 ++++++++ drivers/media/i2c/soc_camera/ov2640.c | 141 ++++++++++++++++++--- drivers/media/platform/soc_camera/soc_camera.c | 8 +- 3 files changed, 182 insertions(+), 20 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov2640.txt
Signature · 1 line
1.9.1
PATCH v3 1/5 media: soc-camera: use icd->control instead of icd->pdev for reset()
icd->control is the sub device dev, i.e. i2c device. icd->pdev is the soc camera device's device.
To be consitent with power() function, we will call reset() with icd->control as well.
---v2->v3:
1. check whether icd->control is NULL or not.
drivers/media/platform/soc_camera/soc_camera.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/media/platform/soc_camera/soc_camera.c +5 -3
@@ -688,7 +688,8 @@ static int soc_camera_open(struct file *file)/* The camera could have been already on, try to reset */ if (sdesc->subdev_desc.reset) - sdesc->subdev_desc.reset (icd->pdev); +if (icd->control) + sdesc->subdev_desc.reset (icd->control); ret =soc_camera_add_device (icd);if (ret <0 ) {
@@ -1175,7 +1176,8 @@ static void scan_add_host(struct soc_camera_host *ici)/* The camera could have been already on, try to reset */ if (ssdd->reset) - ssdd->reset (icd->pdev); +if (icd->control) + ssdd->reset (icd->control); icd->parent = ici->v4l2_dev.dev;
@@ -1461,7 +1463,7 @@ static int soc_camera_async_bound(struct v4l2_async_notifier *notifier,memcpy (&sdesc->subdev_desc, ssdd,sizeof (sdesc->subdev_desc));if (ssdd->reset) - ssdd->reset (icd->pdev); + ssdd->reset (&client->dev); } icd->control = &client->dev;
Signature · 1 line
1.9.1
PATCH v3 2/5 media: ov2640: add async probe function
In reply to Josh WuTo support async probe for ov2640, we need remove the code to get 'mclk' in ov2640_probe() function. oterwise, if soc_camera host is not probed in the moment, then we will fail to get 'mclk' and quit the ov2640_probe() function.
So in this patch, we move such 'mclk' getting code to ov2640_s_power() function. That make ov2640 survive, as we can pass a NULL (priv-clk) to soc_camera_set_power() function.
And if soc_camera host is probed, the when ov2640_s_power() is called, then we can get the 'mclk' and that make us enable/disable soc_camera host's clock as well.
---
v2 -> v3:
v1 -> v2:
no changes.
drivers/media/i2c/soc_camera/ov2640.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
drivers/media/i2c/soc_camera/ov2640.c +21 -10
@@ -739,6 +739,15 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on)struct i2c_client *client =v4l2_get_subdevdata (sd);struct soc_camera_subdev_desc *ssdd =soc_camera_i2c_to_desc (client);struct ov2640_priv *priv =to_ov2640 (client); +struct v4l2_clk *clk; + +if (!priv->clk) { + clk =v4l2_clk_get (&client->dev,"mclk" ); +if (IS_ERR (clk)) +dev_warn (&client->dev,"Cannot get the mclk. maybe soc-camera host is not probed yet.\n" ); +else + priv->clk = clk; + }return soc_camera_set_power (&client->dev, ssdd, priv->clk, on); }
@@ -1078,21 +1087,21 @@ static int ov2640_probe(struct i2c_client *client,if (priv->hdl.error)return priv->hdl.error; - priv->clk =v4l2_clk_get (&client->dev,"mclk" ); -if (IS_ERR (priv->clk)) { - ret =PTR_ERR (priv->clk); - goto eclkget; - } - ret =ov2640_video_probe (client);if (ret) { -v4l2_clk_put (priv->clk); -eclkget: -v4l2_ctrl_handler_free (&priv->hdl); + goto evideoprobe; }else {dev_info (&adapter->dev,"OV2640 Probed\n" ); } + ret =v4l2_async_register_subdev (&priv->subdev); +if (ret <0 ) + goto evideoprobe; + +return 0 ; + +evideoprobe: +v4l2_ctrl_handler_free (&priv->hdl);return ret; }
@@ -1100,7 +1109,9 @@ static int ov2640_remove(struct i2c_client *client) {struct ov2640_priv *priv =to_ov2640 (client); -v4l2_clk_put (priv->clk); +v4l2_async_unregister_subdev (&priv->subdev); +if (priv->clk) +v4l2_clk_put (priv->clk);v4l2_device_unregister_subdev (&priv->subdev);v4l2_ctrl_handler_free (&priv->hdl);return 0 ;
Signature · 1 line
1.9.1
PATCH v3 3/5 media: ov2640: add primary dt support
In reply to Josh WuAdd device tree support for ov2640.
---
v2 -> v3:
1. fix gpiod usage.
2. refine the ov2640_probe() function.
v1 -> v2:
1. use gpiod APIs.
2. change the gpio pin's name according to datasheet.
3. reduce the delay for .reset() function.
drivers/media/i2c/soc_camera/ov2640.c | 87 ++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-)
drivers/media/i2c/soc_camera/ov2640.c +81 -6
@@ -18,6 +18,8 @@#include <linux/i2c.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h>
@@ -283,6 +285,10 @@ struct ov2640_priv {u32 cfmt_code;struct v4l2_clk *clk;const struct ov2640_win_size *win; + +struct soc_camera_subdev_desc ssdd_dt; +struct gpio_desc *resetb_gpio; +struct gpio_desc *pwdn_gpio; };/*
@@ -1047,6 +1053,63 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = { .video = &ov2640_subdev_video_ops, }; +/* OF probe functions */ +static int ov2640_hw_power (struct device *dev,int on) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +dev_dbg (&client->dev,"%s: %s the camera\n" , + __func__, on ?"ENABLE" :"DISABLE" ); + +if (priv->pwdn_gpio) +gpiod_direction_output (priv->pwdn_gpio, !on); + +return 0 ; +} + +static int ov2640_hw_reset (struct device *dev) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +if (priv->resetb_gpio) { +/* Active the resetb pin to perform a reset pulse */ +gpiod_direction_output (priv->resetb_gpio,1 ); +usleep_range (3000 ,5000 ); +gpiod_direction_output (priv->resetb_gpio,0 ); + } + +return 0 ; +} + +static int ov2640_probe_dt (struct i2c_client *client, +struct ov2640_priv *priv) +{ +/* reset is not actived */ + priv->resetb_gpio =devm_gpiod_get_optional (&client->dev,"resetb" , +GPIOD_OUT_LOW ); +if (!priv->resetb_gpio) +dev_dbg (&client->dev,"resetb gpio is not assigned!\n" ); +else if (IS_ERR (priv->resetb_gpio)) +return PTR_ERR (priv->resetb_gpio); + +/* Power down actived */ + priv->pwdn_gpio =devm_gpiod_get_optional (&client->dev,"pwdn" , +GPIOD_OUT_HIGH ); +if (!priv->pwdn_gpio) +dev_dbg (&client->dev,"pwdn gpio is not assigned!\n" ); +else if (IS_ERR (priv->pwdn_gpio)) +return PTR_ERR (priv->pwdn_gpio); + +/* Initialize the soc_camera_subdev_desc */ + priv->ssdd_dt.power = ov2640_hw_power; + priv->ssdd_dt.reset = ov2640_hw_reset; + client->dev.platform_data = &priv->ssdd_dt; + +return 0 ; +} +/* * i2c_driver functions */
@@ -1058,12 +1121,6 @@ static int ov2640_probe(struct i2c_client *client,struct i2c_adapter *adapter =to_i2c_adapter (client->dev.parent);int ret; -if (!ssdd) { -dev_err (&adapter->dev, -"OV2640: Missing platform_data for driver\n" ); -return -EINVAL ; - } -if (!i2c_check_functionality (adapter,I2C_FUNC_SMBUS_BYTE_DATA )) {dev_err (&adapter->dev,"OV2640: I2C-Adapter doesn't support SMBUS\n" );
@@ -1077,6 +1134,17 @@ static int ov2640_probe(struct i2c_client *client,return -ENOMEM ; } +if (!ssdd && !client->dev.of_node) { +dev_err (&client->dev,"Missing platform_data for driver\n" ); +return -EINVAL ; + } + +if (!ssdd && client->dev.of_node) { + ret =ov2640_probe_dt (client, priv); +if (ret) +return ret; + } +v4l2_i2c_subdev_init (&priv->subdev, client, &ov2640_subdev_ops);v4l2_ctrl_handler_init (&priv->hdl,2 ); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
@@ -1123,9 +1191,16 @@ static const struct i2c_device_id ov2640_id[] = { };MODULE_DEVICE_TABLE (i2c, ov2640_id); +static const struct of_device_id ov2640_of_match[] = { + {.compatible ="ovti,ov2640" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, ov2640_of_match); +static struct i2c_driver ov2640_i2c_driver = { .driver = { .name ="ov2640" , + .of_match_table =of_match_ptr (ov2640_of_match), }, .probe = ov2640_probe, .remove = ov2640_remove,
Signature · 1 line
1.9.1
PATCH v3 3/5 media: ov2640: add primary dt support
Hi Josh,
Thank you for the patch.
I only have three minor comments. After fixing them,
Quoted 69 lines · On Thursday 11 December 2014 15:35:37 Josh Wu wrote:
Add device tree support for ov2640.
Signed-off-by Josh Wu <[email protected]>---
v2 -> v3:
1. fix gpiod usage.
2. refine theov2640_probe()function.v1 -> v2:
1. use gpiod APIs.
2. change the gpio pin's name according to datasheet.
3. reduce the delay for .reset() function.drivers/media/i2c/soc_camera/ov2640.c | 87 +++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-)(quoted diff) +0
-0
b/drivers/media/i2c/soc_camera/ov2640.cindex 9ee910d..e0bcf5b 100644drivers/media/i2c/soc_camera/ov2640.c +30
-0@@ -18,6 +18,8 @@#include <linux/i2c.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> @@ -283,6 +285,10 @@ struct ov2640_priv {u32 cfmt_code;struct v4l2_clk *clk;const struct ov2640_win_size *win; + +struct soc_camera_subdev_desc ssdd_dt; +struct gpio_desc *resetb_gpio; +struct gpio_desc *pwdn_gpio; };/* @@ -1047,6 +1053,63 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = { .video = &ov2640_subdev_video_ops, }; +/* OF probe functions */ +static int ov2640_hw_power (struct device *dev,int on) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +dev_dbg (&client->dev,"%s: %s the camera\n" , + __func__, on ?"ENABLE" :"DISABLE" ); + +if (priv->pwdn_gpio) +gpiod_direction_output (priv->pwdn_gpio, !on); + +return 0 ; +} + +static int ov2640_hw_reset (struct device *dev) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +if (priv->resetb_gpio) { +/* Active the resetb pin to perform a reset pulse */ +gpiod_direction_output (priv->resetb_gpio,1 ); +usleep_range (3000 ,5000 );
drivers/media/i2c/soc_camera/ov2640.c static struct v4l2_subdev_ops ov2640_subdev_ops = { · line 1089
Quoted 10 lines
drivers/media/i2c/soc_camera/ov2640.c +10
-0+gpiod_direction_output (priv->resetb_gpio,0 ); + } + +return 0 ; +} + +static int ov2640_probe_dt (struct i2c_client *client, +struct ov2640_priv *priv) +{ +/* reset is not actived */
Do you mean that you configure the reset signal as inactive ? I would state that as "Request the reset GPIO deasserted".
drivers/media/i2c/soc_camera/ov2640.c static struct v4l2_subdev_ops ov2640_subdev_ops = { · line 1097
Quoted 8 lines
drivers/media/i2c/soc_camera/ov2640.c +8
-0+ priv->resetb_gpio =devm_gpiod_get_optional (&client->dev,"resetb" , +GPIOD_OUT_LOW ); +if (!priv->resetb_gpio) +dev_dbg (&client->dev,"resetb gpio is not assigned!\n" ); +else if (IS_ERR (priv->resetb_gpio)) +return PTR_ERR (priv->resetb_gpio); + +/* Power down actived */
And "Request the power down GPIO asserted".
Quoted 32 lines
drivers/media/i2c/soc_camera/ov2640.c +15
-6+ priv->pwdn_gpio =devm_gpiod_get_optional (&client->dev,"pwdn" , +GPIOD_OUT_HIGH ); +if (!priv->pwdn_gpio) +dev_dbg (&client->dev,"pwdn gpio is not assigned!\n" ); +else if (IS_ERR (priv->pwdn_gpio)) +return PTR_ERR (priv->pwdn_gpio); + +/* Initialize the soc_camera_subdev_desc */ + priv->ssdd_dt.power = ov2640_hw_power; + priv->ssdd_dt.reset = ov2640_hw_reset; + client->dev.platform_data = &priv->ssdd_dt; + +return 0 ; +} +/* * i2c_driver functions */ @@ -1058,12 +1121,6 @@ static int ov2640_probe(struct i2c_client *client,struct i2c_adapter *adapter =to_i2c_adapter (client->dev.parent);int ret; -if (!ssdd) { -dev_err (&adapter->dev, -"OV2640: Missing platform_data for driver\n" ); -return -EINVAL ; - } -if (!i2c_check_functionality (adapter,I2C_FUNC_SMBUS_BYTE_DATA )) {dev_err (&adapter->dev,"OV2640: I2C-Adapter doesn't support SMBUS\n" );
drivers/media/i2c/soc_camera/ov2640.c static int ov2640_probe(struct i2c_client *client, · line 1142
Quoted 9 lines
drivers/media/i2c/soc_camera/ov2640.c +6
-0@@ -1077,6 +1134,17 @@ static int ov2640_probe(struct i2c_client *client,return -ENOMEM ; } +if (!ssdd && !client->dev.of_node) { +dev_err (&client->dev,"Missing platform_data for driver\n" ); +return -EINVAL ; + } + +if (!ssdd && client->dev.of_node) {
You can just test for !ssdd as you've tested client->dev.of_node above already.
Quoted 25 lines
drivers/media/i2c/soc_camera/ov2640.c +12
-0+ ret =ov2640_probe_dt (client, priv); +if (ret) +return ret; + } +v4l2_i2c_subdev_init (&priv->subdev, client, &ov2640_subdev_ops);v4l2_ctrl_handler_init (&priv->hdl,2 ); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,@@ -1123,9 +1191,16 @@ static const struct i2c_device_id ov2640_id[] = { };MODULE_DEVICE_TABLE (i2c, ov2640_id); +static const struct of_device_id ov2640_of_match[] = { + {.compatible ="ovti,ov2640" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, ov2640_of_match); +static struct i2c_driver ov2640_i2c_driver = { .driver = { .name ="ov2640" , + .of_match_table =of_match_ptr (ov2640_of_match), }, .probe = ov2640_probe, .remove = ov2640_remove,
Signature · 3 lines
Regards, Laurent Pinchart
PATCH v3 3/5 media: ov2640: add primary dt support
Hi, Laurent
Quoted 7 lines · Laurent Pinchart
Hi Josh,
Thank you for the patch.
I only have three minor comments. After fixing them,
Acked-by Laurent Pinchart <[email protected]>
Thanks for the review.
Quoted 75 lines · On Thursday 11 December 2014 15:35:37 Josh Wu wrote:
Quoted 73 lines
Add device tree support for ov2640.
Cc devicetree at vger.kernel.orgSigned-off-by Josh Wu <[email protected]>---
v2 -> v3:
1. fix gpiod usage.
2. refine theov2640_probe()function.v1 -> v2:
1. use gpiod APIs.
2. change the gpio pin's name according to datasheet.
3. reduce the delay for .reset() function.drivers/media/i2c/soc_camera/ov2640.c | 87 +++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-)(quoted diff) +0
-0
b/drivers/media/i2c/soc_camera/ov2640.cindex 9ee910d..e0bcf5b 100644drivers/media/i2c/soc_camera/ov2640.c +34
-0@@ -18,6 +18,8 @@#include <linux/i2c.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> @@ -283,6 +285,10 @@ struct ov2640_priv {u32 cfmt_code;struct v4l2_clk *clk;const struct ov2640_win_size *win; + +struct soc_camera_subdev_desc ssdd_dt; +struct gpio_desc *resetb_gpio; +struct gpio_desc *pwdn_gpio; };/* @@ -1047,6 +1053,63 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = { .video = &ov2640_subdev_video_ops, }; +/* OF probe functions */ +static int ov2640_hw_power (struct device *dev,int on) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +dev_dbg (&client->dev,"%s: %s the camera\n" , + __func__, on ?"ENABLE" :"DISABLE" ); + +if (priv->pwdn_gpio) +gpiod_direction_output (priv->pwdn_gpio, !on); + +return 0 ; +} + +static int ov2640_hw_reset (struct device *dev) +{ +struct i2c_client *client =to_i2c_client (dev); +struct ov2640_priv *priv =to_ov2640 (client); + +if (priv->resetb_gpio) { +/* Active the resetb pin to perform a reset pulse */ +gpiod_direction_output (priv->resetb_gpio,1 ); +usleep_range (3000 ,5000 ); +gpiod_direction_output (priv->resetb_gpio,0 ); + } + +return 0 ;
Quoted 8 lines
drivers/media/i2c/soc_camera/ov2640.c static struct v4l2_subdev_ops ov2640_subdev_ops = { · line 1089
Quoted 6 lines
drivers/media/i2c/soc_camera/ov2640.c +6
-0+} + +static int ov2640_probe_dt (struct i2c_client *client, +struct ov2640_priv *priv) +{ +/* reset is not actived */ Do you mean that you configure the reset signal as inactive ? I would state that as "Request the reset GPIO deasserted".
yes, exactly. I'll take your sentence. thanks.
Quoted 10 lines
drivers/media/i2c/soc_camera/ov2640.c static struct v4l2_subdev_ops ov2640_subdev_ops = { · line 1097
Quoted 9 lines
drivers/media/i2c/soc_camera/ov2640.c +8
-0+ priv->resetb_gpio =devm_gpiod_get_optional (&client->dev,"resetb" , +GPIOD_OUT_LOW ); +if (!priv->resetb_gpio) +dev_dbg (&client->dev,"resetb gpio is not assigned!\n" ); +else if (IS_ERR (priv->resetb_gpio)) +return PTR_ERR (priv->resetb_gpio); + +/* Power down actived */ And "Request the power down GPIO asserted".
ditto.
Quoted 36 lines
Quoted 36 lines
drivers/media/i2c/soc_camera/ov2640.c +15
-6+ priv->pwdn_gpio =devm_gpiod_get_optional (&client->dev,"pwdn" , +GPIOD_OUT_HIGH ); +if (!priv->pwdn_gpio) +dev_dbg (&client->dev,"pwdn gpio is not assigned!\n" ); +else if (IS_ERR (priv->pwdn_gpio)) +return PTR_ERR (priv->pwdn_gpio); + +/* Initialize the soc_camera_subdev_desc */ + priv->ssdd_dt.power = ov2640_hw_power; + priv->ssdd_dt.reset = ov2640_hw_reset; + client->dev.platform_data = &priv->ssdd_dt; + +return 0 ; +} +/* * i2c_driver functions */ @@ -1058,12 +1121,6 @@ static int ov2640_probe(struct i2c_client *client,struct i2c_adapter *adapter =to_i2c_adapter (client->dev.parent);int ret; -if (!ssdd) { -dev_err (&adapter->dev, -"OV2640: Missing platform_data for driver\n" ); -return -EINVAL ; - } -if (!i2c_check_functionality (adapter,I2C_FUNC_SMBUS_BYTE_DATA )) {dev_err (&adapter->dev,"OV2640: I2C-Adapter doesn't support SMBUS\n" );@@ -1077,6 +1134,17 @@ static int ov2640_probe(struct i2c_client *client,return -ENOMEM ; }
Quoted 8 lines
drivers/media/i2c/soc_camera/ov2640.c static int ov2640_probe(struct i2c_client *client, · line 1142
Quoted 6 lines
drivers/media/i2c/soc_camera/ov2640.c +6
-0+if (!ssdd && !client->dev.of_node) { +dev_err (&client->dev,"Missing platform_data for driver\n" ); +return -EINVAL ; + } + +if (!ssdd && client->dev.of_node) {You can just test for !ssdd as you've tested
client->dev.of_nodeabove already.
Right, thanks.
Best Regards,
Josh Wu
Quoted 26 lines
Quoted 26 lines
drivers/media/i2c/soc_camera/ov2640.c +12
-0+ ret =ov2640_probe_dt (client, priv); +if (ret) +return ret; + } +v4l2_i2c_subdev_init (&priv->subdev, client, &ov2640_subdev_ops);v4l2_ctrl_handler_init (&priv->hdl,2 ); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,@@ -1123,9 +1191,16 @@ static const struct i2c_device_id ov2640_id[] = { };MODULE_DEVICE_TABLE (i2c, ov2640_id); +static const struct of_device_id ov2640_of_match[] = { + {.compatible ="ovti,ov2640" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, ov2640_of_match); +static struct i2c_driver ov2640_i2c_driver = { .driver = { .name ="ov2640" , + .of_match_table =of_match_ptr (ov2640_of_match), }, .probe = ov2640_probe, .remove = ov2640_remove,
PATCH v3 4/5 media: ov2640: add a master clock for sensor
In reply to Josh WuThe master clock (xvclk) is mandatory. It's a common clock framework clock. It can make sensor output a pixel clock to the camera interface.
---
v2 -> v3:
1. should return PTR_ERR().
v1 -> v2:
1. change the clock's name.
2. Make the clock is mandatory.
drivers/media/i2c/soc_camera/ov2640.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
drivers/media/i2c/soc_camera/ov2640.c +22 -1
@@ -13,6 +13,7 @@* published by the Free Software Foundation. */ +#include <linux/clk.h> #include <linux/init.h> #include <linux/module.h> #include <linux/i2c.h>
@@ -31,6 +32,7 @@#define VAL_SET (x, mask, rshift, lshift) \ ((((x) >> rshift) & mask) << lshift) +/* * DSP registers * register offset for BANK_SEL == BANK_SEL_DSP
@@ -284,6 +286,7 @@ struct ov2640_priv {struct v4l2_ctrl_handler hdl;u32 cfmt_code;struct v4l2_clk *clk; +struct clk *master_clk;const struct ov2640_win_size *win;struct soc_camera_subdev_desc ssdd_dt;
@@ -746,6 +749,7 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on)struct soc_camera_subdev_desc *ssdd =soc_camera_i2c_to_desc (client);struct ov2640_priv *priv =to_ov2640 (client);struct v4l2_clk *clk; +int ret;if (!priv->clk) { clk =v4l2_clk_get (&client->dev,"mclk" );
@@ -755,7 +759,20 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) priv->clk = clk; } -return soc_camera_set_power (&client->dev, ssdd, priv->clk, on); +if (on) { + ret =clk_prepare_enable (priv->master_clk); +if (ret) +return ret; + }else { +clk_disable_unprepare (priv->master_clk); + } + + ret =soc_camera_set_power (&client->dev, ssdd, priv->clk, on); + +if (ret && on) +clk_disable_unprepare (priv->master_clk); + +return ret; }/* Select the nearest higher resolution for capture */
@@ -1145,6 +1162,10 @@ static int ov2640_probe(struct i2c_client *client,return ret; } + priv->master_clk =devm_clk_get (&client->dev,"xvclk" ); +if (IS_ERR (priv->master_clk)) +return PTR_ERR (priv->master_clk); +v4l2_i2c_subdev_init (&priv->subdev, client, &ov2640_subdev_ops);v4l2_ctrl_handler_init (&priv->hdl,2 ); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
Signature · 1 line
1.9.1
PATCH v3 4/5 media: ov2640: add a master clock for sensor
Hi Josh,
Thank you for the patch.
Quoted 5 lines · On Thursday 11 December 2014 15:35:38 Josh Wu wrote:
The master clock (xvclk) is mandatory. It's a common clock framework clock. It can make sensor output a pixel clock to the camera interface.
Signed-off-by Josh Wu <[email protected]>
Quoted 80 lines
---
v2 -> v3:
1. should returnPTR_ERR().v1 -> v2:
1. change the clock's name.
2. Make the clock is mandatory.drivers/media/i2c/soc_camera/ov2640.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/media/i2c/soc_camera/ov2640.cindex e0bcf5b..055702c 100644drivers/media/i2c/soc_camera/ov2640.c +22
-1@@ -13,6 +13,7 @@* published by the Free Software Foundation. */ +#include <linux/clk.h> #include <linux/init.h> #include <linux/module.h> #include <linux/i2c.h> @@ -31,6 +32,7 @@#define VAL_SET (x, mask, rshift, lshift) \ ((((x) >> rshift) & mask) << lshift) +/* * DSP registers * register offset for BANK_SEL == BANK_SEL_DSP @@ -284,6 +286,7 @@ struct ov2640_priv {struct v4l2_ctrl_handler hdl;u32 cfmt_code;struct v4l2_clk *clk; +struct clk *master_clk;const struct ov2640_win_size *win;struct soc_camera_subdev_desc ssdd_dt;@@ -746,6 +749,7 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);struct ov2640_priv *priv =to_ov2640 (client);struct v4l2_clk *clk; +int ret;if (!priv->clk) { clk =v4l2_clk_get (&client->dev,"mclk" );@@ -755,7 +759,20 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) priv->clk = clk; } -return soc_camera_set_power (&client->dev, ssdd, priv->clk, on); +if (on) { + ret =clk_prepare_enable (priv->master_clk); +if (ret) +return ret; + }else { +clk_disable_unprepare (priv->master_clk); + } + + ret =soc_camera_set_power (&client->dev, ssdd, priv->clk, on); + +if (ret && on) +clk_disable_unprepare (priv->master_clk); + +return ret; }/* Select the nearest higher resolution for capture */ @@ -1145,6 +1162,10 @@ static int ov2640_probe(struct i2c_client *client,return ret; } + priv->master_clk =devm_clk_get (&client->dev,"xvclk" ); +if (IS_ERR (priv->master_clk)) +return PTR_ERR (priv->master_clk); +v4l2_i2c_subdev_init (&priv->subdev, client, &ov2640_subdev_ops);v4l2_ctrl_handler_init (&priv->hdl,2 ); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
Signature · 3 lines
Regards, Laurent Pinchart
PATCH v3 5/5 media: ov2640: dt: add the device tree binding document
In reply to Josh WuAdd the document for ov2640 dt.
---
v2 -> v3:
1. fix incorrect description.
2. Add assigned-clocks & assigned-clock-rates.
3. resetb pin should be ACTIVE_LOW.
v1 -> v2:
1. change the compatible string to be consistent with verdor file.
2. change the clock and pins' name.
3. add missed pinctrl in example.
.../devicetree/bindings/media/i2c/ov2640.txt | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov2640.txt
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +53 -0
@@ -0,0 +1,53 @@ +* Omnivision ov2640 CMOS sensor + +The Omnivision OV2640 sensor support multiple resolutions output, such as +CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB +output format. + +Required Properties: +- compatible: Must be "ovti,ov2640" +- clocks: reference to the xvclk input clock. It can be an external fixed + clock or a programmable clock from SoC. +- clock-names: Must be "xvclk". +- assigned-clocks: reference to the above 'clocks' property. +- assigned-clock-rates: reference to the clock frequency of xvclk. Typical + value is 25Mhz (25000000). + This clock should only have single user. Specifying + Conflicting rate configuration in multiple consumer + nodes for a shared clock is forbidden. + +Optional Properties: +- resetb-gpios: reference to the GPIO connected to the resetb pin, if any. +- pwdn-gpios: reference to the GPIO connected to the pwdn pin, if any. + +The device node must contain one 'port' child node for its digital output +video port, in accordance with the video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + i2c1: i2c at f0018000 { + ov2640: camera at 0x30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn &pinctrl_ov2640_resetb>; + + resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>; + + clocks = <&pck1>; + clock-names = "xvclk"; + + assigned-clocks = <&pck1>; + assigned-clock-rates = <25000000>; + + port { + ov2640_0: endpoint { + remote-endpoint = <&isi_0>; + bus-width = <8>; + }; + }; + }; + };
Signature · 1 line
1.9.1
PATCH v3 5/5 media: ov2640: dt: add the device tree binding document
Hi Josh,
Thank you for the patch.
Quoted 26 lines · On Thursday 11 December 2014 15:35:39 Josh Wu wrote:
Add the document for ov2640 dt.
Signed-off-by Josh Wu <[email protected]>---
v2 -> v3:
1. fix incorrect description.
2. Add assigned-clocks & assigned-clock-rates.
3. resetb pin should beACTIVE_LOW.v1 -> v2:
1. change the compatible string to be consistent with verdor file.
2. change the clock and pins' name.
3. add missed pinctrl in example..../devicetree/bindings/media/i2c/ov2640.txt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov2640.txt(quoted diff) +0
-0
b/Documentation/devicetree/bindings/media/i2c/ov2640.txtnew file mode 100644
index 0000000..958e120
Documentation/devicetree/bindings/media/i2c/ov2640.txt line 10
Quoted 10 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +10
-0@@ -0,0 +1,53 @@ +* Omnivision ov2640 CMOS sensor + +The Omnivision OV2640 sensor support multiple resolutions output, such as +CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB +output format. + +Required Properties: +- compatible: Must be "ovti,ov2640" +- clocks: reference to the xvclk input clock. It can be an external fixed + clock or a programmable clock from SoC.
It could also be a variable clock provided by something else. I would just drop the second sentence.
Quoted 8 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +6
-0+- clock-names: Must be "xvclk". +- assigned-clocks: reference to the above 'clocks' property. +- assigned-clock-rates: reference to the clock frequency of xvclk. Typical + value is 25Mhz (25000000). + This clock should only have single user. Specifying + Conflicting rate configuration in multipleconsumer
+ nodes for a shared clock is forbidden.
Those two properties are optional. I'm not sure they should even be mentioned in the ov2640 bindings. For one thing they're not needed if the clock doesn't need to be forced to a specific frequency, and the clock rate could also be configured through other means depending on the platform.
Quoted 8 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +8
-0+ +Optional Properties: +- resetb-gpios: reference to the GPIO connected to the resetb pin, if any. +- pwdn-gpios: reference to the GPIO connected to the pwdn pin, if any. + +The device node must contain one 'port' child node for its digital output +video port, in accordance with the video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt.
Documentation/devicetree/bindings/media/i2c/ov2640.txt
Quoted 10 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +10
-0+ +Example: + + i2c1: i2c@f0018000 { + ov2640: camera@0x30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn
&pinctrl_ov2640_resetb>;
Quoted 18 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +18
-0+ + resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>; + + clocks = <&pck1>; + clock-names = "xvclk"; + + assigned-clocks = <&pck1>; + assigned-clock-rates = <25000000>; + + port { + ov2640_0: endpoint { + remote-endpoint = <&isi_0>; + bus-width = <8>; + }; + }; + }; + };
Signature · 3 lines
Regards, Laurent Pinchart
PATCH v3 5/5 media: ov2640: dt: add the device tree binding document
Hi, Laurent
Quoted 35 lines · Laurent Pinchart
Hi Josh,
Thank you for the patch.
Quoted 30 lines · On Thursday 11 December 2014 15:35:39 Josh Wu wrote:
Add the document for ov2640 dt.
Cc devicetree at vger.kernel.orgSigned-off-by Josh Wu <[email protected]>---
v2 -> v3:
1. fix incorrect description.
2. Add assigned-clocks & assigned-clock-rates.
3. resetb pin should beACTIVE_LOW.v1 -> v2:
1. change the compatible string to be consistent with verdor file.
2. change the clock and pins' name.
3. add missed pinctrl in example..../devicetree/bindings/media/i2c/ov2640.txt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+)create mode 100644
Documentation/devicetree/bindings/media/i2c/ov2640.txt(quoted diff) +0
-0
b/Documentation/devicetree/bindings/media/i2c/ov2640.txtnew file mode 100644
index 0000000..958e120Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +4
-0@@ -0,0 +1,53 @@ +* Omnivision ov2640 CMOS sensor + +The Omnivision OV2640 sensor support multiple resolutions output, such as +CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB
Quoted 8 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt line 10
Quoted 6 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +6
-0+output format. + +Required Properties: +- compatible: Must be "ovti,ov2640" +- clocks: reference to the xvclk input clock. It can be an external fixed + clock or a programmable clock from SoC.It could also be a variable clock provided by something else. I would just drop the second sentence.
I mention this since these are the cases in at91 platform. Sure. I'll drop it.
Quoted 9 lines
Quoted 9 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +6
-0+- clock-names: Must be "xvclk". +- assigned-clocks: reference to the above 'clocks' property. +- assigned-clock-rates: reference to the clock frequency of xvclk. Typical + value is 25Mhz (25000000). + This clock should only have single user. Specifying + Conflicting rate configuration in multipleconsumer
+ nodes for a shared clock is forbidden.
Quoted 4 lines
Those two properties are optional. I'm not sure they should even be mentioned in the ov2640 bindings. For one thing they're not needed if the clock doesn't need to be forced to a specific frequency, and the clock rate could also be configured through other means depending on the platform.
hmm, if the clock is fixed then this 'assigned-clock-rates' is not needed. And I only find one binding document mentioned the assigned-clocks. It looks like a general property for all clocks. We don't need mention it repeatedly.
So I'd like to drop this two properties in next version.
Thanks and Best Regards,
Josh Wu
Quoted 38 lines
Quoted 9 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +8
-0+ +Optional Properties: +- resetb-gpios: reference to the GPIO connected to the resetb pin, if any. +- pwdn-gpios: reference to the GPIO connected to the pwdn pin, if any. + +The device node must contain one 'port' child node for its digital output +video port, in accordance with the video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt.Documentation/devicetree/bindings/media/i2c/ov2640.txt
Quoted 10 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +10
-0+ +Example: + + i2c1: i2c at f0018000 { + ov2640: camera at 0x30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn
&pinctrl_ov2640_resetb>;Quoted 18 lines
Documentation/devicetree/bindings/media/i2c/ov2640.txt new file +18
-0+ + resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>; + + clocks = <&pck1>; + clock-names = "xvclk"; + + assigned-clocks = <&pck1>; + assigned-clock-rates = <25000000>; + + port { + ov2640_0: endpoint { + remote-endpoint = <&isi_0>; + bus-width = <8>; + }; + }; + }; + };