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