camsys: v0.e.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
249 static int camsys_mrv_clkout_cb(void *ptr, unsigned int on,unsigned int inclk)
250 {
251     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
252     camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
253     
254     mutex_lock(&clk->lock);
255     if (on && (clk->out_on != on)) {  
256
257         clk_set_rate(clk->cif_clk_out,inclk);
258         clk_prepare_enable(clk->cif_clk_out);
259         
260                 clk->out_on = on;
261         camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
262                     inclk);
263     } else if (!on && clk->out_on) {
264         if(!IS_ERR_OR_NULL(clk->cif_clk_pll)) {
265             clk_set_parent(clk->cif_clk_out, clk->cif_clk_pll);
266         } else {
267             camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
268         }
269
270         clk_disable_unprepare( clk->cif_clk_out);
271
272         clk->out_on = 0;
273
274         camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
275     }
276     mutex_unlock(&clk->lock);    
277
278     return 0;
279 }
280 static irqreturn_t camsys_mrv_irq(int irq, void *data)
281 {
282     camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
283     camsys_irqstas_t *irqsta;
284     camsys_irqpool_t *irqpool;
285     unsigned int isp_mis,mipi_mis,mi_mis,*mis;
286
287     isp_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_MIS));
288     mipi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_MIS));
289     mi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_MIS));    
290
291     __raw_writel(isp_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_ICR)); 
292     __raw_writel(mipi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_ICR)); 
293     __raw_writel(mi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_ICR)); 
294
295     spin_lock(&camsys_dev->irq.lock);
296     if (!list_empty(&camsys_dev->irq.irq_pool)) {
297         list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
298             if (irqpool->pid != 0) {
299                 switch(irqpool->mis)
300                 {
301                     case MRV_ISP_MIS:
302                     {
303                         mis = &isp_mis;
304                         break;
305                     }
306
307                     case MRV_MIPI_MIS:
308                     {
309                         mis = &mipi_mis;
310                         break;
311                     }
312                     case MRV_MI_MIS:
313                     {
314                         mis = &mi_mis;
315                         break;
316                     }
317
318                     default:     
319                     {
320                         camsys_trace(2,"Thread(pid:%d) irqpool mis(%d) is invalidate",irqpool->pid,irqpool->mis);
321                         goto end;
322                     }
323                 }
324
325                 if (*mis != 0) {
326                     spin_lock(&irqpool->lock);
327                     if (!list_empty(&irqpool->deactive)) {
328                         irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
329                         irqsta->sta.mis = *mis;                                                 
330                         list_del_init(&irqsta->list);            
331                         list_add_tail(&irqsta->list,&irqpool->active);                        
332                         wake_up(&irqpool->done);
333                     }
334                     spin_unlock(&irqpool->lock);
335                 }
336             }
337         }
338     }
339 end:    
340     spin_unlock(&camsys_dev->irq.lock);
341
342     return IRQ_HANDLED;
343 }
344 static int camsys_mrv_remove_cb(struct platform_device *pdev)
345 {
346     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
347     camsys_mrv_clk_t *mrv_clk=NULL;
348
349     if (camsys_dev->clk != NULL) {
350
351         mrv_clk = (camsys_mrv_clk_t*)camsys_dev->clk;
352         if (mrv_clk->out_on)
353             camsys_mrv_clkout_cb(mrv_clk,0,0);
354         if (mrv_clk->in_on)
355             camsys_mrv_clkin_cb(mrv_clk,0);
356     
357         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
358                         devm_clk_put(&pdev->dev,mrv_clk->pd_isp);
359         }
360         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
361             devm_clk_put(&pdev->dev,mrv_clk->aclk_isp);
362         }
363         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
364             devm_clk_put(&pdev->dev,mrv_clk->hclk_isp);
365         }
366         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
367             devm_clk_put(&pdev->dev,mrv_clk->isp);
368         }
369         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
370             devm_clk_put(&pdev->dev,mrv_clk->isp_jpe);
371         }
372         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
373             devm_clk_put(&pdev->dev,mrv_clk->pclkin_isp);
374         }
375         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
376             devm_clk_put(&pdev->dev,mrv_clk->cif_clk_out);
377         }
378
379         kfree(mrv_clk);
380         mrv_clk = NULL;
381     }
382
383     return 0;
384 }
385 int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
386 {
387     int err = 0;   
388     camsys_mrv_clk_t *mrv_clk=NULL;
389     
390         err = request_irq(camsys_dev->irq.irq_id, camsys_mrv_irq, 0, CAMSYS_MARVIN_IRQNAME,camsys_dev);
391     if (err) {
392         camsys_err("request irq for %s failed",CAMSYS_MARVIN_IRQNAME);
393         goto end;
394     }
395
396     //Clk and Iomux init
397     mrv_clk = kzalloc(sizeof(camsys_mrv_clk_t),GFP_KERNEL);
398     if (mrv_clk == NULL) {
399         camsys_err("Allocate camsys_mrv_clk_t failed!");
400         err = -EINVAL;
401         goto clk_failed;
402     }
403      
404     mrv_clk->pd_isp = devm_clk_get(&pdev->dev, "pd_isp");
405     mrv_clk->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
406     mrv_clk->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
407     mrv_clk->isp = devm_clk_get(&pdev->dev, "clk_isp");
408     mrv_clk->isp_jpe = devm_clk_get(&pdev->dev, "clk_isp_jpe");
409     mrv_clk->pclkin_isp = devm_clk_get(&pdev->dev, "pclkin_isp");
410     mrv_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_cif_out");
411     mrv_clk->cif_clk_pll = devm_clk_get(&pdev->dev, "clk_cif_pll");
412     mrv_clk->clk_mipi_24m = devm_clk_get(&pdev->dev,"clk_mipi_24m"); 
413     
414         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) ||
415         IS_ERR_OR_NULL(mrv_clk->isp) || IS_ERR_OR_NULL(mrv_clk->isp_jpe) || IS_ERR_OR_NULL(mrv_clk->pclkin_isp) || 
416         IS_ERR_OR_NULL(mrv_clk->cif_clk_out) || IS_ERR_OR_NULL(mrv_clk->clk_mipi_24m)) {
417         camsys_err("Get %s clock resouce failed!\n",miscdev_name);
418         err = -EINVAL;
419         goto clk_failed;
420     }
421     
422     clk_set_rate(mrv_clk->isp,210000000);
423     clk_set_rate(mrv_clk->isp_jpe, 210000000);
424     
425     mutex_init(&mrv_clk->lock);
426     
427     mrv_clk->in_on = false;
428     mrv_clk->out_on = 0;
429         
430     camsys_dev->clk = (void*)mrv_clk;
431     camsys_dev->clkin_cb = camsys_mrv_clkin_cb;
432     camsys_dev->clkout_cb = camsys_mrv_clkout_cb;
433     camsys_dev->reset_cb = camsys_mrv_reset_cb;
434     camsys_dev->iomux = camsys_mrv_iomux_cb;
435     camsys_dev->flash_trigger_cb = camsys_mrv_flash_trigger_cb;
436     
437     camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
438     camsys_dev->miscdev.name = miscdev_name;
439     camsys_dev->miscdev.nodename = miscdev_name;
440     camsys_dev->miscdev.fops = &camsys_fops;
441
442     err = misc_register(&camsys_dev->miscdev);
443     if (err < 0) {
444         camsys_err("misc register %s failed!",miscdev_name);
445         goto misc_register_failed;
446     }   
447
448     //Variable init
449     camsys_dev->dev_id = CAMSYS_DEVID_MARVIN;
450     camsys_dev->platform_remove = camsys_mrv_remove_cb;
451    
452          
453     return 0;
454 misc_register_failed:
455     if (!IS_ERR_OR_NULL(camsys_dev->miscdev.this_device)) {
456         misc_deregister(&camsys_dev->miscdev);
457     }
458
459 clk_failed:
460     if (mrv_clk != NULL) {
461         if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
462             clk_put(mrv_clk->pd_isp);
463         }
464         if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
465             clk_put(mrv_clk->aclk_isp);
466         }
467         if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
468             clk_put(mrv_clk->hclk_isp);
469         }
470         if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
471             clk_put(mrv_clk->isp);
472         }
473         if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
474             clk_put(mrv_clk->isp_jpe);
475         }
476         if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
477             clk_put(mrv_clk->pclkin_isp);
478         }
479         if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
480             clk_put(mrv_clk->cif_clk_out);
481         }
482
483         kfree(mrv_clk);
484         mrv_clk = NULL;
485     }
486     
487 end:
488     return err;
489 }
490 EXPORT_SYMBOL_GPL(camsys_mrv_probe_cb);
491