aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m001.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-03-13 05:08:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:22 -0400
commit36034dc325ecab63c8cfb992fbf9a1a8e94738a2 (patch)
treeb4c2c5b611c07584fc6327591c670891e2689bd7 /drivers/media/video/mt9m001.c
parentd75b1dcc84a5c8bf3e660dd1ba3ae6cd5e6d0929 (diff)
V4L/DVB (11032): mt9m001: allow setting of bus width from board code
This patch removes the phytec specific setting of the bus width and switches to the more generic query_bus_param/set_bus_param hooks Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r--drivers/media/video/mt9m001.c143
1 files changed, 40 insertions, 103 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index a6703d25227f..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,12 +207,14 @@ 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_DATA_ACTIVE_HIGH | 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}
@@ -598,6 +533,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
598 struct soc_camera_link *icl = mt9m001->client->dev.platform_data; 533 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
599 s32 data; 534 s32 data;
600 int ret; 535 int ret;
536 unsigned long flags;
601 537
602 /* 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.
603 * So this entire test is completely redundant. */ 539 * So this entire test is completely redundant. */
@@ -618,18 +554,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
618 case 0x8421: 554 case 0x8421:
619 mt9m001->model = V4L2_IDENT_MT9M001C12ST; 555 mt9m001->model = V4L2_IDENT_MT9M001C12ST;
620 icd->formats = mt9m001_colour_formats; 556 icd->formats = mt9m001_colour_formats;
621 if (gpio_is_valid(icl->gpio))
622 icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
623 else
624 icd->num_formats = 1;
625 break; 557 break;
626 case 0x8431: 558 case 0x8431:
627 mt9m001->model = V4L2_IDENT_MT9M001C12STM; 559 mt9m001->model = V4L2_IDENT_MT9M001C12STM;
628 icd->formats = mt9m001_monochrome_formats; 560 icd->formats = mt9m001_monochrome_formats;
629 if (gpio_is_valid(icl->gpio))
630 icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
631 else
632 icd->num_formats = 1;
633 break; 561 break;
634 default: 562 default:
635 ret = -ENODEV; 563 ret = -ENODEV;
@@ -638,6 +566,26 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
638 goto ei2c; 566 goto ei2c;
639 } 567 }
640 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
641 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,
642 data == 0x8431 ? "C12STM" : "C12ST"); 590 data == 0x8431 ? "C12STM" : "C12ST");
643 591
@@ -703,18 +651,10 @@ static int mt9m001_probe(struct i2c_client *client,
703 icd->height_max = 1024; 651 icd->height_max = 1024;
704 icd->y_skip_top = 1; 652 icd->y_skip_top = 1;
705 icd->iface = icl->bus_id; 653 icd->iface = icl->bus_id;
706 /* Default datawidth - this is the only width this camera (normally)
707 * supports. It is only with extra logic that it can support
708 * other widths. Therefore it seems to be a sensible default. */
709 mt9m001->datawidth = 10;
710 /* Simulated autoexposure. If enabled, we calculate shutter width 654 /* Simulated autoexposure. If enabled, we calculate shutter width
711 * ourselves in the driver based on vertical blanking and frame width */ 655 * ourselves in the driver based on vertical blanking and frame width */
712 mt9m001->autoexposure = 1; 656 mt9m001->autoexposure = 1;
713 657
714 ret = bus_switch_request(mt9m001, icl);
715 if (ret)
716 goto eswinit;
717
718 ret = soc_camera_device_register(icd); 658 ret = soc_camera_device_register(icd);
719 if (ret) 659 if (ret)
720 goto eisdr; 660 goto eisdr;
@@ -722,8 +662,6 @@ static int mt9m001_probe(struct i2c_client *client,
722 return 0; 662 return 0;
723 663
724eisdr: 664eisdr:
725 bus_switch_release(mt9m001);
726eswinit:
727 kfree(mt9m001); 665 kfree(mt9m001);
728 return ret; 666 return ret;
729} 667}
@@ -733,7 +671,6 @@ static int mt9m001_remove(struct i2c_client *client)
733 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 671 struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
734 672
735 soc_camera_device_unregister(&mt9m001->icd); 673 soc_camera_device_unregister(&mt9m001->icd);
736 bus_switch_release(mt9m001);
737 kfree(mt9m001); 674 kfree(mt9m001);
738 675
739 return 0; 676 return 0;