Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_cif.c
1 #include "camsys_cif.h"
2
3 static const char miscdev_cif0_name[] = CAMSYS_CIF0_DEVNAME;
4 static const char miscdev_cif1_name[] = CAMSYS_CIF1_DEVNAME;
5
6 static int camsys_cif_iomux_cb(camsys_extdev_t *extdev,void *ptr)
7 {
8     unsigned int cif_vol_sel;
9 #if 0    
10     if (extdev->dev_cfg & CAMSYS_DEVCFG_FLASHLIGHT) {
11         iomux_set(ISP_FLASH_TRIG);  
12         if (extdev->fl.fl.io != 0xffffffff) {
13             iomux_set(ISP_FL_TRIG);
14         }
15     } 
16
17     if (extdev->dev_cfg & CAMSYS_DEVCFG_PREFLASHLIGHT) {
18         iomux_set(ISP_PRELIGHT_TRIG);
19     }
20     
21     if (extdev->dev_cfg & CAMSYS_DEVCFG_SHUTTER) {
22         iomux_set(ISP_SHUTTER_OPEN);
23         iomux_set(ISP_SHUTTER_TRIG);
24     }
25
26     iomux_set(CIF0_CLKOUT);
27 #endif
28
29     struct pinctrl      *pinctrl;
30     struct pinctrl_state    *state;
31     int retval = 0;
32     char state_str[20] = {0};
33
34     struct device *dev = &(extdev->pdev->dev);
35     
36     if (extdev->phy.type == CamSys_Phy_Cif) {
37         if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_8b)&& (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
38
39            strcpy(state_str,"isp_dvp8bit");
40
41         }
42
43         if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b)&& (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
44            strcpy(state_str,"isp_dvp10bit");
45         }
46
47         if (extdev->phy.info.cif.fmt == CamSys_Fmt_Raw_12b) {
48            strcpy(state_str,"isp_dvp12bit");
49
50         }
51     }else{
52            strcpy(state_str,"default");
53     }
54
55     //mux CIF0_CLKOUT
56
57     pinctrl = devm_pinctrl_get(dev);
58     if (IS_ERR(pinctrl)) {
59         camsys_err("%s:Get pinctrl failed!\n",__func__);
60         return -1;
61     }
62     state = pinctrl_lookup_state(pinctrl,
63                          state_str);
64     if (IS_ERR(state)){
65         dev_err(dev, "%s:could not get %s pinstate\n",__func__,state_str);
66         return -1;
67         }
68
69     if (!IS_ERR(state)) {
70         retval = pinctrl_select_state(pinctrl, state);
71         if (retval){
72             dev_err(dev,
73                 "%s:could not set %s pins\n",__func__,state_str);
74                 return -1;
75
76                 }
77     }
78
79     //set 1.8v vol domain for rk32
80     __raw_writel(((1<<1)|(1<<(1+16))),RK_GRF_VIRT+0x0380);
81    __raw_writel(0xffffffff, RK_GRF_VIRT+0x01d4);   
82
83     //set cif vol domain
84     if (extdev->phy.type == CamSys_Phy_Cif) {
85
86         #if 0
87         if (!IS_ERR_OR_NULL(extdev->dovdd.ldo)) {
88             if (extdev->dovdd.max_uv >= 25000000) {
89                 __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
90             } else {
91                 __raw_writel((1<<(1+16)),RK30_GRF_BASE+0x018c);
92             }
93         } else {
94             __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
95         }
96         #else
97
98         //set 1.8v vol domain
99         __raw_writel(((1<<1)|(1<<(1+16))),RK_GRF_VIRT+0x0380);
100         #endif
101         
102         //set driver strength
103       //  __raw_writel(0xffffffff, RK_GRF_VIRT+0x01dc);   
104     }
105     
106                 
107     return 0;
108 }
109 static int camsys_cif_clkin_cb(void *ptr, unsigned int on)
110 {
111     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
112     camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
113     
114     spin_lock(&clk->lock);
115     if (on && !clk->in_on) {        
116         clk_prepare_enable(clk->aclk_cif);
117         clk_prepare_enable(clk->hclk_cif);
118         clk_prepare_enable(clk->cif_clk_in);
119         
120         clk->in_on = true;
121         camsys_trace(1, "%s clock in turn on",dev_name(camsys_dev->miscdev.this_device));
122     } else if (!on && clk->in_on) {
123         clk_disable_unprepare(clk->hclk_cif);
124         clk_disable_unprepare(clk->cif_clk_in);         
125         clk_disable_unprepare(clk->pd_cif);
126         clk->in_on = false;
127         camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
128     }
129     spin_unlock(&clk->lock);
130     return 0;
131 }
132
133 static int camsys_cif_clkout_cb(void *ptr, unsigned int on,unsigned int clkin)
134 {
135     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
136     camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
137     struct clk *cif_clk_out_div;
138     
139     
140     spin_lock(&clk->lock);
141     if (on && (clk->out_on != on)) {        
142         clk_prepare_enable(clk->cif_clk_out);
143         clk_set_rate(clk->cif_clk_out,clkin);
144         
145         clk->out_on = on;
146         camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
147                     clk->out_on);
148     } else if (!on && clk->out_on) {
149         if (strcmp(dev_name(camsys_dev->miscdev.this_device),miscdev_cif1_name)==0) {
150             cif_clk_out_div =  clk_get(NULL, "cif1_out_div");
151         } else{
152             cif_clk_out_div =  clk_get(NULL, "cif0_out_div");
153             if(IS_ERR_OR_NULL(cif_clk_out_div)) {
154                 cif_clk_out_div =  clk_get(NULL, "cif_out_div");
155             }
156         }
157
158         if(!IS_ERR_OR_NULL(cif_clk_out_div)) {
159             clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
160             clk_put(cif_clk_out_div);
161         } else {
162             camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
163         }
164         clk_disable_unprepare(clk->cif_clk_out);
165         clk->out_on = 0;
166
167         camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
168     }
169     spin_unlock(&clk->lock);
170
171     {
172   //  __raw_writel(0x00, CRU_PCLK_REG30+RK30_CRU_BASE);
173     }
174
175     return 0;
176 }
177
178 static irqreturn_t camsys_cif_irq(int irq, void *data)
179 {
180     camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
181     camsys_irqstas_t *irqsta;
182     camsys_irqpool_t *irqpool;
183     unsigned int intsta,frmsta;
184
185     intsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
186     frmsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
187    printk("get oneframe,intsta = 0x%x \n",intsta);
188  
189     if (intsta & 0x200) {
190         __raw_writel(0x200,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
191         __raw_writel(0xf000,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
192     }
193
194     if (intsta &0x01) {
195         __raw_writel(0x01,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
196         __raw_writel(0x02,camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
197         __raw_writel(0xf001,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
198     }    
199     
200     spin_lock(&camsys_dev->irq.lock);
201     list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
202         spin_lock(&irqpool->lock);
203         if (!list_empty(&irqpool->deactive)) {
204             irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
205             irqsta->sta.mis = intsta;
206             irqsta->sta.ris = intsta;
207             list_del_init(&irqsta->list);            
208             list_add_tail(&irqsta->list,&irqpool->active);
209             irqsta = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
210             //wake_up_all(&camsys_dev->irq.irq_done);
211             wake_up(&irqpool->done);
212         }
213         spin_unlock(&irqpool->lock);
214     }
215     spin_unlock(&camsys_dev->irq.lock);
216    
217     return IRQ_HANDLED;
218 }
219
220 static int camsys_cif_remove(struct platform_device *pdev)
221 {
222     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
223     camsys_cif_clk_t *cif_clk;
224     
225     if (camsys_dev->clk != NULL) {
226         cif_clk = (camsys_cif_clk_t*)camsys_dev->clk;
227         if (cif_clk->out_on) 
228             camsys_cif_clkout_cb(camsys_dev->clk, 0,0);
229         if (cif_clk->in_on)
230             camsys_cif_clkin_cb(camsys_dev->clk, 0);
231
232         if (cif_clk->pd_cif)
233             clk_put(cif_clk->pd_cif);
234         if (cif_clk->aclk_cif)
235             clk_put(cif_clk->aclk_cif);
236         if (cif_clk->hclk_cif)
237             clk_put(cif_clk->hclk_cif);
238         if (cif_clk->cif_clk_in)
239             clk_put(cif_clk->cif_clk_in);
240         if (cif_clk->cif_clk_out)
241             clk_put(cif_clk->cif_clk_out);
242     
243         kfree(cif_clk);
244         cif_clk = NULL;
245     }
246
247     return 0;
248 }
249
250 int camsys_cif_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
251 {
252     int err = 0;   
253     camsys_cif_clk_t *cif_clk;
254
255     //Irq init
256     err = request_irq(camsys_dev->irq.irq_id, camsys_cif_irq, 0, CAMSYS_CIF_IRQNAME,camsys_dev);
257     if (err) {
258         camsys_err("request irq for %s failed",CAMSYS_CIF_IRQNAME);
259         goto end;
260     }
261
262     //Clk and Iomux init
263     cif_clk = kzalloc(sizeof(camsys_cif_clk_t),GFP_KERNEL);
264     if (cif_clk == NULL) {
265         camsys_err("Allocate camsys_cif_clk_t failed!");
266         err = -EINVAL;
267         goto end;
268     }
269     
270     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
271         cif_clk->aclk_cif = devm_clk_get(&pdev->dev, "g_aclk_vip");
272         cif_clk->hclk_cif = devm_clk_get(&pdev->dev, "g_hclk_vip");
273         cif_clk->cif_clk_in = devm_clk_get(&pdev->dev, "g_pclkin_cif");
274         cif_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out");
275         spin_lock_init(&cif_clk->lock);
276         cif_clk->in_on = false;
277         cif_clk->out_on = false;
278     } else {           
279         cif_clk->aclk_cif = devm_clk_get(&pdev->dev, "g_aclk_vip");
280         cif_clk->hclk_cif = devm_clk_get(&pdev->dev, "g_hclk_vip");
281         cif_clk->cif_clk_in = devm_clk_get(&pdev->dev, "g_pclkin_ci");
282         cif_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out");
283         spin_lock_init(&cif_clk->lock);
284         cif_clk->in_on = false;
285         cif_clk->out_on = false;
286     }
287
288  //   clk_prepare_enable(cif_clk->aclk_cif);
289  //   clk_prepare_enable(cif_clk->hclk_cif);
290  //   clk_prepare_enable(cif_clk->cif_clk_in);
291  //   clk_prepare_enable(cif_clk->cif_clk_out);
292
293
294     
295     camsys_dev->clk = (void*)cif_clk;
296     camsys_dev->clkin_cb = camsys_cif_clkin_cb;
297     camsys_dev->clkout_cb = camsys_cif_clkout_cb;
298     camsys_dev->iomux = camsys_cif_iomux_cb;
299     
300     //Misc device init
301     camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
302     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
303         camsys_dev->miscdev.name = miscdev_cif1_name;
304         camsys_dev->miscdev.nodename = miscdev_cif1_name;        
305     } else {
306         camsys_dev->miscdev.name = miscdev_cif0_name;
307         camsys_dev->miscdev.nodename = miscdev_cif0_name;
308     }
309     camsys_dev->miscdev.fops = &camsys_fops;
310     err = misc_register(&camsys_dev->miscdev);
311     if (err < 0) {
312         camsys_trace(1,"Register /dev/%s misc device failed",camsys_dev->miscdev.name);
313         goto misc_register_failed;
314     } else {
315         camsys_trace(1,"Register /dev/%s misc device success",camsys_dev->miscdev.name);
316     }
317
318     //Variable init
319     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
320         camsys_dev->dev_id = CAMSYS_DEVID_CIF_1;
321     } else {
322         camsys_dev->dev_id = CAMSYS_DEVID_CIF_0;
323     }
324     camsys_dev->platform_remove = camsys_cif_remove;
325
326     return 0;
327
328 misc_register_failed:
329     if (!IS_ERR(camsys_dev->miscdev.this_device)) {
330         misc_deregister(&camsys_dev->miscdev);
331     }
332
333     if (cif_clk) {
334
335         if (cif_clk->pd_cif)
336             clk_put(cif_clk->pd_cif);
337         if (cif_clk->aclk_cif)
338             clk_put(cif_clk->aclk_cif);
339         if (cif_clk->hclk_cif)
340             clk_put(cif_clk->hclk_cif);
341         if (cif_clk->cif_clk_in)
342             clk_put(cif_clk->cif_clk_in);
343         if (cif_clk->cif_clk_out)
344             clk_put(cif_clk->cif_clk_out);
345     
346         kfree(cif_clk);
347         cif_clk = NULL;
348     }
349     
350 end:
351     return err;
352 }
353 EXPORT_SYMBOL_GPL(camsys_cif_probe_cb);
354