isp10: rockchip: v0.1.6
[firefly-linux-kernel-4.4.55.git] / drivers / media / platform / rk-isp10 / cif_isp10_pltfrm.c
1 /*
2  *************************************************************************
3  * Rockchip driver for CIF ISP 1.0
4  * (Based on Intel driver for sofiaxxx)
5  *
6  * Copyright (C) 2015 Intel Mobile Communications GmbH
7  * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
8  *
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *************************************************************************
15  */
16
17 #ifndef CONFIG_OF
18 #error "this driver requires a kernel with device tree support"
19 #endif
20
21 #include <linux/of.h>
22 #include <linux/platform_device.h>
23 #include <linux/interrupt.h>
24 #include <linux/kernel.h>
25 #include <linux/i2c.h>
26 #include <linux/io.h>
27 #include <linux/jiffies.h>
28 #include <linux/list.h>
29 #include "cif_isp10.h"
30 #include <linux/platform_data/rk_isp10_platform.h>
31 #include "cif_isp10_regs.h"
32 #ifndef CONFIG_DEBUG_FS
33 #include <linux/debugfs.h>
34 #include <linux/fs.h>
35 #include <media/v4l2-controls_rockchip.h>
36 #ifdef CONFIG_CIF_ISP10_REG_TRACE
37 #include <stdarg.h>
38
39 static struct {
40         char *reg_trace;
41         loff_t reg_trace_read_pos;
42         loff_t reg_trace_write_pos;
43         size_t reg_trace_max_size;
44         void __iomem *base_addr;
45         bool rtrace;
46         bool ftrace;
47         bool internal;
48         spinlock_t lock;/* spin lock */
49 } cif_isp10_reg_trace;
50 #endif
51 #endif
52
53 struct cif_isp10_pltfrm_csi_config {
54         struct list_head list;
55         u32 pps;
56         struct cif_isp10_csi_config csi_config;
57 };
58
59 struct cif_isp10_pltfrm_data {
60         struct pinctrl *pinctrl;
61         struct pinctrl_state *pins_default;
62         struct pinctrl_state *pins_sleep;
63         struct pinctrl_state *pins_inactive;
64         void __iomem *base_addr;
65         int irq;
66         struct {
67                 int mis;
68                 int (*isr)(unsigned int mis, void *cntxt);
69         } irq_handlers[4];
70         struct list_head csi0_configs;
71         struct list_head csi1_configs;
72         s32 exp_time;
73         u16 gain;
74
75 #ifndef CONFIG_DEBUG_FS
76         struct {
77                 struct dentry *dir;
78                 struct dentry *cif_isp10_file;
79                 struct dentry *csi0_file;
80                 struct dentry *csi1_file;
81 #ifdef CONFIG_CIF_ISP10_REG_TRACE
82                 struct dentry *reg_trace_file;
83 #endif
84                 void (*print_func)(void *cntxt, const char *block_name);
85                 void *print_cntxt;
86         } dbgfs;
87 #endif
88 };
89
90 void cif_isp10_pltfrm_debug_register_print_cb(
91         struct device *dev,
92         void (*print)(void *cntxt, const char *block),
93         void *cntxt) {
94 #ifndef CONFIG_DEBUG_FS
95         struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
96
97         pdata->dbgfs.print_cntxt = cntxt;
98         pdata->dbgfs.print_func = print;
99 #endif
100 }
101
102 #ifndef CONFIG_DEBUG_FS
103 #define CIF_ISP10_DBGFS_BUF_SIZE 1024
104 static char cif_isp10_dbgfs_buf[CIF_ISP10_DBGFS_BUF_SIZE];
105
106 static int cif_isp10_dbgfs_fill_csi_config_from_string(
107         struct device *dev,
108         struct cif_isp10_csi_config *csi_config,
109         char *strp)
110 {
111         char *token;
112
113         token = strsep(&strp, " ");
114         if (IS_ERR_OR_NULL(token))
115                 goto missing_token;
116         if (IS_ERR_VALUE(kstrtou32(token, 10,
117                         &csi_config->vc)))
118                 goto wrong_token_format;
119         token = strsep(&strp, " ");
120         if (IS_ERR_OR_NULL(token))
121                 goto missing_token;
122         if (IS_ERR_VALUE(kstrtou32(token, 10,
123                         &csi_config->nb_lanes)))
124                 goto wrong_token_format;
125         token = strsep(&strp, " ");
126         if (IS_ERR_OR_NULL(token))
127                 goto missing_token;
128         if (IS_ERR_VALUE(kstrtou32(token, 16,
129                         &csi_config->dphy1)))
130                 goto wrong_token_format;
131         token = strsep(&strp, " ");
132         if (IS_ERR_OR_NULL(token))
133                 goto missing_token;
134         if (IS_ERR_VALUE(kstrtou32(token, 16,
135                         &csi_config->dphy2)))
136                 goto wrong_token_format;
137         token = strsep(&strp, " ");
138         if (!IS_ERR_OR_NULL(token)) {
139                 if (IS_ERR_VALUE(kstrtou32(token, 10,
140                                 &csi_config->ana_bandgab_bias)))
141                         goto wrong_token_format;
142         } else {
143                 csi_config->ana_bandgab_bias = (u32)-1;
144         }
145
146         return 0;
147 missing_token:
148         cif_isp10_pltfrm_pr_err(dev,
149                 "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
150         return -EINVAL;
151 wrong_token_format:
152         cif_isp10_pltfrm_pr_err(dev,
153                 "wrong token format, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
154         return -EINVAL;
155 }
156
157 static int cif_isp10_dbgfs_csi_configs_init(
158         struct device *dev,
159         enum cif_isp10_inp inp,
160         struct list_head *csi_configs)
161 {
162         int ret = 0;
163         struct device *img_src_dev = NULL;
164         struct device_node *parent_node = NULL;
165         struct device_node *child_node = NULL, *prev_node = NULL;
166         struct cif_isp10_pltfrm_csi_config *cfg = NULL;
167         u32 pps;
168
169         img_src_dev = cif_isp10_pltfrm_get_img_src_device(dev, inp);
170         if (IS_ERR_OR_NULL(img_src_dev)) {
171                 ret = -EFAULT;
172                 goto err;
173         }
174         parent_node = of_node_get(img_src_dev->of_node);
175         put_device(img_src_dev);
176         img_src_dev = NULL;
177
178         while (!IS_ERR_OR_NULL(child_node =
179                 of_get_next_child(parent_node, prev_node))) {
180                 if (!strncasecmp(child_node->name,
181                         "intel,camera-module-csi-config",
182                         strlen("intel,camera-module-csi-config"))) {
183                         ret = of_property_read_u32(child_node,
184                                 "intel,csi-pixels-per-second", &pps);
185                         if (IS_ERR_VALUE(ret)) {
186                                 cif_isp10_pltfrm_pr_err(dev,
187                                         "reading property 'intel,csi-pixels-per-second'\n");
188                                 goto err;
189                         }
190                         cfg = kmalloc(
191                                 sizeof(struct cif_isp10_pltfrm_csi_config),
192                         GFP_KERNEL);
193                         if (!cfg) {
194                                 cif_isp10_pltfrm_pr_err(dev,
195                                         "memory allocation failed\n");
196                                 ret = -ENOMEM;
197                                 goto err;
198                         }
199                         cfg->pps = pps;
200                         ret = cif_isp10_pltfrm_fill_csi_config_from_node(
201                                         dev, &cfg->csi_config, child_node);
202                         if (IS_ERR_VALUE(ret))
203                                 goto err;
204                         list_add_tail(&cfg->list, csi_configs);
205                         cfg = NULL;
206                 }
207                 of_node_put(prev_node);
208                 prev_node = child_node;
209         }
210         of_node_put(prev_node);
211         of_node_put(parent_node);
212
213         return 0;
214 err:
215         of_node_put(prev_node);
216         of_node_put(child_node);
217         of_node_put(parent_node);
218         kfree(cfg);
219         if (!IS_ERR_OR_NULL(img_src_dev))
220                 put_device(img_src_dev);
221         return ret;
222 }
223
224 static ssize_t cif_isp10_dbgfs_csi_read(
225         struct file *f,
226         char __user *out,
227         size_t count,
228         loff_t *pos)
229 {
230         u32 out_size = 0;
231         u32 str_len;
232         struct cif_isp10_pltfrm_csi_config *cfg;
233         u32 index = 0;
234         struct list_head *list_pos;
235         struct device *dev = f->f_inode->i_private;
236         struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
237         struct list_head *csi_configs;
238         enum cif_isp10_inp inp;
239
240         if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
241                 csi_configs = &pdata->csi0_configs;
242                 inp = CIF_ISP10_INP_CSI_0;
243         } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
244                 csi_configs = &pdata->csi1_configs;
245                 inp = CIF_ISP10_INP_CSI_1;
246         } else {
247                 cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
248                 return -EINVAL;
249         }
250
251         if (list_empty(csi_configs))
252                 if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
253                 dev, inp, csi_configs)))
254                         return -EFAULT;
255
256         if (*pos)
257                 return 0;
258
259         list_for_each(list_pos, csi_configs) {
260                 cfg = list_entry(list_pos,
261                         struct cif_isp10_pltfrm_csi_config, list);
262                 sprintf(cif_isp10_dbgfs_buf,
263                         "csi-config-%d:\n"
264                         "   pps = %d\n"
265                         "   vc = %d\n"
266                         "   nb_lanes = %d\n"
267                         "   dphy1 = 0x%08x\n"
268                         "   dphy2 = 0x%08x\n"
269                         "   ana_bandgap_bias = %d\n",
270                         index,
271                         cfg->pps, cfg->csi_config.vc, cfg->csi_config.nb_lanes,
272                         cfg->csi_config.dphy1, cfg->csi_config.dphy2,
273                         cfg->csi_config.ana_bandgab_bias);
274                 index++;
275                 str_len = strnlen(cif_isp10_dbgfs_buf,
276                         CIF_ISP10_DBGFS_BUF_SIZE);
277                 if (str_len > count) {
278                         *pos += out_size;
279                         return 0;
280                 }
281                 *pos = 0;
282                 if (IS_ERR_VALUE(simple_read_from_buffer(
283                         out + out_size, str_len, pos,
284                         cif_isp10_dbgfs_buf, str_len)))
285                         break;
286                 out_size += strnlen(cif_isp10_dbgfs_buf,
287                         CIF_ISP10_DBGFS_BUF_SIZE);
288                 count -= str_len;
289         }
290
291         *pos += out_size;
292         return out_size;
293 }
294
295 static ssize_t cif_isp10_dbgfs_csi_write(
296         struct file *f,
297         const char __user *in,
298         size_t count,
299         loff_t *pos)
300 {
301         ssize_t ret;
302         char *strp = cif_isp10_dbgfs_buf;
303         char *token;
304         struct device *dev = f->f_inode->i_private;
305         struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
306         struct list_head *csi_configs;
307         enum cif_isp10_inp inp;
308
309         if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
310                 cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
311                 return -EINVAL;
312         }
313
314         if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
315                 csi_configs = &pdata->csi0_configs;
316                 inp = CIF_ISP10_INP_CSI_0;
317         } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
318                 csi_configs = &pdata->csi1_configs;
319                 inp = CIF_ISP10_INP_CSI_1;
320         } else {
321                 cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
322                 return -EINVAL;
323         }
324
325         if (list_empty(csi_configs))
326                 if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
327                 dev, inp, csi_configs)))
328                         return -EFAULT;
329
330         memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
331         ret = simple_write_to_buffer(strp,
332                 CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
333         if (IS_ERR_VALUE(ret))
334                 return ret;
335
336         token = strsep(&strp, " ");
337         if (!strcmp(token, "push")) {
338                 struct cif_isp10_pltfrm_csi_config cfg;
339
340                 token = strsep(&strp, " ");
341                 if (IS_ERR_OR_NULL(token)) {
342                         cif_isp10_pltfrm_pr_err(dev,
343                                 "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
344                         return -EINVAL;
345                 }
346                 if (IS_ERR_VALUE(kstrtou32(token, 10,
347                                 &cfg.pps))) {
348                         cif_isp10_pltfrm_pr_err(dev,
349                                 "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
350                         return -EINVAL;
351                 }
352                 ret = cif_isp10_dbgfs_fill_csi_config_from_string(
353                         dev, &cfg.csi_config, strp);
354                 if (IS_ERR_VALUE(ret))
355                         return ret;
356                 ret = cif_isp10_pltfrm_l_s_csi_config(
357                         dev, inp, cfg.pps, &cfg.csi_config);
358                 if (IS_ERR_VALUE(ret))
359                         return ret;
360         } else if (!strncmp(token, "reset", 5)) {
361         } else {
362                 cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
363                 return -EINVAL;
364         }
365
366         return count;
367 }
368
369 void cif_isp10_dbgfs_fill_sensor_aec_para(
370         struct cif_isp10_device *cif_isp10_dev,
371         s32 exp_time,
372         u16 gain)
373 {
374         struct cif_isp10_pltfrm_data *pdata;
375
376         pdata = (struct cif_isp10_pltfrm_data *)
377                         cif_isp10_dev->dev->platform_data;
378         pdata->exp_time = exp_time;
379         pdata->gain = gain;
380 }
381
382 static ssize_t cif_isp10_dbgfs_sensor_read(
383         struct file *f,
384         char __user *out,
385         size_t count,
386         loff_t *pos)
387 {
388         u32 out_size = 0;
389         u32 str_len;
390         struct device *dev = f->f_inode->i_private;
391         struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
392
393         if (*pos)
394                 return 0;
395
396         sprintf(cif_isp10_dbgfs_buf,
397                 "sensor current exp_time: %d\n"
398                 "               gain = %d\n",
399                 pdata->exp_time,
400                 pdata->gain);
401         str_len = strnlen(cif_isp10_dbgfs_buf,
402                           CIF_ISP10_DBGFS_BUF_SIZE);
403         if (str_len > count) {
404                 *pos += out_size;
405                 return 0;
406         }
407         *pos = 0;
408         if (IS_ERR_VALUE(simple_read_from_buffer(
409                 out + out_size, str_len, pos,
410                 cif_isp10_dbgfs_buf, str_len)))
411                 goto ERR;
412         out_size += strnlen(cif_isp10_dbgfs_buf,
413                 CIF_ISP10_DBGFS_BUF_SIZE);
414         count -= str_len;
415
416         *pos += out_size;
417 ERR:
418         return out_size;
419 }
420
421 static ssize_t cif_isp10_dbgfs_sensor_write(
422         struct file *f,
423         const char __user *in,
424         size_t count,
425         loff_t *pos)
426 {
427         return 0;
428 }
429
430 static ssize_t cif_isp10_dbgfs_write(
431         struct file *f,
432         const char __user *in,
433         size_t count,
434         loff_t *pos)
435 {
436         ssize_t ret;
437         char *strp = cif_isp10_dbgfs_buf;
438         char *token;
439         struct device *dev = f->f_inode->i_private;
440         struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
441
442         if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
443                 cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
444                 return -EINVAL;
445         }
446
447         memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
448         ret = simple_write_to_buffer(strp,
449                 CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
450         if (IS_ERR_VALUE(ret))
451                 return ret;
452
453         token = strsep(&strp, " ");
454         if (!strncmp(token, "print", 5)) {
455                 token = strsep(&strp, " ");
456                 if (IS_ERR_OR_NULL(token)) {
457                         cif_isp10_pltfrm_pr_err(dev,
458                                 "missing token, command format is 'print all|<list of block name>'\n");
459                         return -EINVAL;
460                 }
461                 if (!strncmp(token, "register", 8)) {
462                         u32 addr;
463                         struct cif_isp10_pltfrm_data *pdata =
464                                 dev->platform_data;
465                         token = strsep(&strp, " ");
466                         while (token) {
467                                 if (IS_ERR_VALUE(kstrtou32(token,
468                                         16, &addr))) {
469                                         cif_isp10_pltfrm_pr_err(dev,
470                                                 "malformed token, must be a hexadecimal register address\n");
471                                         return -EINVAL;
472                                 }
473                                 pr_info("0x%04x: 0x%08x\n",
474                                         addr,
475                                         ioread32(pdata->base_addr +
476                                                 addr));
477                                 token = strsep(&strp, " ");
478                         }
479                 } else if (pdata->dbgfs.print_func) {
480                         unsigned long flags;
481
482                         local_irq_save(flags);
483                         while (token) {
484                                 pdata->dbgfs.print_func(
485                                         pdata->dbgfs.print_cntxt,
486                                         token);
487                                 token = strsep(&strp, " ");
488                         }
489                         local_irq_restore(flags);
490                 }
491         } else if (!strncmp(token, "power", 5)) {
492                 token = strsep(&strp, " ");
493                 if (IS_ERR_OR_NULL(token)) {
494                         cif_isp10_pltfrm_pr_err(dev,
495                                 "missing token, command format is 'power [off|on]'\n");
496                         return -EINVAL;
497                 }
498                 if (!strncmp(token, "on", 2)) {
499                         if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
500                                 CIF_ISP10_PM_STATE_SW_STNDBY, NULL)))
501                                 cif_isp10_pltfrm_pr_err(dev,
502                                         "power on failed\n");
503                         else
504                                 cif_isp10_pltfrm_pr_info(dev,
505                                         "switched on\n");
506                 } else if (!strncmp(token, "off", 3)) {
507                         if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
508                                 CIF_ISP10_PM_STATE_OFF, NULL)))
509                                 cif_isp10_pltfrm_pr_err(dev,
510                                         "power off failed\n");
511                         else
512                                 cif_isp10_pltfrm_pr_info(dev,
513                                         "switched off\n");
514                 } else {
515                         cif_isp10_pltfrm_pr_err(dev,
516                                 "missing token, command format is 'power [off|on]'\n");
517                         return -EINVAL;
518                 }
519         } else if (!strncmp(token, "set", 3)) {
520                 token = strsep(&strp, " ");
521                 if (IS_ERR_OR_NULL(token)) {
522                         cif_isp10_pltfrm_pr_err(dev,
523                                 "missing token, command format is 'set register <hex addr>=<hex val>'\n");
524                         return -EINVAL;
525                 }
526                 if (!strncmp(token, "register", 8)) {
527                         u32 addr;
528                         u32 val;
529                         struct cif_isp10_pltfrm_data *pdata =
530                                 dev->platform_data;
531                         token = strsep(&strp, "=");
532                         if (IS_ERR_VALUE(kstrtou32(token,
533                                 16, &addr))) {
534                                 cif_isp10_pltfrm_pr_err(dev,
535                                         "malformed token, address must be a hexadecimal register address\n");
536                                 return -EINVAL;
537                         }
538                         token = strp;
539                         if (IS_ERR_VALUE(kstrtou32(token,
540                                 16, &val))) {
541                                 cif_isp10_pltfrm_pr_err(dev,
542                                         "malformed token, value must be a hexadecimal value\n");
543                                 return -EINVAL;
544                         }
545                         iowrite32(val, pdata->base_addr + addr);
546                 } else {
547                         cif_isp10_pltfrm_pr_err(dev,
548                                 "unknown command %s\n", token);
549                         return -EINVAL;
550                 }
551         } else {
552                 cif_isp10_pltfrm_pr_err(dev,
553                         "unknown command %s\n", token);
554                 return -EINVAL;
555         }
556         return count;
557 }
558
559 static const struct file_operations cif_isp10_dbgfs_csi_fops = {
560         .read = cif_isp10_dbgfs_csi_read,
561         .write = cif_isp10_dbgfs_csi_write
562 };
563
564 static const struct file_operations cif_isp10_dbgfs_fops = {
565         .write = cif_isp10_dbgfs_write
566 };
567
568 static const struct file_operations cif_isp10_dbgfs_sensor_fops = {
569         .read = cif_isp10_dbgfs_sensor_read,
570         .write = cif_isp10_dbgfs_sensor_write
571 };
572
573 #ifdef CONFIG_CIF_ISP10_REG_TRACE
574
575 static inline int cif_isp10_pltfrm_trace_printf(
576         struct device *dev,
577         const char *fmt,
578         va_list args)
579 {
580         int i;
581         u32 rem_size;
582         unsigned long flags = 0;
583
584         if (!in_irq())
585                 spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
586         cif_isp10_reg_trace.internal = true;
587
588         rem_size = cif_isp10_reg_trace.reg_trace_max_size -
589                 cif_isp10_reg_trace.reg_trace_write_pos;
590
591         if (rem_size <= 0) {
592                 if (!in_irq())
593                         spin_unlock_irqrestore(
594                                 &cif_isp10_reg_trace.lock, flags);
595                 cif_isp10_reg_trace.internal = false;
596                 return 0;
597         }
598
599         i = vsnprintf(cif_isp10_reg_trace.reg_trace +
600                 cif_isp10_reg_trace.reg_trace_write_pos,
601                 rem_size,
602                 fmt, args);
603         if (i == rem_size) /* buffer full */
604                 i = 0;
605         else if (i < 0)
606                 cif_isp10_pltfrm_pr_err(dev,
607                         "error writing trace buffer, error %d\n", i);
608         else
609                 cif_isp10_reg_trace.reg_trace_write_pos += i;
610         cif_isp10_reg_trace.internal = false;
611         if (!in_irq())
612                 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
613
614         return i;
615 }
616
617 inline int cif_isp10_pltfrm_rtrace_printf(
618         struct device *dev,
619         const char *fmt,
620         ...)
621 {
622         va_list args;
623         int i;
624
625         va_start(args, fmt);
626         i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
627         va_end(args);
628
629         return i;
630 }
631
632 inline int cif_isp10_pltfrm_ftrace_printf(
633         struct device *dev,
634         const char *fmt,
635         ...)
636 {
637         va_list args;
638         int i;
639
640         if (!cif_isp10_reg_trace.ftrace ||
641                 cif_isp10_reg_trace.internal)
642                 return 0;
643
644         va_start(args, fmt);
645         i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
646         va_end(args);
647
648         return i;
649 }
650
651 static void cif_isp10_dbgfs_reg_trace_clear(
652         struct device *dev)
653 {
654         cif_isp10_reg_trace.reg_trace_write_pos = 0;
655         cif_isp10_reg_trace.reg_trace_read_pos = 0;
656 }
657
658 static ssize_t cif_isp10_dbgfs_reg_trace_read(
659         struct file *f,
660         char __user *out,
661         size_t count,
662         loff_t *pos)
663 {
664         ssize_t bytes;
665         size_t available = cif_isp10_reg_trace.reg_trace_write_pos -
666                 cif_isp10_reg_trace.reg_trace_read_pos;
667         size_t rem = count;
668
669         cif_isp10_reg_trace.internal = true;
670
671         if (!available)
672                 cif_isp10_reg_trace.reg_trace_read_pos = 0;
673
674         while (rem && available) {
675                 bytes = simple_read_from_buffer(
676                         out + (count - rem), count,
677                         &cif_isp10_reg_trace.reg_trace_read_pos,
678                         cif_isp10_reg_trace.reg_trace,
679                         cif_isp10_reg_trace.reg_trace_write_pos);
680                 if (bytes < 0) {
681                         cif_isp10_pltfrm_pr_err(NULL,
682                                 "buffer read failed with error %d\n",
683                                 bytes);
684                         cif_isp10_reg_trace.internal = false;
685                         return bytes;
686                 }
687                 rem -= bytes;
688                 available = cif_isp10_reg_trace.reg_trace_write_pos -
689                         cif_isp10_reg_trace.reg_trace_read_pos;
690         }
691
692         cif_isp10_reg_trace.internal = false;
693         return count - rem;
694 }
695
696 static ssize_t cif_isp10_dbgfs_reg_trace_write(
697         struct file *f,
698         const char __user *in,
699         size_t count,
700         loff_t *pos)
701 {
702         ssize_t ret;
703         char *strp = cif_isp10_dbgfs_buf;
704         char *token;
705         struct device *dev = f->f_inode->i_private;
706         u32 max_size;
707         unsigned long flags = 0;
708
709         if (!in_irq())
710                 spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
711
712         cif_isp10_reg_trace.internal = true;
713
714         if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
715                 cif_isp10_pltfrm_pr_err(dev, "command line too long\n");
716                 return -EINVAL;
717         }
718
719         memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
720         ret = simple_write_to_buffer(strp,
721                 CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
722         if (IS_ERR_VALUE(ret))
723                 goto err;
724
725         token = strsep(&strp, " ");
726         if (!strncmp(token, "clear", 5)) {
727                 cif_isp10_dbgfs_reg_trace_clear(dev);
728                 cif_isp10_pltfrm_pr_info(dev,
729                         "register trace buffer cleared\n");
730         } else if (!strcmp(token, "size")) {
731                 token = strsep(&strp, " ");
732                 if (IS_ERR_OR_NULL(token)) {
733                         cif_isp10_pltfrm_pr_err(dev,
734                                 "missing token, command format is 'size <num entries>'\n");
735                         ret = -EINVAL;
736                         goto err;
737                 }
738                 if (IS_ERR_VALUE(kstrtou32(token, 10,
739                                 &max_size))) {
740                         cif_isp10_pltfrm_pr_err(dev,
741                                 "wrong token format, <num entries> must be positive integer>'\n");
742                         ret = -EINVAL;
743                         goto err;
744                 }
745                 if (cif_isp10_reg_trace.reg_trace) {
746                         devm_kfree(dev, cif_isp10_reg_trace.reg_trace);
747                         cif_isp10_reg_trace.reg_trace = NULL;
748                 }
749                 cif_isp10_dbgfs_reg_trace_clear(dev);
750                 if (max_size > 0) {
751                         cif_isp10_reg_trace.reg_trace = devm_kzalloc(dev,
752                                 max_size, GFP_KERNEL);
753                         if (!cif_isp10_reg_trace.reg_trace) {
754                                 cif_isp10_pltfrm_pr_err(dev,
755                                         "memory allocation failed\n");
756                                 ret = -ENOMEM;
757                                 goto err;
758                         }
759                         cif_isp10_reg_trace.reg_trace_max_size = max_size;
760                         cif_isp10_pltfrm_pr_info(dev,
761                                 "register trace buffer size set to %d Byte\n",
762                                 max_size);
763                 }
764         } else if (!strncmp(token, "rtrace", 6)) {
765                 token = strsep(&strp, " ");
766                 if (IS_ERR_OR_NULL(token)) {
767                         cif_isp10_pltfrm_pr_err(dev,
768                                 "missing token, command format is 'rtrace [off|on]'\n");
769                         ret = -EINVAL;
770                         goto err;
771                 }
772                 if (!strncmp(token, "on", 2)) {
773                         cif_isp10_reg_trace.rtrace = true;
774                         cif_isp10_pltfrm_pr_info(dev,
775                                 "register trace enabled\n");
776                 } else if (!strncmp(token, "off", 3)) {
777                         cif_isp10_reg_trace.rtrace = false;
778                         cif_isp10_pltfrm_pr_info(dev,
779                                 "register trace disabled\n");
780                 } else {
781                         cif_isp10_pltfrm_pr_err(dev,
782                                 "missing token, command format is 'rtrace [off|on]'\n");
783                         ret = -EINVAL;
784                         goto err;
785                 }
786         } else if (!strncmp(token, "ftrace", 6)) {
787                 token = strsep(&strp, " ");
788                 if (IS_ERR_OR_NULL(token)) {
789                         cif_isp10_pltfrm_pr_err(dev,
790                                 "missing token, command format is 'ftrace [off|on]'\n");
791                         ret = -EINVAL;
792                         goto err;
793                 }
794                 if (!strncmp(token, "on", 2)) {
795                         cif_isp10_reg_trace.ftrace = true;
796                         cif_isp10_pltfrm_pr_info(dev,
797                                 "function trace enabled\n");
798                 } else if (!strncmp(token, "off", 3)) {
799                         cif_isp10_reg_trace.ftrace = false;
800                         cif_isp10_pltfrm_pr_info(dev,
801                                 "function trace disabled\n");
802                 } else {
803                         cif_isp10_pltfrm_pr_err(dev,
804                                 "missing token, command format is 'ftrace [off|on]'\n");
805                         ret = -EINVAL;
806                         goto err;
807                 }
808         } else {
809                 cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
810                 ret = -EINVAL;
811                 goto err;
812         }
813         cif_isp10_reg_trace.internal = false;
814         if (!in_irq())
815                 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
816         return count;
817 err:
818         cif_isp10_reg_trace.internal = false;
819         if (!in_irq())
820                 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
821         return ret;
822 }
823
824 static const struct file_operations
825 cif_isp10_dbgfs_reg_trace_fops = {
826         .read = cif_isp10_dbgfs_reg_trace_read,
827         .write = cif_isp10_dbgfs_reg_trace_write
828 };
829
830 #endif
831 #endif
832
833 static irqreturn_t cif_isp10_pltfrm_irq_handler(int irq, void *cntxt)
834 {
835         unsigned int i, mis_val;
836         int ret;
837         struct device *dev = cntxt;
838         struct cif_isp10_pltfrm_data *pdata =
839                 dev_get_platdata(dev);
840         void *cif_isp10_dev = dev_get_drvdata(dev);
841
842         if (irq != pdata->irq)
843                 return IRQ_NONE;
844
845         for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
846                 if (IS_ERR_VALUE(pdata->irq_handlers[i].mis))
847                         break;
848
849                 if (IS_ERR_OR_NULL(pdata->irq_handlers[i].isr)) {
850                         cif_isp10_pltfrm_pr_err(NULL,
851                                 "ISR for IRQ #%d not set\n", irq);
852                         break;
853                 }
854
855                 mis_val = cif_ioread32(pdata->base_addr +
856                         pdata->irq_handlers[i].mis);
857                 if (mis_val == 0)
858                         continue;
859
860                 ret = pdata->irq_handlers[i].isr(mis_val, cif_isp10_dev);
861                 if (IS_ERR_VALUE(ret)) {
862                         cif_isp10_pltfrm_pr_err(NULL,
863                                 "ISR for IRQ #%d failed with error %d\n",
864                                 irq, ret);
865                 }
866                 return IRQ_HANDLED;
867         }
868
869         return IRQ_NONE;
870 }
871
872 const char *cif_isp10_pltfrm_pm_state_string(
873         enum cif_isp10_pm_state pm_state)
874 {
875         switch (pm_state) {
876         case CIF_ISP10_PM_STATE_OFF:
877                 return "CIF_ISP10_PM_STATE_OFF";
878         case CIF_ISP10_PM_STATE_SUSPENDED:
879                 return "CIF_ISP10_PM_STATE_SUSPENDED";
880         case CIF_ISP10_PM_STATE_SW_STNDBY:
881                 return "CIF_ISP10_PM_STATE_SW_STNDBY";
882         case CIF_ISP10_PM_STATE_STREAMING:
883                 return "CIF_ISP10_PM_STATE_STREAMING";
884         default:
885                 return "PM_STATE_UNKNOWN";
886         }
887 }
888
889 inline void cif_isp10_pltfrm_write_reg(
890         struct device *dev,
891         u32 data,
892         CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
893 {
894         iowrite32(data, addr);
895 #ifdef CONFIG_CIF_ISP10_REG_TRACE
896         {
897                 unsigned long flags = 0;
898
899                 if (!in_irq())
900                         spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
901                 cif_isp10_reg_trace.internal = true;
902                 if (((cif_isp10_reg_trace.reg_trace_write_pos +
903                         (20 * sizeof(char))) <
904                         cif_isp10_reg_trace.reg_trace_max_size) &&
905                         cif_isp10_reg_trace.rtrace) {
906                         int bytes =
907                                 sprintf(cif_isp10_reg_trace.reg_trace +
908                                         cif_isp10_reg_trace.reg_trace_write_pos,
909                                         "%04x %08x\n",
910                                         addr - cif_isp10_reg_trace.base_addr,
911                                         data);
912                         if (bytes > 0)
913                                 cif_isp10_reg_trace.reg_trace_write_pos +=
914                                         bytes;
915                         else
916                                 cif_isp10_pltfrm_pr_err(dev,
917                                         "error writing trace buffer, error %d\n",
918                                         bytes);
919                 }
920                 cif_isp10_reg_trace.internal = false;
921                 if (!in_irq())
922                         spin_unlock_irqrestore(
923                                 &cif_isp10_reg_trace.lock, flags);
924         }
925 #endif
926 }
927
928 inline void cif_isp10_pltfrm_write_reg_OR(
929         struct device *dev,
930         u32 data,
931         CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
932 {
933         cif_isp10_pltfrm_write_reg(dev,
934                 (ioread32(addr) | data), addr);
935 }
936
937 inline void cif_isp10_pltfrm_write_reg_AND(
938         struct device *dev,
939         u32 data,
940         CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
941 {
942         cif_isp10_pltfrm_write_reg(dev,
943                 (ioread32(addr) & data), addr);
944 }
945
946 inline u32 cif_isp10_pltfrm_read_reg(
947         struct device *dev,
948         CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
949 {
950         return ioread32(addr);
951 }
952
953 int cif_isp10_pltfrm_dev_init(
954         struct cif_isp10_device *cif_isp10_dev,
955         struct device **_dev,
956         void __iomem **reg_base_addr)
957 {
958         int ret;
959         struct cif_isp10_pltfrm_data *pdata;
960         struct device *dev = *_dev;
961         struct platform_device *pdev =
962                 container_of(dev, struct platform_device, dev);
963         struct resource *res;
964         void __iomem *base_addr;
965         unsigned int i, irq;
966
967         dev_set_drvdata(dev, cif_isp10_dev);
968         cif_isp10_dev->dev = dev;
969
970         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
971         if (!pdata) {
972                 cif_isp10_pltfrm_pr_err(dev,
973                         "could not allocate memory for platform data\n");
974                 ret = -ENOMEM;
975                 goto err;
976         }
977
978         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "register");
979         if (!res) {
980                 cif_isp10_pltfrm_pr_err(NULL,
981                         "platform_get_resource_byname failed\n");
982                 ret = -ENODEV;
983                 goto err;
984         }
985         base_addr = devm_ioremap_resource(&pdev->dev, res);
986         if (IS_ERR_OR_NULL(base_addr)) {
987                 cif_isp10_pltfrm_pr_err(NULL, "devm_ioremap_resource failed\n");
988                 if (IS_ERR(base_addr))
989                         ret = PTR_ERR(base_addr);
990                 else
991                         ret = -ENODEV;
992         }
993         *reg_base_addr = base_addr;
994         pdata->base_addr = base_addr;
995
996         irq = platform_get_irq_byname(pdev, "cif_isp10_irq");
997         if (IS_ERR_VALUE(irq)) {
998                 ret = irq;
999                 cif_isp10_pltfrm_pr_err(NULL,
1000                 "platform_get_irq_byname failed\n");
1001                 goto err;
1002         }
1003
1004         ret = devm_request_threaded_irq(dev,
1005                         irq,
1006                         cif_isp10_pltfrm_irq_handler,
1007                         NULL,
1008                         0,
1009                         dev_driver_string(dev),
1010                         dev);
1011         if (IS_ERR_VALUE(ret)) {
1012                 cif_isp10_pltfrm_pr_err(NULL,
1013                 "devm_request_threaded_irq failed\n");
1014                 goto err;
1015         }
1016         pdata->irq = irq;
1017
1018         pdata->pinctrl = devm_pinctrl_get(dev);
1019         if (!IS_ERR_OR_NULL(pdata->pinctrl)) {
1020                 pdata->pins_default = pinctrl_lookup_state(pdata->pinctrl,
1021                         PINCTRL_STATE_DEFAULT);
1022                 if (IS_ERR(pdata->pins_default))
1023                         cif_isp10_pltfrm_pr_err(dev,
1024                                                 "could not get default pinstate\n");
1025
1026                 pdata->pins_sleep = pinctrl_lookup_state(pdata->pinctrl,
1027                         PINCTRL_STATE_SLEEP);
1028                 if (IS_ERR(pdata->pins_sleep))
1029                         cif_isp10_pltfrm_pr_warn(dev,
1030                                                 "could not get pins_sleep pinstate\n");
1031
1032                 pdata->pins_inactive = pinctrl_lookup_state(pdata->pinctrl,
1033                         "inactive");
1034                 if (IS_ERR(pdata->pins_inactive))
1035                         cif_isp10_pltfrm_pr_warn(dev,
1036                                                 "could not get pins_inactive pinstate\n");
1037
1038                 if (!IS_ERR_OR_NULL(pdata->pins_default))
1039                         pinctrl_select_state(pdata->pinctrl,
1040                                 pdata->pins_default);
1041         }
1042
1043         for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++)
1044                 pdata->irq_handlers[i].mis = -EINVAL;
1045
1046         dev->platform_data = pdata;
1047
1048         INIT_LIST_HEAD(&pdata->csi0_configs);
1049         INIT_LIST_HEAD(&pdata->csi1_configs);
1050
1051 #ifndef CONFIG_DEBUG_FS
1052         pdata->dbgfs.dir = debugfs_create_dir("cif_isp10", NULL);
1053         pdata->dbgfs.csi0_file = debugfs_create_file(
1054                 "csi-0",
1055                 0644,
1056                 pdata->dbgfs.dir,
1057                 dev,
1058                 &cif_isp10_dbgfs_csi_fops);
1059         pdata->dbgfs.csi1_file = debugfs_create_file(
1060                 "csi-1",
1061                 0644,
1062                 pdata->dbgfs.dir,
1063                 dev,
1064                 &cif_isp10_dbgfs_csi_fops);
1065         pdata->dbgfs.cif_isp10_file = debugfs_create_file(
1066                 "cif_isp20",
1067                 0200,
1068                 pdata->dbgfs.dir,
1069                 dev,
1070                 &cif_isp10_dbgfs_fops);
1071         pdata->dbgfs.cif_isp10_file = debugfs_create_file(
1072                 "sensor",
1073                 0644,
1074                 pdata->dbgfs.dir,
1075                 dev,
1076                 &cif_isp10_dbgfs_sensor_fops);
1077 #ifdef CONFIG_CIF_ISP10_REG_TRACE
1078         pdata->dbgfs.reg_trace_file = debugfs_create_file(
1079                 "reg_trace",
1080                 0644,
1081                 pdata->dbgfs.dir,
1082                 dev,
1083                 &cif_isp10_dbgfs_reg_trace_fops);
1084         spin_lock_init(&cif_isp10_reg_trace.lock);
1085         cif_isp10_reg_trace.reg_trace = NULL;
1086         cif_isp10_dbgfs_reg_trace_clear(dev);
1087         cif_isp10_reg_trace.reg_trace_max_size = 0;
1088         cif_isp10_reg_trace.base_addr = base_addr;
1089         cif_isp10_reg_trace.rtrace = true;
1090         cif_isp10_reg_trace.ftrace = false;
1091         cif_isp10_reg_trace.internal = false;
1092 #endif
1093 #endif
1094
1095         return 0;
1096 err:
1097         cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
1098         if (!IS_ERR_OR_NULL(pdata))
1099                 devm_kfree(dev, pdata);
1100         return ret;
1101 }
1102
1103 int cif_isp10_pltfrm_soc_init(
1104         struct cif_isp10_device *cif_isp10_dev,
1105         struct pltfrm_soc_cfg *soc_cfg)
1106 {
1107         struct pltfrm_soc_cfg_para cfg_para;
1108         struct device *dev = cif_isp10_dev->dev;
1109         struct platform_device *pdev =
1110                 container_of(dev, struct platform_device, dev);
1111         struct pltfrm_soc_init_para init_para;
1112         int ret = 0;
1113
1114         if (!IS_ERR_OR_NULL(soc_cfg) && !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
1115                 cfg_para.cmd = PLTFRM_SOC_INIT;
1116                 cfg_para.cfg_para = &init_para;
1117                 init_para.pdev = pdev;
1118                 init_para.isp_base = cif_isp10_dev->config.base_addr;
1119                 ret = soc_cfg->soc_cfg(&cfg_para);
1120                 if (ret == 0)
1121                         cif_isp10_dev->soc_cfg = soc_cfg;
1122         }
1123
1124         return ret;
1125 }
1126
1127 int cif_isp10_pltfrm_mipi_dphy_config(
1128         struct cif_isp10_device *cif_isp10_dev)
1129 {
1130         struct pltfrm_soc_cfg_para cfg_para;
1131         struct pltfrm_soc_cfg *soc_cfg;
1132         int ret = 0;
1133
1134         soc_cfg = cif_isp10_dev->soc_cfg;
1135         if (!IS_ERR_OR_NULL(soc_cfg) &&
1136                 !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
1137                 cfg_para.cmd =
1138                         PLTFRM_MIPI_DPHY_CFG;
1139                 cfg_para.cfg_para =
1140                         (void *)(&cif_isp10_dev->config.cam_itf.cfg.mipi);
1141                 ret = soc_cfg->soc_cfg(&cfg_para);
1142         }
1143
1144         return ret;
1145 }
1146
1147 int cif_isp10_pltfrm_pm_set_state(
1148         struct device *dev,
1149         enum cif_isp10_pm_state pm_state)
1150 {
1151         int ret;
1152         struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
1153         struct pltfrm_soc_cfg *soc_cfg = cif_isp10_dev->soc_cfg;
1154         struct pltfrm_soc_cfg_para cfg_para;
1155
1156         switch (pm_state) {
1157         case CIF_ISP10_PM_STATE_OFF:
1158         case CIF_ISP10_PM_STATE_SUSPENDED:
1159                 cfg_para.cmd = PLTFRM_CLKDIS;
1160                 cfg_para.cfg_para = NULL;
1161                 ret = soc_cfg->soc_cfg(&cfg_para);
1162                 break;
1163         case CIF_ISP10_PM_STATE_SW_STNDBY:
1164         case CIF_ISP10_PM_STATE_STREAMING:
1165                 cfg_para.cmd = PLTFRM_CLKEN;
1166                 cfg_para.cfg_para = NULL;
1167                 ret = soc_cfg->soc_cfg(&cfg_para);
1168                 break;
1169         default:
1170                 cif_isp10_pltfrm_pr_err(dev,
1171                         "unknown or unsupported PM state %d\n", pm_state);
1172                 return -EINVAL;
1173         }
1174
1175         if (IS_ERR_VALUE(ret))
1176                 cif_isp10_pltfrm_pr_err(dev,
1177                         "setting pm state to %s failed with error %d\n",
1178                         cif_isp10_pltfrm_pm_state_string(pm_state), ret);
1179         else
1180                 cif_isp10_pltfrm_pr_dbg(dev,
1181                         "successfully changed pm state to %s\n",
1182                         cif_isp10_pltfrm_pm_state_string(pm_state));
1183         return ret;
1184 }
1185
1186 int cif_isp10_pltfrm_g_interface_config(
1187         struct cif_isp10_img_src *img_src,
1188         struct pltfrm_cam_itf *cam_itf)
1189 {
1190         int ret = 0;
1191
1192         ret = cif_isp10_img_src_ioctl(img_src,
1193                         PLTFRM_CIFCAM_G_ITF_CFG, (void *)cam_itf);
1194         if (IS_ERR_VALUE(ret)) {
1195                 cif_isp10_pltfrm_pr_err(
1196                         dev,
1197                         "cif_isp10_img_src_ioctl PLTFRM_CIFCAM_G_ITF_CFG failed!\n");
1198                 return ret;
1199         }
1200         return 0;
1201 }
1202
1203 int cif_isp10_pltfrm_pinctrl_set_state(
1204         struct device *dev,
1205         enum cif_isp10_pinctrl_state pinctrl_state)
1206 {
1207         int ret = 0;
1208         struct cif_isp10_pltfrm_data *pdata = dev_get_platdata(dev);
1209
1210         cif_isp10_pltfrm_pr_dbg(dev,
1211                 "set pinctrl state to %d\n", pinctrl_state);
1212
1213         if (!pdata) {
1214                 cif_isp10_pltfrm_pr_err(dev,
1215                         "unable to retrieve CIF platform data\n");
1216                 ret = -EINVAL;
1217                 goto err;
1218         }
1219         if (IS_ERR_OR_NULL(pdata->pinctrl))
1220                 return 0;
1221
1222         switch (pinctrl_state) {
1223         case CIF_ISP10_PINCTRL_STATE_SLEEP:
1224                 if (!IS_ERR_OR_NULL(pdata->pins_sleep))
1225                         ret = pinctrl_select_state(pdata->pinctrl,
1226                                 pdata->pins_sleep);
1227                 break;
1228         case CIF_ISP10_PINCTRL_STATE_ACTIVE:
1229         case CIF_ISP10_PINCTRL_STATE_DEFAULT:
1230                 if (!IS_ERR_OR_NULL(pdata->pins_default))
1231                         ret = pinctrl_select_state(pdata->pinctrl,
1232                                 pdata->pins_default);
1233                 break;
1234         case CIF_ISP10_PINCTRL_STATE_INACTIVE:
1235                 if (!IS_ERR_OR_NULL(pdata->pins_inactive))
1236                         ret = pinctrl_select_state(pdata->pinctrl,
1237                                 pdata->pins_inactive);
1238                 break;
1239         default:
1240                 cif_isp10_pltfrm_pr_err(dev,
1241                         "unknown or unsupported pinctrl state %d\n",
1242                         pinctrl_state);
1243                 ret = -EINVAL;
1244                 goto err;
1245         }
1246
1247         if (IS_ERR_VALUE(ret))
1248                 goto err;
1249
1250         return 0;
1251 err:
1252         cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
1253         return ret;
1254 }
1255
1256 int cif_isp10_pltfrm_irq_register_isr(
1257         struct device *dev,
1258         unsigned int mis,
1259         int (*isr)(unsigned int mis, void *cntxt),
1260         void *cntxt)
1261 {
1262         int ret = 0;
1263         unsigned int i;
1264         int slot = -EINVAL;
1265         struct platform_device *pdev =
1266                 container_of(dev, struct platform_device, dev);
1267         struct cif_isp10_pltfrm_data *pdata =
1268                 dev_get_platdata(&pdev->dev);
1269         bool skip_request_irq = false;
1270         const char *irq_name;
1271
1272         switch (mis) {
1273         case CIF_MIPI_MIS:
1274                 irq_name = "CIF_ISP10_MIPI_IRQ";
1275                 break;
1276         case CIF_ISP_MIS:
1277                 irq_name = "CIF_ISP10_ISP_IRQ";
1278                 break;
1279         case CIF_MI_MIS:
1280                 irq_name = "CIF_ISP10_MI_IRQ";
1281                 break;
1282         default:
1283                 cif_isp10_pltfrm_pr_err(dev,
1284                         "unknown or unsupported IRQ %d\n", mis);
1285                 ret = -EINVAL;
1286                 goto err;
1287         }
1288         cif_isp10_pltfrm_pr_dbg(dev,
1289                 "registering ISR for IRQ %s\n", irq_name);
1290
1291         for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
1292                 if (IS_ERR_VALUE(slot) &&
1293                         IS_ERR_VALUE(pdata->irq_handlers[i].mis))
1294                         slot = (int)i;
1295                 if (pdata->irq_handlers[i].mis == mis) {
1296                         cif_isp10_pltfrm_pr_dbg(dev,
1297                                 "overwriting ISR for IRQ %s\n", irq_name);
1298                         slot = (int)i;
1299                         skip_request_irq = true;
1300                         break;
1301                 }
1302         }
1303         if (IS_ERR_VALUE(slot)) {
1304                 if (!isr)
1305                         return 0;
1306                 cif_isp10_pltfrm_pr_err(dev,
1307                         "cannot register ISR for IRQ %s, too many ISRs already registered\n",
1308                         irq_name);
1309                 ret = -EFAULT;
1310                 goto err;
1311         }
1312         pdata->irq_handlers[slot].isr = isr;
1313         if (!isr) {
1314                 pdata->irq_handlers[slot].mis = -EINVAL;
1315                 skip_request_irq = true;
1316         } else {
1317                 pdata->irq_handlers[slot].mis = mis;
1318         }
1319
1320         return 0;
1321 err:
1322         cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
1323         return ret;
1324 }
1325
1326 const char *cif_isp10_pltfrm_get_device_type(
1327         struct device *dev)
1328 {
1329         return dev->of_node->type;
1330 }
1331
1332 const char *cif_isp10_pltfrm_dev_string(
1333         struct device *dev)
1334 {
1335         return dev_driver_string(dev);
1336 }
1337
1338 int cif_isp10_pltfrm_get_img_src_device(
1339         struct device *dev,
1340         struct cif_isp10_img_src **img_src_array,
1341         unsigned int array_len)
1342 {
1343         struct device_node *node = NULL;
1344         struct device_node *camera_list_node = NULL;
1345         struct i2c_client *client = NULL;
1346         int ret = 0;
1347         int index, size = 0;
1348         const __be32 *phandle;
1349         int num_cameras = 0;
1350         struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
1351
1352         node = of_node_get(dev->of_node);
1353         if (IS_ERR_OR_NULL(node)) {
1354                 dev_err(dev, "Unable to obtain CIF device node\n");
1355                 ret = -EEXIST;
1356                 goto err;
1357         }
1358
1359         phandle = of_get_property(node,
1360                 "rockchip,camera-modules-attached", &size);
1361         if (IS_ERR_OR_NULL(phandle)) {
1362                 cif_isp10_pltfrm_pr_err(dev,
1363                         "no camera-modules-attached'\n");
1364                         ret = -EINVAL;
1365                         goto err;
1366         }
1367
1368         for (index = 0; index < size / sizeof(*phandle); index++) {
1369                 camera_list_node = of_parse_phandle(node,
1370                         "rockchip,camera-modules-attached", index);
1371                 of_node_put(node);
1372                 if (IS_ERR_OR_NULL(camera_list_node)) {
1373                         cif_isp10_pltfrm_pr_err(dev,
1374                                 "invalid index %d for property 'rockchip,camera-modules-attached'\n",
1375                                 index);
1376                                 ret = -EINVAL;
1377                                 goto err;
1378                 }
1379
1380                 if (!strcmp(camera_list_node->type,
1381                                         "v4l2-i2c-subdev")) {
1382                         client = of_find_i2c_device_by_node(
1383                                 camera_list_node);
1384                         of_node_put(camera_list_node);
1385                         if (IS_ERR_OR_NULL(client)) {
1386                                 cif_isp10_pltfrm_pr_err(dev,
1387                                         "could not get camera i2c client, maybe not yet created, deferring device probing...\n");
1388                                 continue;
1389                         }
1390                 } else {
1391                         cif_isp10_pltfrm_pr_dbg(dev,
1392                                 "device of type %s not supported\n",
1393                                 camera_list_node->type);
1394                         of_node_put(camera_list_node);
1395                         continue;
1396                 }
1397
1398                 img_src_array[num_cameras] =
1399                         cif_isp10_img_src_to_img_src(
1400                                 &client->dev,
1401                                 cif_isp10_dev->soc_cfg);
1402                 if (!IS_ERR_OR_NULL(img_src_array[num_cameras])) {
1403                         cif_isp10_pltfrm_pr_info(dev,
1404                                 "%s attach to cif isp10 img_src_array[%d]\n",
1405                                 cif_isp10_img_src_g_name(
1406                                         img_src_array[num_cameras]),
1407                                 num_cameras);
1408                         num_cameras++;
1409                         if (num_cameras >= array_len) {
1410                                 cif_isp10_pltfrm_pr_err(dev,
1411                                         "cif isp10 isn't support > %d 'camera modules attached'\n",
1412                                         array_len);
1413                                 break;
1414                         }
1415                 } else {
1416                         continue;
1417                 }
1418         }
1419
1420         return num_cameras;
1421 err:
1422         dev_err(dev, "failed with error %d\n", ret);
1423         if (!IS_ERR_OR_NULL(client))
1424                 put_device(&client->dev);
1425         if (!IS_ERR_OR_NULL(camera_list_node))
1426                 of_node_put(camera_list_node);
1427         return ret;
1428 }
1429
1430 void cif_isp10_pltfrm_dev_release(
1431         struct device *dev)
1432 {
1433 #ifndef CONFIG_DEBUG_FS
1434         {
1435                 struct cif_isp10_pltfrm_data *pdata =
1436                         dev->platform_data;
1437                 debugfs_remove(pdata->dbgfs.csi0_file);
1438                 debugfs_remove(pdata->dbgfs.csi1_file);
1439                 debugfs_remove_recursive(pdata->dbgfs.dir);
1440         }
1441 #endif
1442 }
1443