aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9v022.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
commite958e27adeade7fa085dd396a8a0dfaef7e338c1 (patch)
tree3bba3d91531f778e54d380ec4ba099c7e86ccf8c /drivers/media/video/mt9v022.c
parent36034dc325ecab63c8cfb992fbf9a1a8e94738a2 (diff)
V4L/DVB (11033): mt9v022: 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/mt9v022.c')
-rw-r--r--drivers/media/video/mt9v022.c141
1 files changed, 42 insertions, 99 deletions
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 3871d4a2d8ff..4d3b4813c322 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -13,7 +13,6 @@
13#include <linux/i2c.h> 13#include <linux/i2c.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/log2.h> 15#include <linux/log2.h>
16#include <linux/gpio.h>
17 16
18#include <media/v4l2-common.h> 17#include <media/v4l2-common.h>
19#include <media/v4l2-chip-ident.h> 18#include <media/v4l2-chip-ident.h>
@@ -89,9 +88,7 @@ struct mt9v022 {
89 struct i2c_client *client; 88 struct i2c_client *client;
90 struct soc_camera_device icd; 89 struct soc_camera_device icd;
91 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ 90 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
92 int switch_gpio;
93 u16 chip_control; 91 u16 chip_control;
94 unsigned char datawidth;
95}; 92};
96 93
97static int reg_read(struct soc_camera_device *icd, const u8 reg) 94static int reg_read(struct soc_camera_device *icd, const u8 reg)
@@ -209,66 +206,6 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
209 return 0; 206 return 0;
210} 207}
211 208
212static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
213{
214#ifdef CONFIG_MT9V022_PCA9536_SWITCH
215 int ret;
216 unsigned int gpio = icl->gpio;
217
218 if (gpio_is_valid(gpio)) {
219 /* We have a data bus switch. */
220 ret = gpio_request(gpio, "mt9v022");
221 if (ret < 0) {
222 dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
223 return ret;
224 }
225
226 ret = gpio_direction_output(gpio, 0);
227 if (ret < 0) {
228 dev_err(&mt9v022->client->dev,
229 "Cannot set GPIO %u to output\n", gpio);
230 gpio_free(gpio);
231 return ret;
232 }
233 }
234
235 mt9v022->switch_gpio = gpio;
236#else
237 mt9v022->switch_gpio = -EINVAL;
238#endif
239 return 0;
240}
241
242static void bus_switch_release(struct mt9v022 *mt9v022)
243{
244#ifdef CONFIG_MT9V022_PCA9536_SWITCH
245 if (gpio_is_valid(mt9v022->switch_gpio))
246 gpio_free(mt9v022->switch_gpio);
247#endif
248}
249
250static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
251{
252#ifdef CONFIG_MT9V022_PCA9536_SWITCH
253 if (!gpio_is_valid(mt9v022->switch_gpio))
254 return -ENODEV;
255
256 gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
257 return 0;
258#else
259 return -ENODEV;
260#endif
261}
262
263static int bus_switch_possible(struct mt9v022 *mt9v022)
264{
265#ifdef CONFIG_MT9V022_PCA9536_SWITCH
266 return gpio_is_valid(mt9v022->switch_gpio);
267#else
268 return 0;
269#endif
270}
271
272static int mt9v022_set_bus_param(struct soc_camera_device *icd, 209static int mt9v022_set_bus_param(struct soc_camera_device *icd,
273 unsigned long flags) 210 unsigned long flags)
274{ 211{
@@ -282,19 +219,17 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
282 if (!is_power_of_2(width_flag)) 219 if (!is_power_of_2(width_flag))
283 return -EINVAL; 220 return -EINVAL;
284 221
285 if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || 222 if (icl->set_bus_param) {
286 (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || 223 ret = icl->set_bus_param(icl, width_flag);
287 (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { 224 if (ret)
288 /* Well, we actually only can do 10 or 8 bits... */
289 if (width_flag == SOCAM_DATAWIDTH_9)
290 return -EINVAL;
291
292 ret = bus_switch_act(mt9v022,
293 width_flag == SOCAM_DATAWIDTH_8);
294 if (ret < 0)
295 return ret; 225 return ret;
296 226 } else {
297 mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; 227 /*
228 * Without board specific bus width settings we only support the
229 * sensors native bus width
230 */
231 if (width_flag != SOCAM_DATAWIDTH_10)
232 return -EINVAL;
298 } 233 }
299 234
300 flags = soc_camera_apply_sensor_flags(icl, flags); 235 flags = soc_camera_apply_sensor_flags(icl, flags);
@@ -328,10 +263,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
328static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) 263static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
329{ 264{
330 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 265 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
331 unsigned int width_flag = SOCAM_DATAWIDTH_10; 266 struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
267 unsigned int width_flag;
332 268
333 if (bus_switch_possible(mt9v022)) 269 if (icl->query_bus_param)
334 width_flag |= SOCAM_DATAWIDTH_8; 270 width_flag = icl->query_bus_param(icl) &
271 SOCAM_DATAWIDTH_MASK;
272 else
273 width_flag = SOCAM_DATAWIDTH_10;
335 274
336 return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | 275 return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
337 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | 276 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
@@ -715,6 +654,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
715 struct soc_camera_link *icl = mt9v022->client->dev.platform_data; 654 struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
716 s32 data; 655 s32 data;
717 int ret; 656 int ret;
657 unsigned long flags;
718 658
719 if (!icd->dev.parent || 659 if (!icd->dev.parent ||
720 to_soc_camera_host(icd->dev.parent)->nr != icd->iface) 660 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
@@ -748,22 +688,36 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
748 ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); 688 ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
749 mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; 689 mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
750 icd->formats = mt9v022_colour_formats; 690 icd->formats = mt9v022_colour_formats;
751 if (gpio_is_valid(icl->gpio))
752 icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
753 else
754 icd->num_formats = 1;
755 } else { 691 } else {
756 ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); 692 ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
757 mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; 693 mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
758 icd->formats = mt9v022_monochrome_formats; 694 icd->formats = mt9v022_monochrome_formats;
759 if (gpio_is_valid(icl->gpio))
760 icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
761 else
762 icd->num_formats = 1;
763 } 695 }
764 696
765 if (!ret) 697 if (ret < 0)
766 ret = soc_camera_video_start(icd); 698 goto eisis;
699
700 icd->num_formats = 0;
701
702 /*
703 * This is a 10bit sensor, so by default we only allow 10bit.
704 * The platform may support different bus widths due to
705 * different routing of the data lines.
706 */
707 if (icl->query_bus_param)
708 flags = icl->query_bus_param(icl);
709 else
710 flags = SOCAM_DATAWIDTH_10;
711
712 if (flags & SOCAM_DATAWIDTH_10)
713 icd->num_formats++;
714 else
715 icd->formats++;
716
717 if (flags & SOCAM_DATAWIDTH_8)
718 icd->num_formats++;
719
720 ret = soc_camera_video_start(icd);
767 if (ret < 0) 721 if (ret < 0)
768 goto eisis; 722 goto eisis;
769 723
@@ -828,14 +782,6 @@ static int mt9v022_probe(struct i2c_client *client,
828 icd->height_max = 480; 782 icd->height_max = 480;
829 icd->y_skip_top = 1; 783 icd->y_skip_top = 1;
830 icd->iface = icl->bus_id; 784 icd->iface = icl->bus_id;
831 /* Default datawidth - this is the only width this camera (normally)
832 * supports. It is only with extra logic that it can support
833 * other widths. Therefore it seems to be a sensible default. */
834 mt9v022->datawidth = 10;
835
836 ret = bus_switch_request(mt9v022, icl);
837 if (ret)
838 goto eswinit;
839 785
840 ret = soc_camera_device_register(icd); 786 ret = soc_camera_device_register(icd);
841 if (ret) 787 if (ret)
@@ -844,8 +790,6 @@ static int mt9v022_probe(struct i2c_client *client,
844 return 0; 790 return 0;
845 791
846eisdr: 792eisdr:
847 bus_switch_release(mt9v022);
848eswinit:
849 kfree(mt9v022); 793 kfree(mt9v022);
850 return ret; 794 return ret;
851} 795}
@@ -855,7 +799,6 @@ static int mt9v022_remove(struct i2c_client *client)
855 struct mt9v022 *mt9v022 = i2c_get_clientdata(client); 799 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
856 800
857 soc_camera_device_unregister(&mt9v022->icd); 801 soc_camera_device_unregister(&mt9v022->icd);
858 bus_switch_release(mt9v022);
859 kfree(mt9v022); 802 kfree(mt9v022);
860 803
861 return 0; 804 return 0;