camsys_drv : v0.f.0
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_marvin.c
1 #include "camsys_marvin.h"
2 #include "camsys_soc_priv.h"
3 #include "camsys_gpio.h"
4
5 #include <linux/rockchip/common.h> 
6 #include <dt-bindings/clock/rk_system_status.h>
7
8 extern int rockchip_set_system_status(unsigned long status);
9 extern int rockchip_clear_system_status(unsigned long status);
10
11 static const char miscdev_name[] = CAMSYS_MARVIN_DEVNAME;
12
13
14 static int camsys_mrv_iomux_cb(camsys_extdev_t *extdev,void *ptr)
15 {
16     struct pinctrl      *pinctrl;
17     struct pinctrl_state    *state;
18     int retval = 0;
19     char state_str[20] = {0};
20     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
21     struct device *dev = &(extdev->pdev->dev);
22     camsys_soc_priv_t *soc;
23
24     // DVP IO Config
25     
26     if (extdev->phy.type == CamSys_Phy_Cif) {
27
28         switch (extdev->phy.info.cif.fmt)
29         {
30             case CamSys_Fmt_Raw_8b:
31             case CamSys_Fmt_Yuv420_8b:
32             case CamSys_Fmt_Yuv422_8b:
33             {
34                 if (extdev->phy.info.cif.cifio == CamSys_SensorBit0_CifBit0) {
35                     strcpy(state_str,"isp_dvp8bit0");
36                 } else if (extdev->phy.info.cif.cifio == CamSys_SensorBit0_CifBit2) {
37                     strcpy(state_str,"isp_dvp8bit2");
38                 } else {
39                     camsys_err("extdev->phy.info.cif.cifio: 0x%x is invalidate!", extdev->phy.info.cif.cifio);
40                     goto fail;
41                 }
42
43                 break;
44             }
45
46             case CamSys_Fmt_Raw_10b:
47             {
48                 strcpy(state_str,"isp_dvp10bit");
49                 break;
50             }
51
52             case CamSys_Fmt_Raw_12b:
53             {
54                 strcpy(state_str,"isp_dvp12bit");
55                 break;
56             }
57
58             default:
59             {
60                 camsys_err("extdev->phy.info.cif.fmt: 0x%x is invalidate!",extdev->phy.info.cif.fmt);
61                 goto fail;
62             }
63         }        
64     } else {
65         if (extdev->dev_cfg & CAMSYS_DEVCFG_FLASHLIGHT) {
66             if (extdev->dev_cfg & CAMSYS_DEVCFG_PREFLASHLIGHT) {
67                 strcpy(state_str,"isp_mipi_fl_prefl");
68             } else {
69                 strcpy(state_str,"isp_mipi_fl");
70             }
71         } else {
72             strcpy(state_str,"default");
73         }
74     }
75
76     camsys_trace(1,"marvin pinctrl select: %s", state_str);
77     
78     pinctrl = devm_pinctrl_get(dev);
79     if (IS_ERR(pinctrl)) {
80         camsys_err("devm_pinctrl_get failed!");
81         goto fail;
82     }
83     state = pinctrl_lookup_state(pinctrl,
84                          state_str);
85     if (IS_ERR(state)){
86         camsys_err("pinctrl_lookup_state failed!");
87         goto fail;
88     }
89
90     if (!IS_ERR(state)) {
91         retval = pinctrl_select_state(pinctrl, state);
92         if (retval){
93             camsys_err("pinctrl_select_state failed!");
94             goto fail;
95         }
96     }
97
98     if (camsys_dev->soc) {
99         soc = (camsys_soc_priv_t*)camsys_dev->soc;
100         if (soc->soc_cfg) {
101             (soc->soc_cfg)(Cif_IoDomain_Cfg,(void*)&extdev->dovdd.min_uv);
102             (soc->soc_cfg)(Clk_DriverStrength_Cfg,(void*)&extdev->clk.driver_strength);
103         } else {
104             camsys_err("camsys_dev->soc->soc_cfg is NULL!");
105         }
106     } else {
107         camsys_err("camsys_dev->soc is NULL!");
108     }
109     
110     return 0;
111 fail:
112     return -1;
113 }
114
115 static int camsys_mrv_flash_trigger_cb(void *ptr,unsigned int on)
116 {
117     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
118     struct device *dev = &(camsys_dev->pdev->dev);
119     int flash_trigger_io ;
120     struct pinctrl      *pinctrl;
121     struct pinctrl_state    *state;
122     char state_str[20] = {0};
123     int retval = 0;
124     enum of_gpio_flags flags;
125
126     if(!on){
127         strcpy(state_str,"isp_flash_as_gpio");
128         pinctrl = devm_pinctrl_get(dev);
129         if (IS_ERR(pinctrl)) {
130             camsys_err("devm_pinctrl_get failed!");
131         }
132         state = pinctrl_lookup_state(pinctrl,
133                              state_str);
134         if (IS_ERR(state)){
135             camsys_err("pinctrl_lookup_state failed!");
136         }
137
138         if (!IS_ERR(state)) {
139             retval = pinctrl_select_state(pinctrl, state);
140             if (retval){
141                 camsys_err("pinctrl_select_state failed!");
142             }
143
144         }
145
146         //get gpio index
147         flash_trigger_io = of_get_named_gpio_flags(camsys_dev->pdev->dev.of_node, "rockchip,gpios", 0, &flags);
148         if(gpio_is_valid(flash_trigger_io)){
149             flash_trigger_io = of_get_named_gpio_flags(camsys_dev->pdev->dev.of_node, "rockchip,gpios", 0, &flags);
150             gpio_request(flash_trigger_io,"camsys_gpio");
151             gpio_direction_output(flash_trigger_io, 1);
152             }
153
154     }else{
155         strcpy(state_str,"isp_flash_as_trigger_out");
156         pinctrl = devm_pinctrl_get(dev);
157         if (IS_ERR(pinctrl)) {
158             camsys_err("devm_pinctrl_get failed!");
159         }
160         state = pinctrl_lookup_state(pinctrl,
161                              state_str);
162         if (IS_ERR(state)){
163             camsys_err("pinctrl_lookup_state failed!");
164         }
165
166         if (!IS_ERR(state)) {
167             retval = pinctrl_select_state(pinctrl, state);
168             if (retval){
169                 camsys_err("pinctrl_select_state failed!");
170             }
171
172         }
173     }
174     return retval;
175 }
176
177
178 static int camsys_mrv_reset_cb(void *ptr,unsigned int on)
179 {
180     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
181     camsys_soc_priv_t *soc;
182
183
184     if (camsys_dev->soc) {
185         soc = (camsys_soc_priv_t*)camsys_dev->soc;
186         if (soc->soc_cfg) {
187             (soc->soc_cfg)(Isp_SoftRst,(void*)on);
188         } else {
189             camsys_err("camsys_dev->soc->soc_cfg is NULL!");
190         }
191     } else {
192         camsys_err("camsys_dev->soc is NULL!");
193     }
194     
195     return 0;
196 }
197
198 static int camsys_mrv_clkin_cb(void *ptr, unsigned int on)
199 {
200     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
201     camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
202     unsigned long isp_clk;
203         
204     if (on && !clk->in_on) {
205                 rockchip_set_system_status(SYS_STATUS_ISP);
206
207                 if (on == 1) {
208                     isp_clk = 210000000;           
209                 } else {
210                     isp_clk = 420000000;            
211                 }
212
213                 clk_set_rate(clk->isp,isp_clk);
214         clk_set_rate(clk->isp_jpe, isp_clk);
215
216         clk_prepare_enable(clk->aclk_isp);
217         clk_prepare_enable(clk->hclk_isp);
218         clk_prepare_enable(clk->isp);
219         clk_prepare_enable(clk->isp_jpe);
220         clk_prepare_enable(clk->clk_mipi_24m); 
221         clk_prepare_enable(clk->pclkin_isp); 
222                 clk_prepare_enable(clk->pd_isp);
223
224         clk->in_on = true;
225
226         camsys_trace(1, "%s clock(f: %ld Hz) in turn on",dev_name(camsys_dev->miscdev.this_device),isp_clk);
227         camsys_mrv_reset_cb(ptr,1);
228         udelay(100);
229         camsys_mrv_reset_cb(ptr,0);
230         
231     } else if (!on && clk->in_on) {
232
233         clk_disable_unprepare(clk->aclk_isp);
234         clk_disable_unprepare(clk->hclk_isp);
235         clk_disable_unprepare(clk->isp);
236         clk_disable_unprepare(clk->isp_jpe);
237         clk_disable_unprepare(clk->clk_mipi_24m); 
238         clk_disable_unprepare(clk->pclkin_isp); 
239                 clk_disable_unprepare(clk->pd_isp);
240
241                 rockchip_clear_system_status(SYS_STATUS_ISP);
242         clk->in_on = false;
243         camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
244     }
245     
246     return 0;
247 }
248 static int camsys_mrv_clkout_cb(void *ptr, unsigned int on,unsigned int inclk)
249 {
250     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
251     camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
252     
253     mutex_lock(&clk->lock);
254     if (on && (clk->out_on != on)) {  
255
256         clk_set_rate(clk->cif_clk_out,inclk);
257         clk_prepare_enable(clk->cif_clk_out);
258         
259                 clk->out_on = on;
260         camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
261                     inclk);
262     } else if (!on && clk->out_on) {
263         if(!IS_ERR_OR_NULL(clk->cif_clk_pll)) {
264             clk_set_parent(clk->cif_clk_out, clk->cif_clk_pll);
265         } else {
266             camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
267         }
268
269         clk_disable_unprepare( clk->cif_clk_out);
270
271         clk->out_on = 0;
272
273         camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
274     }
275     mutex_unlock(&clk->lock);    
276
277     return 0;
278 }
279 static irqreturn_t camsys_mrv_irq(int irq, void *data)
280 {
281     camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
282     camsys_irqstas_t *irqsta;
283     camsys_irqpool_t *irqpool;
284     unsigned int isp_mis,mipi_mis,mi_mis,*mis;
285         
286         unsigned int mi_ris,mi_imis;
287
288     isp_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_MIS));
289     mipi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_MIS));
290
291         mi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_MIS));
292 #if 1   
293         mi_ris =  __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_RIS));
294         mi_imis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_IMIS));
295         while((mi_ris & mi_imis) != mi_mis){
296                 camsys_trace(2,"mi_mis status erro,mi_mis 0x%x,mi_ris 0x%x,imis 0x%x\n",mi_mis,mi_ris,mi_imis);
297                 mi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_MIS));
298                 mi_ris =  __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_RIS));
299         mi_imis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_IMIS));
300         }
301
302 #endif
303
304     __raw_writel(isp_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_ICR)); 
305     __raw_writel(mipi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_ICR)); 
306         __raw_writel(mi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_ICR)); 
307
308     spin_lock(&camsys_dev->irq.lock);
309     if (!list_empty(&camsys_dev->irq.irq_pool)) {
310         list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
311             if (irqpool->pid != 0) {
312                 switch(irqpool->mis)
313                 {
314                     case MRV_ISP_MIS:
315                     {
316                         mis = &isp_mis;
317                         break;
318                     }
319
320                     case MRV_MIPI_MIS:
321                     {
322                         mis = &mipi_mis;
323                         break;
324                     }
325                     case MRV_MI_MIS:
326                     {
327                         mis = &mi_mis;
328                         break;
329                     }
330
331                     default:     
332                     {
333                         camsys_trace(2,"Thread(pid:%d) irqpool mis(%d) is invalidate",irqpool->pid,irqpool->mis);
334                         goto end;
335                     }
336                 }
337
338                 if (*mis != 0) {
339                     spin_lock(&irqpool->lock);
340                     if (!list_empty(&irqpool->deactive)) {
341                         irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
342                         irqsta->sta.mis = *mis;                                                 
343                         list_del_init(&irqsta->list);            
344                         list_add_tail(&irqsta->list,&irqpool->active);                        
345                         wake_up(&irqpool->done);
346                     }
347                     spin_unlock(&irqpool->lock);
348                 }
349             }
350         }
351     }
352 end:    
353     spin_unlock(&camsys_dev->irq.lock);
354
355     return IRQ_HANDLED;
356 }
357 static int camsys_mrv_remove_cb(struct platform_device *pdev)
358 {
359     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
360     camsys_mrv_clk_t *mrv_clk=NULL;
361
362     if (camsys_dev->clk != NULL) {
363
364         mrv_clk = (camsys_mrv_clk_t*)camsys_dev->clk;
365         if (mrv_clk->out_on)
366             camsys_mrv_clkout_cb(mrv_clk,0,0);
367         if (mrv_clk->in_on)
368             camsys_mrv_clkin_cb(mrv_clk,0);
369     
370         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
371                         devm_clk_put(&pdev->dev,mrv_clk->pd_isp);
372         }
373         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
374             devm_clk_put(&pdev->dev,mrv_clk->aclk_isp);
375         }
376         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
377             devm_clk_put(&pdev->dev,mrv_clk->hclk_isp);
378         }
379         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
380             devm_clk_put(&pdev->dev,mrv_clk->isp);
381         }
382         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
383             devm_clk_put(&pdev->dev,mrv_clk->isp_jpe);
384         }
385         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
386             devm_clk_put(&pdev->dev,mrv_clk->pclkin_isp);
387         }
388         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
389             devm_clk_put(&pdev->dev,mrv_clk->cif_clk_out);
390         }
391
392         kfree(mrv_clk);
393         mrv_clk = NULL;
394     }
395
396     return 0;
397 }
398 int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
399 {
400     int err = 0;   
401     camsys_mrv_clk_t *mrv_clk=NULL;
402     
403         err = request_irq(camsys_dev->irq.irq_id, camsys_mrv_irq, 0, CAMSYS_MARVIN_IRQNAME,camsys_dev);
404     if (err) {
405         camsys_err("request irq for %s failed",CAMSYS_MARVIN_IRQNAME);
406         goto end;
407     }
408
409     //Clk and Iomux init
410     mrv_clk = kzalloc(sizeof(camsys_mrv_clk_t),GFP_KERNEL);
411     if (mrv_clk == NULL) {
412         camsys_err("Allocate camsys_mrv_clk_t failed!");
413         err = -EINVAL;
414         goto clk_failed;
415     }
416      
417     mrv_clk->pd_isp = devm_clk_get(&pdev->dev, "pd_isp");
418     mrv_clk->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
419     mrv_clk->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
420     mrv_clk->isp = devm_clk_get(&pdev->dev, "clk_isp");
421     mrv_clk->isp_jpe = devm_clk_get(&pdev->dev, "clk_isp_jpe");
422     mrv_clk->pclkin_isp = devm_clk_get(&pdev->dev, "pclkin_isp");
423     mrv_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out");
424     mrv_clk->cif_clk_pll = devm_clk_get(&pdev->dev, "clk_cif_pll");
425     mrv_clk->clk_mipi_24m = devm_clk_get(&pdev->dev,"clk_mipi_24m"); 
426     
427         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) ||
428         IS_ERR_OR_NULL(mrv_clk->isp) || IS_ERR_OR_NULL(mrv_clk->isp_jpe) || IS_ERR_OR_NULL(mrv_clk->pclkin_isp) || 
429         IS_ERR_OR_NULL(mrv_clk->cif_clk_out) || IS_ERR_OR_NULL(mrv_clk->clk_mipi_24m)) {
430         camsys_err("Get %s clock resouce failed!\n",miscdev_name);
431         err = -EINVAL;
432         goto clk_failed;
433     }
434     
435     clk_set_rate(mrv_clk->isp,210000000);
436     clk_set_rate(mrv_clk->isp_jpe, 210000000);
437     
438     mutex_init(&mrv_clk->lock);
439     
440     mrv_clk->in_on = false;
441     mrv_clk->out_on = 0;
442         
443     camsys_dev->clk = (void*)mrv_clk;
444     camsys_dev->clkin_cb = camsys_mrv_clkin_cb;
445     camsys_dev->clkout_cb = camsys_mrv_clkout_cb;
446     camsys_dev->reset_cb = camsys_mrv_reset_cb;
447     camsys_dev->iomux = camsys_mrv_iomux_cb;
448     camsys_dev->flash_trigger_cb = camsys_mrv_flash_trigger_cb;
449     
450     camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
451     camsys_dev->miscdev.name = miscdev_name;
452     camsys_dev->miscdev.nodename = miscdev_name;
453     camsys_dev->miscdev.fops = &camsys_fops;
454
455     err = misc_register(&camsys_dev->miscdev);
456     if (err < 0) {
457         camsys_err("misc register %s failed!",miscdev_name);
458         goto misc_register_failed;
459     }   
460
461     //Variable init
462     camsys_dev->dev_id = CAMSYS_DEVID_MARVIN;
463     camsys_dev->platform_remove = camsys_mrv_remove_cb;
464    
465          
466     return 0;
467 misc_register_failed:
468     if (!IS_ERR_OR_NULL(camsys_dev->miscdev.this_device)) {
469         misc_deregister(&camsys_dev->miscdev);
470     }
471
472 clk_failed:
473     if (mrv_clk != NULL) {
474         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
475             clk_put(mrv_clk->pd_isp);
476         }
477         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
478             clk_put(mrv_clk->aclk_isp);
479         }
480         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
481             clk_put(mrv_clk->hclk_isp);
482         }
483         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
484             clk_put(mrv_clk->isp);
485         }
486         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
487             clk_put(mrv_clk->isp_jpe);
488         }
489         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
490             clk_put(mrv_clk->pclkin_isp);
491         }
492         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
493             clk_put(mrv_clk->cif_clk_out);
494         }
495
496         kfree(mrv_clk);
497         mrv_clk = NULL;
498     }
499     
500 end:
501     return err;
502 }
503 EXPORT_SYMBOL_GPL(camsys_mrv_probe_cb);
504