camsys driver: v0.0x21.2: compatible with kernel4.4
[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_vol_sel;
9 #if 0
10     if (extdev->dev_cfg & CAMSYS_DEVCFG_FLASHLIGHT) {
11                 iomux_set(ISP_FLASH_TRIG);
12                 if (extdev->fl.fl.io != 0xffffffff) {
13                         iomux_set(ISP_FL_TRIG);
14                 }
15         }
16
17     if (extdev->dev_cfg & CAMSYS_DEVCFG_PREFLASHLIGHT) {
18                 iomux_set(ISP_PRELIGHT_TRIG);
19     }
20
21     if (extdev->dev_cfg & CAMSYS_DEVCFG_SHUTTER) {
22                 iomux_set(ISP_SHUTTER_OPEN);
23                 iomux_set(ISP_SHUTTER_TRIG);
24     }
25
26     iomux_set(CIF0_CLKOUT);
27 #endif
28
29     struct pinctrl      *pinctrl;
30     struct pinctrl_state    *state;
31     int retval = 0;
32     char state_str[20] = {0};
33
34     struct device *dev = &(extdev->pdev->dev);
35
36     if (extdev->phy.type == CamSys_Phy_Cif) {
37                 if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_8b) &&
38                         (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
39
40                         strcpy(state_str, "isp_dvp8bit");
41
42                 }
43
44                 if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b) &&
45                         (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
46                         strcpy(state_str, "isp_dvp10bit");
47                 }
48
49                 if (extdev->phy.info.cif.fmt == CamSys_Fmt_Raw_12b) {
50                         strcpy(state_str, "isp_dvp12bit");
51
52                 }
53         } else {
54                 strcpy(state_str, "default");
55     }
56
57     /*mux CIF0_CLKOUT*/
58
59     pinctrl = devm_pinctrl_get(dev);
60     if (IS_ERR(pinctrl)) {
61                 camsys_err("%s:Get pinctrl failed!\n", __func__);
62                 return -1;
63     }
64     state = pinctrl_lookup_state(pinctrl,
65                                                                 state_str);
66         if (IS_ERR(state)) {
67                 dev_err(dev,
68                         "%s:could not get %s pinstate\n",
69                         __func__, state_str);
70                 return -1;
71         }
72
73     if (!IS_ERR(state)) {
74                 retval = pinctrl_select_state(pinctrl, state);
75                 if (retval) {
76                         dev_err(dev,
77                                 "%s:could not set %s pins\n",
78                                 __func__, state_str);
79                                 return -1;
80
81                         }
82     }
83
84     /*set 1.8v vol domain for rk32*/
85         __raw_writel(((1<<1)|(1<<(1+16))), RK_GRF_VIRT+0x0380);
86         __raw_writel(0xffffffff,  RK_GRF_VIRT+0x01d4);
87
88     /*set cif vol domain*/
89     if (extdev->phy.type == CamSys_Phy_Cif) {
90
91                 #if 0
92                 if (!IS_ERR_OR_NULL(extdev->dovdd.ldo)) {
93                         if (extdev->dovdd.max_uv >= 25000000) {
94                                 __raw_writel(((1<<1)|(1<<(1+16))),
95                                         RK30_GRF_BASE+0x018c);
96                         } else {
97                                 __raw_writel((1<<(1+16)), RK30_GRF_BASE+0x018c);
98                         }
99                 } else {
100                          __raw_writel(((1<<1)|(1<<(1+16))),
101                                         RK30_GRF_BASE+0x018c);
102                 }
103                 #else
104
105                 /*set 1.8v vol domain*/
106                 __raw_writel(((1<<1)|(1<<(1+16))), RK_GRF_VIRT+0x0380);
107                 #endif
108
109                 /*set driver strength*/
110                 /*  __raw_writel(0xffffffff,  RK_GRF_VIRT+0x01dc);*/
111         }
112
113     return 0;
114 }
115 static int camsys_cif_clkin_cb(void *ptr,  unsigned int on)
116 {
117         camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
118         camsys_cif_clk_t *clk = (camsys_cif_clk_t *)camsys_dev->clk;
119
120     spin_lock(&clk->lock);
121         if (on && !clk->in_on) {
122                 clk_prepare_enable(clk->aclk_cif);
123                 clk_prepare_enable(clk->hclk_cif);
124                 clk_prepare_enable(clk->cif_clk_in);
125
126                 clk->in_on = true;
127                 camsys_trace(1,  "%s clock in turn on",
128                         dev_name(camsys_dev->miscdev.this_device));
129     } else if (!on && clk->in_on) {
130                 clk_disable_unprepare(clk->hclk_cif);
131                 clk_disable_unprepare(clk->cif_clk_in);
132                 clk_disable_unprepare(clk->pd_cif);
133                 clk->in_on = false;
134                 camsys_trace(1,  "%s clock in turn off",
135                         dev_name(camsys_dev->miscdev.this_device));
136         }
137         spin_unlock(&clk->lock);
138         return 0;
139 }
140
141 static int camsys_cif_clkout_cb(void *ptr, unsigned int on, unsigned int clkin)
142 {
143         camsys_dev_t *camsys_dev = (camsys_dev_t *)ptr;
144         camsys_cif_clk_t *clk = (camsys_cif_clk_t *)camsys_dev->clk;
145     struct clk *cif_clk_out_div;
146
147         spin_lock(&clk->lock);
148         if (on && (clk->out_on != on)) {
149                 clk_prepare_enable(clk->cif_clk_out);
150                 clk_set_rate(clk->cif_clk_out, clkin);
151
152                 clk->out_on = on;
153                 camsys_trace(1,  "%s clock out(rate: %dHz) turn on",
154                         dev_name(camsys_dev->miscdev.this_device),
155                                         clk->out_on);
156         } else if (!on && clk->out_on) {
157                 if (strcmp(dev_name(camsys_dev->miscdev.this_device),
158                         miscdev_cif1_name) == 0) {
159                         cif_clk_out_div =  clk_get(NULL,  "cif1_out_div");
160                 } else{
161                         cif_clk_out_div =  clk_get(NULL,  "cif0_out_div");
162                         if (IS_ERR_OR_NULL(cif_clk_out_div)) {
163                                 cif_clk_out_div =
164                                         clk_get(NULL,  "cif_out_div");
165                         }
166                 }
167
168                 if (!IS_ERR_OR_NULL(cif_clk_out_div)) {
169                         clk_set_parent(clk->cif_clk_out,  cif_clk_out_div);
170                         clk_put(cif_clk_out_div);
171                 } else {
172                         camsys_warn("%s clock out may be not off!",
173                                 dev_name(camsys_dev->miscdev.this_device));
174                 }
175                 clk_disable_unprepare(clk->cif_clk_out);
176                 clk->out_on = 0;
177
178                 camsys_trace(1,  "%s clock out turn off",
179                         dev_name(camsys_dev->miscdev.this_device));
180         }
181         spin_unlock(&clk->lock);
182
183         /*  __raw_writel(0x00,  CRU_PCLK_REG30+RK30_CRU_BASE);*/
184
185         return 0;
186 }
187
188 static irqreturn_t camsys_cif_irq(int irq,  void *data)
189 {
190     camsys_dev_t *camsys_dev = (camsys_dev_t *)data;
191     camsys_irqstas_t *irqsta;
192     camsys_irqpool_t *irqpool;
193     unsigned int intsta, frmsta;
194
195     intsta = __raw_readl(camsys_dev->devmems.registermem->vir_base +
196                 CIF_INITSTA);
197     frmsta = __raw_readl(camsys_dev->devmems.registermem->vir_base +
198                 CIF_FRAME_STATUS);
199    printk("get oneframe, intsta = 0x%x \n", intsta);
200
201     if (intsta & 0x200) {
202                 __raw_writel(0x200,
203                         camsys_dev->devmems.registermem->vir_base +
204                         CIF_INITSTA);
205                 __raw_writel(0xf000,
206                         camsys_dev->devmems.registermem->vir_base +
207                         CIF_CTRL);
208         }
209
210         if (intsta &0x01) {
211                 __raw_writel(0x01,
212                         camsys_dev->devmems.registermem->vir_base +
213                         CIF_INITSTA);
214                 __raw_writel(0x02,
215                         camsys_dev->devmems.registermem->vir_base +
216                         CIF_FRAME_STATUS);
217                 __raw_writel(0xf001,
218                         camsys_dev->devmems.registermem->vir_base +
219                         CIF_CTRL);
220         }
221
222         spin_lock(&camsys_dev->irq.lock);
223         list_for_each_entry(irqpool,  &camsys_dev->irq.irq_pool,  list) {
224                 spin_lock(&irqpool->lock);
225                 if (!list_empty(&irqpool->deactive)) {
226                         irqsta = list_first_entry
227                                 (&irqpool->deactive,  camsys_irqstas_t,  list);
228                         irqsta->sta.mis = intsta;
229                         irqsta->sta.ris = intsta;
230                         list_del_init(&irqsta->list);
231                         list_add_tail(&irqsta->list, &irqpool->active);
232                         irqsta = list_first_entry
233                                 (&irqpool->active,  camsys_irqstas_t,  list);
234                         /*wake_up_all(&camsys_dev->irq.irq_done);*/
235                         wake_up(&irqpool->done);
236                 }
237                 spin_unlock(&irqpool->lock);
238         }
239         spin_unlock(&camsys_dev->irq.lock);
240
241         return IRQ_HANDLED;
242 }
243
244 static int camsys_cif_remove(struct platform_device *pdev)
245 {
246         camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
247         camsys_cif_clk_t *cif_clk;
248
249         if (camsys_dev->clk != NULL) {
250                 cif_clk = (camsys_cif_clk_t *)camsys_dev->clk;
251                 if (cif_clk->out_on)
252                         camsys_cif_clkout_cb(camsys_dev->clk, 0, 0);
253                 if (cif_clk->in_on)
254                         camsys_cif_clkin_cb(camsys_dev->clk, 0);
255
256                 if (cif_clk->pd_cif)
257                         clk_put(cif_clk->pd_cif);
258                 if (cif_clk->aclk_cif)
259                         clk_put(cif_clk->aclk_cif);
260                 if (cif_clk->hclk_cif)
261                         clk_put(cif_clk->hclk_cif);
262                 if (cif_clk->cif_clk_in)
263                         clk_put(cif_clk->cif_clk_in);
264                 if (cif_clk->cif_clk_out)
265                         clk_put(cif_clk->cif_clk_out);
266
267                 kfree(cif_clk);
268                 cif_clk = NULL;
269         }
270
271         return 0;
272 }
273
274 int camsys_cif_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
275 {
276         int err = 0;
277         camsys_cif_clk_t *cif_clk;
278
279     /*Irq init*/
280         err = request_irq(camsys_dev->irq.irq_id,
281                 camsys_cif_irq,  0,  CAMSYS_CIF_IRQNAME,
282                 camsys_dev);
283         if (err) {
284                 camsys_err("request irq for %s failed", CAMSYS_CIF_IRQNAME);
285                 goto end;
286         }
287
288     /*Clk and Iomux init*/
289         cif_clk = kzalloc(sizeof(camsys_cif_clk_t), GFP_KERNEL);
290         if (cif_clk == NULL) {
291                 camsys_err("Allocate camsys_cif_clk_t failed!");
292                 err = -EINVAL;
293                 goto end;
294         }
295
296         if (strcmp(dev_name(&pdev->dev), CAMSYS_PLATFORM_CIF1_NAME) == 0) {
297                 cif_clk->aclk_cif = devm_clk_get(&pdev->dev,  "g_aclk_vip");
298                 cif_clk->hclk_cif = devm_clk_get(&pdev->dev,  "g_hclk_vip");
299                 cif_clk->cif_clk_in = devm_clk_get(&pdev->dev,  "g_pclkin_cif");
300                 cif_clk->cif_clk_out = devm_clk_get(&pdev->dev,  "clk_cif_out");
301                 spin_lock_init(&cif_clk->lock);
302                 cif_clk->in_on = false;
303                 cif_clk->out_on = false;
304         } else {
305                 cif_clk->aclk_cif = devm_clk_get(&pdev->dev,  "g_aclk_vip");
306                 cif_clk->hclk_cif = devm_clk_get(&pdev->dev,  "g_hclk_vip");
307                 cif_clk->cif_clk_in = devm_clk_get(&pdev->dev,  "g_pclkin_ci");
308                 cif_clk->cif_clk_out = devm_clk_get(&pdev->dev,  "clk_cif_out");
309                 spin_lock_init(&cif_clk->lock);
310                 cif_clk->in_on = false;
311                 cif_clk->out_on = false;
312         }
313
314         /*
315         *clk_prepare_enable(cif_clk->aclk_cif);
316         clk_prepare_enable(cif_clk->hclk_cif);
317         clk_prepare_enable(cif_clk->cif_clk_in);
318         clk_prepare_enable(cif_clk->cif_clk_out);
319         */
320
321         camsys_dev->clk = (void *)cif_clk;
322         camsys_dev->clkin_cb = camsys_cif_clkin_cb;
323         camsys_dev->clkout_cb = camsys_cif_clkout_cb;
324         camsys_dev->iomux = camsys_cif_iomux_cb;
325
326     /*Misc device init*/
327         camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
328         if (strcmp(dev_name(&pdev->dev), CAMSYS_PLATFORM_CIF1_NAME) == 0) {
329             camsys_dev->miscdev.name = miscdev_cif1_name;
330             camsys_dev->miscdev.nodename = miscdev_cif1_name;
331         } else {
332             camsys_dev->miscdev.name = miscdev_cif0_name;
333             camsys_dev->miscdev.nodename = miscdev_cif0_name;
334         }
335         camsys_dev->miscdev.fops = &camsys_fops;
336         err = misc_register(&camsys_dev->miscdev);
337         if (err < 0) {
338             camsys_trace(1,
339                         "Register /dev/%s misc device failed",
340                         camsys_dev->miscdev.name);
341             goto misc_register_failed;
342         } else {
343             camsys_trace(1,
344                         "Register /dev/%s misc device success",
345                         camsys_dev->miscdev.name);
346         }
347
348         /*Variable init*/
349         if (strcmp(dev_name(&pdev->dev), CAMSYS_PLATFORM_CIF1_NAME) == 0) {
350                 camsys_dev->dev_id = CAMSYS_DEVID_CIF_1;
351         } else {
352             camsys_dev->dev_id = CAMSYS_DEVID_CIF_0;
353         }
354         camsys_dev->platform_remove = camsys_cif_remove;
355
356         return 0;
357
358 misc_register_failed:
359         if (!IS_ERR(camsys_dev->miscdev.this_device)) {
360                 misc_deregister(&camsys_dev->miscdev);
361         }
362
363         if (cif_clk) {
364
365                 if (cif_clk->pd_cif)
366                         clk_put(cif_clk->pd_cif);
367                 if (cif_clk->aclk_cif)
368                         clk_put(cif_clk->aclk_cif);
369                 if (cif_clk->hclk_cif)
370                         clk_put(cif_clk->hclk_cif);
371                 if (cif_clk->cif_clk_in)
372                         clk_put(cif_clk->cif_clk_in);
373                 if (cif_clk->cif_clk_out)
374                         clk_put(cif_clk->cif_clk_out);
375
376                 kfree(cif_clk);
377                 cif_clk = NULL;
378         }
379
380 end:
381         return err;
382 }
383 EXPORT_SYMBOL_GPL(camsys_cif_probe_cb);
384