diff options
-rw-r--r-- | drivers/media/i2c/soc_camera/imx074.c | 18 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m001.c | 17 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m111.c | 20 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t031.c | 19 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t112.c | 25 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c | 17 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov2640.c | 19 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov5642.c | 20 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov6650.c | 17 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov772x.c | 15 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.c | 17 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.h | 1 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9740.c | 18 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/rj54n1cb0c.c | 17 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/tw9910.c | 24 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera.c | 162 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera_platform.c | 2 | ||||
-rw-r--r-- | include/media/soc_camera.h | 13 |
18 files changed, 362 insertions, 79 deletions
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index a315d4386c8e..2d8367891801 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | 19 | ||
20 | #include <media/soc_camera.h> | 20 | #include <media/soc_camera.h> |
21 | #include <media/v4l2-clk.h> | ||
21 | #include <media/v4l2-subdev.h> | 22 | #include <media/v4l2-subdev.h> |
22 | 23 | ||
23 | /* IMX074 registers */ | 24 | /* IMX074 registers */ |
@@ -76,6 +77,7 @@ struct imx074_datafmt { | |||
76 | struct imx074 { | 77 | struct imx074 { |
77 | struct v4l2_subdev subdev; | 78 | struct v4l2_subdev subdev; |
78 | const struct imx074_datafmt *fmt; | 79 | const struct imx074_datafmt *fmt; |
80 | struct v4l2_clk *clk; | ||
79 | }; | 81 | }; |
80 | 82 | ||
81 | static const struct imx074_datafmt imx074_colour_fmts[] = { | 83 | static const struct imx074_datafmt imx074_colour_fmts[] = { |
@@ -254,8 +256,9 @@ static int imx074_s_power(struct v4l2_subdev *sd, int on) | |||
254 | { | 256 | { |
255 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 257 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
256 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 258 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
259 | struct imx074 *priv = to_imx074(client); | ||
257 | 260 | ||
258 | return soc_camera_set_power(&client->dev, ssdd, on); | 261 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
259 | } | 262 | } |
260 | 263 | ||
261 | static int imx074_g_mbus_config(struct v4l2_subdev *sd, | 264 | static int imx074_g_mbus_config(struct v4l2_subdev *sd, |
@@ -412,6 +415,7 @@ static int imx074_probe(struct i2c_client *client, | |||
412 | struct imx074 *priv; | 415 | struct imx074 *priv; |
413 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 416 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
414 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 417 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
418 | int ret; | ||
415 | 419 | ||
416 | if (!ssdd) { | 420 | if (!ssdd) { |
417 | dev_err(&client->dev, "IMX074: missing platform data!\n"); | 421 | dev_err(&client->dev, "IMX074: missing platform data!\n"); |
@@ -432,13 +436,23 @@ static int imx074_probe(struct i2c_client *client, | |||
432 | 436 | ||
433 | priv->fmt = &imx074_colour_fmts[0]; | 437 | priv->fmt = &imx074_colour_fmts[0]; |
434 | 438 | ||
435 | return imx074_video_probe(client); | 439 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); |
440 | if (IS_ERR(priv->clk)) | ||
441 | return PTR_ERR(priv->clk); | ||
442 | |||
443 | ret = imx074_video_probe(client); | ||
444 | if (ret < 0) | ||
445 | v4l2_clk_put(priv->clk); | ||
446 | |||
447 | return ret; | ||
436 | } | 448 | } |
437 | 449 | ||
438 | static int imx074_remove(struct i2c_client *client) | 450 | static int imx074_remove(struct i2c_client *client) |
439 | { | 451 | { |
440 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 452 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
453 | struct imx074 *priv = to_imx074(client); | ||
441 | 454 | ||
455 | v4l2_clk_put(priv->clk); | ||
442 | if (ssdd->free_bus) | 456 | if (ssdd->free_bus) |
443 | ssdd->free_bus(ssdd); | 457 | ssdd->free_bus(ssdd); |
444 | 458 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 3f1f437ee1c6..df97033fa6ef 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <media/soc_camera.h> | 17 | #include <media/soc_camera.h> |
18 | #include <media/soc_mediabus.h> | 18 | #include <media/soc_mediabus.h> |
19 | #include <media/v4l2-clk.h> | ||
19 | #include <media/v4l2-subdev.h> | 20 | #include <media/v4l2-subdev.h> |
20 | #include <media/v4l2-ctrls.h> | 21 | #include <media/v4l2-ctrls.h> |
21 | 22 | ||
@@ -93,6 +94,7 @@ struct mt9m001 { | |||
93 | struct v4l2_ctrl *exposure; | 94 | struct v4l2_ctrl *exposure; |
94 | }; | 95 | }; |
95 | struct v4l2_rect rect; /* Sensor window */ | 96 | struct v4l2_rect rect; /* Sensor window */ |
97 | struct v4l2_clk *clk; | ||
96 | const struct mt9m001_datafmt *fmt; | 98 | const struct mt9m001_datafmt *fmt; |
97 | const struct mt9m001_datafmt *fmts; | 99 | const struct mt9m001_datafmt *fmts; |
98 | int num_fmts; | 100 | int num_fmts; |
@@ -355,8 +357,9 @@ static int mt9m001_s_power(struct v4l2_subdev *sd, int on) | |||
355 | { | 357 | { |
356 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 358 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
357 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 359 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
360 | struct mt9m001 *mt9m001 = to_mt9m001(client); | ||
358 | 361 | ||
359 | return soc_camera_set_power(&client->dev, ssdd, on); | 362 | return soc_camera_set_power(&client->dev, ssdd, mt9m001->clk, on); |
360 | } | 363 | } |
361 | 364 | ||
362 | static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 365 | static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
@@ -681,9 +684,18 @@ static int mt9m001_probe(struct i2c_client *client, | |||
681 | mt9m001->rect.width = MT9M001_MAX_WIDTH; | 684 | mt9m001->rect.width = MT9M001_MAX_WIDTH; |
682 | mt9m001->rect.height = MT9M001_MAX_HEIGHT; | 685 | mt9m001->rect.height = MT9M001_MAX_HEIGHT; |
683 | 686 | ||
687 | mt9m001->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
688 | if (IS_ERR(mt9m001->clk)) { | ||
689 | ret = PTR_ERR(mt9m001->clk); | ||
690 | goto eclkget; | ||
691 | } | ||
692 | |||
684 | ret = mt9m001_video_probe(ssdd, client); | 693 | ret = mt9m001_video_probe(ssdd, client); |
685 | if (ret) | 694 | if (ret) { |
695 | v4l2_clk_put(mt9m001->clk); | ||
696 | eclkget: | ||
686 | v4l2_ctrl_handler_free(&mt9m001->hdl); | 697 | v4l2_ctrl_handler_free(&mt9m001->hdl); |
698 | } | ||
687 | 699 | ||
688 | return ret; | 700 | return ret; |
689 | } | 701 | } |
@@ -693,6 +705,7 @@ static int mt9m001_remove(struct i2c_client *client) | |||
693 | struct mt9m001 *mt9m001 = to_mt9m001(client); | 705 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
694 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 706 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
695 | 707 | ||
708 | v4l2_clk_put(mt9m001->clk); | ||
696 | v4l2_device_unregister_subdev(&mt9m001->subdev); | 709 | v4l2_device_unregister_subdev(&mt9m001->subdev); |
697 | v4l2_ctrl_handler_free(&mt9m001->hdl); | 710 | v4l2_ctrl_handler_free(&mt9m001->hdl); |
698 | mt9m001_video_remove(ssdd); | 711 | mt9m001_video_remove(ssdd); |
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index 1aaca0423df7..de3605df47c5 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | ||
19 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
20 | #include <media/v4l2-clk.h> | ||
20 | #include <media/v4l2-common.h> | 21 | #include <media/v4l2-common.h> |
21 | #include <media/v4l2-ctrls.h> | 22 | #include <media/v4l2-ctrls.h> |
22 | 23 | ||
@@ -206,6 +207,7 @@ struct mt9m111 { | |||
206 | struct v4l2_ctrl *gain; | 207 | struct v4l2_ctrl *gain; |
207 | struct mt9m111_context *ctx; | 208 | struct mt9m111_context *ctx; |
208 | struct v4l2_rect rect; /* cropping rectangle */ | 209 | struct v4l2_rect rect; /* cropping rectangle */ |
210 | struct v4l2_clk *clk; | ||
209 | int width; /* output */ | 211 | int width; /* output */ |
210 | int height; /* sizes */ | 212 | int height; /* sizes */ |
211 | struct mutex power_lock; /* lock to protect power_count */ | 213 | struct mutex power_lock; /* lock to protect power_count */ |
@@ -775,14 +777,14 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111) | |||
775 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 777 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
776 | int ret; | 778 | int ret; |
777 | 779 | ||
778 | ret = soc_camera_power_on(&client->dev, ssdd); | 780 | ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk); |
779 | if (ret < 0) | 781 | if (ret < 0) |
780 | return ret; | 782 | return ret; |
781 | 783 | ||
782 | ret = mt9m111_resume(mt9m111); | 784 | ret = mt9m111_resume(mt9m111); |
783 | if (ret < 0) { | 785 | if (ret < 0) { |
784 | dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); | 786 | dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); |
785 | soc_camera_power_off(&client->dev, ssdd); | 787 | soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); |
786 | } | 788 | } |
787 | 789 | ||
788 | return ret; | 790 | return ret; |
@@ -794,7 +796,7 @@ static void mt9m111_power_off(struct mt9m111 *mt9m111) | |||
794 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 796 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
795 | 797 | ||
796 | mt9m111_suspend(mt9m111); | 798 | mt9m111_suspend(mt9m111); |
797 | soc_camera_power_off(&client->dev, ssdd); | 799 | soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); |
798 | } | 800 | } |
799 | 801 | ||
800 | static int mt9m111_s_power(struct v4l2_subdev *sd, int on) | 802 | static int mt9m111_s_power(struct v4l2_subdev *sd, int on) |
@@ -973,9 +975,18 @@ static int mt9m111_probe(struct i2c_client *client, | |||
973 | mt9m111->lastpage = -1; | 975 | mt9m111->lastpage = -1; |
974 | mutex_init(&mt9m111->power_lock); | 976 | mutex_init(&mt9m111->power_lock); |
975 | 977 | ||
978 | mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
979 | if (IS_ERR(mt9m111->clk)) { | ||
980 | ret = PTR_ERR(mt9m111->clk); | ||
981 | goto eclkget; | ||
982 | } | ||
983 | |||
976 | ret = mt9m111_video_probe(client); | 984 | ret = mt9m111_video_probe(client); |
977 | if (ret) | 985 | if (ret) { |
986 | v4l2_clk_put(mt9m111->clk); | ||
987 | eclkget: | ||
978 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 988 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
989 | } | ||
979 | 990 | ||
980 | return ret; | 991 | return ret; |
981 | } | 992 | } |
@@ -984,6 +995,7 @@ static int mt9m111_remove(struct i2c_client *client) | |||
984 | { | 995 | { |
985 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 996 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
986 | 997 | ||
998 | v4l2_clk_put(mt9m111->clk); | ||
987 | v4l2_device_unregister_subdev(&mt9m111->subdev); | 999 | v4l2_device_unregister_subdev(&mt9m111->subdev); |
988 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 1000 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
989 | 1001 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index b3dfeb6d1037..47d18d0bafe7 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | 19 | ||
20 | #include <media/soc_camera.h> | 20 | #include <media/soc_camera.h> |
21 | #include <media/v4l2-clk.h> | ||
21 | #include <media/v4l2-subdev.h> | 22 | #include <media/v4l2-subdev.h> |
22 | #include <media/v4l2-ctrls.h> | 23 | #include <media/v4l2-ctrls.h> |
23 | 24 | ||
@@ -75,6 +76,7 @@ struct mt9t031 { | |||
75 | struct v4l2_ctrl *exposure; | 76 | struct v4l2_ctrl *exposure; |
76 | }; | 77 | }; |
77 | struct v4l2_rect rect; /* Sensor window */ | 78 | struct v4l2_rect rect; /* Sensor window */ |
79 | struct v4l2_clk *clk; | ||
78 | u16 xskip; | 80 | u16 xskip; |
79 | u16 yskip; | 81 | u16 yskip; |
80 | unsigned int total_h; | 82 | unsigned int total_h; |
@@ -585,16 +587,17 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on) | |||
585 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 587 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
586 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 588 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
587 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | 589 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); |
590 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
588 | int ret; | 591 | int ret; |
589 | 592 | ||
590 | if (on) { | 593 | if (on) { |
591 | ret = soc_camera_power_on(&client->dev, ssdd); | 594 | ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); |
592 | if (ret < 0) | 595 | if (ret < 0) |
593 | return ret; | 596 | return ret; |
594 | vdev->dev.type = &mt9t031_dev_type; | 597 | vdev->dev.type = &mt9t031_dev_type; |
595 | } else { | 598 | } else { |
596 | vdev->dev.type = NULL; | 599 | vdev->dev.type = NULL; |
597 | soc_camera_power_off(&client->dev, ssdd); | 600 | soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); |
598 | } | 601 | } |
599 | 602 | ||
600 | return 0; | 603 | return 0; |
@@ -785,9 +788,18 @@ static int mt9t031_probe(struct i2c_client *client, | |||
785 | mt9t031->xskip = 1; | 788 | mt9t031->xskip = 1; |
786 | mt9t031->yskip = 1; | 789 | mt9t031->yskip = 1; |
787 | 790 | ||
791 | mt9t031->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
792 | if (IS_ERR(mt9t031->clk)) { | ||
793 | ret = PTR_ERR(mt9t031->clk); | ||
794 | goto eclkget; | ||
795 | } | ||
796 | |||
788 | ret = mt9t031_video_probe(client); | 797 | ret = mt9t031_video_probe(client); |
789 | if (ret) | 798 | if (ret) { |
799 | v4l2_clk_put(mt9t031->clk); | ||
800 | eclkget: | ||
790 | v4l2_ctrl_handler_free(&mt9t031->hdl); | 801 | v4l2_ctrl_handler_free(&mt9t031->hdl); |
802 | } | ||
791 | 803 | ||
792 | return ret; | 804 | return ret; |
793 | } | 805 | } |
@@ -796,6 +808,7 @@ static int mt9t031_remove(struct i2c_client *client) | |||
796 | { | 808 | { |
797 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 809 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
798 | 810 | ||
811 | v4l2_clk_put(mt9t031->clk); | ||
799 | v4l2_device_unregister_subdev(&mt9t031->subdev); | 812 | v4l2_device_unregister_subdev(&mt9t031->subdev); |
800 | v4l2_ctrl_handler_free(&mt9t031->hdl); | 813 | v4l2_ctrl_handler_free(&mt9t031->hdl); |
801 | 814 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index 9b276dde5ac8..46f431a13782 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <media/mt9t112.h> | 28 | #include <media/mt9t112.h> |
29 | #include <media/soc_camera.h> | 29 | #include <media/soc_camera.h> |
30 | #include <media/v4l2-clk.h> | ||
30 | #include <media/v4l2-common.h> | 31 | #include <media/v4l2-common.h> |
31 | 32 | ||
32 | /* you can check PLL/clock info */ | 33 | /* you can check PLL/clock info */ |
@@ -89,6 +90,7 @@ struct mt9t112_priv { | |||
89 | struct mt9t112_camera_info *info; | 90 | struct mt9t112_camera_info *info; |
90 | struct i2c_client *client; | 91 | struct i2c_client *client; |
91 | struct v4l2_rect frame; | 92 | struct v4l2_rect frame; |
93 | struct v4l2_clk *clk; | ||
92 | const struct mt9t112_format *format; | 94 | const struct mt9t112_format *format; |
93 | int num_formats; | 95 | int num_formats; |
94 | u32 flags; | 96 | u32 flags; |
@@ -768,8 +770,9 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on) | |||
768 | { | 770 | { |
769 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 771 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
770 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 772 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
773 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
771 | 774 | ||
772 | return soc_camera_set_power(&client->dev, ssdd, on); | 775 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
773 | } | 776 | } |
774 | 777 | ||
775 | static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { | 778 | static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { |
@@ -1092,16 +1095,29 @@ static int mt9t112_probe(struct i2c_client *client, | |||
1092 | 1095 | ||
1093 | v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); | 1096 | v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); |
1094 | 1097 | ||
1098 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
1099 | if (IS_ERR(priv->clk)) | ||
1100 | return PTR_ERR(priv->clk); | ||
1101 | |||
1095 | ret = mt9t112_camera_probe(client); | 1102 | ret = mt9t112_camera_probe(client); |
1096 | if (ret) | ||
1097 | return ret; | ||
1098 | 1103 | ||
1099 | /* Cannot fail: using the default supported pixel code */ | 1104 | /* Cannot fail: using the default supported pixel code */ |
1100 | mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); | 1105 | if (!ret) |
1106 | mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); | ||
1107 | else | ||
1108 | v4l2_clk_put(priv->clk); | ||
1101 | 1109 | ||
1102 | return ret; | 1110 | return ret; |
1103 | } | 1111 | } |
1104 | 1112 | ||
1113 | static int mt9t112_remove(struct i2c_client *client) | ||
1114 | { | ||
1115 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
1116 | |||
1117 | v4l2_clk_put(priv->clk); | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1105 | static const struct i2c_device_id mt9t112_id[] = { | 1121 | static const struct i2c_device_id mt9t112_id[] = { |
1106 | { "mt9t112", 0 }, | 1122 | { "mt9t112", 0 }, |
1107 | { } | 1123 | { } |
@@ -1113,6 +1129,7 @@ static struct i2c_driver mt9t112_i2c_driver = { | |||
1113 | .name = "mt9t112", | 1129 | .name = "mt9t112", |
1114 | }, | 1130 | }, |
1115 | .probe = mt9t112_probe, | 1131 | .probe = mt9t112_probe, |
1132 | .remove = mt9t112_remove, | ||
1116 | .id_table = mt9t112_id, | 1133 | .id_table = mt9t112_id, |
1117 | }; | 1134 | }; |
1118 | 1135 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 41ff4535eb0d..f9f95f815b1a 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
20 | #include <media/soc_mediabus.h> | 20 | #include <media/soc_mediabus.h> |
21 | #include <media/v4l2-subdev.h> | 21 | #include <media/v4l2-subdev.h> |
22 | #include <media/v4l2-clk.h> | ||
22 | #include <media/v4l2-ctrls.h> | 23 | #include <media/v4l2-ctrls.h> |
23 | 24 | ||
24 | /* | 25 | /* |
@@ -153,6 +154,7 @@ struct mt9v022 { | |||
153 | struct v4l2_ctrl *hblank; | 154 | struct v4l2_ctrl *hblank; |
154 | struct v4l2_ctrl *vblank; | 155 | struct v4l2_ctrl *vblank; |
155 | struct v4l2_rect rect; /* Sensor window */ | 156 | struct v4l2_rect rect; /* Sensor window */ |
157 | struct v4l2_clk *clk; | ||
156 | const struct mt9v022_datafmt *fmt; | 158 | const struct mt9v022_datafmt *fmt; |
157 | const struct mt9v022_datafmt *fmts; | 159 | const struct mt9v022_datafmt *fmts; |
158 | const struct mt9v02x_register *reg; | 160 | const struct mt9v02x_register *reg; |
@@ -498,8 +500,9 @@ static int mt9v022_s_power(struct v4l2_subdev *sd, int on) | |||
498 | { | 500 | { |
499 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 501 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
500 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 502 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
503 | struct mt9v022 *mt9v022 = to_mt9v022(client); | ||
501 | 504 | ||
502 | return soc_camera_set_power(&client->dev, ssdd, on); | 505 | return soc_camera_set_power(&client->dev, ssdd, mt9v022->clk, on); |
503 | } | 506 | } |
504 | 507 | ||
505 | static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 508 | static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
@@ -936,9 +939,18 @@ static int mt9v022_probe(struct i2c_client *client, | |||
936 | mt9v022->rect.width = MT9V022_MAX_WIDTH; | 939 | mt9v022->rect.width = MT9V022_MAX_WIDTH; |
937 | mt9v022->rect.height = MT9V022_MAX_HEIGHT; | 940 | mt9v022->rect.height = MT9V022_MAX_HEIGHT; |
938 | 941 | ||
942 | mt9v022->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
943 | if (IS_ERR(mt9v022->clk)) { | ||
944 | ret = PTR_ERR(mt9v022->clk); | ||
945 | goto eclkget; | ||
946 | } | ||
947 | |||
939 | ret = mt9v022_video_probe(client); | 948 | ret = mt9v022_video_probe(client); |
940 | if (ret) | 949 | if (ret) { |
950 | v4l2_clk_put(mt9v022->clk); | ||
951 | eclkget: | ||
941 | v4l2_ctrl_handler_free(&mt9v022->hdl); | 952 | v4l2_ctrl_handler_free(&mt9v022->hdl); |
953 | } | ||
942 | 954 | ||
943 | return ret; | 955 | return ret; |
944 | } | 956 | } |
@@ -948,6 +960,7 @@ static int mt9v022_remove(struct i2c_client *client) | |||
948 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 960 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
949 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 961 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
950 | 962 | ||
963 | v4l2_clk_put(mt9v022->clk); | ||
951 | v4l2_device_unregister_subdev(&mt9v022->subdev); | 964 | v4l2_device_unregister_subdev(&mt9v022->subdev); |
952 | if (ssdd->free_bus) | 965 | if (ssdd->free_bus) |
953 | ssdd->free_bus(ssdd); | 966 | ssdd->free_bus(ssdd); |
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 7961cba6880a..6c6b1c3b45e3 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/videodev2.h> | 22 | #include <linux/videodev2.h> |
23 | 23 | ||
24 | #include <media/soc_camera.h> | 24 | #include <media/soc_camera.h> |
25 | #include <media/v4l2-clk.h> | ||
25 | #include <media/v4l2-subdev.h> | 26 | #include <media/v4l2-subdev.h> |
26 | #include <media/v4l2-ctrls.h> | 27 | #include <media/v4l2-ctrls.h> |
27 | 28 | ||
@@ -302,6 +303,7 @@ struct ov2640_priv { | |||
302 | struct v4l2_subdev subdev; | 303 | struct v4l2_subdev subdev; |
303 | struct v4l2_ctrl_handler hdl; | 304 | struct v4l2_ctrl_handler hdl; |
304 | enum v4l2_mbus_pixelcode cfmt_code; | 305 | enum v4l2_mbus_pixelcode cfmt_code; |
306 | struct v4l2_clk *clk; | ||
305 | const struct ov2640_win_size *win; | 307 | const struct ov2640_win_size *win; |
306 | }; | 308 | }; |
307 | 309 | ||
@@ -758,8 +760,9 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) | |||
758 | { | 760 | { |
759 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 761 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
760 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 762 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
763 | struct ov2640_priv *priv = to_ov2640(client); | ||
761 | 764 | ||
762 | return soc_camera_set_power(&client->dev, ssdd, on); | 765 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
763 | } | 766 | } |
764 | 767 | ||
765 | /* Select the nearest higher resolution for capture */ | 768 | /* Select the nearest higher resolution for capture */ |
@@ -1097,11 +1100,20 @@ static int ov2640_probe(struct i2c_client *client, | |||
1097 | if (priv->hdl.error) | 1100 | if (priv->hdl.error) |
1098 | return priv->hdl.error; | 1101 | return priv->hdl.error; |
1099 | 1102 | ||
1103 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
1104 | if (IS_ERR(priv->clk)) { | ||
1105 | ret = PTR_ERR(priv->clk); | ||
1106 | goto eclkget; | ||
1107 | } | ||
1108 | |||
1100 | ret = ov2640_video_probe(client); | 1109 | ret = ov2640_video_probe(client); |
1101 | if (ret) | 1110 | if (ret) { |
1111 | v4l2_clk_put(priv->clk); | ||
1112 | eclkget: | ||
1102 | v4l2_ctrl_handler_free(&priv->hdl); | 1113 | v4l2_ctrl_handler_free(&priv->hdl); |
1103 | else | 1114 | } else { |
1104 | dev_info(&adapter->dev, "OV2640 Probed\n"); | 1115 | dev_info(&adapter->dev, "OV2640 Probed\n"); |
1116 | } | ||
1105 | 1117 | ||
1106 | return ret; | 1118 | return ret; |
1107 | } | 1119 | } |
@@ -1110,6 +1122,7 @@ static int ov2640_remove(struct i2c_client *client) | |||
1110 | { | 1122 | { |
1111 | struct ov2640_priv *priv = to_ov2640(client); | 1123 | struct ov2640_priv *priv = to_ov2640(client); |
1112 | 1124 | ||
1125 | v4l2_clk_put(priv->clk); | ||
1113 | v4l2_device_unregister_subdev(&priv->subdev); | 1126 | v4l2_device_unregister_subdev(&priv->subdev); |
1114 | v4l2_ctrl_handler_free(&priv->hdl); | 1127 | v4l2_ctrl_handler_free(&priv->hdl); |
1115 | return 0; | 1128 | return 0; |
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index c93a157d1d93..0a5c5d4fedd6 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/v4l2-mediabus.h> | 24 | #include <linux/v4l2-mediabus.h> |
25 | 25 | ||
26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
27 | #include <media/v4l2-clk.h> | ||
27 | #include <media/v4l2-subdev.h> | 28 | #include <media/v4l2-subdev.h> |
28 | 29 | ||
29 | /* OV5642 registers */ | 30 | /* OV5642 registers */ |
@@ -609,6 +610,7 @@ struct ov5642 { | |||
609 | struct v4l2_subdev subdev; | 610 | struct v4l2_subdev subdev; |
610 | const struct ov5642_datafmt *fmt; | 611 | const struct ov5642_datafmt *fmt; |
611 | struct v4l2_rect crop_rect; | 612 | struct v4l2_rect crop_rect; |
613 | struct v4l2_clk *clk; | ||
612 | 614 | ||
613 | /* blanking information */ | 615 | /* blanking information */ |
614 | int total_width; | 616 | int total_width; |
@@ -917,12 +919,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on) | |||
917 | { | 919 | { |
918 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 920 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
919 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 921 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
922 | struct ov5642 *priv = to_ov5642(client); | ||
920 | int ret; | 923 | int ret; |
921 | 924 | ||
922 | if (!on) | 925 | if (!on) |
923 | return soc_camera_power_off(&client->dev, ssdd); | 926 | return soc_camera_power_off(&client->dev, ssdd, priv->clk); |
924 | 927 | ||
925 | ret = soc_camera_power_on(&client->dev, ssdd); | 928 | ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); |
926 | if (ret < 0) | 929 | if (ret < 0) |
927 | return ret; | 930 | return ret; |
928 | 931 | ||
@@ -1002,6 +1005,7 @@ static int ov5642_probe(struct i2c_client *client, | |||
1002 | { | 1005 | { |
1003 | struct ov5642 *priv; | 1006 | struct ov5642 *priv; |
1004 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 1007 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
1008 | int ret; | ||
1005 | 1009 | ||
1006 | if (!ssdd) { | 1010 | if (!ssdd) { |
1007 | dev_err(&client->dev, "OV5642: missing platform data!\n"); | 1011 | dev_err(&client->dev, "OV5642: missing platform data!\n"); |
@@ -1023,13 +1027,23 @@ static int ov5642_probe(struct i2c_client *client, | |||
1023 | priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH; | 1027 | priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH; |
1024 | priv->total_height = BLANKING_MIN_HEIGHT; | 1028 | priv->total_height = BLANKING_MIN_HEIGHT; |
1025 | 1029 | ||
1026 | return ov5642_video_probe(client); | 1030 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); |
1031 | if (IS_ERR(priv->clk)) | ||
1032 | return PTR_ERR(priv->clk); | ||
1033 | |||
1034 | ret = ov5642_video_probe(client); | ||
1035 | if (ret < 0) | ||
1036 | v4l2_clk_put(priv->clk); | ||
1037 | |||
1038 | return ret; | ||
1027 | } | 1039 | } |
1028 | 1040 | ||
1029 | static int ov5642_remove(struct i2c_client *client) | 1041 | static int ov5642_remove(struct i2c_client *client) |
1030 | { | 1042 | { |
1031 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 1043 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
1044 | struct ov5642 *priv = to_ov5642(client); | ||
1032 | 1045 | ||
1046 | v4l2_clk_put(priv->clk); | ||
1033 | if (ssdd->free_bus) | 1047 | if (ssdd->free_bus) |
1034 | ssdd->free_bus(ssdd); | 1048 | ssdd->free_bus(ssdd); |
1035 | 1049 | ||
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index d2869d87d3b1..ab01598ec83f 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | 33 | ||
34 | #include <media/soc_camera.h> | 34 | #include <media/soc_camera.h> |
35 | #include <media/v4l2-clk.h> | ||
35 | #include <media/v4l2-ctrls.h> | 36 | #include <media/v4l2-ctrls.h> |
36 | 37 | ||
37 | /* Register definitions */ | 38 | /* Register definitions */ |
@@ -195,6 +196,7 @@ struct ov6650 { | |||
195 | struct v4l2_ctrl *blue; | 196 | struct v4l2_ctrl *blue; |
196 | struct v4l2_ctrl *red; | 197 | struct v4l2_ctrl *red; |
197 | }; | 198 | }; |
199 | struct v4l2_clk *clk; | ||
198 | bool half_scale; /* scale down output by 2 */ | 200 | bool half_scale; /* scale down output by 2 */ |
199 | struct v4l2_rect rect; /* sensor cropping window */ | 201 | struct v4l2_rect rect; /* sensor cropping window */ |
200 | unsigned long pclk_limit; /* from host */ | 202 | unsigned long pclk_limit; /* from host */ |
@@ -425,8 +427,9 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on) | |||
425 | { | 427 | { |
426 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 428 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
427 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 429 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
430 | struct ov6650 *priv = to_ov6650(client); | ||
428 | 431 | ||
429 | return soc_camera_set_power(&client->dev, ssdd, on); | 432 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
430 | } | 433 | } |
431 | 434 | ||
432 | static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 435 | static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
@@ -1013,9 +1016,18 @@ static int ov6650_probe(struct i2c_client *client, | |||
1013 | priv->code = V4L2_MBUS_FMT_YUYV8_2X8; | 1016 | priv->code = V4L2_MBUS_FMT_YUYV8_2X8; |
1014 | priv->colorspace = V4L2_COLORSPACE_JPEG; | 1017 | priv->colorspace = V4L2_COLORSPACE_JPEG; |
1015 | 1018 | ||
1019 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
1020 | if (IS_ERR(priv->clk)) { | ||
1021 | ret = PTR_ERR(priv->clk); | ||
1022 | goto eclkget; | ||
1023 | } | ||
1024 | |||
1016 | ret = ov6650_video_probe(client); | 1025 | ret = ov6650_video_probe(client); |
1017 | if (ret) | 1026 | if (ret) { |
1027 | v4l2_clk_put(priv->clk); | ||
1028 | eclkget: | ||
1018 | v4l2_ctrl_handler_free(&priv->hdl); | 1029 | v4l2_ctrl_handler_free(&priv->hdl); |
1030 | } | ||
1019 | 1031 | ||
1020 | return ret; | 1032 | return ret; |
1021 | } | 1033 | } |
@@ -1024,6 +1036,7 @@ static int ov6650_remove(struct i2c_client *client) | |||
1024 | { | 1036 | { |
1025 | struct ov6650 *priv = to_ov6650(client); | 1037 | struct ov6650 *priv = to_ov6650(client); |
1026 | 1038 | ||
1039 | v4l2_clk_put(priv->clk); | ||
1027 | v4l2_device_unregister_subdev(&priv->subdev); | 1040 | v4l2_device_unregister_subdev(&priv->subdev); |
1028 | v4l2_ctrl_handler_free(&priv->hdl); | 1041 | v4l2_ctrl_handler_free(&priv->hdl); |
1029 | return 0; | 1042 | return 0; |
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index b2f623603986..7f2b3c8926af 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <media/ov772x.h> | 27 | #include <media/ov772x.h> |
28 | #include <media/soc_camera.h> | 28 | #include <media/soc_camera.h> |
29 | #include <media/v4l2-clk.h> | ||
29 | #include <media/v4l2-ctrls.h> | 30 | #include <media/v4l2-ctrls.h> |
30 | #include <media/v4l2-subdev.h> | 31 | #include <media/v4l2-subdev.h> |
31 | 32 | ||
@@ -395,6 +396,7 @@ struct ov772x_win_size { | |||
395 | struct ov772x_priv { | 396 | struct ov772x_priv { |
396 | struct v4l2_subdev subdev; | 397 | struct v4l2_subdev subdev; |
397 | struct v4l2_ctrl_handler hdl; | 398 | struct v4l2_ctrl_handler hdl; |
399 | struct v4l2_clk *clk; | ||
398 | struct ov772x_camera_info *info; | 400 | struct ov772x_camera_info *info; |
399 | const struct ov772x_color_format *cfmt; | 401 | const struct ov772x_color_format *cfmt; |
400 | const struct ov772x_win_size *win; | 402 | const struct ov772x_win_size *win; |
@@ -655,8 +657,9 @@ static int ov772x_s_power(struct v4l2_subdev *sd, int on) | |||
655 | { | 657 | { |
656 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 658 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
657 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 659 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
660 | struct ov772x_priv *priv = to_ov772x(sd); | ||
658 | 661 | ||
659 | return soc_camera_set_power(&client->dev, ssdd, on); | 662 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
660 | } | 663 | } |
661 | 664 | ||
662 | static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) | 665 | static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) |
@@ -1072,13 +1075,22 @@ static int ov772x_probe(struct i2c_client *client, | |||
1072 | if (priv->hdl.error) | 1075 | if (priv->hdl.error) |
1073 | return priv->hdl.error; | 1076 | return priv->hdl.error; |
1074 | 1077 | ||
1078 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
1079 | if (IS_ERR(priv->clk)) { | ||
1080 | ret = PTR_ERR(priv->clk); | ||
1081 | goto eclkget; | ||
1082 | } | ||
1083 | |||
1075 | ret = ov772x_video_probe(priv); | 1084 | ret = ov772x_video_probe(priv); |
1076 | if (ret < 0) { | 1085 | if (ret < 0) { |
1086 | v4l2_clk_put(priv->clk); | ||
1087 | eclkget: | ||
1077 | v4l2_ctrl_handler_free(&priv->hdl); | 1088 | v4l2_ctrl_handler_free(&priv->hdl); |
1078 | } else { | 1089 | } else { |
1079 | priv->cfmt = &ov772x_cfmts[0]; | 1090 | priv->cfmt = &ov772x_cfmts[0]; |
1080 | priv->win = &ov772x_win_sizes[0]; | 1091 | priv->win = &ov772x_win_sizes[0]; |
1081 | } | 1092 | } |
1093 | |||
1082 | return ret; | 1094 | return ret; |
1083 | } | 1095 | } |
1084 | 1096 | ||
@@ -1086,6 +1098,7 @@ static int ov772x_remove(struct i2c_client *client) | |||
1086 | { | 1098 | { |
1087 | struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); | 1099 | struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); |
1088 | 1100 | ||
1101 | v4l2_clk_put(priv->clk); | ||
1089 | v4l2_device_unregister_subdev(&priv->subdev); | 1102 | v4l2_device_unregister_subdev(&priv->subdev); |
1090 | v4l2_ctrl_handler_free(&priv->hdl); | 1103 | v4l2_ctrl_handler_free(&priv->hdl); |
1091 | return 0; | 1104 | return 0; |
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 7d1f10f301d3..e968c3fdbd9e 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/videodev2.h> | 28 | #include <linux/videodev2.h> |
29 | 29 | ||
30 | #include <media/soc_camera.h> | 30 | #include <media/soc_camera.h> |
31 | #include <media/v4l2-clk.h> | ||
31 | #include <media/v4l2-common.h> | 32 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-ctrls.h> | 33 | #include <media/v4l2-ctrls.h> |
33 | 34 | ||
@@ -324,8 +325,9 @@ static int ov9640_s_power(struct v4l2_subdev *sd, int on) | |||
324 | { | 325 | { |
325 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 326 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
326 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 327 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
328 | struct ov9640_priv *priv = to_ov9640_sensor(sd); | ||
327 | 329 | ||
328 | return soc_camera_set_power(&client->dev, ssdd, on); | 330 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
329 | } | 331 | } |
330 | 332 | ||
331 | /* select nearest higher resolution for capture */ | 333 | /* select nearest higher resolution for capture */ |
@@ -700,10 +702,18 @@ static int ov9640_probe(struct i2c_client *client, | |||
700 | if (priv->hdl.error) | 702 | if (priv->hdl.error) |
701 | return priv->hdl.error; | 703 | return priv->hdl.error; |
702 | 704 | ||
703 | ret = ov9640_video_probe(client); | 705 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); |
706 | if (IS_ERR(priv->clk)) { | ||
707 | ret = PTR_ERR(priv->clk); | ||
708 | goto eclkget; | ||
709 | } | ||
704 | 710 | ||
705 | if (ret) | 711 | ret = ov9640_video_probe(client); |
712 | if (ret) { | ||
713 | v4l2_clk_put(priv->clk); | ||
714 | eclkget: | ||
706 | v4l2_ctrl_handler_free(&priv->hdl); | 715 | v4l2_ctrl_handler_free(&priv->hdl); |
716 | } | ||
707 | 717 | ||
708 | return ret; | 718 | return ret; |
709 | } | 719 | } |
@@ -713,6 +723,7 @@ static int ov9640_remove(struct i2c_client *client) | |||
713 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 723 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
714 | struct ov9640_priv *priv = to_ov9640_sensor(sd); | 724 | struct ov9640_priv *priv = to_ov9640_sensor(sd); |
715 | 725 | ||
726 | v4l2_clk_put(priv->clk); | ||
716 | v4l2_device_unregister_subdev(&priv->subdev); | 727 | v4l2_device_unregister_subdev(&priv->subdev); |
717 | v4l2_ctrl_handler_free(&priv->hdl); | 728 | v4l2_ctrl_handler_free(&priv->hdl); |
718 | return 0; | 729 | return 0; |
diff --git a/drivers/media/i2c/soc_camera/ov9640.h b/drivers/media/i2c/soc_camera/ov9640.h index 6b33a972c83c..65d13ff17536 100644 --- a/drivers/media/i2c/soc_camera/ov9640.h +++ b/drivers/media/i2c/soc_camera/ov9640.h | |||
@@ -199,6 +199,7 @@ struct ov9640_reg { | |||
199 | struct ov9640_priv { | 199 | struct ov9640_priv { |
200 | struct v4l2_subdev subdev; | 200 | struct v4l2_subdev subdev; |
201 | struct v4l2_ctrl_handler hdl; | 201 | struct v4l2_ctrl_handler hdl; |
202 | struct v4l2_clk *clk; | ||
202 | 203 | ||
203 | int model; | 204 | int model; |
204 | int revision; | 205 | int revision; |
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 0bc21a643c08..ea76863dfdb4 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/v4l2-mediabus.h> | 17 | #include <linux/v4l2-mediabus.h> |
18 | 18 | ||
19 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
20 | #include <media/v4l2-clk.h> | ||
20 | #include <media/v4l2-ctrls.h> | 21 | #include <media/v4l2-ctrls.h> |
21 | 22 | ||
22 | #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) | 23 | #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) |
@@ -195,6 +196,7 @@ struct ov9740_reg { | |||
195 | struct ov9740_priv { | 196 | struct ov9740_priv { |
196 | struct v4l2_subdev subdev; | 197 | struct v4l2_subdev subdev; |
197 | struct v4l2_ctrl_handler hdl; | 198 | struct v4l2_ctrl_handler hdl; |
199 | struct v4l2_clk *clk; | ||
198 | 200 | ||
199 | u16 model; | 201 | u16 model; |
200 | u8 revision; | 202 | u8 revision; |
@@ -778,7 +780,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) | |||
778 | int ret; | 780 | int ret; |
779 | 781 | ||
780 | if (on) { | 782 | if (on) { |
781 | ret = soc_camera_power_on(&client->dev, ssdd); | 783 | ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); |
782 | if (ret < 0) | 784 | if (ret < 0) |
783 | return ret; | 785 | return ret; |
784 | 786 | ||
@@ -792,7 +794,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) | |||
792 | priv->current_enable = true; | 794 | priv->current_enable = true; |
793 | } | 795 | } |
794 | 796 | ||
795 | soc_camera_power_off(&client->dev, ssdd); | 797 | soc_camera_power_off(&client->dev, ssdd, priv->clk); |
796 | } | 798 | } |
797 | 799 | ||
798 | return 0; | 800 | return 0; |
@@ -958,9 +960,18 @@ static int ov9740_probe(struct i2c_client *client, | |||
958 | if (priv->hdl.error) | 960 | if (priv->hdl.error) |
959 | return priv->hdl.error; | 961 | return priv->hdl.error; |
960 | 962 | ||
963 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
964 | if (IS_ERR(priv->clk)) { | ||
965 | ret = PTR_ERR(priv->clk); | ||
966 | goto eclkget; | ||
967 | } | ||
968 | |||
961 | ret = ov9740_video_probe(client); | 969 | ret = ov9740_video_probe(client); |
962 | if (ret < 0) | 970 | if (ret < 0) { |
971 | v4l2_clk_put(priv->clk); | ||
972 | eclkget: | ||
963 | v4l2_ctrl_handler_free(&priv->hdl); | 973 | v4l2_ctrl_handler_free(&priv->hdl); |
974 | } | ||
964 | 975 | ||
965 | return ret; | 976 | return ret; |
966 | } | 977 | } |
@@ -969,6 +980,7 @@ static int ov9740_remove(struct i2c_client *client) | |||
969 | { | 980 | { |
970 | struct ov9740_priv *priv = i2c_get_clientdata(client); | 981 | struct ov9740_priv *priv = i2c_get_clientdata(client); |
971 | 982 | ||
983 | v4l2_clk_put(priv->clk); | ||
972 | v4l2_device_unregister_subdev(&priv->subdev); | 984 | v4l2_device_unregister_subdev(&priv->subdev); |
973 | v4l2_ctrl_handler_free(&priv->hdl); | 985 | v4l2_ctrl_handler_free(&priv->hdl); |
974 | return 0; | 986 | return 0; |
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index 81b515c2fb36..7e6d97847874 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <media/rj54n1cb0c.h> | 18 | #include <media/rj54n1cb0c.h> |
19 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
20 | #include <media/v4l2-clk.h> | ||
20 | #include <media/v4l2-subdev.h> | 21 | #include <media/v4l2-subdev.h> |
21 | #include <media/v4l2-ctrls.h> | 22 | #include <media/v4l2-ctrls.h> |
22 | 23 | ||
@@ -150,6 +151,7 @@ struct rj54n1_clock_div { | |||
150 | struct rj54n1 { | 151 | struct rj54n1 { |
151 | struct v4l2_subdev subdev; | 152 | struct v4l2_subdev subdev; |
152 | struct v4l2_ctrl_handler hdl; | 153 | struct v4l2_ctrl_handler hdl; |
154 | struct v4l2_clk *clk; | ||
153 | struct rj54n1_clock_div clk_div; | 155 | struct rj54n1_clock_div clk_div; |
154 | const struct rj54n1_datafmt *fmt; | 156 | const struct rj54n1_datafmt *fmt; |
155 | struct v4l2_rect rect; /* Sensor window */ | 157 | struct v4l2_rect rect; /* Sensor window */ |
@@ -1158,8 +1160,9 @@ static int rj54n1_s_power(struct v4l2_subdev *sd, int on) | |||
1158 | { | 1160 | { |
1159 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1161 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1160 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 1162 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
1163 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
1161 | 1164 | ||
1162 | return soc_camera_set_power(&client->dev, ssdd, on); | 1165 | return soc_camera_set_power(&client->dev, ssdd, rj54n1->clk, on); |
1163 | } | 1166 | } |
1164 | 1167 | ||
1165 | static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) | 1168 | static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) |
@@ -1355,9 +1358,18 @@ static int rj54n1_probe(struct i2c_client *client, | |||
1355 | rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / | 1358 | rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / |
1356 | (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); | 1359 | (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); |
1357 | 1360 | ||
1361 | rj54n1->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
1362 | if (IS_ERR(rj54n1->clk)) { | ||
1363 | ret = PTR_ERR(rj54n1->clk); | ||
1364 | goto eclkget; | ||
1365 | } | ||
1366 | |||
1358 | ret = rj54n1_video_probe(client, rj54n1_priv); | 1367 | ret = rj54n1_video_probe(client, rj54n1_priv); |
1359 | if (ret < 0) | 1368 | if (ret < 0) { |
1369 | v4l2_clk_put(rj54n1->clk); | ||
1370 | eclkget: | ||
1360 | v4l2_ctrl_handler_free(&rj54n1->hdl); | 1371 | v4l2_ctrl_handler_free(&rj54n1->hdl); |
1372 | } | ||
1361 | 1373 | ||
1362 | return ret; | 1374 | return ret; |
1363 | } | 1375 | } |
@@ -1367,6 +1379,7 @@ static int rj54n1_remove(struct i2c_client *client) | |||
1367 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 1379 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
1368 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 1380 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
1369 | 1381 | ||
1382 | v4l2_clk_put(rj54n1->clk); | ||
1370 | v4l2_device_unregister_subdev(&rj54n1->subdev); | 1383 | v4l2_device_unregister_subdev(&rj54n1->subdev); |
1371 | if (ssdd->free_bus) | 1384 | if (ssdd->free_bus) |
1372 | ssdd->free_bus(ssdd); | 1385 | ssdd->free_bus(ssdd); |
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index b15e1d8194da..ab54628d9411 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <media/soc_camera.h> | 28 | #include <media/soc_camera.h> |
29 | #include <media/tw9910.h> | 29 | #include <media/tw9910.h> |
30 | #include <media/v4l2-clk.h> | ||
30 | #include <media/v4l2-subdev.h> | 31 | #include <media/v4l2-subdev.h> |
31 | 32 | ||
32 | #define GET_ID(val) ((val & 0xF8) >> 3) | 33 | #define GET_ID(val) ((val & 0xF8) >> 3) |
@@ -227,6 +228,7 @@ struct tw9910_scale_ctrl { | |||
227 | 228 | ||
228 | struct tw9910_priv { | 229 | struct tw9910_priv { |
229 | struct v4l2_subdev subdev; | 230 | struct v4l2_subdev subdev; |
231 | struct v4l2_clk *clk; | ||
230 | struct tw9910_video_info *info; | 232 | struct tw9910_video_info *info; |
231 | const struct tw9910_scale_ctrl *scale; | 233 | const struct tw9910_scale_ctrl *scale; |
232 | v4l2_std_id norm; | 234 | v4l2_std_id norm; |
@@ -558,8 +560,9 @@ static int tw9910_s_power(struct v4l2_subdev *sd, int on) | |||
558 | { | 560 | { |
559 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 561 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
560 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 562 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
563 | struct tw9910_priv *priv = to_tw9910(client); | ||
561 | 564 | ||
562 | return soc_camera_set_power(&client->dev, ssdd, on); | 565 | return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); |
563 | } | 566 | } |
564 | 567 | ||
565 | static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) | 568 | static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) |
@@ -899,6 +902,7 @@ static int tw9910_probe(struct i2c_client *client, | |||
899 | struct i2c_adapter *adapter = | 902 | struct i2c_adapter *adapter = |
900 | to_i2c_adapter(client->dev.parent); | 903 | to_i2c_adapter(client->dev.parent); |
901 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); | 904 | struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); |
905 | int ret; | ||
902 | 906 | ||
903 | if (!ssdd || !ssdd->drv_priv) { | 907 | if (!ssdd || !ssdd->drv_priv) { |
904 | dev_err(&client->dev, "TW9910: missing platform data!\n"); | 908 | dev_err(&client->dev, "TW9910: missing platform data!\n"); |
@@ -922,7 +926,22 @@ static int tw9910_probe(struct i2c_client *client, | |||
922 | 926 | ||
923 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); | 927 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); |
924 | 928 | ||
925 | return tw9910_video_probe(client); | 929 | priv->clk = v4l2_clk_get(&client->dev, "mclk"); |
930 | if (IS_ERR(priv->clk)) | ||
931 | return PTR_ERR(priv->clk); | ||
932 | |||
933 | ret = tw9910_video_probe(client); | ||
934 | if (ret < 0) | ||
935 | v4l2_clk_put(priv->clk); | ||
936 | |||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int tw9910_remove(struct i2c_client *client) | ||
941 | { | ||
942 | struct tw9910_priv *priv = to_tw9910(client); | ||
943 | v4l2_clk_put(priv->clk); | ||
944 | return 0; | ||
926 | } | 945 | } |
927 | 946 | ||
928 | static const struct i2c_device_id tw9910_id[] = { | 947 | static const struct i2c_device_id tw9910_id[] = { |
@@ -936,6 +955,7 @@ static struct i2c_driver tw9910_i2c_driver = { | |||
936 | .name = "tw9910", | 955 | .name = "tw9910", |
937 | }, | 956 | }, |
938 | .probe = tw9910_probe, | 957 | .probe = tw9910_probe, |
958 | .remove = tw9910_remove, | ||
939 | .id_table = tw9910_id, | 959 | .id_table = tw9910_id, |
940 | }; | 960 | }; |
941 | 961 | ||
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index fa8a728b7a5d..fe3930e882e1 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | 31 | ||
32 | #include <media/soc_camera.h> | 32 | #include <media/soc_camera.h> |
33 | #include <media/v4l2-clk.h> | ||
33 | #include <media/v4l2-common.h> | 34 | #include <media/v4l2-common.h> |
34 | #include <media/v4l2-ioctl.h> | 35 | #include <media/v4l2-ioctl.h> |
35 | #include <media/v4l2-dev.h> | 36 | #include <media/v4l2-dev.h> |
@@ -50,13 +51,19 @@ static LIST_HEAD(hosts); | |||
50 | static LIST_HEAD(devices); | 51 | static LIST_HEAD(devices); |
51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | 52 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
52 | 53 | ||
53 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) | 54 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, |
55 | struct v4l2_clk *clk) | ||
54 | { | 56 | { |
55 | int ret = regulator_bulk_enable(ssdd->num_regulators, | 57 | int ret = clk ? v4l2_clk_enable(clk) : 0; |
58 | if (ret < 0) { | ||
59 | dev_err(dev, "Cannot enable clock\n"); | ||
60 | return ret; | ||
61 | } | ||
62 | ret = regulator_bulk_enable(ssdd->num_regulators, | ||
56 | ssdd->regulators); | 63 | ssdd->regulators); |
57 | if (ret < 0) { | 64 | if (ret < 0) { |
58 | dev_err(dev, "Cannot enable regulators\n"); | 65 | dev_err(dev, "Cannot enable regulators\n"); |
59 | return ret; | 66 | goto eregenable;; |
60 | } | 67 | } |
61 | 68 | ||
62 | if (ssdd->power) { | 69 | if (ssdd->power) { |
@@ -64,16 +71,25 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) | |||
64 | if (ret < 0) { | 71 | if (ret < 0) { |
65 | dev_err(dev, | 72 | dev_err(dev, |
66 | "Platform failed to power-on the camera.\n"); | 73 | "Platform failed to power-on the camera.\n"); |
67 | regulator_bulk_disable(ssdd->num_regulators, | 74 | goto epwron; |
68 | ssdd->regulators); | ||
69 | } | 75 | } |
70 | } | 76 | } |
71 | 77 | ||
78 | return 0; | ||
79 | |||
80 | epwron: | ||
81 | regulator_bulk_disable(ssdd->num_regulators, | ||
82 | ssdd->regulators); | ||
83 | eregenable: | ||
84 | if (clk) | ||
85 | v4l2_clk_disable(clk); | ||
86 | |||
72 | return ret; | 87 | return ret; |
73 | } | 88 | } |
74 | EXPORT_SYMBOL(soc_camera_power_on); | 89 | EXPORT_SYMBOL(soc_camera_power_on); |
75 | 90 | ||
76 | int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd) | 91 | int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, |
92 | struct v4l2_clk *clk) | ||
77 | { | 93 | { |
78 | int ret = 0; | 94 | int ret = 0; |
79 | int err; | 95 | int err; |
@@ -94,6 +110,9 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd | |||
94 | ret = ret ? : err; | 110 | ret = ret ? : err; |
95 | } | 111 | } |
96 | 112 | ||
113 | if (clk) | ||
114 | v4l2_clk_disable(clk); | ||
115 | |||
97 | return ret; | 116 | return ret; |
98 | } | 117 | } |
99 | EXPORT_SYMBOL(soc_camera_power_off); | 118 | EXPORT_SYMBOL(soc_camera_power_off); |
@@ -512,9 +531,11 @@ static int soc_camera_add_device(struct soc_camera_device *icd) | |||
512 | if (ici->icd) | 531 | if (ici->icd) |
513 | return -EBUSY; | 532 | return -EBUSY; |
514 | 533 | ||
515 | ret = ici->ops->clock_start(ici); | 534 | if (!icd->clk) { |
516 | if (ret < 0) | 535 | ret = ici->ops->clock_start(ici); |
517 | return ret; | 536 | if (ret < 0) |
537 | return ret; | ||
538 | } | ||
518 | 539 | ||
519 | if (ici->ops->add) { | 540 | if (ici->ops->add) { |
520 | ret = ici->ops->add(icd); | 541 | ret = ici->ops->add(icd); |
@@ -527,7 +548,8 @@ static int soc_camera_add_device(struct soc_camera_device *icd) | |||
527 | return 0; | 548 | return 0; |
528 | 549 | ||
529 | eadd: | 550 | eadd: |
530 | ici->ops->clock_stop(ici); | 551 | if (!icd->clk) |
552 | ici->ops->clock_stop(ici); | ||
531 | return ret; | 553 | return ret; |
532 | } | 554 | } |
533 | 555 | ||
@@ -540,7 +562,8 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) | |||
540 | 562 | ||
541 | if (ici->ops->remove) | 563 | if (ici->ops->remove) |
542 | ici->ops->remove(icd); | 564 | ici->ops->remove(icd); |
543 | ici->ops->clock_stop(ici); | 565 | if (!icd->clk) |
566 | ici->ops->clock_stop(ici); | ||
544 | ici->icd = NULL; | 567 | ici->icd = NULL; |
545 | } | 568 | } |
546 | 569 | ||
@@ -1094,6 +1117,57 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
1094 | mutex_unlock(&list_lock); | 1117 | mutex_unlock(&list_lock); |
1095 | } | 1118 | } |
1096 | 1119 | ||
1120 | /* | ||
1121 | * It is invalid to call v4l2_clk_enable() after a successful probing | ||
1122 | * asynchronously outside of V4L2 operations, i.e. with .host_lock not held. | ||
1123 | */ | ||
1124 | static int soc_camera_clk_enable(struct v4l2_clk *clk) | ||
1125 | { | ||
1126 | struct soc_camera_device *icd = clk->priv; | ||
1127 | struct soc_camera_host *ici; | ||
1128 | |||
1129 | if (!icd || !icd->parent) | ||
1130 | return -ENODEV; | ||
1131 | |||
1132 | ici = to_soc_camera_host(icd->parent); | ||
1133 | |||
1134 | if (!try_module_get(ici->ops->owner)) | ||
1135 | return -ENODEV; | ||
1136 | |||
1137 | /* | ||
1138 | * If a different client is currently being probed, the host will tell | ||
1139 | * you to go | ||
1140 | */ | ||
1141 | return ici->ops->clock_start(ici); | ||
1142 | } | ||
1143 | |||
1144 | static void soc_camera_clk_disable(struct v4l2_clk *clk) | ||
1145 | { | ||
1146 | struct soc_camera_device *icd = clk->priv; | ||
1147 | struct soc_camera_host *ici; | ||
1148 | |||
1149 | if (!icd || !icd->parent) | ||
1150 | return; | ||
1151 | |||
1152 | ici = to_soc_camera_host(icd->parent); | ||
1153 | |||
1154 | ici->ops->clock_stop(ici); | ||
1155 | |||
1156 | module_put(ici->ops->owner); | ||
1157 | } | ||
1158 | |||
1159 | /* | ||
1160 | * Eventually, it would be more logical to make the respective host the clock | ||
1161 | * owner, but then we would have to copy this struct for each ici. Besides, it | ||
1162 | * would introduce the circular dependency problem, unless we port all client | ||
1163 | * drivers to release the clock, when not in use. | ||
1164 | */ | ||
1165 | static const struct v4l2_clk_ops soc_camera_clk_ops = { | ||
1166 | .owner = THIS_MODULE, | ||
1167 | .enable = soc_camera_clk_enable, | ||
1168 | .disable = soc_camera_clk_disable, | ||
1169 | }; | ||
1170 | |||
1097 | #ifdef CONFIG_I2C_BOARDINFO | 1171 | #ifdef CONFIG_I2C_BOARDINFO |
1098 | static int soc_camera_init_i2c(struct soc_camera_device *icd, | 1172 | static int soc_camera_init_i2c(struct soc_camera_device *icd, |
1099 | struct soc_camera_desc *sdesc) | 1173 | struct soc_camera_desc *sdesc) |
@@ -1103,19 +1177,32 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
1103 | struct soc_camera_host_desc *shd = &sdesc->host_desc; | 1177 | struct soc_camera_host_desc *shd = &sdesc->host_desc; |
1104 | struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); | 1178 | struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); |
1105 | struct v4l2_subdev *subdev; | 1179 | struct v4l2_subdev *subdev; |
1180 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; | ||
1181 | int ret; | ||
1106 | 1182 | ||
1107 | if (!adap) { | 1183 | if (!adap) { |
1108 | dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", | 1184 | dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", |
1109 | shd->i2c_adapter_id); | 1185 | shd->i2c_adapter_id); |
1110 | goto ei2cga; | 1186 | return -ENODEV; |
1111 | } | 1187 | } |
1112 | 1188 | ||
1113 | shd->board_info->platform_data = &sdesc->subdev_desc; | 1189 | shd->board_info->platform_data = &sdesc->subdev_desc; |
1114 | 1190 | ||
1191 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", | ||
1192 | shd->i2c_adapter_id, shd->board_info->addr); | ||
1193 | |||
1194 | icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); | ||
1195 | if (IS_ERR(icd->clk)) { | ||
1196 | ret = PTR_ERR(icd->clk); | ||
1197 | goto eclkreg; | ||
1198 | } | ||
1199 | |||
1115 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, | 1200 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
1116 | shd->board_info, NULL); | 1201 | shd->board_info, NULL); |
1117 | if (!subdev) | 1202 | if (!subdev) { |
1203 | ret = -ENODEV; | ||
1118 | goto ei2cnd; | 1204 | goto ei2cnd; |
1205 | } | ||
1119 | 1206 | ||
1120 | client = v4l2_get_subdevdata(subdev); | 1207 | client = v4l2_get_subdevdata(subdev); |
1121 | 1208 | ||
@@ -1124,9 +1211,11 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
1124 | 1211 | ||
1125 | return 0; | 1212 | return 0; |
1126 | ei2cnd: | 1213 | ei2cnd: |
1214 | v4l2_clk_unregister(icd->clk); | ||
1215 | icd->clk = NULL; | ||
1216 | eclkreg: | ||
1127 | i2c_put_adapter(adap); | 1217 | i2c_put_adapter(adap); |
1128 | ei2cga: | 1218 | return ret; |
1129 | return -ENODEV; | ||
1130 | } | 1219 | } |
1131 | 1220 | ||
1132 | static void soc_camera_free_i2c(struct soc_camera_device *icd) | 1221 | static void soc_camera_free_i2c(struct soc_camera_device *icd) |
@@ -1139,6 +1228,8 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) | |||
1139 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); | 1228 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); |
1140 | i2c_unregister_device(client); | 1229 | i2c_unregister_device(client); |
1141 | i2c_put_adapter(adap); | 1230 | i2c_put_adapter(adap); |
1231 | v4l2_clk_unregister(icd->clk); | ||
1232 | icd->clk = NULL; | ||
1142 | } | 1233 | } |
1143 | #else | 1234 | #else |
1144 | #define soc_camera_init_i2c(icd, sdesc) (-ENODEV) | 1235 | #define soc_camera_init_i2c(icd, sdesc) (-ENODEV) |
@@ -1176,26 +1267,31 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1176 | if (ssdd->reset) | 1267 | if (ssdd->reset) |
1177 | ssdd->reset(icd->pdev); | 1268 | ssdd->reset(icd->pdev); |
1178 | 1269 | ||
1179 | mutex_lock(&ici->host_lock); | ||
1180 | ret = ici->ops->clock_start(ici); | ||
1181 | mutex_unlock(&ici->host_lock); | ||
1182 | if (ret < 0) | ||
1183 | goto eadd; | ||
1184 | |||
1185 | /* Must have icd->vdev before registering the device */ | 1270 | /* Must have icd->vdev before registering the device */ |
1186 | ret = video_dev_create(icd); | 1271 | ret = video_dev_create(icd); |
1187 | if (ret < 0) | 1272 | if (ret < 0) |
1188 | goto evdc; | 1273 | goto evdc; |
1189 | 1274 | ||
1275 | /* | ||
1276 | * ..._video_start() will create a device node, video_register_device() | ||
1277 | * itself is protected against concurrent open() calls, but we also have | ||
1278 | * to protect our data also during client probing. | ||
1279 | */ | ||
1280 | mutex_lock(&ici->host_lock); | ||
1281 | |||
1190 | /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ | 1282 | /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ |
1191 | if (shd->board_info) { | 1283 | if (shd->board_info) { |
1192 | ret = soc_camera_init_i2c(icd, sdesc); | 1284 | ret = soc_camera_init_i2c(icd, sdesc); |
1193 | if (ret < 0) | 1285 | if (ret < 0) |
1194 | goto eadddev; | 1286 | goto eadd; |
1195 | } else if (!shd->add_device || !shd->del_device) { | 1287 | } else if (!shd->add_device || !shd->del_device) { |
1196 | ret = -EINVAL; | 1288 | ret = -EINVAL; |
1197 | goto eadddev; | 1289 | goto eadd; |
1198 | } else { | 1290 | } else { |
1291 | ret = ici->ops->clock_start(ici); | ||
1292 | if (ret < 0) | ||
1293 | goto eadd; | ||
1294 | |||
1199 | if (shd->module_name) | 1295 | if (shd->module_name) |
1200 | ret = request_module(shd->module_name); | 1296 | ret = request_module(shd->module_name); |
1201 | 1297 | ||
@@ -1231,13 +1327,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1231 | 1327 | ||
1232 | icd->field = V4L2_FIELD_ANY; | 1328 | icd->field = V4L2_FIELD_ANY; |
1233 | 1329 | ||
1234 | /* | ||
1235 | * ..._video_start() will create a device node, video_register_device() | ||
1236 | * itself is protected against concurrent open() calls, but we also have | ||
1237 | * to protect our data. | ||
1238 | */ | ||
1239 | mutex_lock(&ici->host_lock); | ||
1240 | |||
1241 | ret = soc_camera_video_start(icd); | 1330 | ret = soc_camera_video_start(icd); |
1242 | if (ret < 0) | 1331 | if (ret < 0) |
1243 | goto evidstart; | 1332 | goto evidstart; |
@@ -1250,14 +1339,14 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1250 | icd->field = mf.field; | 1339 | icd->field = mf.field; |
1251 | } | 1340 | } |
1252 | 1341 | ||
1253 | ici->ops->clock_stop(ici); | 1342 | if (!shd->board_info) |
1343 | ici->ops->clock_stop(ici); | ||
1254 | 1344 | ||
1255 | mutex_unlock(&ici->host_lock); | 1345 | mutex_unlock(&ici->host_lock); |
1256 | 1346 | ||
1257 | return 0; | 1347 | return 0; |
1258 | 1348 | ||
1259 | evidstart: | 1349 | evidstart: |
1260 | mutex_unlock(&ici->host_lock); | ||
1261 | soc_camera_free_user_formats(icd); | 1350 | soc_camera_free_user_formats(icd); |
1262 | eiufmt: | 1351 | eiufmt: |
1263 | ectrl: | 1352 | ectrl: |
@@ -1266,16 +1355,15 @@ ectrl: | |||
1266 | } else { | 1355 | } else { |
1267 | shd->del_device(icd); | 1356 | shd->del_device(icd); |
1268 | module_put(control->driver->owner); | 1357 | module_put(control->driver->owner); |
1269 | } | ||
1270 | enodrv: | 1358 | enodrv: |
1271 | eadddev: | 1359 | eadddev: |
1360 | ici->ops->clock_stop(ici); | ||
1361 | } | ||
1362 | eadd: | ||
1272 | video_device_release(icd->vdev); | 1363 | video_device_release(icd->vdev); |
1273 | icd->vdev = NULL; | 1364 | icd->vdev = NULL; |
1274 | evdc: | ||
1275 | mutex_lock(&ici->host_lock); | ||
1276 | ici->ops->clock_stop(ici); | ||
1277 | mutex_unlock(&ici->host_lock); | 1365 | mutex_unlock(&ici->host_lock); |
1278 | eadd: | 1366 | evdc: |
1279 | v4l2_ctrl_handler_free(&icd->ctrl_handler); | 1367 | v4l2_ctrl_handler_free(&icd->ctrl_handler); |
1280 | return ret; | 1368 | return ret; |
1281 | } | 1369 | } |
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index bdf909d2ec35..ceaddfb85e49 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c | |||
@@ -54,7 +54,7 @@ static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on) | |||
54 | { | 54 | { |
55 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | 55 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); |
56 | 56 | ||
57 | return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, on); | 57 | return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, NULL, on); |
58 | } | 58 | } |
59 | 59 | ||
60 | static struct v4l2_subdev_core_ops platform_subdev_core_ops = { | 60 | static struct v4l2_subdev_core_ops platform_subdev_core_ops = { |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index dfa24df960df..f582323fafb7 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -49,6 +49,7 @@ struct soc_camera_device { | |||
49 | /* soc_camera.c private count. Only accessed with .host_lock held */ | 49 | /* soc_camera.c private count. Only accessed with .host_lock held */ |
50 | int use_count; | 50 | int use_count; |
51 | struct file *streamer; /* stream owner */ | 51 | struct file *streamer; /* stream owner */ |
52 | struct v4l2_clk *clk; | ||
52 | union { | 53 | union { |
53 | struct videobuf_queue vb_vidq; | 54 | struct videobuf_queue vb_vidq; |
54 | struct vb2_queue vb2_vidq; | 55 | struct vb2_queue vb2_vidq; |
@@ -325,14 +326,16 @@ static inline void soc_camera_limit_side(int *start, int *length, | |||
325 | unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, | 326 | unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, |
326 | const struct v4l2_mbus_config *cfg); | 327 | const struct v4l2_mbus_config *cfg); |
327 | 328 | ||
328 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd); | 329 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, |
329 | int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd); | 330 | struct v4l2_clk *clk); |
331 | int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, | ||
332 | struct v4l2_clk *clk); | ||
330 | 333 | ||
331 | static inline int soc_camera_set_power(struct device *dev, | 334 | static inline int soc_camera_set_power(struct device *dev, |
332 | struct soc_camera_subdev_desc *ssdd, bool on) | 335 | struct soc_camera_subdev_desc *ssdd, struct v4l2_clk *clk, bool on) |
333 | { | 336 | { |
334 | return on ? soc_camera_power_on(dev, ssdd) | 337 | return on ? soc_camera_power_on(dev, ssdd, clk) |
335 | : soc_camera_power_off(dev, ssdd); | 338 | : soc_camera_power_off(dev, ssdd, clk); |
336 | } | 339 | } |
337 | 340 | ||
338 | /* This is only temporary here - until v4l2-subdev begins to link to video_device */ | 341 | /* This is only temporary here - until v4l2-subdev begins to link to video_device */ |