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.c164
1 files changed, 58 insertions, 106 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index c1bf75ef2741..fa7e5093edeb 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -12,7 +12,6 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/i2c.h> 13#include <linux/i2c.h>
14#include <linux/log2.h> 14#include <linux/log2.h>
15#include <linux/gpio.h>
16 15
17#include <media/v4l2-common.h> 16#include <media/v4l2-common.h>
18#include <media/v4l2-chip-ident.h> 17#include <media/v4l2-chip-ident.h>
@@ -73,9 +72,7 @@ struct mt9m001 {
73 struct i2c_client *client; 72 struct i2c_client *client;
74 struct soc_camera_device icd; 73 struct soc_camera_device icd;
75 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ 74 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
76 int switch_gpio;
77 unsigned char autoexposure; 75 unsigned char autoexposure;
78 unsigned char datawidth;
79}; 76};
80 77
81static int reg_read(struct soc_camera_device *icd, const u8 reg) 78static int reg_read(struct soc_camera_device *icd, const u8 reg)
@@ -181,92 +178,28 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
181 return 0; 178 return 0;
182} 179}
183 180
184static int bus_switch_request(struct mt9m001 *mt9m001,
185 struct soc_camera_link *icl)
186{
187#ifdef CONFIG_MT9M001_PCA9536_SWITCH
188 int ret;
189 unsigned int gpio = icl->gpio;
190
191 if (gpio_is_valid(gpio)) {
192 /* We have a data bus switch. */
193 ret = gpio_request(gpio, "mt9m001");
194 if (ret < 0) {
195 dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
196 gpio);
197 return ret;
198 }
199
200 ret = gpio_direction_output(gpio, 0);
201 if (ret < 0) {
202 dev_err(&mt9m001->client->dev,
203 "Cannot set GPIO %u to output\n", gpio);
204 gpio_free(gpio);
205 return ret;
206 }
207 }
208
209 mt9m001->switch_gpio = gpio;
210#else
211 mt9m001->switch_gpio = -EINVAL;
212#endif
213 return 0;
214}
215
216static void bus_switch_release(struct mt9m001 *mt9m001)
217{
218#ifdef CONFIG_MT9M001_PCA9536_SWITCH
219 if (gpio_is_valid(mt9m001->switch_gpio))
220 gpio_free(mt9m001->switch_gpio);
221#endif
222}
223
224static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
225{
226#ifdef CONFIG_MT9M001_PCA9536_SWITCH
227 if (!gpio_is_valid(mt9m001->switch_gpio))
228 return -ENODEV;
229
230 gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
231 return 0;
232#else
233 return -ENODEV;
234#endif
235}
236
237static int bus_switch_possible(struct mt9m001 *mt9m001)
238{
239#ifdef CONFIG_MT9M001_PCA9536_SWITCH
240 return gpio_is_valid(mt9m001->switch_gpio);
241#else
242 return 0;
243#endif
244}
245
246static int mt9m001_set_bus_param(struct soc_camera_device *icd, 181static int mt9m001_set_bus_param(struct soc_camera_device *icd,
247 unsigned long flags) 182 unsigned long flags)
248{ 183{
249 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 184 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
250 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; 185 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
251 int ret; 186 unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
252 187
253 /* Flags validity verified in test_bus_param */ 188 /* Only one width bit may be set */
189 if (!is_power_of_2(width_flag))
190 return -EINVAL;
254 191
255 if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || 192 if (icl->set_bus_param)
256 (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || 193 return icl->set_bus_param(icl, width_flag);
257 (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
258 /* Well, we actually only can do 10 or 8 bits... */
259 if (width_flag == SOCAM_DATAWIDTH_9)
260 return -EINVAL;
261 ret = bus_switch_act(mt9m001,
262 width_flag == SOCAM_DATAWIDTH_8);
263 if (ret < 0)
264 return ret;
265 194
266 mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; 195 /*
267 } 196 * Without board specific bus width settings we only support the
197 * sensors native bus width
198 */
199 if (width_flag == SOCAM_DATAWIDTH_10)
200 return 0;
268 201
269 return 0; 202 return -EINVAL;
270} 203}
271 204
272static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) 205static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
@@ -274,18 +207,20 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
274 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 207 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
275 struct soc_camera_link *icl = mt9m001->client->dev.platform_data; 208 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
276 /* MT9M001 has all capture_format parameters fixed */ 209 /* MT9M001 has all capture_format parameters fixed */
277 unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | 210 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING |
278 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | 211 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
279 SOCAM_MASTER; 212 SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER;
280 213
281 if (bus_switch_possible(mt9m001)) 214 if (icl->query_bus_param)
282 flags |= SOCAM_DATAWIDTH_8; 215 flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
216 else
217 flags |= SOCAM_DATAWIDTH_10;
283 218
284 return soc_camera_apply_sensor_flags(icl, flags); 219 return soc_camera_apply_sensor_flags(icl, flags);
285} 220}
286 221
287static int mt9m001_set_fmt(struct soc_camera_device *icd, 222static int mt9m001_set_crop(struct soc_camera_device *icd,
288 __u32 pixfmt, struct v4l2_rect *rect) 223 struct v4l2_rect *rect)
289{ 224{
290 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 225 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
291 int ret; 226 int ret;
@@ -324,6 +259,20 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd,
324 return ret; 259 return ret;
325} 260}
326 261
262static int mt9m001_set_fmt(struct soc_camera_device *icd,
263 struct v4l2_format *f)
264{
265 struct v4l2_rect rect = {
266 .left = icd->x_current,
267 .top = icd->y_current,
268 .width = f->fmt.pix.width,
269 .height = f->fmt.pix.height,
270 };
271
272 /* No support for scaling so far, just crop. TODO: use skipping */
273 return mt9m001_set_crop(icd, &rect);
274}
275
327static int mt9m001_try_fmt(struct soc_camera_device *icd, 276static int mt9m001_try_fmt(struct soc_camera_device *icd,
328 struct v4l2_format *f) 277 struct v4l2_format *f)
329{ 278{
@@ -449,6 +398,7 @@ static struct soc_camera_ops mt9m001_ops = {
449 .release = mt9m001_release, 398 .release = mt9m001_release,
450 .start_capture = mt9m001_start_capture, 399 .start_capture = mt9m001_start_capture,
451 .stop_capture = mt9m001_stop_capture, 400 .stop_capture = mt9m001_stop_capture,
401 .set_crop = mt9m001_set_crop,
452 .set_fmt = mt9m001_set_fmt, 402 .set_fmt = mt9m001_set_fmt,
453 .try_fmt = mt9m001_try_fmt, 403 .try_fmt = mt9m001_try_fmt,
454 .set_bus_param = mt9m001_set_bus_param, 404 .set_bus_param = mt9m001_set_bus_param,
@@ -583,6 +533,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
583 struct soc_camera_link *icl = mt9m001->client->dev.platform_data; 533 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
584 s32 data; 534 s32 data;
585 int ret; 535 int ret;
536 unsigned long flags;
586 537
587 /* We must have a parent by now. And it cannot be a wrong one. 538 /* We must have a parent by now. And it cannot be a wrong one.
588 * So this entire test is completely redundant. */ 539 * So this entire test is completely redundant. */
@@ -603,18 +554,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
603 case 0x8421: 554 case 0x8421:
604 mt9m001->model = V4L2_IDENT_MT9M001C12ST; 555 mt9m001->model = V4L2_IDENT_MT9M001C12ST;
605 icd->formats = mt9m001_colour_formats; 556 icd->formats = mt9m001_colour_formats;
606 if (gpio_is_valid(icl->gpio))
607 icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
608 else
609 icd->num_formats = 1;
610 break; 557 break;
611 case 0x8431: 558 case 0x8431:
612 mt9m001->model = V4L2_IDENT_MT9M001C12STM; 559 mt9m001->model = V4L2_IDENT_MT9M001C12STM;
613 icd->formats = mt9m001_monochrome_formats; 560 icd->formats = mt9m001_monochrome_formats;
614 if (gpio_is_valid(icl->gpio))
615 icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
616 else
617 icd->num_formats = 1;
618 break; 561 break;
619 default: 562 default:
620 ret = -ENODEV; 563 ret = -ENODEV;
@@ -623,6 +566,26 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
623 goto ei2c; 566 goto ei2c;
624 } 567 }
625 568
569 icd->num_formats = 0;
570
571 /*
572 * This is a 10bit sensor, so by default we only allow 10bit.
573 * The platform may support different bus widths due to
574 * different routing of the data lines.
575 */
576 if (icl->query_bus_param)
577 flags = icl->query_bus_param(icl);
578 else
579 flags = SOCAM_DATAWIDTH_10;
580
581 if (flags & SOCAM_DATAWIDTH_10)
582 icd->num_formats++;
583 else
584 icd->formats++;
585
586 if (flags & SOCAM_DATAWIDTH_8)
587 icd->num_formats++;
588
626 dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, 589 dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
627 data == 0x8431 ? "C12STM" : "C12ST"); 590 data == 0x8431 ? "C12STM" : "C12ST");
628 591
@@ -688,18 +651,10 @@ static int mt9m001_probe(struct i2c_client *client,
688 icd->height_max = 1024; 651 icd->height_max = 1024;
689 icd->y_skip_top = 1; 652 icd->y_skip_top = 1;
690 icd->iface = icl->bus_id; 653 icd->iface = icl->bus_id;
691 /* Default datawidth - this is the only width this camera (normally)
692 * supports. It is only with extra logic that it can support
693 * other widths. Therefore it seems to be a sensible default. */
694 mt9m001->datawidth = 10;
695 /* Simulated autoexposure. If enabled, we calculate shutter width 654 /* Simulated autoexposure. If enabled, we calculate shutter width
696 * ourselves in the driver based on vertical blanking and frame width */ 655 * ourselves in the driver based on vertical blanking and frame width */
697 mt9m001->autoexposure = 1; 656 mt9m001->autoexposure = 1;
698 657
699 ret = bus_switch_request(mt9m001, icl);
700 if (ret)
701 goto eswinit;
702
703 ret = soc_camera_device_register(icd); 658 ret = soc_camera_device_register(icd);
704 if (ret) 659 if (ret)
705 goto eisdr; 660 goto eisdr;
@@ -707,8 +662,6 @@ static int mt9m001_probe(struct i2c_client *client,
707 return 0; 662 return 0;
708 663
709eisdr: 664eisdr:
710 bus_switch_release(mt9m001);
711eswinit:
712 kfree(mt9m001); 665 kfree(mt9m001);
713 return ret; 666 return ret;
714} 667}
@@ -718,7 +671,6 @@ static int mt9m001_remove(struct i2c_client *client)
718 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 671 struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
719 672
720 soc_camera_device_unregister(&mt9m001->icd); 673 soc_camera_device_unregister(&mt9m001->icd);
721 bus_switch_release(mt9m001);
722 kfree(mt9m001); 674 kfree(mt9m001);
723 675
724 return 0; 676 return 0;