aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Almesberger <werner@openmoko.org>2009-03-10 14:02:28 +0000
committerAndy Green <agreen@octopus.localdomain>2009-03-10 14:02:28 +0000
commitbe03383f4a472291bcf747e959ffb208d3fd56ce (patch)
tree0d62b0558bb39fa8ae304506ac41a31a92316307
parent675a93c65029c2cda2d00bb73f9d7f0e1c9d42dc (diff)
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 <werner@openmoko.org>
-rw-r--r--arch/arm/mach-s3c6410/mach-om-3d7k.c14
-rw-r--r--drivers/media/video/s3c_camera_driver.c83
-rw-r--r--drivers/media/video/samsung/4xa_sensor.c10
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 <plat/cpu.h>
#include <plat/tzic-sp890.h>
#include <plat/usb-control.h>
-/* temp -- move to camera driver along with _NORMAL register setting */
-#include <plat/regs-sys.h>
-#include <plat/regs-syscon-power.h>
/* #include <plat/udc.h> */
#include <linux/i2c.h>
@@ -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 <linux/mfd/pcf50633/core.h> /* @@@ hack - WA */
+#include <plat/gpio-bank-f.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include <mach/map.h>
+#include <plat/regs-sys.h>
+#include <plat/regs-syscon-power.h>
+
+
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)