]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/dream/camera/msm_io7x.c
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel...
[net-next-2.6.git] / drivers / staging / dream / camera / msm_io7x.c
CommitLineData
eb7b797b
BS
1/*
2 * Copyright (c) 2008-2009 QUALCOMM Incorporated
3 */
4
5#include <linux/delay.h>
6#include <linux/clk.h>
7#include <linux/io.h>
8#include <mach/gpio.h>
9#include <mach/board.h>
10#include <mach/camera.h>
11
12#define CAMIF_CFG_RMSK 0x1fffff
13#define CAM_SEL_BMSK 0x2
14#define CAM_PCLK_SRC_SEL_BMSK 0x60000
15#define CAM_PCLK_INVERT_BMSK 0x80000
16#define CAM_PAD_REG_SW_RESET_BMSK 0x100000
17
18#define EXT_CAM_HSYNC_POL_SEL_BMSK 0x10000
19#define EXT_CAM_VSYNC_POL_SEL_BMSK 0x8000
20#define MDDI_CLK_CHICKEN_BIT_BMSK 0x80
21
22#define CAM_SEL_SHFT 0x1
23#define CAM_PCLK_SRC_SEL_SHFT 0x11
24#define CAM_PCLK_INVERT_SHFT 0x13
25#define CAM_PAD_REG_SW_RESET_SHFT 0x14
26
27#define EXT_CAM_HSYNC_POL_SEL_SHFT 0x10
28#define EXT_CAM_VSYNC_POL_SEL_SHFT 0xF
29#define MDDI_CLK_CHICKEN_BIT_SHFT 0x7
30#define APPS_RESET_OFFSET 0x00000210
31
32static struct clk *camio_vfe_mdc_clk;
33static struct clk *camio_mdc_clk;
34static struct clk *camio_vfe_clk;
35
36static struct msm_camera_io_ext camio_ext;
37static struct resource *appio, *mdcio;
38void __iomem *appbase, *mdcbase;
39
40static struct msm_camera_io_ext camio_ext;
41static struct resource *appio, *mdcio;
42void __iomem *appbase, *mdcbase;
43
44extern int clk_set_flags(struct clk *clk, unsigned long flags);
45
46int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
47{
48 int rc = -1;
49 struct clk *clk = NULL;
50
51 switch (clktype) {
52 case CAMIO_VFE_MDC_CLK:
53 clk = camio_vfe_mdc_clk = clk_get(NULL, "vfe_mdc_clk");
54 break;
55
56 case CAMIO_MDC_CLK:
57 clk = camio_mdc_clk = clk_get(NULL, "mdc_clk");
58 break;
59
60 case CAMIO_VFE_CLK:
61 clk = camio_vfe_clk = clk_get(NULL, "vfe_clk");
62 break;
63
64 default:
65 break;
66 }
67
68 if (!IS_ERR(clk)) {
69 clk_enable(clk);
70 rc = 0;
71 }
72
73 return rc;
74}
75
76int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
77{
78 int rc = -1;
79 struct clk *clk = NULL;
80
81 switch (clktype) {
82 case CAMIO_VFE_MDC_CLK:
83 clk = camio_vfe_mdc_clk;
84 break;
85
86 case CAMIO_MDC_CLK:
87 clk = camio_mdc_clk;
88 break;
89
90 case CAMIO_VFE_CLK:
91 clk = camio_vfe_clk;
92 break;
93
94 default:
95 break;
96 }
97
98 if (!IS_ERR(clk)) {
99 clk_disable(clk);
100 clk_put(clk);
101 rc = 0;
102 }
103
104 return rc;
105}
106
107void msm_camio_clk_rate_set(int rate)
108{
109 struct clk *clk = camio_vfe_clk;
110
111 if (clk != ERR_PTR(-ENOENT))
112 clk_set_rate(clk, rate);
113}
114
115int msm_camio_enable(struct platform_device *pdev)
116{
117 int rc = 0;
118 struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
119 struct msm_camera_device_platform_data *camdev = sinfo->pdata;
120
121 camio_ext = camdev->ioext;
122
123 appio = request_mem_region(camio_ext.appphy,
124 camio_ext.appsz, pdev->name);
125 if (!appio) {
126 rc = -EBUSY;
127 goto enable_fail;
128 }
129
130 appbase = ioremap(camio_ext.appphy,
131 camio_ext.appsz);
132 if (!appbase) {
133 rc = -ENOMEM;
134 goto apps_no_mem;
135 }
136
137 mdcio = request_mem_region(camio_ext.mdcphy,
138 camio_ext.mdcsz, pdev->name);
139 if (!mdcio) {
140 rc = -EBUSY;
141 goto mdc_busy;
142 }
143
144 mdcbase = ioremap(camio_ext.mdcphy,
145 camio_ext.mdcsz);
146 if (!mdcbase) {
147 rc = -ENOMEM;
148 goto mdc_no_mem;
149 }
150
151 camdev->camera_gpio_on();
152
153 msm_camio_clk_enable(CAMIO_VFE_CLK);
154 msm_camio_clk_enable(CAMIO_MDC_CLK);
155 msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
156 return 0;
157
158mdc_no_mem:
159 release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
160mdc_busy:
161 iounmap(appbase);
162apps_no_mem:
163 release_mem_region(camio_ext.appphy, camio_ext.appsz);
164enable_fail:
165 return rc;
166}
167
168void msm_camio_disable(struct platform_device *pdev)
169{
170 struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
171 struct msm_camera_device_platform_data *camdev = sinfo->pdata;
172
173 iounmap(mdcbase);
174 release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
175 iounmap(appbase);
176 release_mem_region(camio_ext.appphy, camio_ext.appsz);
177
178 camdev->camera_gpio_off();
179
180 msm_camio_clk_disable(CAMIO_VFE_CLK);
181 msm_camio_clk_disable(CAMIO_MDC_CLK);
182 msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
183}
184
185void msm_camio_camif_pad_reg_reset(void)
186{
187 uint32_t reg;
188 uint32_t mask, value;
189
190 /* select CLKRGM_VFE_SRC_CAM_VFE_SRC: internal source */
191 msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
192
193 reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
194
195 mask = CAM_SEL_BMSK |
196 CAM_PCLK_SRC_SEL_BMSK |
197 CAM_PCLK_INVERT_BMSK;
198
199 value = 1 << CAM_SEL_SHFT |
200 3 << CAM_PCLK_SRC_SEL_SHFT |
201 0 << CAM_PCLK_INVERT_SHFT;
202
203 writel((reg & (~mask)) | (value & mask), mdcbase);
204 mdelay(10);
205
206 reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
207 mask = CAM_PAD_REG_SW_RESET_BMSK;
208 value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
209 writel((reg & (~mask)) | (value & mask), mdcbase);
210 mdelay(10);
211
212 reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
213 mask = CAM_PAD_REG_SW_RESET_BMSK;
214 value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
215 writel((reg & (~mask)) | (value & mask), mdcbase);
216 mdelay(10);
217
218 msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
219 mdelay(10);
220}
221
222void msm_camio_vfe_blk_reset(void)
223{
224 uint32_t val;
225
226 val = readl(appbase + 0x00000210);
227 val |= 0x1;
228 writel(val, appbase + 0x00000210);
229 mdelay(10);
230
231 val = readl(appbase + 0x00000210);
232 val &= ~0x1;
233 writel(val, appbase + 0x00000210);
234 mdelay(10);
235}
236
237void msm_camio_camif_pad_reg_reset_2(void)
238{
239 uint32_t reg;
240 uint32_t mask, value;
241
242 reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
243 mask = CAM_PAD_REG_SW_RESET_BMSK;
244 value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
245 writel((reg & (~mask)) | (value & mask), mdcbase);
246 mdelay(10);
247
248 reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
249 mask = CAM_PAD_REG_SW_RESET_BMSK;
250 value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
251 writel((reg & (~mask)) | (value & mask), mdcbase);
252 mdelay(10);
253}
254
255void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
256{
257 struct clk *clk = NULL;
258
259 clk = camio_vfe_clk;
260
261 if (clk != NULL && clk != ERR_PTR(-ENOENT)) {
262 switch (srctype) {
263 case MSM_CAMIO_CLK_SRC_INTERNAL:
264 clk_set_flags(clk, 0x00000100 << 1);
265 break;
266
267 case MSM_CAMIO_CLK_SRC_EXTERNAL:
268 clk_set_flags(clk, 0x00000100);
269 break;
270
271 default:
272 break;
273 }
274 }
275}
276
277int msm_camio_probe_on(struct platform_device *pdev)
278{
279 struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
280 struct msm_camera_device_platform_data *camdev = sinfo->pdata;
281 camdev->camera_gpio_on();
282 return msm_camio_clk_enable(CAMIO_VFE_CLK);
283}
284
285int msm_camio_probe_off(struct platform_device *pdev)
286{
287 struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
288 struct msm_camera_device_platform_data *camdev = sinfo->pdata;
289 camdev->camera_gpio_off();
290 return msm_camio_clk_disable(CAMIO_VFE_CLK);
291}