• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/dream/camera/
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;
35static struct clk *camio_vfe_axi_clk;
36static struct msm_camera_io_ext camio_ext;
37static struct resource *appio, *mdcio;
38void __iomem *appbase, *mdcbase;
39
40extern int clk_set_flags(struct clk *clk, unsigned long flags);
41
42int 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
80int 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
115void 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
123int 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
167mdc_no_mem:
168	release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
169mdc_busy:
170	iounmap(appbase);
171apps_no_mem:
172	release_mem_region(camio_ext.appphy, camio_ext.appsz);
173enable_fail:
174	return rc;
175}
176
177void 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
195void 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
242void 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
257void 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
275void 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
297void 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
304int 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
313int 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}
321