2 *************************************************************************
3 * Rockchip driver for CIF ISP 1.0
4 * (Based on Intel driver for sofiaxxx)
6 * Copyright (C) 2015 Intel Mobile Communications GmbH
7 * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
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 *************************************************************************
18 #error "this driver requires a kernel with device tree support"
22 #include <linux/platform_device.h>
23 #include <linux/interrupt.h>
24 #include <linux/kernel.h>
25 #include <linux/i2c.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>
35 #include <media/v4l2-controls_rockchip.h>
36 #ifdef CONFIG_CIF_ISP10_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;
48 spinlock_t lock;/* spin lock */
49 } cif_isp10_reg_trace;
53 struct cif_isp10_pltfrm_csi_config {
54 struct list_head list;
56 struct cif_isp10_csi_config csi_config;
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;
68 int (*isr)(unsigned int mis, void *cntxt);
70 struct list_head csi0_configs;
71 struct list_head csi1_configs;
75 #ifndef CONFIG_DEBUG_FS
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;
84 void (*print_func)(void *cntxt, const char *block_name);
90 void cif_isp10_pltfrm_debug_register_print_cb(
92 void (*print)(void *cntxt, const char *block),
94 #ifndef CONFIG_DEBUG_FS
95 struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
97 pdata->dbgfs.print_cntxt = cntxt;
98 pdata->dbgfs.print_func = print;
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];
106 static int cif_isp10_dbgfs_fill_csi_config_from_string(
108 struct cif_isp10_csi_config *csi_config,
113 token = strsep(&strp, " ");
114 if (IS_ERR_OR_NULL(token))
116 if (IS_ERR_VALUE(kstrtou32(token, 10,
118 goto wrong_token_format;
119 token = strsep(&strp, " ");
120 if (IS_ERR_OR_NULL(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))
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))
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;
143 csi_config->ana_bandgab_bias = (u32)-1;
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");
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");
157 static int cif_isp10_dbgfs_csi_configs_init(
159 enum cif_isp10_inp inp,
160 struct list_head *csi_configs)
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;
169 img_src_dev = cif_isp10_pltfrm_get_img_src_device(dev, inp);
170 if (IS_ERR_OR_NULL(img_src_dev)) {
174 parent_node = of_node_get(img_src_dev->of_node);
175 put_device(img_src_dev);
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");
191 sizeof(struct cif_isp10_pltfrm_csi_config),
194 cif_isp10_pltfrm_pr_err(dev,
195 "memory allocation failed\n");
200 ret = cif_isp10_pltfrm_fill_csi_config_from_node(
201 dev, &cfg->csi_config, child_node);
202 if (IS_ERR_VALUE(ret))
204 list_add_tail(&cfg->list, csi_configs);
207 of_node_put(prev_node);
208 prev_node = child_node;
210 of_node_put(prev_node);
211 of_node_put(parent_node);
215 of_node_put(prev_node);
216 of_node_put(child_node);
217 of_node_put(parent_node);
219 if (!IS_ERR_OR_NULL(img_src_dev))
220 put_device(img_src_dev);
224 static ssize_t cif_isp10_dbgfs_csi_read(
232 struct cif_isp10_pltfrm_csi_config *cfg;
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;
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;
247 cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
251 if (list_empty(csi_configs))
252 if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
253 dev, inp, csi_configs)))
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,
269 " ana_bandgap_bias = %d\n",
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);
275 str_len = strnlen(cif_isp10_dbgfs_buf,
276 CIF_ISP10_DBGFS_BUF_SIZE);
277 if (str_len > count) {
282 if (IS_ERR_VALUE(simple_read_from_buffer(
283 out + out_size, str_len, pos,
284 cif_isp10_dbgfs_buf, str_len)))
286 out_size += strnlen(cif_isp10_dbgfs_buf,
287 CIF_ISP10_DBGFS_BUF_SIZE);
295 static ssize_t cif_isp10_dbgfs_csi_write(
297 const char __user *in,
302 char *strp = cif_isp10_dbgfs_buf;
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;
309 if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
310 cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
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;
321 cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
325 if (list_empty(csi_configs))
326 if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
327 dev, inp, csi_configs)))
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))
336 token = strsep(&strp, " ");
337 if (!strcmp(token, "push")) {
338 struct cif_isp10_pltfrm_csi_config cfg;
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");
346 if (IS_ERR_VALUE(kstrtou32(token, 10,
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");
352 ret = cif_isp10_dbgfs_fill_csi_config_from_string(
353 dev, &cfg.csi_config, strp);
354 if (IS_ERR_VALUE(ret))
356 ret = cif_isp10_pltfrm_l_s_csi_config(
357 dev, inp, cfg.pps, &cfg.csi_config);
358 if (IS_ERR_VALUE(ret))
360 } else if (!strncmp(token, "reset", 5)) {
362 cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
369 void cif_isp10_dbgfs_fill_sensor_aec_para(
370 struct cif_isp10_device *cif_isp10_dev,
374 struct cif_isp10_pltfrm_data *pdata;
376 pdata = (struct cif_isp10_pltfrm_data *)
377 cif_isp10_dev->dev->platform_data;
378 pdata->exp_time = exp_time;
382 static ssize_t cif_isp10_dbgfs_sensor_read(
390 struct device *dev = f->f_inode->i_private;
391 struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
396 sprintf(cif_isp10_dbgfs_buf,
397 "sensor current exp_time: %d\n"
401 str_len = strnlen(cif_isp10_dbgfs_buf,
402 CIF_ISP10_DBGFS_BUF_SIZE);
403 if (str_len > count) {
408 if (IS_ERR_VALUE(simple_read_from_buffer(
409 out + out_size, str_len, pos,
410 cif_isp10_dbgfs_buf, str_len)))
412 out_size += strnlen(cif_isp10_dbgfs_buf,
413 CIF_ISP10_DBGFS_BUF_SIZE);
421 static ssize_t cif_isp10_dbgfs_sensor_write(
423 const char __user *in,
430 static ssize_t cif_isp10_dbgfs_write(
432 const char __user *in,
437 char *strp = cif_isp10_dbgfs_buf;
439 struct device *dev = f->f_inode->i_private;
440 struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
442 if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
443 cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
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))
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");
461 if (!strncmp(token, "register", 8)) {
463 struct cif_isp10_pltfrm_data *pdata =
465 token = strsep(&strp, " ");
467 if (IS_ERR_VALUE(kstrtou32(token,
469 cif_isp10_pltfrm_pr_err(dev,
470 "malformed token, must be a hexadecimal register address\n");
473 pr_info("0x%04x: 0x%08x\n",
475 ioread32(pdata->base_addr +
477 token = strsep(&strp, " ");
479 } else if (pdata->dbgfs.print_func) {
482 local_irq_save(flags);
484 pdata->dbgfs.print_func(
485 pdata->dbgfs.print_cntxt,
487 token = strsep(&strp, " ");
489 local_irq_restore(flags);
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");
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");
504 cif_isp10_pltfrm_pr_info(dev,
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");
512 cif_isp10_pltfrm_pr_info(dev,
515 cif_isp10_pltfrm_pr_err(dev,
516 "missing token, command format is 'power [off|on]'\n");
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");
526 if (!strncmp(token, "register", 8)) {
529 struct cif_isp10_pltfrm_data *pdata =
531 token = strsep(&strp, "=");
532 if (IS_ERR_VALUE(kstrtou32(token,
534 cif_isp10_pltfrm_pr_err(dev,
535 "malformed token, address must be a hexadecimal register address\n");
539 if (IS_ERR_VALUE(kstrtou32(token,
541 cif_isp10_pltfrm_pr_err(dev,
542 "malformed token, value must be a hexadecimal value\n");
545 iowrite32(val, pdata->base_addr + addr);
547 cif_isp10_pltfrm_pr_err(dev,
548 "unknown command %s\n", token);
552 cif_isp10_pltfrm_pr_err(dev,
553 "unknown command %s\n", token);
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
564 static const struct file_operations cif_isp10_dbgfs_fops = {
565 .write = cif_isp10_dbgfs_write
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
573 #ifdef CONFIG_CIF_ISP10_REG_TRACE
575 static inline int cif_isp10_pltfrm_trace_printf(
582 unsigned long flags = 0;
585 spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
586 cif_isp10_reg_trace.internal = true;
588 rem_size = cif_isp10_reg_trace.reg_trace_max_size -
589 cif_isp10_reg_trace.reg_trace_write_pos;
593 spin_unlock_irqrestore(
594 &cif_isp10_reg_trace.lock, flags);
595 cif_isp10_reg_trace.internal = false;
599 i = vsnprintf(cif_isp10_reg_trace.reg_trace +
600 cif_isp10_reg_trace.reg_trace_write_pos,
603 if (i == rem_size) /* buffer full */
606 cif_isp10_pltfrm_pr_err(dev,
607 "error writing trace buffer, error %d\n", i);
609 cif_isp10_reg_trace.reg_trace_write_pos += i;
610 cif_isp10_reg_trace.internal = false;
612 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
617 inline int cif_isp10_pltfrm_rtrace_printf(
626 i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
632 inline int cif_isp10_pltfrm_ftrace_printf(
640 if (!cif_isp10_reg_trace.ftrace ||
641 cif_isp10_reg_trace.internal)
645 i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
651 static void cif_isp10_dbgfs_reg_trace_clear(
654 cif_isp10_reg_trace.reg_trace_write_pos = 0;
655 cif_isp10_reg_trace.reg_trace_read_pos = 0;
658 static ssize_t cif_isp10_dbgfs_reg_trace_read(
665 size_t available = cif_isp10_reg_trace.reg_trace_write_pos -
666 cif_isp10_reg_trace.reg_trace_read_pos;
669 cif_isp10_reg_trace.internal = true;
672 cif_isp10_reg_trace.reg_trace_read_pos = 0;
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);
681 cif_isp10_pltfrm_pr_err(NULL,
682 "buffer read failed with error %d\n",
684 cif_isp10_reg_trace.internal = false;
688 available = cif_isp10_reg_trace.reg_trace_write_pos -
689 cif_isp10_reg_trace.reg_trace_read_pos;
692 cif_isp10_reg_trace.internal = false;
696 static ssize_t cif_isp10_dbgfs_reg_trace_write(
698 const char __user *in,
703 char *strp = cif_isp10_dbgfs_buf;
705 struct device *dev = f->f_inode->i_private;
707 unsigned long flags = 0;
710 spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
712 cif_isp10_reg_trace.internal = true;
714 if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
715 cif_isp10_pltfrm_pr_err(dev, "command line too long\n");
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))
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");
738 if (IS_ERR_VALUE(kstrtou32(token, 10,
740 cif_isp10_pltfrm_pr_err(dev,
741 "wrong token format, <num entries> must be positive integer>'\n");
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;
749 cif_isp10_dbgfs_reg_trace_clear(dev);
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");
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",
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");
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");
781 cif_isp10_pltfrm_pr_err(dev,
782 "missing token, command format is 'rtrace [off|on]'\n");
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");
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");
803 cif_isp10_pltfrm_pr_err(dev,
804 "missing token, command format is 'ftrace [off|on]'\n");
809 cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
813 cif_isp10_reg_trace.internal = false;
815 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
818 cif_isp10_reg_trace.internal = false;
820 spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
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
833 static irqreturn_t cif_isp10_pltfrm_irq_handler(int irq, void *cntxt)
835 unsigned int i, mis_val;
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);
842 if (irq != pdata->irq)
845 for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
846 if (IS_ERR_VALUE(pdata->irq_handlers[i].mis))
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);
855 mis_val = cif_ioread32(pdata->base_addr +
856 pdata->irq_handlers[i].mis);
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",
872 const char *cif_isp10_pltfrm_pm_state_string(
873 enum cif_isp10_pm_state 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";
885 return "PM_STATE_UNKNOWN";
889 inline void cif_isp10_pltfrm_write_reg(
892 CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
894 iowrite32(data, addr);
895 #ifdef CONFIG_CIF_ISP10_REG_TRACE
897 unsigned long flags = 0;
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) {
907 sprintf(cif_isp10_reg_trace.reg_trace +
908 cif_isp10_reg_trace.reg_trace_write_pos,
910 addr - cif_isp10_reg_trace.base_addr,
913 cif_isp10_reg_trace.reg_trace_write_pos +=
916 cif_isp10_pltfrm_pr_err(dev,
917 "error writing trace buffer, error %d\n",
920 cif_isp10_reg_trace.internal = false;
922 spin_unlock_irqrestore(
923 &cif_isp10_reg_trace.lock, flags);
928 inline void cif_isp10_pltfrm_write_reg_OR(
931 CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
933 cif_isp10_pltfrm_write_reg(dev,
934 (ioread32(addr) | data), addr);
937 inline void cif_isp10_pltfrm_write_reg_AND(
940 CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
942 cif_isp10_pltfrm_write_reg(dev,
943 (ioread32(addr) & data), addr);
946 inline u32 cif_isp10_pltfrm_read_reg(
948 CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
950 return ioread32(addr);
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)
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;
967 dev_set_drvdata(dev, cif_isp10_dev);
968 cif_isp10_dev->dev = dev;
970 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
972 cif_isp10_pltfrm_pr_err(dev,
973 "could not allocate memory for platform data\n");
978 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "register");
980 cif_isp10_pltfrm_pr_err(NULL,
981 "platform_get_resource_byname failed\n");
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);
993 *reg_base_addr = base_addr;
994 pdata->base_addr = base_addr;
996 irq = platform_get_irq_byname(pdev, "cif_isp10_irq");
997 if (IS_ERR_VALUE(irq)) {
999 cif_isp10_pltfrm_pr_err(NULL,
1000 "platform_get_irq_byname failed\n");
1004 ret = devm_request_threaded_irq(dev,
1006 cif_isp10_pltfrm_irq_handler,
1009 dev_driver_string(dev),
1011 if (IS_ERR_VALUE(ret)) {
1012 cif_isp10_pltfrm_pr_err(NULL,
1013 "devm_request_threaded_irq failed\n");
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");
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");
1032 pdata->pins_inactive = pinctrl_lookup_state(pdata->pinctrl,
1034 if (IS_ERR(pdata->pins_inactive))
1035 cif_isp10_pltfrm_pr_warn(dev,
1036 "could not get pins_inactive pinstate\n");
1038 if (!IS_ERR_OR_NULL(pdata->pins_default))
1039 pinctrl_select_state(pdata->pinctrl,
1040 pdata->pins_default);
1043 for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++)
1044 pdata->irq_handlers[i].mis = -EINVAL;
1046 dev->platform_data = pdata;
1048 INIT_LIST_HEAD(&pdata->csi0_configs);
1049 INIT_LIST_HEAD(&pdata->csi1_configs);
1051 #ifndef CONFIG_DEBUG_FS
1052 pdata->dbgfs.dir = debugfs_create_dir("cif_isp10", NULL);
1053 pdata->dbgfs.csi0_file = debugfs_create_file(
1058 &cif_isp10_dbgfs_csi_fops);
1059 pdata->dbgfs.csi1_file = debugfs_create_file(
1064 &cif_isp10_dbgfs_csi_fops);
1065 pdata->dbgfs.cif_isp10_file = debugfs_create_file(
1070 &cif_isp10_dbgfs_fops);
1071 pdata->dbgfs.cif_isp10_file = debugfs_create_file(
1076 &cif_isp10_dbgfs_sensor_fops);
1077 #ifdef CONFIG_CIF_ISP10_REG_TRACE
1078 pdata->dbgfs.reg_trace_file = debugfs_create_file(
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;
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);
1103 int cif_isp10_pltfrm_soc_init(
1104 struct cif_isp10_device *cif_isp10_dev,
1105 struct pltfrm_soc_cfg *soc_cfg)
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;
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);
1121 cif_isp10_dev->soc_cfg = soc_cfg;
1127 int cif_isp10_pltfrm_mipi_dphy_config(
1128 struct cif_isp10_device *cif_isp10_dev)
1130 struct pltfrm_soc_cfg_para cfg_para;
1131 struct pltfrm_soc_cfg *soc_cfg;
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)) {
1138 PLTFRM_MIPI_DPHY_CFG;
1140 (void *)(&cif_isp10_dev->config.cam_itf.cfg.mipi);
1141 ret = soc_cfg->soc_cfg(&cfg_para);
1147 int cif_isp10_pltfrm_pm_set_state(
1149 enum cif_isp10_pm_state pm_state)
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;
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);
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);
1170 cif_isp10_pltfrm_pr_err(dev,
1171 "unknown or unsupported PM state %d\n", pm_state);
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);
1180 cif_isp10_pltfrm_pr_dbg(dev,
1181 "successfully changed pm state to %s\n",
1182 cif_isp10_pltfrm_pm_state_string(pm_state));
1186 int cif_isp10_pltfrm_g_interface_config(
1187 struct cif_isp10_img_src *img_src,
1188 struct pltfrm_cam_itf *cam_itf)
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(
1197 "cif_isp10_img_src_ioctl PLTFRM_CIFCAM_G_ITF_CFG failed!\n");
1203 int cif_isp10_pltfrm_pinctrl_set_state(
1205 enum cif_isp10_pinctrl_state pinctrl_state)
1208 struct cif_isp10_pltfrm_data *pdata = dev_get_platdata(dev);
1210 cif_isp10_pltfrm_pr_dbg(dev,
1211 "set pinctrl state to %d\n", pinctrl_state);
1214 cif_isp10_pltfrm_pr_err(dev,
1215 "unable to retrieve CIF platform data\n");
1219 if (IS_ERR_OR_NULL(pdata->pinctrl))
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,
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);
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);
1240 cif_isp10_pltfrm_pr_err(dev,
1241 "unknown or unsupported pinctrl state %d\n",
1247 if (IS_ERR_VALUE(ret))
1252 cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
1256 int cif_isp10_pltfrm_irq_register_isr(
1259 int (*isr)(unsigned int mis, void *cntxt),
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;
1274 irq_name = "CIF_ISP10_MIPI_IRQ";
1277 irq_name = "CIF_ISP10_ISP_IRQ";
1280 irq_name = "CIF_ISP10_MI_IRQ";
1283 cif_isp10_pltfrm_pr_err(dev,
1284 "unknown or unsupported IRQ %d\n", mis);
1288 cif_isp10_pltfrm_pr_dbg(dev,
1289 "registering ISR for IRQ %s\n", irq_name);
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))
1295 if (pdata->irq_handlers[i].mis == mis) {
1296 cif_isp10_pltfrm_pr_dbg(dev,
1297 "overwriting ISR for IRQ %s\n", irq_name);
1299 skip_request_irq = true;
1303 if (IS_ERR_VALUE(slot)) {
1306 cif_isp10_pltfrm_pr_err(dev,
1307 "cannot register ISR for IRQ %s, too many ISRs already registered\n",
1312 pdata->irq_handlers[slot].isr = isr;
1314 pdata->irq_handlers[slot].mis = -EINVAL;
1315 skip_request_irq = true;
1317 pdata->irq_handlers[slot].mis = mis;
1322 cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
1326 const char *cif_isp10_pltfrm_get_device_type(
1329 return dev->of_node->type;
1332 const char *cif_isp10_pltfrm_dev_string(
1335 return dev_driver_string(dev);
1338 int cif_isp10_pltfrm_get_img_src_device(
1340 struct cif_isp10_img_src **img_src_array,
1341 unsigned int array_len)
1343 struct device_node *node = NULL;
1344 struct device_node *camera_list_node = NULL;
1345 struct i2c_client *client = NULL;
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);
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");
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");
1368 for (index = 0; index < size / sizeof(*phandle); index++) {
1369 camera_list_node = of_parse_phandle(node,
1370 "rockchip,camera-modules-attached", index);
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",
1380 if (!strcmp(camera_list_node->type,
1381 "v4l2-i2c-subdev")) {
1382 client = of_find_i2c_device_by_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");
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);
1398 img_src_array[num_cameras] =
1399 cif_isp10_img_src_to_img_src(
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]),
1409 if (num_cameras >= array_len) {
1410 cif_isp10_pltfrm_pr_err(dev,
1411 "cif isp10 isn't support > %d 'camera modules attached'\n",
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);
1430 void cif_isp10_pltfrm_dev_release(
1433 #ifndef CONFIG_DEBUG_FS
1435 struct cif_isp10_pltfrm_data *pdata =
1437 debugfs_remove(pdata->dbgfs.csi0_file);
1438 debugfs_remove(pdata->dbgfs.csi1_file);
1439 debugfs_remove_recursive(pdata->dbgfs.dir);