Full support for Ginger Console
[linux-ginger.git] / arch / arm / mach-omap2 / board-ldp-camera.c
blobbc5400b884a90e0f3e344f13be8b857ce17ca8a2
1 /*
2 * linux/arch/arm/mach-omap2/board-ldp-camera.c
4 * Copyright (C) 2009 Texas Instruments Inc.
5 * Sergio Aguirre <saaguirre@ti.com>
7 * Modified from mach-omap2/board-ldp.c
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #ifdef CONFIG_TWL4030_CORE
16 #include <linux/clk.h>
17 #include <linux/platform_device.h>
18 #include <linux/delay.h>
19 #include <linux/mm.h>
21 #include <linux/i2c/twl4030.h>
23 #include <asm/io.h>
25 #include <mach/gpio.h>
27 static int cam_inited;
28 #include <media/v4l2-int-device.h>
29 #include <../drivers/media/video/omap34xxcam.h>
30 #include <../drivers/media/video/isp/ispreg.h>
32 #define LDPCAM_USE_XCLKB 1
34 #define VAUX_1_8_V 0x05
35 #define VAUX_DEV_GRP_P1 0x20
36 #define VAUX_DEV_GRP_NONE 0x00
38 #if defined(CONFIG_VIDEO_OV3640) || defined(CONFIG_VIDEO_OV3640_MODULE)
39 #define OV3640_RESET_GPIO 98
40 #define OV3640_STANDBY_GPIO 7
41 #include <media/ov3640.h>
42 #include <../drivers/media/video/isp/ispcsi2.h>
43 #define OV3640_CSI2_CLOCK_POLARITY 0 /* +/- pin order */
44 #define OV3640_CSI2_DATA0_POLARITY 0 /* +/- pin order */
45 #define OV3640_CSI2_DATA1_POLARITY 0 /* +/- pin order */
46 #define OV3640_CSI2_CLOCK_LANE 1 /* Clock lane position: 1 */
47 #define OV3640_CSI2_DATA0_LANE 2 /* Data0 lane position: 2 */
48 #define OV3640_CSI2_DATA1_LANE 3 /* Data1 lane position: 3 */
49 #define OV3640_CSI2_PHY_THS_TERM 4
50 #define OV3640_CSI2_PHY_THS_SETTLE 14
51 #define OV3640_CSI2_PHY_TCLK_TERM 0
52 #define OV3640_CSI2_PHY_TCLK_MISS 1
53 #define OV3640_CSI2_PHY_TCLK_SETTLE 14
55 #define OV3640_BIGGEST_FRAME_BYTE_SIZE PAGE_ALIGN(2048 * 1536 * 2)
57 static struct omap34xxcam_sensor_config ov3640_hwc = {
58 .sensor_isp = 0,
59 .capture_mem = OV3640_BIGGEST_FRAME_BYTE_SIZE * 2,
60 .ival_default = { 1, 15 },
63 static struct isp_interface_config ov3640_if_config = {
64 .ccdc_par_ser = ISP_CSIA,
65 .dataline_shift = 0x0,
66 .hsvs_syncdetect = ISPCTRL_SYNC_DETECT_VSRISE,
67 .strobe = 0x0,
68 .prestrobe = 0x0,
69 .shutter = 0x0,
70 .prev_sph = 2,
71 .prev_slv = 1,
72 .wenlog = ISPCCDC_CFG_WENLOG_AND,
73 .wait_hs_vs = 2,
74 .u.csi.crc = 0x0,
75 .u.csi.mode = 0x0,
76 .u.csi.edge = 0x0,
77 .u.csi.signalling = 0x0,
78 .u.csi.strobe_clock_inv = 0x0,
79 .u.csi.vs_edge = 0x0,
80 .u.csi.channel = 0x1,
81 .u.csi.vpclk = 0x1,
82 .u.csi.data_start = 0x0,
83 .u.csi.data_size = 0x0,
84 .u.csi.format = V4L2_PIX_FMT_SGRBG10,
87 static int ov3640_sensor_set_prv_data(struct v4l2_int_device *s, void *priv)
89 struct omap34xxcam_hw_config *hwc = priv;
91 hwc->u.sensor.sensor_isp = ov3640_hwc.sensor_isp;
92 hwc->dev_index = 1;
93 hwc->dev_minor = 4;
94 hwc->dev_type = OMAP34XXCAM_SLAVE_SENSOR;
95 return 0;
98 static int ov3640_sensor_power_set(struct v4l2_int_device *s,
99 enum v4l2_power power)
101 struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
102 struct isp_csi2_lanes_cfg lanecfg;
103 struct isp_csi2_phy_cfg phyconfig;
104 static enum v4l2_power previous_power = V4L2_POWER_OFF;
106 if (!cam_inited) {
107 printk(KERN_ERR "OV3640: Unable to control board GPIOs!\n");
108 return -EFAULT;
111 switch (power) {
112 case V4L2_POWER_ON:
113 if (previous_power == V4L2_POWER_OFF)
114 isp_csi2_reset();
115 lanecfg.clk.pol = OV3640_CSI2_CLOCK_POLARITY;
116 lanecfg.clk.pos = OV3640_CSI2_CLOCK_LANE;
117 lanecfg.data[0].pol = OV3640_CSI2_DATA0_POLARITY;
118 lanecfg.data[0].pos = OV3640_CSI2_DATA0_LANE;
119 lanecfg.data[1].pol = OV3640_CSI2_DATA1_POLARITY;
120 lanecfg.data[1].pos = OV3640_CSI2_DATA1_LANE;
121 lanecfg.data[2].pol = 0;
122 lanecfg.data[2].pos = 0;
123 lanecfg.data[3].pol = 0;
124 lanecfg.data[3].pos = 0;
125 isp_csi2_complexio_lanes_config(&lanecfg);
126 isp_csi2_complexio_lanes_update(true);
128 phyconfig.ths_term = OV3640_CSI2_PHY_THS_TERM;
129 phyconfig.ths_settle = OV3640_CSI2_PHY_THS_SETTLE;
130 phyconfig.tclk_term = OV3640_CSI2_PHY_TCLK_TERM;
131 phyconfig.tclk_miss = OV3640_CSI2_PHY_TCLK_MISS;
132 phyconfig.tclk_settle = OV3640_CSI2_PHY_TCLK_SETTLE;
133 isp_csi2_phy_config(&phyconfig);
134 isp_csi2_phy_update(true);
136 isp_configure_interface(vdev->cam->isp, &ov3640_if_config);
138 if (previous_power == V4L2_POWER_OFF) {
139 /* turn on analog power */
140 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
141 VAUX_1_8_V, TWL4030_VAUX4_DEDICATED);
142 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
143 VAUX_DEV_GRP_P1, TWL4030_VAUX4_DEV_GRP);
144 udelay(100);
145 /* Turn ON Omnivision sensor */
146 gpio_set_value(OV3640_RESET_GPIO, 1);
147 gpio_set_value(OV3640_STANDBY_GPIO, 0);
148 udelay(100);
150 /* RESET Omnivision sensor */
151 gpio_set_value(OV3640_RESET_GPIO, 0);
152 udelay(100);
153 gpio_set_value(OV3640_RESET_GPIO, 1);
155 break;
156 case V4L2_POWER_OFF:
157 /* Power Down Sequence */
158 isp_csi2_complexio_power(ISP_CSI2_POWER_OFF);
159 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
160 VAUX_DEV_GRP_NONE, TWL4030_VAUX4_DEV_GRP);
161 break;
162 case V4L2_POWER_STANDBY:
163 break;
165 previous_power = power;
166 return 0;
169 static u32 ov3640_sensor_set_xclk(struct v4l2_int_device *s, u32 xclkfreq)
171 struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
173 return isp_set_xclk(vdev->cam->isp, xclkfreq, LDPCAM_USE_XCLKB);
176 struct ov3640_platform_data ldp_ov3640_platform_data = {
177 .power_set = ov3640_sensor_power_set,
178 .priv_data_set = ov3640_sensor_set_prv_data,
179 .set_xclk = ov3640_sensor_set_xclk,
182 #endif
184 void __init ldp_cam_init(void)
186 #if defined(CONFIG_VIDEO_OV3640) || defined(CONFIG_VIDEO_OV3640_MODULE)
187 cam_inited = 0;
188 /* Request and configure gpio pins */
189 if (gpio_request(OV3640_RESET_GPIO, "ov3640_reset_gpio") != 0) {
190 printk(KERN_ERR "Could not request GPIO %d",
191 OV3640_RESET_GPIO);
192 return;
194 if (gpio_request(OV3640_STANDBY_GPIO, "ov3640_standby_gpio") != 0) {
195 printk(KERN_ERR "Could not request GPIO %d",
196 OV3640_STANDBY_GPIO);
197 gpio_free(OV3640_RESET_GPIO);
198 return;
200 /* set to output mode */
201 gpio_direction_output(OV3640_RESET_GPIO, true);
202 gpio_direction_output(OV3640_STANDBY_GPIO, true);
203 #endif
204 cam_inited = 1;
206 #else
207 void __init ldp_cam_init(void)
210 #endif