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>
21 #include <linux/i2c/twl4030.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
= {
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
,
72 .wenlog
= ISPCCDC_CFG_WENLOG_AND
,
77 .u
.csi
.signalling
= 0x0,
78 .u
.csi
.strobe_clock_inv
= 0x0,
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
;
94 hwc
->dev_type
= OMAP34XXCAM_SLAVE_SENSOR
;
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
;
107 printk(KERN_ERR
"OV3640: Unable to control board GPIOs!\n");
113 if (previous_power
== V4L2_POWER_OFF
)
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
);
145 /* Turn ON Omnivision sensor */
146 gpio_set_value(OV3640_RESET_GPIO
, 1);
147 gpio_set_value(OV3640_STANDBY_GPIO
, 0);
150 /* RESET Omnivision sensor */
151 gpio_set_value(OV3640_RESET_GPIO
, 0);
153 gpio_set_value(OV3640_RESET_GPIO
, 1);
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
);
162 case V4L2_POWER_STANDBY
:
165 previous_power
= power
;
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
,
184 void __init
ldp_cam_init(void)
186 #if defined(CONFIG_VIDEO_OV3640) || defined(CONFIG_VIDEO_OV3640_MODULE)
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",
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
);
200 /* set to output mode */
201 gpio_direction_output(OV3640_RESET_GPIO
, true);
202 gpio_direction_output(OV3640_STANDBY_GPIO
, true);
207 void __init
ldp_cam_init(void)