diff options
-rw-r--r-- | drivers/media/i2c/soc_camera/imx074.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m001.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m111.c | 52 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t031.c | 11 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t112.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov2640.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov5642.c | 10 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov6650.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov772x.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.c | 10 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9740.c | 24 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/rj54n1cb0c.c | 9 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/tw9910.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera.c | 89 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera_platform.c | 11 | ||||
-rw-r--r-- | include/media/soc_camera.h | 10 |
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 | ||
271 | static 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 | |||
271 | static int imx074_g_mbus_config(struct v4l2_subdev *sd, | 279 | static 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 | ||
293 | static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { | 301 | static 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 | ||
297 | static struct v4l2_subdev_ops imx074_subdev_ops = { | 306 | static 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 | ||
380 | static 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 | |||
380 | static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 388 | static 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 | ||
571 | static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | 580 | static 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 | ||
834 | static 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 | |||
853 | static 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 | |||
834 | static int mt9m111_s_power(struct v4l2_subdev *sd, int on) | 862 | static 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 | ||
863 | out: | ||
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 = { | |||
616 | static int mt9t031_s_power(struct v4l2_subdev *sd, int on) | 616 | static 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 | ||
779 | static 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 | |||
779 | static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { | 787 | static 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 | ||
448 | static 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 | |||
448 | static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 456 | static 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 | ||
669 | static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | 678 | static 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 | ||
745 | static 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 */ |
746 | static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height) | 754 | static 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 | ||
993 | static int ov2640_g_mbus_config(struct v4l2_subdev *sd, | 1002 | static 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 | ||
934 | static int ov5642_s_power(struct v4l2_subdev *sd, int on) | 934 | static 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 | ||
435 | static 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 | |||
435 | static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 443 | static 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 | ||
686 | static 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 | |||
686 | static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) | 694 | static 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 | ||
1001 | static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | 1010 | static 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 | ||
336 | static 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 */ |
337 | static void ov9640_res_roundup(u32 *width, u32 *height) | 345 | static 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 | ||
787 | static int ov9740_s_power(struct v4l2_subdev *sd, int on) | 787 | static 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 | ||
1183 | static 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 | |||
1183 | static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) | 1191 | static 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 | ||
1235 | static int rj54n1_g_mbus_config(struct v4l2_subdev *sd, | 1244 | static 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 | ||
569 | static 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 | |||
569 | static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) | 577 | static 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 | ||
819 | static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | 828 | static 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); | |||
50 | static LIST_HEAD(devices); | 50 | static LIST_HEAD(devices); |
51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | 51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
52 | 52 | ||
53 | static int soc_camera_power_on(struct soc_camera_device *icd, | 53 | int 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 | |||
79 | esdpwr: | ||
80 | if (icl->power) | ||
81 | icl->power(icd->control, 0); | ||
82 | elinkpwr: | ||
83 | regulator_bulk_disable(icl->num_regulators, | ||
84 | icl->regulators); | ||
85 | return ret; | 72 | return ret; |
86 | } | 73 | } |
74 | EXPORT_SYMBOL(soc_camera_power_on); | ||
87 | 75 | ||
88 | static int soc_camera_power_off(struct soc_camera_device *icd, | 76 | int 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 | } |
99 | EXPORT_SYMBOL(soc_camera_power_off); | ||
100 | |||
101 | static 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 | |||
113 | static 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 | ||
120 | const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( | 125 | const 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: | |||
594 | esfmt: | 599 | esfmt: |
595 | pm_runtime_disable(&icd->vdev->dev); | 600 | pm_runtime_disable(&icd->vdev->dev); |
596 | eresume: | 601 | eresume: |
597 | soc_camera_power_off(icd, icl); | 602 | __soc_camera_power_off(icd); |
598 | epower: | 603 | epower: |
599 | ici->ops->remove(icd); | 604 | ici->ops->remove(icd); |
600 | eiciadd: | 605 | eiciadd: |
@@ -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; |
1186 | evdc: | 1195 | evdc: |
1187 | soc_camera_power_off(icd, icl); | 1196 | __soc_camera_power_off(icd); |
1188 | epower: | 1197 | epower: |
1189 | ici->ops->remove(icd); | 1198 | ici->ops->remove(icd); |
1190 | eadd: | 1199 | eadd: |
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 | ||
53 | static struct v4l2_subdev_core_ops platform_subdev_core_ops; | 53 | static 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 | |||
60 | static struct v4l2_subdev_core_ops platform_subdev_core_ops = { | ||
61 | .s_power = soc_camera_platform_s_power, | ||
62 | }; | ||
54 | 63 | ||
55 | static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | 64 | static 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, | |||
254 | unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl, | 254 | unsigned 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 | ||
257 | int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl); | ||
258 | int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl); | ||
259 | |||
260 | static 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> |
259 | static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client) | 269 | static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client) |