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