add isp driver for rk3288
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_cif.c
1 #include "camsys_cif.h"
2
3 static const char miscdev_cif0_name[] = CAMSYS_CIF0_DEVNAME;
4 static const char miscdev_cif1_name[] = CAMSYS_CIF1_DEVNAME;
5
6 static int camsys_cif_iomux_cb(camsys_extdev_t *extdev,void *ptr)
7 {
8     unsigned int cif_index;
9     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
10
11     if (strcmp(dev_name(camsys_dev->miscdev.this_device), CAMSYS_CIF1_DEVNAME)==0) {
12         cif_index = 1;
13     } else {
14         cif_index = 0;
15     }
16     
17 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
18     switch(cif_index){
19         case 0:
20         {
21                     iomux_set(CIF0_CLKOUT);
22             write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
23             write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));            
24             break;
25         }
26         default:
27             camsys_err("Cif index(%d) is invalidate!!!\n",cif_index);
28             break;
29     }
30 #elif defined(CONFIG_ARCH_RK30)
31     switch(cif_index){
32         case 0:
33         {
34             rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);            
35             break;
36         }
37         case 1:
38         {
39             rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
40             rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
41             rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
42             rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
43             rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
44             rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
45             rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
46             rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
47             
48             rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
49             rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
50             rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
51             rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
52             rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
53             rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
54             rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
55             rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
56             break;
57         }
58         default:
59             camsys_err("Cif index(%d) is invalidate!!!\n", cif_index);
60             break;
61         }
62 #elif defined(CONFIG_ARCH_RK319X)
63     switch(cif_index){
64         case 0:
65         {
66             unsigned int cif_vol_sel;
67             //set cif vol domain
68             cif_vol_sel = __raw_readl(RK30_GRF_BASE+0x018c);
69                 __raw_writel( (cif_vol_sel |0x20002),RK30_GRF_BASE+0x018c);
70             //set driver strength
71                 __raw_writel(0xffffffff, RK30_GRF_BASE+0x01dc);
72                 
73             iomux_set(CIF0_CLKOUT);
74             iomux_set(CIF0_CLKIN);
75             iomux_set(CIF0_HREF);
76             iomux_set(CIF0_VSYNC);
77             iomux_set(CIF0_D0);
78             iomux_set(CIF0_D1);
79             iomux_set(CIF0_D2);
80             iomux_set(CIF0_D3);
81             iomux_set(CIF0_D4);
82             iomux_set(CIF0_D5);
83             iomux_set(CIF0_D6);
84             iomux_set(CIF0_D7);
85             iomux_set(CIF0_D8);
86             iomux_set(CIF0_D9);
87             camsys_trace(1, "%s cif iomux success\n",dev_name(camsys_dev->miscdev.this_device));
88             break;
89         }
90         case 1:
91         default:
92             camsys_err("Cif index(%d) is invalidate!!!\n", cif_index);
93             break;
94         }
95 #endif
96                 
97     return 0;
98 }
99 static int camsys_cif_clkin_cb(void *ptr, unsigned int on)
100 {
101     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
102     camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
103     
104     spin_lock(&clk->lock);
105     if (on && !clk->in_on) {        
106         clk_enable(clk->pd_cif);
107         clk_enable(clk->aclk_cif);
108         clk_enable(clk->hclk_cif);
109         clk_enable(clk->cif_clk_in);
110         
111         clk->in_on = true;
112         camsys_trace(1, "%s clock in turn on",dev_name(camsys_dev->miscdev.this_device));
113     } else if (!on && clk->in_on) {
114         clk_disable(clk->aclk_cif);
115         clk_disable(clk->hclk_cif);
116         clk_disable(clk->cif_clk_in);           
117         clk_disable(clk->pd_cif);
118         clk->in_on = false;
119         camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
120     }
121     spin_unlock(&clk->lock);
122     return 0;
123 }
124
125 static int camsys_cif_clkout_cb(void *ptr, unsigned int on)
126 {
127     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
128     camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
129     struct clk *cif_clk_out_div;
130     
131     
132     spin_lock(&clk->lock);
133     if (on && (clk->out_on != on)) {        
134         clk_enable(clk->cif_clk_out);
135         clk_set_rate(clk->cif_clk_out,on);
136         
137         clk->out_on = on;
138         camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
139                     clk->out_on);
140     } else if (!on && clk->out_on) {
141         if (strcmp(dev_name(camsys_dev->miscdev.this_device),miscdev_cif1_name)==0) {
142             cif_clk_out_div =  clk_get(NULL, "cif1_out_div");
143         } else{
144             cif_clk_out_div =  clk_get(NULL, "cif0_out_div");
145             if(IS_ERR_OR_NULL(cif_clk_out_div)) {
146                 cif_clk_out_div =  clk_get(NULL, "cif_out_div");
147             }
148         }
149
150         if(!IS_ERR_OR_NULL(cif_clk_out_div)) {
151             clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
152             clk_put(cif_clk_out_div);
153         } else {
154             camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
155         }
156         clk_disable(clk->cif_clk_out);
157         clk->out_on = 0;
158
159         camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
160     }
161     spin_unlock(&clk->lock);
162
163     {
164   //  __raw_writel(0x00, CRU_PCLK_REG30+RK30_CRU_BASE);
165     }
166
167     return 0;
168 }
169
170 static irqreturn_t camsys_cif_irq(int irq, void *data)
171 {
172     camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
173     camsys_irqstas_t *irqsta;
174     camsys_irqpool_t *irqpool;
175     unsigned int intsta,frmsta;
176
177     intsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
178     frmsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
179    printk("get oneframe,intsta = 0x%x \n",intsta);
180  
181     if (intsta & 0x200) {
182         __raw_writel(0x200,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
183         __raw_writel(0xf000,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
184     }
185
186     if (intsta &0x01) {
187         __raw_writel(0x01,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
188         __raw_writel(0x02,camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
189         __raw_writel(0xf001,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
190     }    
191     
192     spin_lock(&camsys_dev->irq.lock);
193     list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
194         spin_lock(&irqpool->lock);
195         if (!list_empty(&irqpool->deactive)) {
196             irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
197             irqsta->sta.mis = intsta;
198             irqsta->sta.ris = intsta;
199             list_del_init(&irqsta->list);            
200             list_add_tail(&irqsta->list,&irqpool->active);
201             irqsta = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
202             //wake_up_all(&camsys_dev->irq.irq_done);
203             wake_up(&irqpool->done);
204         }
205         spin_unlock(&irqpool->lock);
206     }
207     spin_unlock(&camsys_dev->irq.lock);
208    
209     return IRQ_HANDLED;
210 }
211
212 static int camsys_cif_remove(struct platform_device *pdev)
213 {
214     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
215     camsys_cif_clk_t *cif_clk;
216     
217     if (camsys_dev->clk != NULL) {
218         cif_clk = (camsys_cif_clk_t*)camsys_dev->clk;
219         if (cif_clk->out_on) 
220             camsys_cif_clkout_cb(camsys_dev->clk, 0);
221         if (cif_clk->in_on)
222             camsys_cif_clkin_cb(camsys_dev->clk, 0);
223
224         if (cif_clk->pd_cif)
225             clk_put(cif_clk->pd_cif);
226         if (cif_clk->aclk_cif)
227             clk_put(cif_clk->aclk_cif);
228         if (cif_clk->hclk_cif)
229             clk_put(cif_clk->hclk_cif);
230         if (cif_clk->cif_clk_in)
231             clk_put(cif_clk->cif_clk_in);
232         if (cif_clk->cif_clk_out)
233             clk_put(cif_clk->cif_clk_out);
234     
235         kfree(cif_clk);
236         cif_clk = NULL;
237     }
238
239     return 0;
240 }
241
242 int camsys_cif_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
243 {
244     int err = 0;   
245     camsys_cif_clk_t *cif_clk;
246
247     //Irq init
248     err = request_irq(camsys_dev->irq.irq_id, camsys_cif_irq, 0, CAMSYS_CIF_IRQNAME,camsys_dev);
249     if (err) {
250         camsys_err("request irq for %s failed",CAMSYS_CIF_IRQNAME);
251         goto end;
252     }
253
254     //Clk and Iomux init
255     cif_clk = kzalloc(sizeof(camsys_cif_clk_t),GFP_KERNEL);
256     if (cif_clk == NULL) {
257         camsys_err("Allocate camsys_cif_clk_t failed!");
258         err = -EINVAL;
259         goto end;
260     }
261     
262     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
263         cif_clk->pd_cif = clk_get(NULL, "pd_cif1");
264         cif_clk->aclk_cif = clk_get(NULL, "aclk_cif1");
265         cif_clk->hclk_cif = clk_get(NULL, "hclk_cif1");
266         cif_clk->cif_clk_in = clk_get(NULL, "cif1_in");
267         cif_clk->cif_clk_out = clk_get(NULL, "cif1_out");
268         spin_lock_init(&cif_clk->lock);
269         cif_clk->in_on = false;
270         cif_clk->out_on = false;
271     } else {           
272         cif_clk->pd_cif = clk_get(NULL, "pd_cif0");
273         cif_clk->aclk_cif = clk_get(NULL, "aclk_cif0");
274         cif_clk->hclk_cif = clk_get(NULL, "hclk_cif0");
275         cif_clk->cif_clk_in = clk_get(NULL, "pclkin_cif0");
276         cif_clk->cif_clk_out = clk_get(NULL, "cif0_out");
277         spin_lock_init(&cif_clk->lock);
278         cif_clk->in_on = false;
279         cif_clk->out_on = false;
280     }
281     camsys_dev->clk = (void*)cif_clk;
282     camsys_dev->clkin_cb = camsys_cif_clkin_cb;
283     camsys_dev->clkout_cb = camsys_cif_clkout_cb;
284     camsys_dev->iomux = camsys_cif_iomux_cb;
285     
286     //Misc device init
287     camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
288     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
289         camsys_dev->miscdev.name = miscdev_cif1_name;
290         camsys_dev->miscdev.nodename = miscdev_cif1_name;        
291     } else {
292         camsys_dev->miscdev.name = miscdev_cif0_name;
293         camsys_dev->miscdev.nodename = miscdev_cif0_name;
294     }
295     camsys_dev->miscdev.fops = &camsys_fops;
296     err = misc_register(&camsys_dev->miscdev);
297     if (err < 0) {
298         camsys_trace(1,"Register /dev/%s misc device failed",camsys_dev->miscdev.name);
299         goto misc_register_failed;
300     } else {
301         camsys_trace(1,"Register /dev/%s misc device success",camsys_dev->miscdev.name);
302     }
303
304     //Variable init
305     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
306         camsys_dev->dev_id = CAMSYS_DEVID_CIF_1;
307     } else {
308         camsys_dev->dev_id = CAMSYS_DEVID_CIF_0;
309     }
310     camsys_dev->platform_remove = camsys_cif_remove;
311
312     return 0;
313
314 misc_register_failed:
315     if (!IS_ERR(camsys_dev->miscdev.this_device)) {
316         misc_deregister(&camsys_dev->miscdev);
317     }
318
319     if (cif_clk) {
320
321         if (cif_clk->pd_cif)
322             clk_put(cif_clk->pd_cif);
323         if (cif_clk->aclk_cif)
324             clk_put(cif_clk->aclk_cif);
325         if (cif_clk->hclk_cif)
326             clk_put(cif_clk->hclk_cif);
327         if (cif_clk->cif_clk_in)
328             clk_put(cif_clk->cif_clk_in);
329         if (cif_clk->cif_clk_out)
330             clk_put(cif_clk->cif_clk_out);
331     
332         kfree(cif_clk);
333         cif_clk = NULL;
334     }
335     
336 end:
337     return err;
338 }
339 EXPORT_SYMBOL_GPL(camsys_cif_probe_cb);
340