diff options
author | Jonathan Corbet <corbet@lwn.net> | 2007-05-21 23:37:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-05-22 15:16:27 -0400 |
commit | 7acf90c70c6ee063f7465b2f10e2083bc49f355b (patch) | |
tree | 6b00a98e964864b400ec03dc52598cb5aa0c1ea7 /drivers/media | |
parent | 82c01d3d5a26f82aea1fb2e9a357dfb6404f44db (diff) |
V4L/DVB (5690): Cafe_ccic: Properly power down the sensor
The proper method for powering down the sensor on OLPC systems has
changed somewhat; in particular, the sensor must be powered down
completely (rather than simply told to power down) or the associated
"camera active" LED will stay on.
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/cafe_ccic-regs.h | 6 | ||||
-rw-r--r-- | drivers/media/video/cafe_ccic.c | 18 |
2 files changed, 23 insertions, 1 deletions
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h index b2c22a0d664..8e2a87cdc79 100644 --- a/drivers/media/video/cafe_ccic-regs.h +++ b/drivers/media/video/cafe_ccic-regs.h | |||
@@ -150,6 +150,12 @@ | |||
150 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ | 150 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ |
151 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | 151 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ |
152 | 152 | ||
153 | #define REG_GL_FCR 0x3038 /* GPIO functional control register */ | ||
154 | #define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */ | ||
155 | #define REG_GL_GPIOR 0x315c /* GPIO register */ | ||
156 | #define GGPIO_OUT 0x80000 /* GPIO output */ | ||
157 | #define GGPIO_VAL 0x00008 /* Output pin value */ | ||
158 | |||
153 | #define REG_LEN REG_GL_IMASK + 4 | 159 | #define REG_LEN REG_GL_IMASK + 4 |
154 | 160 | ||
155 | 161 | ||
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) | |||
775 | spin_lock_irqsave(&cam->dev_lock, flags); | 775 | spin_lock_irqsave(&cam->dev_lock, flags); |
776 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | 776 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); |
777 | /* | 777 | /* |
778 | * Part one of the sensor dance: turn the global | ||
779 | * GPIO signal on. | ||
780 | */ | ||
781 | cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); | ||
782 | cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL); | ||
783 | /* | ||
778 | * Put the sensor into operational mode (assumes OLPC-style | 784 | * Put the sensor into operational mode (assumes OLPC-style |
779 | * wiring). Control 0 is reset - set to 1 to operate. | 785 | * wiring). Control 0 is reset - set to 1 to operate. |
780 | * Control 1 is power down, set to 0 to operate. | 786 | * Control 1 is power down, set to 0 to operate. |
@@ -784,6 +790,7 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam) | |||
784 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | 790 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); |
785 | // mdelay(1); /* Enough? */ | 791 | // mdelay(1); /* Enough? */ |
786 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 792 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
793 | msleep(5); /* Just to be sure */ | ||
787 | } | 794 | } |
788 | 795 | ||
789 | static void cafe_ctlr_power_down(struct cafe_camera *cam) | 796 | static void cafe_ctlr_power_down(struct cafe_camera *cam) |
@@ -792,6 +799,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam) | |||
792 | 799 | ||
793 | spin_lock_irqsave(&cam->dev_lock, flags); | 800 | spin_lock_irqsave(&cam->dev_lock, flags); |
794 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); | 801 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); |
802 | cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); | ||
803 | cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT); | ||
795 | cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); | 804 | cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); |
796 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 805 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
797 | } | 806 | } |
@@ -851,6 +860,7 @@ static int cafe_cam_init(struct cafe_camera *cam) | |||
851 | ret = 0; | 860 | ret = 0; |
852 | cam->state = S_IDLE; | 861 | cam->state = S_IDLE; |
853 | out: | 862 | out: |
863 | cafe_ctlr_power_down(cam); | ||
854 | mutex_unlock(&cam->s_mutex); | 864 | mutex_unlock(&cam->s_mutex); |
855 | return ret; | 865 | return ret; |
856 | } | 866 | } |
@@ -2103,10 +2113,16 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
2103 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); | 2113 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); |
2104 | if (ret) | 2114 | if (ret) |
2105 | goto out_iounmap; | 2115 | goto out_iounmap; |
2116 | /* | ||
2117 | * Initialize the controller and leave it powered up. It will | ||
2118 | * stay that way until the sensor driver shows up. | ||
2119 | */ | ||
2106 | cafe_ctlr_init(cam); | 2120 | cafe_ctlr_init(cam); |
2107 | cafe_ctlr_power_up(cam); | 2121 | cafe_ctlr_power_up(cam); |
2108 | /* | 2122 | /* |
2109 | * Set up I2C/SMBUS communications | 2123 | * Set up I2C/SMBUS communications. We have to drop the mutex here |
2124 | * because the sensor could attach in this call chain, leading to | ||
2125 | * unsightly deadlocks. | ||
2110 | */ | 2126 | */ |
2111 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | 2127 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ |
2112 | ret = cafe_smbus_setup(cam); | 2128 | ret = cafe_smbus_setup(cam); |