]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/dream/camera/msm_io8x.c
895161ae2e1485479fe31d1bd47b36e4995cd6a8
[net-next-2.6.git] / drivers / staging / dream / camera / msm_io8x.c
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
32 static struct clk *camio_vfe_mdc_clk;
33 static struct clk *camio_mdc_clk;
34 static struct clk *camio_vfe_clk;
35 static struct clk *camio_vfe_axi_clk;
36 static struct msm_camera_io_ext camio_ext;
37 static struct resource *appio, *mdcio;
38 void __iomem *appbase, *mdcbase;
39
40 extern int clk_set_flags(struct clk *clk, unsigned long flags);
41
42 int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
43 {
44         int rc = 0;
45         struct clk *clk = NULL;
46
47         switch (clktype) {
48         case CAMIO_VFE_MDC_CLK:
49                 camio_vfe_mdc_clk =
50                 clk = clk_get(NULL, "vfe_mdc_clk");
51                 break;
52
53         case CAMIO_MDC_CLK:
54                 camio_mdc_clk =
55                 clk = clk_get(NULL, "mdc_clk");
56                 break;
57
58         case CAMIO_VFE_CLK:
59                 camio_vfe_clk =
60                 clk = clk_get(NULL, "vfe_clk");
61                 break;
62
63         case CAMIO_VFE_AXI_CLK:
64                 camio_vfe_axi_clk =
65                 clk = clk_get(NULL, "vfe_axi_clk");
66                 break;
67
68         default:
69                 break;
70         }
71
72         if (!IS_ERR(clk))
73                 clk_enable(clk);
74         else
75                 rc = -1;
76
77         return rc;
78 }
79
80 int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
81 {
82         int rc = 0;
83         struct clk *clk = NULL;
84
85         switch (clktype) {
86         case CAMIO_VFE_MDC_CLK:
87                 clk = camio_vfe_mdc_clk;
88                 break;
89
90         case CAMIO_MDC_CLK:
91                 clk = camio_mdc_clk;
92                 break;
93
94         case CAMIO_VFE_CLK:
95                 clk = camio_vfe_clk;
96                 break;
97
98         case CAMIO_VFE_AXI_CLK:
99                 clk = camio_vfe_axi_clk;
100                 break;
101
102         default:
103                 break;
104         }
105
106         if (!IS_ERR(clk)) {
107                 clk_disable(clk);
108                 clk_put(clk);
109         } else
110                 rc = -1;
111
112         return rc;
113 }
114
115 void msm_camio_clk_rate_set(int rate)
116 {
117         struct clk *clk = camio_vfe_mdc_clk;
118
119         /* TODO: check return */
120         clk_set_rate(clk, rate);
121 }
122
123 int msm_camio_enable(struct platform_device *pdev)
124 {
125         int rc = 0;
126         struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
127         struct msm_camera_device_platform_data *camdev = sinfo->pdata;
128
129         camio_ext = camdev->ioext;
130
131         appio = request_mem_region(camio_ext.appphy,
132                 camio_ext.appsz, pdev->name);
133         if (!appio) {
134                 rc = -EBUSY;
135                 goto enable_fail;
136         }
137
138         appbase = ioremap(camio_ext.appphy,
139                 camio_ext.appsz);
140         if (!appbase) {
141                 rc = -ENOMEM;
142                 goto apps_no_mem;
143         }
144
145         mdcio = request_mem_region(camio_ext.mdcphy,
146                 camio_ext.mdcsz, pdev->name);
147         if (!mdcio) {
148                 rc = -EBUSY;
149                 goto mdc_busy;
150         }
151
152         mdcbase = ioremap(camio_ext.mdcphy,
153                 camio_ext.mdcsz);
154         if (!mdcbase) {
155                 rc = -ENOMEM;
156                 goto mdc_no_mem;
157         }
158
159         camdev->camera_gpio_on();
160
161         msm_camio_clk_enable(CAMIO_VFE_CLK);
162         msm_camio_clk_enable(CAMIO_MDC_CLK);
163         msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
164         msm_camio_clk_enable(CAMIO_VFE_AXI_CLK);
165         return 0;
166
167 mdc_no_mem:
168         release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
169 mdc_busy:
170         iounmap(appbase);
171 apps_no_mem:
172         release_mem_region(camio_ext.appphy, camio_ext.appsz);
173 enable_fail:
174         return rc;
175 }
176
177 void msm_camio_disable(struct platform_device *pdev)
178 {
179         struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
180         struct msm_camera_device_platform_data *camdev = sinfo->pdata;
181
182         iounmap(mdcbase);
183         release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
184         iounmap(appbase);
185         release_mem_region(camio_ext.appphy, camio_ext.appsz);
186
187         camdev->camera_gpio_off();
188
189         msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
190         msm_camio_clk_disable(CAMIO_MDC_CLK);
191         msm_camio_clk_disable(CAMIO_VFE_CLK);
192         msm_camio_clk_disable(CAMIO_VFE_AXI_CLK);
193 }
194
195 void msm_camio_camif_pad_reg_reset(void)
196 {
197         uint32_t reg;
198         uint32_t mask, value;
199
200         /* select CLKRGM_VFE_SRC_CAM_VFE_SRC:  internal source */
201         msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
202
203         reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
204
205         mask = CAM_SEL_BMSK |
206                 CAM_PCLK_SRC_SEL_BMSK |
207                 CAM_PCLK_INVERT_BMSK |
208                 EXT_CAM_HSYNC_POL_SEL_BMSK |
209                 EXT_CAM_VSYNC_POL_SEL_BMSK |
210                 MDDI_CLK_CHICKEN_BIT_BMSK;
211
212         value = 1 << CAM_SEL_SHFT |
213                 3 << CAM_PCLK_SRC_SEL_SHFT |
214                 0 << CAM_PCLK_INVERT_SHFT |
215                 0 << EXT_CAM_HSYNC_POL_SEL_SHFT |
216                 0 << EXT_CAM_VSYNC_POL_SEL_SHFT |
217                 0 << MDDI_CLK_CHICKEN_BIT_SHFT;
218         writel((reg & (~mask)) | (value & mask), mdcbase);
219         mdelay(10);
220
221         reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
222         mask = CAM_PAD_REG_SW_RESET_BMSK;
223         value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
224         writel((reg & (~mask)) | (value & mask), mdcbase);
225         mdelay(10);
226
227         reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
228         mask = CAM_PAD_REG_SW_RESET_BMSK;
229         value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
230         writel((reg & (~mask)) | (value & mask), mdcbase);
231         mdelay(10);
232
233         msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
234
235         mdelay(10);
236
237         /* todo: check return */
238         if (camio_vfe_clk)
239                 clk_set_rate(camio_vfe_clk, 96000000);
240 }
241
242 void msm_camio_vfe_blk_reset(void)
243 {
244         uint32_t val;
245
246         val = readl(appbase + 0x00000210);
247         val |= 0x1;
248         writel(val, appbase + 0x00000210);
249         mdelay(10);
250
251         val = readl(appbase + 0x00000210);
252         val &= ~0x1;
253         writel(val, appbase + 0x00000210);
254         mdelay(10);
255 }
256
257 void msm_camio_camif_pad_reg_reset_2(void)
258 {
259         uint32_t reg;
260         uint32_t mask, value;
261
262         reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
263         mask = CAM_PAD_REG_SW_RESET_BMSK;
264         value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
265         writel((reg & (~mask)) | (value & mask), mdcbase);
266         mdelay(10);
267
268         reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
269         mask = CAM_PAD_REG_SW_RESET_BMSK;
270         value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
271         writel((reg & (~mask)) | (value & mask), mdcbase);
272         mdelay(10);
273 }
274
275 void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
276 {
277         struct clk *clk = NULL;
278
279         clk = camio_vfe_clk;
280
281         if (clk != NULL) {
282                 switch (srctype) {
283                 case MSM_CAMIO_CLK_SRC_INTERNAL:
284                         clk_set_flags(clk, 0x00000100 << 1);
285                         break;
286
287                 case MSM_CAMIO_CLK_SRC_EXTERNAL:
288                         clk_set_flags(clk, 0x00000100);
289                         break;
290
291                 default:
292                         break;
293                 }
294         }
295 }
296
297 void msm_camio_clk_axi_rate_set(int rate)
298 {
299         struct clk *clk = camio_vfe_axi_clk;
300         /* todo: check return */
301         clk_set_rate(clk, rate);
302 }
303
304 int msm_camio_probe_on(struct platform_device *pdev)
305 {
306         struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
307         struct msm_camera_device_platform_data *camdev = sinfo->pdata;
308
309         camdev->camera_gpio_on();
310         return msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
311 }
312
313 int msm_camio_probe_off(struct platform_device *pdev)
314 {
315         struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
316         struct msm_camera_device_platform_data *camdev = sinfo->pdata;
317
318         camdev->camera_gpio_off();
319         return msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
320 }