aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/cafe_ccic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-22 16:47:51 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-22 16:47:51 -0700
commit7992018d979460af59fbae8a48f9641305aea438 (patch)
treede64367c49aa76606e7ea8354b299d067f1c0bda /drivers/media/video/cafe_ccic.c
parent5fd52203e1856ad925b1a6adae9a22e533da94e2 (diff)
parentedd75ede2d40eadb98e07d87e88fa970f86ffe9e (diff)
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: V4L/DVB (5691): Ov7670: reset clkrc in rgb565 mode V4L/DVB (5690): Cafe_ccic: Properly power down the sensor V4L/DVB (5680): Tuner-simple.c fix suport for SECAM with FI1216MF V4L/DVB (5630): Dvb-core: Handle failures to create devices V4L/DVB (5639a): Fix dst usage count V4L/DVB (5670): Adding new fields to v4l2_pix_format broke the ABI, reverted that change V4L/DVB (5640): Fix: em28xx shouldn't be selecting VIDEO_BUF V4L/DVB (5639): Fix Kconfig dependencies for ivtv
Diffstat (limited to 'drivers/media/video/cafe_ccic.c')
-rw-r--r--drivers/media/video/cafe_ccic.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 96254dbaf62..c08f650df42 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -775,6 +775,12 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam)
spin_lock_irqsave(&cam->dev_lock, flags);
cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
/*
+ * Part one of the sensor dance: turn the global
+ * GPIO signal on.
+ */
+ cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+ cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);
+ /*
* Put the sensor into operational mode (assumes OLPC-style
* wiring). Control 0 is reset - set to 1 to operate.
* Control 1 is power down, set to 0 to operate.
@@ -784,6 +790,7 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam)
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
// mdelay(1); /* Enough? */
spin_unlock_irqrestore(&cam->dev_lock, flags);
+ msleep(5); /* Just to be sure */
}
static void cafe_ctlr_power_down(struct cafe_camera *cam)
@@ -792,6 +799,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam)
spin_lock_irqsave(&cam->dev_lock, flags);
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+ cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+ cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT);
cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
spin_unlock_irqrestore(&cam->dev_lock, flags);
}
@@ -851,6 +860,7 @@ static int cafe_cam_init(struct cafe_camera *cam)
ret = 0;
cam->state = S_IDLE;
out:
+ cafe_ctlr_power_down(cam);
mutex_unlock(&cam->s_mutex);
return ret;
}
@@ -2103,10 +2113,16 @@ static int cafe_pci_probe(struct pci_dev *pdev,
ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
if (ret)
goto out_iounmap;
+ /*
+ * Initialize the controller and leave it powered up. It will
+ * stay that way until the sensor driver shows up.
+ */
cafe_ctlr_init(cam);
cafe_ctlr_power_up(cam);
/*
- * Set up I2C/SMBUS communications
+ * Set up I2C/SMBUS communications. We have to drop the mutex here
+ * because the sensor could attach in this call chain, leading to
+ * unsightly deadlocks.
*/
mutex_unlock(&cam->s_mutex); /* attach can deadlock */
ret = cafe_smbus_setup(cam);