diff options
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r-- | drivers/media/video/mt9m001.c | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 4ad834326fa8..acb5454b57eb 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -210,40 +210,64 @@ static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) | |||
210 | #endif | 210 | #endif |
211 | } | 211 | } |
212 | 212 | ||
213 | static int mt9m001_set_capture_format(struct soc_camera_device *icd, | 213 | static int bus_switch_possible(struct mt9m001 *mt9m001) |
214 | __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) | 214 | { |
215 | #ifdef CONFIG_MT9M001_PCA9536_SWITCH | ||
216 | return gpio_is_valid(mt9m001->switch_gpio); | ||
217 | #else | ||
218 | return 0; | ||
219 | #endif | ||
220 | } | ||
221 | |||
222 | static int mt9m001_set_bus_param(struct soc_camera_device *icd, | ||
223 | unsigned long flags) | ||
215 | { | 224 | { |
216 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 225 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); |
217 | unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | | 226 | unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; |
218 | IS_DATAWIDTH_8); | ||
219 | int ret; | 227 | int ret; |
220 | const u16 hblank = 9, vblank = 25; | ||
221 | 228 | ||
222 | /* MT9M001 has all capture_format parameters fixed */ | 229 | /* Flags validity verified in test_bus_param */ |
223 | if (!(flags & IS_MASTER) || | ||
224 | !(flags & IS_PCLK_SAMPLE_RISING) || | ||
225 | !(flags & IS_HSYNC_ACTIVE_HIGH) || | ||
226 | !(flags & IS_VSYNC_ACTIVE_HIGH)) | ||
227 | return -EINVAL; | ||
228 | |||
229 | /* Only one width bit may be set */ | ||
230 | if (!is_power_of_2(width_flag)) | ||
231 | return -EINVAL; | ||
232 | 230 | ||
233 | if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || | 231 | if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || |
234 | (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || | 232 | (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || |
235 | (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { | 233 | (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { |
236 | /* Well, we actually only can do 10 or 8 bits... */ | 234 | /* Well, we actually only can do 10 or 8 bits... */ |
237 | if (width_flag == IS_DATAWIDTH_9) | 235 | if (width_flag == SOCAM_DATAWIDTH_9) |
238 | return -EINVAL; | 236 | return -EINVAL; |
239 | ret = bus_switch_act(mt9m001, | 237 | ret = bus_switch_act(mt9m001, |
240 | width_flag == IS_DATAWIDTH_8); | 238 | width_flag == SOCAM_DATAWIDTH_8); |
241 | if (ret < 0) | 239 | if (ret < 0) |
242 | return ret; | 240 | return ret; |
243 | 241 | ||
244 | mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; | 242 | mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; |
245 | } | 243 | } |
246 | 244 | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) | ||
249 | { | ||
250 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
251 | unsigned int width_flag = SOCAM_DATAWIDTH_10; | ||
252 | |||
253 | if (bus_switch_possible(mt9m001)) | ||
254 | width_flag |= SOCAM_DATAWIDTH_8; | ||
255 | |||
256 | /* MT9M001 has all capture_format parameters fixed */ | ||
257 | return SOCAM_PCLK_SAMPLE_RISING | | ||
258 | SOCAM_HSYNC_ACTIVE_HIGH | | ||
259 | SOCAM_VSYNC_ACTIVE_HIGH | | ||
260 | SOCAM_MASTER | | ||
261 | width_flag; | ||
262 | } | ||
263 | |||
264 | static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | ||
265 | __u32 pixfmt, struct v4l2_rect *rect) | ||
266 | { | ||
267 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
268 | int ret; | ||
269 | const u16 hblank = 9, vblank = 25; | ||
270 | |||
247 | /* Blanking and start values - default... */ | 271 | /* Blanking and start values - default... */ |
248 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); | 272 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); |
249 | if (ret >= 0) | 273 | if (ret >= 0) |
@@ -348,12 +372,6 @@ static int mt9m001_set_register(struct soc_camera_device *icd, | |||
348 | } | 372 | } |
349 | #endif | 373 | #endif |
350 | 374 | ||
351 | static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) | ||
352 | { | ||
353 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
354 | return mt9m001->datawidth; | ||
355 | } | ||
356 | |||
357 | const struct v4l2_queryctrl mt9m001_controls[] = { | 375 | const struct v4l2_queryctrl mt9m001_controls[] = { |
358 | { | 376 | { |
359 | .id = V4L2_CID_VFLIP, | 377 | .id = V4L2_CID_VFLIP, |
@@ -401,11 +419,12 @@ static struct soc_camera_ops mt9m001_ops = { | |||
401 | .release = mt9m001_release, | 419 | .release = mt9m001_release, |
402 | .start_capture = mt9m001_start_capture, | 420 | .start_capture = mt9m001_start_capture, |
403 | .stop_capture = mt9m001_stop_capture, | 421 | .stop_capture = mt9m001_stop_capture, |
404 | .set_capture_format = mt9m001_set_capture_format, | 422 | .set_fmt_cap = mt9m001_set_fmt_cap, |
405 | .try_fmt_cap = mt9m001_try_fmt_cap, | 423 | .try_fmt_cap = mt9m001_try_fmt_cap, |
424 | .set_bus_param = mt9m001_set_bus_param, | ||
425 | .query_bus_param = mt9m001_query_bus_param, | ||
406 | .formats = NULL, /* Filled in later depending on the */ | 426 | .formats = NULL, /* Filled in later depending on the */ |
407 | .num_formats = 0, /* camera type and data widths */ | 427 | .num_formats = 0, /* camera type and data widths */ |
408 | .get_datawidth = mt9m001_get_datawidth, | ||
409 | .controls = mt9m001_controls, | 428 | .controls = mt9m001_controls, |
410 | .num_controls = ARRAY_SIZE(mt9m001_controls), | 429 | .num_controls = ARRAY_SIZE(mt9m001_controls), |
411 | .get_control = mt9m001_get_control, | 430 | .get_control = mt9m001_get_control, |