Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7acf90c7 authored by Jonathan Corbet's avatar Jonathan Corbet Committed by Mauro Carvalho Chehab
Browse files

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: default avatarJonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 82c01d3d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -150,6 +150,12 @@
#define REG_GL_IMASK   0x300c  /* Interrupt mask register */
#define   GIMSK_CCIC_EN          0x00000004    /* CCIC Interrupt enable */

#define REG_GL_FCR	0x3038  /* GPIO functional control register */
#define	  GFCR_GPIO_ON	  0x08		/* Camera GPIO enabled */
#define REG_GL_GPIOR	0x315c	/* GPIO register */
#define   GGPIO_OUT  		0x80000	/* GPIO output */
#define   GGPIO_VAL  		0x00008	/* Output pin value */

#define REG_LEN                REG_GL_IMASK + 4


+17 −1
Original line number Diff line number Diff line
@@ -774,6 +774,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.
@@ -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);