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