aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c23
-rw-r--r--drivers/media/video/mt9m001.c3
-rw-r--r--drivers/media/video/mt9v022.c3
-rw-r--r--include/media/soc_camera.h1
4 files changed, 23 insertions, 7 deletions
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 095521e9ee24..01791d74e08e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -380,12 +380,12 @@ static struct pca953x_platform_data pca9536_data = {
380 .gpio_base = NR_BUILTIN_GPIO, 380 .gpio_base = NR_BUILTIN_GPIO,
381}; 381};
382 382
383static int gpio_bus_switch; 383static int gpio_bus_switch = -EINVAL;
384 384
385static int pcm990_camera_set_bus_param(struct soc_camera_link *link, 385static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
386 unsigned long flags) 386 unsigned long flags)
387{ 387{
388 if (gpio_bus_switch <= 0) { 388 if (gpio_bus_switch < 0) {
389 if (flags == SOCAM_DATAWIDTH_10) 389 if (flags == SOCAM_DATAWIDTH_10)
390 return 0; 390 return 0;
391 else 391 else
@@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
404{ 404{
405 int ret; 405 int ret;
406 406
407 if (!gpio_bus_switch) { 407 if (gpio_bus_switch < 0) {
408 ret = gpio_request(NR_BUILTIN_GPIO, "camera"); 408 ret = gpio_request(NR_BUILTIN_GPIO, "camera");
409 if (!ret) { 409 if (!ret) {
410 gpio_bus_switch = NR_BUILTIN_GPIO; 410 gpio_bus_switch = NR_BUILTIN_GPIO;
411 gpio_direction_output(gpio_bus_switch, 0); 411 gpio_direction_output(gpio_bus_switch, 0);
412 } else 412 }
413 gpio_bus_switch = -EINVAL;
414 } 413 }
415 414
416 if (gpio_bus_switch > 0) 415 if (gpio_bus_switch >= 0)
417 return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10; 416 return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
418 else 417 else
419 return SOCAM_DATAWIDTH_10; 418 return SOCAM_DATAWIDTH_10;
420} 419}
421 420
421static void pcm990_camera_free_bus(struct soc_camera_link *link)
422{
423 if (gpio_bus_switch < 0)
424 return;
425
426 gpio_free(gpio_bus_switch);
427 gpio_bus_switch = -EINVAL;
428}
429
422static struct soc_camera_link iclink = { 430static struct soc_camera_link iclink = {
423 .bus_id = 0, /* Must match with the camera ID above */ 431 .bus_id = 0, /* Must match with the camera ID above */
424 .query_bus_param = pcm990_camera_query_bus_param, 432 .query_bus_param = pcm990_camera_query_bus_param,
425 .set_bus_param = pcm990_camera_set_bus_param, 433 .set_bus_param = pcm990_camera_set_bus_param,
434 .free_bus = pcm990_camera_free_bus,
426}; 435};
427 436
428/* Board I2C devices. */ 437/* Board I2C devices. */
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 684f62fa7897..3838ff77381b 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -604,10 +604,13 @@ ei2c:
604static void mt9m001_video_remove(struct soc_camera_device *icd) 604static void mt9m001_video_remove(struct soc_camera_device *icd)
605{ 605{
606 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 606 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
607 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
607 608
608 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, 609 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
609 icd->dev.parent, icd->vdev); 610 icd->dev.parent, icd->vdev);
610 soc_camera_video_stop(icd); 611 soc_camera_video_stop(icd);
612 if (icl->free_bus)
613 icl->free_bus(icl);
611} 614}
612 615
613static int mt9m001_probe(struct i2c_client *client, 616static int mt9m001_probe(struct i2c_client *client,
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 4d3b4813c322..412b399baca4 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -735,10 +735,13 @@ ei2c:
735static void mt9v022_video_remove(struct soc_camera_device *icd) 735static void mt9v022_video_remove(struct soc_camera_device *icd)
736{ 736{
737 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 737 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
738 struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
738 739
739 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, 740 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
740 icd->dev.parent, icd->vdev); 741 icd->dev.parent, icd->vdev);
741 soc_camera_video_stop(icd); 742 soc_camera_video_stop(icd);
743 if (icl->free_bus)
744 icl->free_bus(icl);
742} 745}
743 746
744static int mt9v022_probe(struct i2c_client *client, 747static int mt9v022_probe(struct i2c_client *client,
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 37013688af44..396c32550e04 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -107,6 +107,7 @@ struct soc_camera_link {
107 */ 107 */
108 int (*set_bus_param)(struct soc_camera_link *, unsigned long flags); 108 int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
109 unsigned long (*query_bus_param)(struct soc_camera_link *); 109 unsigned long (*query_bus_param)(struct soc_camera_link *);
110 void (*free_bus)(struct soc_camera_link *);
110}; 111};
111 112
112static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) 113static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)