From be03383f4a472291bcf747e959ffb208d3fd56ce Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 10 Mar 2009 14:02:28 +0000 Subject: add primitive camera power control This dirty hack adds camera activation/deactivation on open/close. This code will have to move to a machine/platform area later. The general driver is the wrong place for it. It also removes the unconditional activation and moves the domain setting to the rest of the power control code. (Thanks, Andy !) Note that opening the camera now always takes about 20 seconds until the settings are downloaded, not just on the first open. Signed-off-by: Werner Almesberger --- arch/arm/mach-s3c6410/mach-om-3d7k.c | 14 ------ drivers/media/video/s3c_camera_driver.c | 83 ++++++++++++++++++++++++++++++-- drivers/media/video/samsung/4xa_sensor.c | 10 +++- 3 files changed, 89 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-s3c6410/mach-om-3d7k.c b/arch/arm/mach-s3c6410/mach-om-3d7k.c index e54abd83bc2..74a88d6cfdc 100644 --- a/arch/arm/mach-s3c6410/mach-om-3d7k.c +++ b/arch/arm/mach-s3c6410/mach-om-3d7k.c @@ -69,9 +69,6 @@ #include #include #include -/* temp -- move to camera driver along with _NORMAL register setting */ -#include -#include /* #include */ #include @@ -1044,17 +1041,6 @@ static void om_3d7k_pcf50633_attach_child_devices(struct pcf50633 *pcf) pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00); pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01); pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01); - -#ifdef CONFIG_S3C_DEV_CAMIF - /* @@@ do this properly later - WA */ - pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x21); - pcf50633_reg_write(om_3d7k_pcf, 0x39, 0x13); - pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x21); - - /* so it doesn't get lost */ - __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) | - S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG); -#endif } static void om_3d7k_l1k002_pwronoff(int level) diff --git a/drivers/media/video/s3c_camera_driver.c b/drivers/media/video/s3c_camera_driver.c index 1d3bffa5edd..3be273494d5 100644 --- a/drivers/media/video/s3c_camera_driver.c +++ b/drivers/media/video/s3c_camera_driver.c @@ -51,6 +51,15 @@ #include "s3c_camif.h" #include "videodev2_s3c.h" +#include /* @@@ hack - WA */ +#include +#include +#include +#include +#include +#include + + static struct clk *cam_clock; camif_cfg_t s3c_fimc[CAMIF_DEV_NUM]; extern camif_cis_t msdma_input; @@ -1311,6 +1320,72 @@ long s3c_camif_ioctl(struct file *file, unsigned int cmd, unsigned long _arg) } } + +void om_3d7k_camera_on(void) +{ + extern struct pcf50633 *om_3d7k_pcf; + int i; + + gpio_direction_output(S3C64XX_GPF(3), 0); + + /* @@@ hack - WA */ + pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x21); + for (i = 0; !(pcf50633_reg_read(om_3d7k_pcf, 0x42) & 0x02); i++) { + if (i == 100) { + printk(KERN_ERR "can't bring up LDO2\n"); + break; + } + msleep(10); + } + + pcf50633_reg_write(om_3d7k_pcf, 0x39, 0x13); + pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x21); + for (i = 0; !(pcf50633_reg_read(om_3d7k_pcf, 0x42) & 0x40); i++) { + if (i == 100) { + printk(KERN_ERR "can't bring up HCLDO\n"); + break; + } + msleep(10); + } + + msleep(100); /* > 0 ms */ + + if (cam_clock) + clk_enable(cam_clock); + + msleep(1); /* > 100 cycles */ + gpio_direction_output(S3C64XX_GPF(3), 1); + msleep(25); /* > 1 Mcycles */ + s3c_gpio_cfgpin(S3C64XX_GPF(3), S3C64XX_GPF3_CAMIF_nRST); + msleep(25); /* just to be sure > 1 Mcycles */ + + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) | + S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG); +} + +void om_3d7k_camera_off(void) +{ + extern struct pcf50633 *om_3d7k_pcf; + + gpio_direction_output(S3C64XX_GPF(3), 0); + + msleep(1); /* > 20 cycles */ + + if (cam_clock) + clk_disable(cam_clock); + msleep(1); /* > 0 ms */ + + /* @@@ hack - WA */ + pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x20); /* 2V8, ... */ + pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x20); /* ... then 1V5 */ + +#if 0 + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) & + ~S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG); +#endif +} + + /* @@@ - WA */ #define s3c_camif_exclusive_open(inode, file) 0 #define s3c_camif_exclusive_release(inode, file) @@ -1339,6 +1414,8 @@ int s3c_camif_open(struct file *file) up(&cfg->cis->lock); } + om_3d7k_camera_on(); + err = s3c_camif_exclusive_open(inode, file); cfg->cis->user++; cfg->status = CAMIF_STOPPED; @@ -1384,6 +1461,9 @@ int s3c_camif_release(struct file *file) cfg->cis->user--; cfg->status = CAMIF_STOPPED; + om_3d7k_camera_off(); + cfg->cis->init_sensor = 0; + return 0; } @@ -1753,9 +1833,6 @@ static int s3c_camif_probe(struct platform_device *pdev) return PTR_ERR(cam_clock); } -printk("cam_clock %p\n", cam_clock); - clk_enable(cam_clock); - /* Print banner */ printk(KERN_INFO "S3C FIMC v%s\n", FIMC_VER); diff --git a/drivers/media/video/samsung/4xa_sensor.c b/drivers/media/video/samsung/4xa_sensor.c index b7f9061ca9b..1e3ca1c822e 100644 --- a/drivers/media/video/samsung/4xa_sensor.c +++ b/drivers/media/video/samsung/4xa_sensor.c @@ -215,8 +215,16 @@ s5k4xa_attach(struct i2c_adapter *adap, int addr, int kind) static int sensor_attach_adapter(struct i2c_adapter *adap) { + extern void om_3d7k_camera_on(void); + extern void om_3d7k_camera_off(void); + int ret; + s3c_camif_open_sensor(&data); - return i2c_probe(adap, &addr_data, s5k4xa_attach); + + om_3d7k_camera_on(); + ret = i2c_probe(adap, &addr_data, s5k4xa_attach); + om_3d7k_camera_off(); + return ret; } static int sensor_detach(struct i2c_client *client) -- cgit v1.2.3