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