add isp driver for rk3288
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_marvin.c
1 #include "camsys_marvin.h"
2
3 static const char miscdev_name[] = CAMSYS_MARVIN_DEVNAME;
4
5
6 static int camsys_mrv_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 cif vol domain
80     if (extdev->phy.type == CamSys_Phy_Cif) {
81
82         #if 0
83         if (!IS_ERR_OR_NULL(extdev->dovdd.ldo)) {
84             if (extdev->dovdd.max_uv >= 25000000) {
85                 __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
86             } else {
87                 __raw_writel((1<<(1+16)),RK30_GRF_BASE+0x018c);
88             }
89         } else {
90             __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
91         }
92         #else
93         __raw_writel(((1<<1)|(1<<(1+16))),RK_GRF_VIRT+0x018c);
94         #endif
95         
96         //set driver strength
97         __raw_writel(0xffffffff, RK_GRF_VIRT+0x01dc);   
98     }
99     
100     return 0;
101 }
102
103 static int camsys_mrv_reset_cb(void *ptr)
104 {
105     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
106     #if 0 //do nothing ,zyc
107     cru_set_soft_reset(SOFT_RST_ISP,true);
108     udelay(100);
109     cru_set_soft_reset(SOFT_RST_ISP,false);
110     #endif
111     camsys_trace(1, "%s soft reset\n",dev_name(camsys_dev->miscdev.this_device));
112     return 0;
113 }
114
115 static int camsys_mrv_clkin_cb(void *ptr, unsigned int on)
116 {
117     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
118     camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
119     
120     spin_lock(&clk->lock);
121     if (on && !clk->in_on) {        
122         clk_enable(clk->pd_isp);
123         clk_enable(clk->aclk_isp);
124         clk_enable(clk->hclk_isp);      
125         clk_enable(clk->isp);
126         clk_enable(clk->isp_jpe);
127         clk_enable(clk->pclkin_isp);
128         
129         clk->in_on = true;
130
131         camsys_trace(1, "%s clock in turn on",dev_name(camsys_dev->miscdev.this_device));
132         camsys_mrv_reset_cb(ptr);       
133         
134     } else if (!on && clk->in_on) {
135         clk_disable(clk->pd_isp);
136         clk_disable(clk->aclk_isp);
137         clk_disable(clk->hclk_isp);
138         clk_disable(clk->isp);
139         clk_disable(clk->isp_jpe);
140         clk_disable(clk->pclkin_isp);
141         clk->in_on = false;
142         camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
143     }
144     spin_unlock(&clk->lock);
145     return 0;
146 }
147
148 static int camsys_mrv_clkout_cb(void *ptr, unsigned int on)
149 {
150     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
151     camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
152     struct clk *cif_clk_out_div;
153     
154     spin_lock(&clk->lock);
155     if (on && (clk->out_on != on)) {        
156         clk_enable(clk->cif_clk_out);
157         clk_set_rate(clk->cif_clk_out,on);
158         
159         clk->out_on = on;
160         camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
161                     clk->out_on);
162     } else if (!on && clk->out_on) {
163         cif_clk_out_div =  clk_get(NULL, "cif0_out_div");
164         if(IS_ERR_OR_NULL(cif_clk_out_div)) {
165             cif_clk_out_div =  clk_get(NULL, "cif_out_div");
166         }
167
168         if(!IS_ERR_OR_NULL(cif_clk_out_div)) {
169             clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
170             clk_put(cif_clk_out_div);
171         } else {
172             camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
173         }
174         clk_disable(clk->cif_clk_out);
175         clk->out_on = 0;
176
177         camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
178     }
179     spin_unlock(&clk->lock);    
180
181     return 0;
182 }
183 static irqreturn_t camsys_mrv_irq(int irq, void *data)
184 {
185     camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
186     camsys_irqstas_t *irqsta;
187     camsys_irqpool_t *irqpool;
188     unsigned int isp_mis,mipi_mis,mi_mis,*mis;
189
190     isp_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_MIS));
191     mipi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_MIS));
192     mi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_MIS));    
193
194     __raw_writel(isp_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_ICR)); 
195     __raw_writel(mipi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_ICR)); 
196     __raw_writel(mi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_ICR)); 
197     
198     spin_lock(&camsys_dev->irq.lock);
199     if (!list_empty(&camsys_dev->irq.irq_pool)) {
200         list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
201             if (irqpool->pid != 0) {
202                 switch(irqpool->mis)
203                 {
204                     case MRV_ISP_MIS:
205                     {
206                         mis = &isp_mis;
207                         break;
208                     }
209
210                     case MRV_MIPI_MIS:
211                     {
212                         mis = &mipi_mis;
213                         break;
214                     }
215                     case MRV_MI_MIS:
216                     {
217                         mis = &mi_mis;
218                         break;
219                     }
220
221                     default:     
222                     {
223                         camsys_trace(2,"Thread(pid:%d) irqpool mis(%d) is invalidate",irqpool->pid,irqpool->mis);
224                         goto end;
225                     }
226                 }
227
228                 if (*mis != 0) {
229                     spin_lock(&irqpool->lock);
230                     if (!list_empty(&irqpool->deactive)) {
231                         irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
232                         irqsta->sta.mis = *mis;                                                 
233                         list_del_init(&irqsta->list);            
234                         list_add_tail(&irqsta->list,&irqpool->active);                        
235                         wake_up(&irqpool->done);
236                     }
237                     spin_unlock(&irqpool->lock);
238                 }
239             }
240         }
241     }
242 end:    
243     spin_unlock(&camsys_dev->irq.lock);
244
245     return IRQ_HANDLED;
246 }
247 static int camsys_mrv_remove_cb(struct platform_device *pdev)
248 {
249     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
250     camsys_mrv_clk_t *mrv_clk=NULL;
251
252     if (camsys_dev->clk != NULL) {
253
254         mrv_clk = (camsys_mrv_clk_t*)camsys_dev->clk;
255         if (mrv_clk->out_on)
256             camsys_mrv_clkout_cb(mrv_clk,0);
257         if (mrv_clk->in_on)
258             camsys_mrv_clkin_cb(mrv_clk,0);
259     
260         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
261             clk_put(mrv_clk->pd_isp);
262         }
263         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
264             clk_put(mrv_clk->aclk_isp);
265         }
266         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
267             clk_put(mrv_clk->hclk_isp);
268         }
269         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
270             clk_put(mrv_clk->isp);
271         }
272         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
273             clk_put(mrv_clk->isp_jpe);
274         }
275         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
276             clk_put(mrv_clk->pclkin_isp);
277         }
278         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
279             clk_put(mrv_clk->cif_clk_out);
280         }
281
282         kfree(mrv_clk);
283         mrv_clk = NULL;
284     }
285
286     return 0;
287 }
288 int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
289 {
290     int err = 0;   
291     camsys_mrv_clk_t *mrv_clk=NULL;
292     //struct clk *clk_parent;
293     
294     err = request_irq(camsys_dev->irq.irq_id, camsys_mrv_irq, 0, CAMSYS_MARVIN_IRQNAME,camsys_dev);
295     if (err) {
296         camsys_err("request irq for %s failed",CAMSYS_MARVIN_IRQNAME);
297         goto end;
298     }
299
300     //Clk and Iomux init
301     mrv_clk = kzalloc(sizeof(camsys_mrv_clk_t),GFP_KERNEL);
302     if (mrv_clk == NULL) {
303         camsys_err("Allocate camsys_mrv_clk_t failed!");
304         err = -EINVAL;
305         goto clk_failed;
306     }
307      
308    // mrv_clk->pd_isp = devm_clk_get(&pdev->dev, "pd_isp");
309     mrv_clk->pd_isp = NULL;
310     mrv_clk->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
311     mrv_clk->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
312     mrv_clk->isp = devm_clk_get(&pdev->dev, "clk_isp");
313     mrv_clk->isp_jpe = devm_clk_get(&pdev->dev, "clk_isp_jpe");
314     mrv_clk->pclkin_isp = devm_clk_get(&pdev->dev, "pclkin_isp");
315     mrv_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_vipout");
316     if (/*IS_ERR_OR_NULL(mrv_clk->pd_isp) ||*/ IS_ERR_OR_NULL(mrv_clk->aclk_isp) || IS_ERR_OR_NULL(mrv_clk->hclk_isp) ||
317         IS_ERR_OR_NULL(mrv_clk->isp) || IS_ERR_OR_NULL(mrv_clk->isp_jpe) || IS_ERR_OR_NULL(mrv_clk->pclkin_isp) || 
318         IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
319         camsys_err("Get %s clock resouce failed!\n",miscdev_name);
320         err = -EINVAL;
321         goto clk_failed;
322     }
323     
324     clk_set_rate(mrv_clk->isp,320000000);
325     clk_set_rate(mrv_clk->isp_jpe,320000000);
326     
327     spin_lock_init(&mrv_clk->lock);
328     
329     mrv_clk->in_on = false;
330     mrv_clk->out_on = 0;
331         
332     camsys_dev->clk = (void*)mrv_clk;
333     camsys_dev->clkin_cb = camsys_mrv_clkin_cb;
334     camsys_dev->clkout_cb = camsys_mrv_clkout_cb;
335     camsys_dev->reset_cb = camsys_mrv_reset_cb;
336     camsys_dev->iomux = camsys_mrv_iomux_cb;
337     
338     camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
339     camsys_dev->miscdev.name = miscdev_name;
340     camsys_dev->miscdev.nodename = miscdev_name;
341     camsys_dev->miscdev.fops = &camsys_fops;
342
343     err = misc_register(&camsys_dev->miscdev);
344     if (err < 0) {
345         camsys_err("misc register %s failed!",miscdev_name);
346         goto misc_register_failed;
347     }   
348
349     //Variable init
350     camsys_dev->dev_id = CAMSYS_DEVID_MARVIN;
351     camsys_dev->platform_remove = camsys_mrv_remove_cb;
352     
353     return 0;
354 misc_register_failed:
355     if (!IS_ERR_OR_NULL(camsys_dev->miscdev.this_device)) {
356         misc_deregister(&camsys_dev->miscdev);
357     }
358
359 clk_failed:
360     if (mrv_clk != NULL) {
361         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
362             clk_put(mrv_clk->pd_isp);
363         }
364         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
365             clk_put(mrv_clk->aclk_isp);
366         }
367         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
368             clk_put(mrv_clk->hclk_isp);
369         }
370         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
371             clk_put(mrv_clk->isp);
372         }
373         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
374             clk_put(mrv_clk->isp_jpe);
375         }
376         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
377             clk_put(mrv_clk->pclkin_isp);
378         }
379         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
380             clk_put(mrv_clk->cif_clk_out);
381         }
382
383         kfree(mrv_clk);
384         mrv_clk = NULL;
385     }
386     
387 end:
388     return err;
389 }
390 EXPORT_SYMBOL_GPL(camsys_mrv_probe_cb);
391