aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r--drivers/media/video/mt9m001.c77
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
213static int mt9m001_set_capture_format(struct soc_camera_device *icd, 213static 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
222static 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
248static 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
264static 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
351static 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
357const struct v4l2_queryctrl mt9m001_controls[] = { 375const 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,