diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/soc_camera.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index d3eeb08be321..9a62ed08d86a 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -53,10 +53,9 @@ static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | |||
53 | static int soc_camera_power_on(struct soc_camera_device *icd, | 53 | static int soc_camera_power_on(struct soc_camera_device *icd, |
54 | struct soc_camera_link *icl) | 54 | struct soc_camera_link *icl) |
55 | { | 55 | { |
56 | int ret; | 56 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
57 | 57 | int ret = regulator_bulk_enable(icl->num_regulators, | |
58 | ret = regulator_bulk_enable(icl->num_regulators, | 58 | icl->regulators); |
59 | icl->regulators); | ||
60 | if (ret < 0) { | 59 | if (ret < 0) { |
61 | dev_err(icd->pdev, "Cannot enable regulators\n"); | 60 | dev_err(icd->pdev, "Cannot enable regulators\n"); |
62 | return ret; | 61 | return ret; |
@@ -67,19 +66,33 @@ static int soc_camera_power_on(struct soc_camera_device *icd, | |||
67 | if (ret < 0) { | 66 | if (ret < 0) { |
68 | dev_err(icd->pdev, | 67 | dev_err(icd->pdev, |
69 | "Platform failed to power-on the camera.\n"); | 68 | "Platform failed to power-on the camera.\n"); |
70 | 69 | goto elinkpwr; | |
71 | regulator_bulk_disable(icl->num_regulators, | ||
72 | icl->regulators); | ||
73 | } | 70 | } |
74 | } | 71 | } |
75 | 72 | ||
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->pdev, 0); | ||
82 | elinkpwr: | ||
83 | regulator_bulk_disable(icl->num_regulators, | ||
84 | icl->regulators); | ||
76 | return ret; | 85 | return ret; |
77 | } | 86 | } |
78 | 87 | ||
79 | static int soc_camera_power_off(struct soc_camera_device *icd, | 88 | static int soc_camera_power_off(struct soc_camera_device *icd, |
80 | struct soc_camera_link *icl) | 89 | struct soc_camera_link *icl) |
81 | { | 90 | { |
82 | int ret; | 91 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
92 | int ret = v4l2_subdev_call(sd, core, s_power, 0); | ||
93 | |||
94 | if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) | ||
95 | return ret; | ||
83 | 96 | ||
84 | if (icl->power) { | 97 | if (icl->power) { |
85 | ret = icl->power(icd->pdev, 0); | 98 | ret = icl->power(icd->pdev, 0); |
@@ -1029,6 +1042,12 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1029 | if (ret < 0) | 1042 | if (ret < 0) |
1030 | goto ereg; | 1043 | goto ereg; |
1031 | 1044 | ||
1045 | /* | ||
1046 | * This will not yet call v4l2_subdev_core_ops::s_power(1), because the | ||
1047 | * subdevice has not been initialised yet. We'll have to call it once | ||
1048 | * again after initialisation, even though it shouldn't be needed, we | ||
1049 | * don't do any IO here. | ||
1050 | */ | ||
1032 | ret = soc_camera_power_on(icd, icl); | 1051 | ret = soc_camera_power_on(icd, icl); |
1033 | if (ret < 0) | 1052 | if (ret < 0) |
1034 | goto epower; | 1053 | goto epower; |
@@ -1099,6 +1118,10 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1099 | if (ret < 0) | 1118 | if (ret < 0) |
1100 | goto evidstart; | 1119 | goto evidstart; |
1101 | 1120 | ||
1121 | ret = v4l2_subdev_call(sd, core, s_power, 1); | ||
1122 | if (ret < 0 && ret != -ENOIOCTLCMD) | ||
1123 | goto esdpwr; | ||
1124 | |||
1102 | /* Try to improve our guess of a reasonable window format */ | 1125 | /* Try to improve our guess of a reasonable window format */ |
1103 | if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { | 1126 | if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { |
1104 | icd->user_width = mf.width; | 1127 | icd->user_width = mf.width; |
@@ -1115,6 +1138,8 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1115 | 1138 | ||
1116 | return 0; | 1139 | return 0; |
1117 | 1140 | ||
1141 | esdpwr: | ||
1142 | video_unregister_device(icd->vdev); | ||
1118 | evidstart: | 1143 | evidstart: |
1119 | mutex_unlock(&icd->video_lock); | 1144 | mutex_unlock(&icd->video_lock); |
1120 | soc_camera_free_user_formats(icd); | 1145 | soc_camera_free_user_formats(icd); |
@@ -1129,6 +1154,7 @@ ectrl: | |||
1129 | enodrv: | 1154 | enodrv: |
1130 | eadddev: | 1155 | eadddev: |
1131 | video_device_release(icd->vdev); | 1156 | video_device_release(icd->vdev); |
1157 | icd->vdev = NULL; | ||
1132 | evdc: | 1158 | evdc: |
1133 | ici->ops->remove(icd); | 1159 | ici->ops->remove(icd); |
1134 | eadd: | 1160 | eadd: |