aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/i2c/soc_camera/imx074.c9
-rw-r--r--drivers/media/i2c/soc_camera/mt9m001.c9
-rw-r--r--drivers/media/i2c/soc_camera/mt9m111.c52
-rw-r--r--drivers/media/i2c/soc_camera/mt9t031.c11
-rw-r--r--drivers/media/i2c/soc_camera/mt9t112.c9
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c9
-rw-r--r--drivers/media/i2c/soc_camera/ov2640.c9
-rw-r--r--drivers/media/i2c/soc_camera/ov5642.c10
-rw-r--r--drivers/media/i2c/soc_camera/ov6650.c9
-rw-r--r--drivers/media/i2c/soc_camera/ov772x.c9
-rw-r--r--drivers/media/i2c/soc_camera/ov9640.c10
-rw-r--r--drivers/media/i2c/soc_camera/ov9740.c24
-rw-r--r--drivers/media/i2c/soc_camera/rj54n1cb0c.c9
-rw-r--r--drivers/media/i2c/soc_camera/tw9910.c9
-rw-r--r--drivers/media/platform/soc_camera.c89
-rw-r--r--drivers/media/platform/soc_camera_platform.c11
-rw-r--r--include/media/soc_camera.h10
17 files changed, 229 insertions, 69 deletions
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
index 351e9bafe8fe..ade19873ed83 100644
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -268,6 +268,14 @@ static int imx074_g_chip_ident(struct v4l2_subdev *sd,
268 return 0; 268 return 0;
269} 269}
270 270
271static int imx074_s_power(struct v4l2_subdev *sd, int on)
272{
273 struct i2c_client *client = v4l2_get_subdevdata(sd);
274 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
275
276 return soc_camera_set_power(&client->dev, icl, on);
277}
278
271static int imx074_g_mbus_config(struct v4l2_subdev *sd, 279static int imx074_g_mbus_config(struct v4l2_subdev *sd,
272 struct v4l2_mbus_config *cfg) 280 struct v4l2_mbus_config *cfg)
273{ 281{
@@ -292,6 +300,7 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
292 300
293static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { 301static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
294 .g_chip_ident = imx074_g_chip_ident, 302 .g_chip_ident = imx074_g_chip_ident,
303 .s_power = imx074_s_power,
295}; 304};
296 305
297static struct v4l2_subdev_ops imx074_subdev_ops = { 306static struct v4l2_subdev_ops imx074_subdev_ops = {
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index 00583f5fd26b..cd71230c51a9 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -377,6 +377,14 @@ static int mt9m001_s_register(struct v4l2_subdev *sd,
377} 377}
378#endif 378#endif
379 379
380static int mt9m001_s_power(struct v4l2_subdev *sd, int on)
381{
382 struct i2c_client *client = v4l2_get_subdevdata(sd);
383 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
384
385 return soc_camera_set_power(&client->dev, icl, on);
386}
387
380static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 388static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
381{ 389{
382 struct mt9m001 *mt9m001 = container_of(ctrl->handler, 390 struct mt9m001 *mt9m001 = container_of(ctrl->handler,
@@ -566,6 +574,7 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
566 .g_register = mt9m001_g_register, 574 .g_register = mt9m001_g_register,
567 .s_register = mt9m001_s_register, 575 .s_register = mt9m001_s_register,
568#endif 576#endif
577 .s_power = mt9m001_s_power,
569}; 578};
570 579
571static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 580static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index 863d722dda06..e555f7739691 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -831,10 +831,37 @@ static int mt9m111_video_probe(struct i2c_client *client)
831 return v4l2_ctrl_handler_setup(&mt9m111->hdl); 831 return v4l2_ctrl_handler_setup(&mt9m111->hdl);
832} 832}
833 833
834static int mt9m111_power_on(struct mt9m111 *mt9m111)
835{
836 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
837 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
838 int ret;
839
840 ret = soc_camera_power_on(&client->dev, icl);
841 if (ret < 0)
842 return ret;
843
844 ret = mt9m111_resume(mt9m111);
845 if (ret < 0) {
846 dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
847 soc_camera_power_off(&client->dev, icl);
848 }
849
850 return ret;
851}
852
853static void mt9m111_power_off(struct mt9m111 *mt9m111)
854{
855 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
856 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
857
858 mt9m111_suspend(mt9m111);
859 soc_camera_power_off(&client->dev, icl);
860}
861
834static int mt9m111_s_power(struct v4l2_subdev *sd, int on) 862static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
835{ 863{
836 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); 864 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
837 struct i2c_client *client = v4l2_get_subdevdata(sd);
838 int ret = 0; 865 int ret = 0;
839 866
840 mutex_lock(&mt9m111->power_lock); 867 mutex_lock(&mt9m111->power_lock);
@@ -844,23 +871,18 @@ static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
844 * update the power state. 871 * update the power state.
845 */ 872 */
846 if (mt9m111->power_count == !on) { 873 if (mt9m111->power_count == !on) {
847 if (on) { 874 if (on)
848 ret = mt9m111_resume(mt9m111); 875 ret = mt9m111_power_on(mt9m111);
849 if (ret) { 876 else
850 dev_err(&client->dev, 877 mt9m111_power_off(mt9m111);
851 "Failed to resume the sensor: %d\n", ret);
852 goto out;
853 }
854 } else {
855 mt9m111_suspend(mt9m111);
856 }
857 } 878 }
858 879
859 /* Update the power count. */ 880 if (!ret) {
860 mt9m111->power_count += on ? 1 : -1; 881 /* Update the power count. */
861 WARN_ON(mt9m111->power_count < 0); 882 mt9m111->power_count += on ? 1 : -1;
883 WARN_ON(mt9m111->power_count < 0);
884 }
862 885
863out:
864 mutex_unlock(&mt9m111->power_lock); 886 mutex_unlock(&mt9m111->power_lock);
865 return ret; 887 return ret;
866} 888}
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index 1415074138a5..9666e202e395 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -616,12 +616,19 @@ static struct device_type mt9t031_dev_type = {
616static int mt9t031_s_power(struct v4l2_subdev *sd, int on) 616static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
617{ 617{
618 struct i2c_client *client = v4l2_get_subdevdata(sd); 618 struct i2c_client *client = v4l2_get_subdevdata(sd);
619 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
619 struct video_device *vdev = soc_camera_i2c_to_vdev(client); 620 struct video_device *vdev = soc_camera_i2c_to_vdev(client);
621 int ret;
620 622
621 if (on) 623 if (on) {
624 ret = soc_camera_power_on(&client->dev, icl);
625 if (ret < 0)
626 return ret;
622 vdev->dev.type = &mt9t031_dev_type; 627 vdev->dev.type = &mt9t031_dev_type;
623 else 628 } else {
624 vdev->dev.type = NULL; 629 vdev->dev.type = NULL;
630 soc_camera_power_off(&client->dev, icl);
631 }
625 632
626 return 0; 633 return 0;
627} 634}
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index e1ae46a7ee96..624ceec44e18 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -776,12 +776,21 @@ static int mt9t112_s_register(struct v4l2_subdev *sd,
776} 776}
777#endif 777#endif
778 778
779static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
780{
781 struct i2c_client *client = v4l2_get_subdevdata(sd);
782 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
783
784 return soc_camera_set_power(&client->dev, icl, on);
785}
786
779static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { 787static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
780 .g_chip_ident = mt9t112_g_chip_ident, 788 .g_chip_ident = mt9t112_g_chip_ident,
781#ifdef CONFIG_VIDEO_ADV_DEBUG 789#ifdef CONFIG_VIDEO_ADV_DEBUG
782 .g_register = mt9t112_g_register, 790 .g_register = mt9t112_g_register,
783 .s_register = mt9t112_s_register, 791 .s_register = mt9t112_s_register,
784#endif 792#endif
793 .s_power = mt9t112_s_power,
785}; 794};
786 795
787 796
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 72479247522a..5f09cb702bf7 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -445,6 +445,14 @@ static int mt9v022_s_register(struct v4l2_subdev *sd,
445} 445}
446#endif 446#endif
447 447
448static int mt9v022_s_power(struct v4l2_subdev *sd, int on)
449{
450 struct i2c_client *client = v4l2_get_subdevdata(sd);
451 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
452
453 return soc_camera_set_power(&client->dev, icl, on);
454}
455
448static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 456static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
449{ 457{
450 struct mt9v022 *mt9v022 = container_of(ctrl->handler, 458 struct mt9v022 *mt9v022 = container_of(ctrl->handler,
@@ -664,6 +672,7 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
664 .g_register = mt9v022_g_register, 672 .g_register = mt9v022_g_register,
665 .s_register = mt9v022_s_register, 673 .s_register = mt9v022_s_register,
666#endif 674#endif
675 .s_power = mt9v022_s_power,
667}; 676};
668 677
669static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 678static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 7c44d1fe3c87..16ed091c702d 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -742,6 +742,14 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
742} 742}
743#endif 743#endif
744 744
745static int ov2640_s_power(struct v4l2_subdev *sd, int on)
746{
747 struct i2c_client *client = v4l2_get_subdevdata(sd);
748 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
749
750 return soc_camera_set_power(&client->dev, icl, on);
751}
752
745/* Select the nearest higher resolution for capture */ 753/* Select the nearest higher resolution for capture */
746static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height) 754static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
747{ 755{
@@ -988,6 +996,7 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
988 .g_register = ov2640_g_register, 996 .g_register = ov2640_g_register,
989 .s_register = ov2640_s_register, 997 .s_register = ov2640_s_register,
990#endif 998#endif
999 .s_power = ov2640_s_power,
991}; 1000};
992 1001
993static int ov2640_g_mbus_config(struct v4l2_subdev *sd, 1002static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index 0bc93313d37a..61824c6911d5 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -933,13 +933,17 @@ static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
933 933
934static int ov5642_s_power(struct v4l2_subdev *sd, int on) 934static int ov5642_s_power(struct v4l2_subdev *sd, int on)
935{ 935{
936 struct i2c_client *client; 936 struct i2c_client *client = v4l2_get_subdevdata(sd);
937 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
937 int ret; 938 int ret;
938 939
939 if (!on) 940 if (!on)
940 return 0; 941 return soc_camera_power_off(&client->dev, icl);
942
943 ret = soc_camera_power_on(&client->dev, icl);
944 if (ret < 0)
945 return ret;
941 946
942 client = v4l2_get_subdevdata(sd);
943 ret = ov5642_write_array(client, ov5642_default_regs_init); 947 ret = ov5642_write_array(client, ov5642_default_regs_init);
944 if (!ret) 948 if (!ret)
945 ret = ov5642_set_resolution(sd); 949 ret = ov5642_set_resolution(sd);
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index 3e028b1970dd..12d57a5dd810 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -432,6 +432,14 @@ static int ov6650_set_register(struct v4l2_subdev *sd,
432} 432}
433#endif 433#endif
434 434
435static int ov6650_s_power(struct v4l2_subdev *sd, int on)
436{
437 struct i2c_client *client = v4l2_get_subdevdata(sd);
438 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
439
440 return soc_camera_set_power(&client->dev, icl, on);
441}
442
435static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 443static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
436{ 444{
437 struct i2c_client *client = v4l2_get_subdevdata(sd); 445 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -866,6 +874,7 @@ static struct v4l2_subdev_core_ops ov6650_core_ops = {
866 .g_register = ov6650_get_register, 874 .g_register = ov6650_get_register,
867 .s_register = ov6650_set_register, 875 .s_register = ov6650_set_register,
868#endif 876#endif
877 .s_power = ov6650_s_power,
869}; 878};
870 879
871/* Request bus settings on camera side */ 880/* Request bus settings on camera side */
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index 6d79b89b8603..a022662da98a 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -683,6 +683,14 @@ static int ov772x_s_register(struct v4l2_subdev *sd,
683} 683}
684#endif 684#endif
685 685
686static int ov772x_s_power(struct v4l2_subdev *sd, int on)
687{
688 struct i2c_client *client = v4l2_get_subdevdata(sd);
689 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
690
691 return soc_camera_set_power(&client->dev, icl, on);
692}
693
686static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) 694static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
687{ 695{
688 __u32 diff; 696 __u32 diff;
@@ -996,6 +1004,7 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
996 .g_register = ov772x_g_register, 1004 .g_register = ov772x_g_register,
997 .s_register = ov772x_s_register, 1005 .s_register = ov772x_s_register,
998#endif 1006#endif
1007 .s_power = ov772x_s_power,
999}; 1008};
1000 1009
1001static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 1010static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index 9ed4ba4236c4..53156ef1ec0c 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -333,6 +333,14 @@ static int ov9640_set_register(struct v4l2_subdev *sd,
333} 333}
334#endif 334#endif
335 335
336static int ov9640_s_power(struct v4l2_subdev *sd, int on)
337{
338 struct i2c_client *client = v4l2_get_subdevdata(sd);
339 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
340
341 return soc_camera_set_power(&client->dev, icl, on);
342}
343
336/* select nearest higher resolution for capture */ 344/* select nearest higher resolution for capture */
337static void ov9640_res_roundup(u32 *width, u32 *height) 345static void ov9640_res_roundup(u32 *width, u32 *height)
338{ 346{
@@ -632,7 +640,7 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = {
632 .g_register = ov9640_get_register, 640 .g_register = ov9640_get_register,
633 .s_register = ov9640_set_register, 641 .s_register = ov9640_set_register,
634#endif 642#endif
635 643 .s_power = ov9640_s_power,
636}; 644};
637 645
638/* Request bus settings on camera side */ 646/* Request bus settings on camera side */
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 3eb07c22516e..10c0ba9f5bcd 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -786,17 +786,27 @@ static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
786 786
787static int ov9740_s_power(struct v4l2_subdev *sd, int on) 787static int ov9740_s_power(struct v4l2_subdev *sd, int on)
788{ 788{
789 struct i2c_client *client = v4l2_get_subdevdata(sd);
790 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
789 struct ov9740_priv *priv = to_ov9740(sd); 791 struct ov9740_priv *priv = to_ov9740(sd);
790 792 int ret;
791 if (!priv->current_enable)
792 return 0;
793 793
794 if (on) { 794 if (on) {
795 ov9740_s_fmt(sd, &priv->current_mf); 795 ret = soc_camera_power_on(&client->dev, icl);
796 ov9740_s_stream(sd, priv->current_enable); 796 if (ret < 0)
797 return ret;
798
799 if (priv->current_enable) {
800 ov9740_s_fmt(sd, &priv->current_mf);
801 ov9740_s_stream(sd, 1);
802 }
797 } else { 803 } else {
798 ov9740_s_stream(sd, 0); 804 if (priv->current_enable) {
799 priv->current_enable = true; 805 ov9740_s_stream(sd, 0);
806 priv->current_enable = true;
807 }
808
809 soc_camera_power_off(&client->dev, icl);
800 } 810 }
801 811
802 return 0; 812 return 0;
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index f6419b22c258..ca1cee7c66cb 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -1180,6 +1180,14 @@ static int rj54n1_s_register(struct v4l2_subdev *sd,
1180} 1180}
1181#endif 1181#endif
1182 1182
1183static int rj54n1_s_power(struct v4l2_subdev *sd, int on)
1184{
1185 struct i2c_client *client = v4l2_get_subdevdata(sd);
1186 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
1187
1188 return soc_camera_set_power(&client->dev, icl, on);
1189}
1190
1183static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) 1191static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
1184{ 1192{
1185 struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl); 1193 struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
@@ -1230,6 +1238,7 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
1230 .g_register = rj54n1_g_register, 1238 .g_register = rj54n1_g_register,
1231 .s_register = rj54n1_s_register, 1239 .s_register = rj54n1_s_register,
1232#endif 1240#endif
1241 .s_power = rj54n1_s_power,
1233}; 1242};
1234 1243
1235static int rj54n1_g_mbus_config(struct v4l2_subdev *sd, 1244static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index 9f53eacb66e3..f28365051878 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -566,6 +566,14 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
566} 566}
567#endif 567#endif
568 568
569static int tw9910_s_power(struct v4l2_subdev *sd, int on)
570{
571 struct i2c_client *client = v4l2_get_subdevdata(sd);
572 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
573
574 return soc_camera_set_power(&client->dev, icl, on);
575}
576
569static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) 577static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
570{ 578{
571 struct i2c_client *client = v4l2_get_subdevdata(sd); 579 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -814,6 +822,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
814 .g_register = tw9910_g_register, 822 .g_register = tw9910_g_register,
815 .s_register = tw9910_s_register, 823 .s_register = tw9910_s_register,
816#endif 824#endif
825 .s_power = tw9910_s_power,
817}; 826};
818 827
819static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 828static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
diff --git a/drivers/media/platform/soc_camera.c b/drivers/media/platform/soc_camera.c
index 3feb43b4f281..8e1548e16f54 100644
--- a/drivers/media/platform/soc_camera.c
+++ b/drivers/media/platform/soc_camera.c
@@ -50,72 +50,77 @@ static LIST_HEAD(hosts);
50static LIST_HEAD(devices); 50static LIST_HEAD(devices);
51static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ 51static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
52 52
53static int soc_camera_power_on(struct soc_camera_device *icd, 53int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl)
54 struct soc_camera_link *icl)
55{ 54{
56 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
57 int ret = regulator_bulk_enable(icl->num_regulators, 55 int ret = regulator_bulk_enable(icl->num_regulators,
58 icl->regulators); 56 icl->regulators);
59 if (ret < 0) { 57 if (ret < 0) {
60 dev_err(icd->pdev, "Cannot enable regulators\n"); 58 dev_err(dev, "Cannot enable regulators\n");
61 return ret; 59 return ret;
62 } 60 }
63 61
64 if (icl->power) { 62 if (icl->power) {
65 ret = icl->power(icd->control, 1); 63 ret = icl->power(dev, 1);
66 if (ret < 0) { 64 if (ret < 0) {
67 dev_err(icd->pdev, 65 dev_err(dev,
68 "Platform failed to power-on the camera.\n"); 66 "Platform failed to power-on the camera.\n");
69 goto elinkpwr; 67 regulator_bulk_disable(icl->num_regulators,
68 icl->regulators);
70 } 69 }
71 } 70 }
72 71
73 ret = v4l2_subdev_call(sd, core, s_power, 1);
74 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
75 goto esdpwr;
76
77 return 0;
78
79esdpwr:
80 if (icl->power)
81 icl->power(icd->control, 0);
82elinkpwr:
83 regulator_bulk_disable(icl->num_regulators,
84 icl->regulators);
85 return ret; 72 return ret;
86} 73}
74EXPORT_SYMBOL(soc_camera_power_on);
87 75
88static int soc_camera_power_off(struct soc_camera_device *icd, 76int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl)
89 struct soc_camera_link *icl)
90{ 77{
91 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
92 int ret = 0; 78 int ret = 0;
93 int err; 79 int err;
94 80
95 err = v4l2_subdev_call(sd, core, s_power, 0);
96 if (err < 0 && err != -ENOIOCTLCMD && err != -ENODEV) {
97 dev_err(icd->pdev, "Subdev failed to power-off the camera.\n");
98 ret = err;
99 }
100
101 if (icl->power) { 81 if (icl->power) {
102 err = icl->power(icd->control, 0); 82 err = icl->power(dev, 0);
103 if (err < 0) { 83 if (err < 0) {
104 dev_err(icd->pdev, 84 dev_err(dev,
105 "Platform failed to power-off the camera.\n"); 85 "Platform failed to power-off the camera.\n");
106 ret = ret ? : err; 86 ret = err;
107 } 87 }
108 } 88 }
109 89
110 err = regulator_bulk_disable(icl->num_regulators, 90 err = regulator_bulk_disable(icl->num_regulators,
111 icl->regulators); 91 icl->regulators);
112 if (err < 0) { 92 if (err < 0) {
113 dev_err(icd->pdev, "Cannot disable regulators\n"); 93 dev_err(dev, "Cannot disable regulators\n");
114 ret = ret ? : err; 94 ret = ret ? : err;
115 } 95 }
116 96
117 return ret; 97 return ret;
118} 98}
99EXPORT_SYMBOL(soc_camera_power_off);
100
101static int __soc_camera_power_on(struct soc_camera_device *icd)
102{
103 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
104 int ret;
105
106 ret = v4l2_subdev_call(sd, core, s_power, 1);
107 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
108 return ret;
109
110 return 0;
111}
112
113static int __soc_camera_power_off(struct soc_camera_device *icd)
114{
115 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
116 int ret;
117
118 ret = v4l2_subdev_call(sd, core, s_power, 0);
119 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
120 return ret;
121
122 return 0;
123}
119 124
120const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( 125const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
121 struct soc_camera_device *icd, unsigned int fourcc) 126 struct soc_camera_device *icd, unsigned int fourcc)
@@ -551,7 +556,7 @@ static int soc_camera_open(struct file *file)
551 goto eiciadd; 556 goto eiciadd;
552 } 557 }
553 558
554 ret = soc_camera_power_on(icd, icl); 559 ret = __soc_camera_power_on(icd);
555 if (ret < 0) 560 if (ret < 0)
556 goto epower; 561 goto epower;
557 562
@@ -594,7 +599,7 @@ einitvb:
594esfmt: 599esfmt:
595 pm_runtime_disable(&icd->vdev->dev); 600 pm_runtime_disable(&icd->vdev->dev);
596eresume: 601eresume:
597 soc_camera_power_off(icd, icl); 602 __soc_camera_power_off(icd);
598epower: 603epower:
599 ici->ops->remove(icd); 604 ici->ops->remove(icd);
600eiciadd: 605eiciadd:
@@ -614,8 +619,6 @@ static int soc_camera_close(struct file *file)
614 mutex_lock(&icd->video_lock); 619 mutex_lock(&icd->video_lock);
615 icd->use_count--; 620 icd->use_count--;
616 if (!icd->use_count) { 621 if (!icd->use_count) {
617 struct soc_camera_link *icl = to_soc_camera_link(icd);
618
619 pm_runtime_suspend(&icd->vdev->dev); 622 pm_runtime_suspend(&icd->vdev->dev);
620 pm_runtime_disable(&icd->vdev->dev); 623 pm_runtime_disable(&icd->vdev->dev);
621 624
@@ -623,7 +626,7 @@ static int soc_camera_close(struct file *file)
623 vb2_queue_release(&icd->vb2_vidq); 626 vb2_queue_release(&icd->vb2_vidq);
624 ici->ops->remove(icd); 627 ici->ops->remove(icd);
625 628
626 soc_camera_power_off(icd, icl); 629 __soc_camera_power_off(icd);
627 } 630 }
628 631
629 if (icd->streamer == file) 632 if (icd->streamer == file)
@@ -1088,8 +1091,14 @@ static int soc_camera_probe(struct soc_camera_device *icd)
1088 * subdevice has not been initialised yet. We'll have to call it once 1091 * subdevice has not been initialised yet. We'll have to call it once
1089 * again after initialisation, even though it shouldn't be needed, we 1092 * again after initialisation, even though it shouldn't be needed, we
1090 * don't do any IO here. 1093 * don't do any IO here.
1094 *
1095 * The device pointer passed to soc_camera_power_on(), and ultimately to
1096 * the platform callback, should be the subdev physical device. However,
1097 * we have no way to retrieve a pointer to that device here. This isn't
1098 * a real issue, as no platform currently uses the device pointer, and
1099 * this soc_camera_power_on() call will be removed in the next commit.
1091 */ 1100 */
1092 ret = soc_camera_power_on(icd, icl); 1101 ret = soc_camera_power_on(icd->pdev, icl);
1093 if (ret < 0) 1102 if (ret < 0)
1094 goto epower; 1103 goto epower;
1095 1104
@@ -1162,7 +1171,7 @@ static int soc_camera_probe(struct soc_camera_device *icd)
1162 1171
1163 ici->ops->remove(icd); 1172 ici->ops->remove(icd);
1164 1173
1165 soc_camera_power_off(icd, icl); 1174 __soc_camera_power_off(icd);
1166 1175
1167 mutex_unlock(&icd->video_lock); 1176 mutex_unlock(&icd->video_lock);
1168 1177
@@ -1184,7 +1193,7 @@ eadddev:
1184 video_device_release(icd->vdev); 1193 video_device_release(icd->vdev);
1185 icd->vdev = NULL; 1194 icd->vdev = NULL;
1186evdc: 1195evdc:
1187 soc_camera_power_off(icd, icl); 1196 __soc_camera_power_off(icd);
1188epower: 1197epower:
1189 ici->ops->remove(icd); 1198 ici->ops->remove(icd);
1190eadd: 1199eadd:
diff --git a/drivers/media/platform/soc_camera_platform.c b/drivers/media/platform/soc_camera_platform.c
index f59ccade07c8..7cf7fd16481f 100644
--- a/drivers/media/platform/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera_platform.c
@@ -50,7 +50,16 @@ static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd,
50 return 0; 50 return 0;
51} 51}
52 52
53static struct v4l2_subdev_core_ops platform_subdev_core_ops; 53static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on)
54{
55 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
56
57 return soc_camera_set_power(p->icd->control, p->icd->link, on);
58}
59
60static struct v4l2_subdev_core_ops platform_subdev_core_ops = {
61 .s_power = soc_camera_platform_s_power,
62};
54 63
55static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 64static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
56 enum v4l2_mbus_pixelcode *code) 65 enum v4l2_mbus_pixelcode *code)
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index d865dcf9879f..982bfc948414 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -254,6 +254,16 @@ unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
254unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl, 254unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl,
255 const struct v4l2_mbus_config *cfg); 255 const struct v4l2_mbus_config *cfg);
256 256
257int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl);
258int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl);
259
260static inline int soc_camera_set_power(struct device *dev,
261 struct soc_camera_link *icl, bool on)
262{
263 return on ? soc_camera_power_on(dev, icl)
264 : soc_camera_power_off(dev, icl);
265}
266
257/* This is only temporary here - until v4l2-subdev begins to link to video_device */ 267/* This is only temporary here - until v4l2-subdev begins to link to video_device */
258#include <linux/i2c.h> 268#include <linux/i2c.h>
259static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client) 269static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client)