[PATCH] add primitive camera power control

Werner Almesberger werner at openmoko.org
Tue Mar 10 14:52:47 CET 2009


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 at openmoko.org>

---

Index: cam/drivers/media/video/s3c_camera_driver.c
===================================================================
--- cam.orig/drivers/media/video/s3c_camera_driver.c	2009-03-10 21:50:21.000000000 +0800
+++ cam/drivers/media/video/s3c_camera_driver.c	2009-03-10 21:52:19.000000000 +0800
@@ -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 @@
 	}
 }
 
+
+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 @@
 		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 @@
 	cfg->cis->user--;
 	cfg->status = CAMIF_STOPPED;
 
+	om_3d7k_camera_off();
+	cfg->cis->init_sensor = 0;
+
 	return 0;
 }
 
@@ -1753,9 +1833,6 @@
 		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);
 
Index: cam/drivers/media/video/samsung/4xa_sensor.c
===================================================================
--- cam.orig/drivers/media/video/samsung/4xa_sensor.c	2009-03-10 21:50:21.000000000 +0800
+++ cam/drivers/media/video/samsung/4xa_sensor.c	2009-03-10 21:51:59.000000000 +0800
@@ -215,8 +215,16 @@
 
 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)
Index: cam/arch/arm/mach-s3c6410/mach-om-3d7k.c
===================================================================
--- cam.orig/arch/arm/mach-s3c6410/mach-om-3d7k.c	2009-03-10 21:50:21.000000000 +0800
+++ cam/arch/arm/mach-s3c6410/mach-om-3d7k.c	2009-03-10 21:51:59.000000000 +0800
@@ -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 @@
 	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)



More information about the openmoko-kernel mailing list