aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/media/video/Kconfig7
-rw-r--r--drivers/media/video/mt9m001.c143
2 files changed, 40 insertions, 110 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 534a022c4d1b..24dfb39a6ccb 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -707,13 +707,6 @@ config SOC_CAMERA_MT9M001
707 This driver supports MT9M001 cameras from Micron, monochrome 707 This driver supports MT9M001 cameras from Micron, monochrome
708 and colour models. 708 and colour models.
709 709
710config MT9M001_PCA9536_SWITCH
711 bool "pca9536 datawidth switch for mt9m001"
712 depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
713 help
714 Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
715 extender to switch between 8 and 10 bit datawidth modes
716
717config SOC_CAMERA_MT9M111 710config SOC_CAMERA_MT9M111
718 tristate "mt9m111 and mt9m112 support" 711 tristate "mt9m111 and mt9m112 support"
719 depends on SOC_CAMERA && I2C 712 depends on SOC_CAMERA && I2C
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;