1 #ifndef __RKCAMSYS_INTERNAL_H__
2 #define __RKCAMSYS_INTERNAL_H__
4 #include <linux/module.h>
5 #include <linux/moduleparam.h>
6 #include <linux/init.h>
7 #include <linux/delay.h>
8 #include <linux/device.h>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/i2c.h>
14 #include <linux/interrupt.h>
15 #include <linux/errno.h>
16 #include <linux/err.h>
17 #include <linux/types.h>
18 #include <linux/proc_fs.h>
19 #include <linux/fcntl.h>
20 #include <linux/clk.h>
21 #include <linux/seq_file.h>
22 #include <linux/cdev.h>
23 #include <linux/miscdevice.h>
24 #include <linux/version.h>
25 #include <linux/device.h>
26 #include <linux/platform_device.h>
27 #include <linux/list.h>
28 #include <linux/mutex.h>
29 #include <linux/regulator/machine.h>
30 #include <linux/log2.h>
31 #include <linux/gpio.h>
32 #include <linux/rockchip/cpu.h>
33 #include <linux/rockchip/iomap.h>
34 #include <linux/rockchip/grf.h>
35 #include <asm/uaccess.h>
37 #include <linux/of_device.h>
38 #include <linux/pinctrl/consumer.h>
39 #include <linux/of_address.h>
40 #include <linux/of_irq.h>
41 #include <linux/of_gpio.h>
42 #include <linux/rockchip/cpu.h>
43 #include <media/camsys_head.h>
44 #include <linux/rockchip-iovmm.h>
47 * C A M S Y S D R I V E R V E R S I O N
52 * 1) add mipi csi phy;
54 * 1) add support cif phy for marvin;
56 * 1) add clock information in struct camsys_devio_name_s;
58 * 1) set isp clock at 32MHz;
60 * 1) iomux d0 d1 for cif phy raw10 in rk319x after i2c operated;
61 * 2) check mis value in camsys_irq_connect;
62 3) add soft rest callback;
64 1) check extdev is activate or not before delete from
65 camsys_dev active list;
67 1) fix deregister a unregister extdev oops
68 in camsys_extdev_deregister;
69 *v0.9.0: 1) set isp freq to 210M
71 1) fix camsys_i2c_write and camsys_i2c_write
72 can't support reg_size=0;
74 1) control ddr freq by marvin self other than by clk unit.
76 * 1) add flash_trigger_out control
78 * 1) add Isp_SoftRst for rk3288;
80 * 1) isp_clk 208.8M for 1lane, isp_clk 416.6M for 2lane;
82 1) mi_mis register may read erro, this may cause
83 mistaken mi frame_end irqs.
85 1) add flash_prelight control.
87 1) raise qos of isp up to the same as lcdc.
91 1) camsys_extdev_register return failed when this
92 dev_id has been registered;
93 2) add support JPG irq connect;
95 1) camsys_extdev_register return -EBUSY when this
96 dev_id has been registered;
98 1) check extdev name when dev_id has been registered;
100 1) enable or disable IOMMU just depending
101 on CONFIG_ROCKCHIP_IOMMU.
103 1) isp iommu status depend on vpu iommu status.
105 1) add flashlight RT8547 driver
106 2) support torch mode
108 1) set CONFIG_CAMSYS_DRV disable as default,
109 enable in defconfig file if needed.
111 1) vpu_node changed from "vpu_service" to "rockchip,vpu_sub"
113 1) use of_find_node_by_name to get vpu node
114 instead of of_find_compatible_node
118 1) enable aclk_rga for rk3368, otherwise,
119 isp reset will cause system halted.
121 1) dts remove aclk_rga, change aclk_isp
122 from <clk_gates17 0> to <&clk_gates16 0>.
123 2) add rl3369 pd_isp enable/disable.
125 1) GPIO(gpio7 GPIO_B5) is EBUSY
126 when register after factory reset,
127 but after power on ,it's normal.
129 1) rk3368 camera: hold vio0 noc clock during the camera work,
130 fixed isp iommu stall failed.
132 1) add isp-dvp-d4d11 iomux support.
134 1) support rk3368-sheep kernel ver4.4.
138 1) some modifications.
140 1) modify for rk3399.
142 1) modify for mipiphy hsfreqrange.
144 1) support drm iommu.
146 * 1) remove memset function wrong called code.
148 * 1) flash module exist risk, fix up it.
150 1) fix drm iommu crash.
151 if process cameraserver was died during streaming, iommu resource
152 was not released correctly. when cameraserver was recovered and
153 streaming again, iommu resource may be conflicted.
155 1) clock clk_vio0_noc would cause mipi lcdc no display on 3368h, remove it.
157 1) some log is boring, so set print level more high.
161 1) modify mipiphy_hsfreqrange for 3368.
163 1) correct mipiphy_hsfreqrange of 3368.
164 2) add csi-phy timing setting for 3368.
166 1) add reference count for marvin.
168 1) delete node in irqpool list when thread disconnect.
170 1) gpio0_D is unavailable on rk3288 with current pinctrl driver.
172 1) modify the condition of DRM iommu, which makes code more readable
173 by using of_parse_phandle to check whether the "iommus" phandle exists
174 in the isp device node.
176 #define CAMSYS_DRIVER_VERSION KERNEL_VERSION(0, 0x22, 2)
178 #define CAMSYS_PLATFORM_DRV_NAME "RockChip-CamSys"
179 #define CAMSYS_PLATFORM_MARVIN_NAME "Platform_MarvinDev"
180 #define CAMSYS_PLATFORM_CIF0_NAME "Platform_Cif0Dev"
181 #define CAMSYS_PLATFORM_CIF1_NAME "Platform_Cif1Dev"
183 #define CAMSYS_REGISTER_RES_NAME "CamSys_RegMem"
184 #define CAMSYS_REGISTER_MIPIPHY_RES_NAME "CamSys_RegMem_MipiPhy"
185 #define CAMSYS_IRQ_RES_NAME "CamSys_Irq"
187 #define CAMSYS_REGISTER_MEM_NAME CAMSYS_REGISTER_RES_NAME
188 #define CAMSYS_I2C_MEM_NAME "CamSys_I2cMem"
189 #define CAMSYS_MIPIPHY_MEM_NAME \
190 CAMSYS_REGISTER_MIPIPHY_RES_NAME
192 #define CAMSYS_NAMELEN_MIN(a) \
193 ((strlen(a) > (CAMSYS_NAME_LEN-1))?(CAMSYS_NAME_LEN-1):strlen(a))
194 #define CAMSYS_IRQPOOL_NUM 128
195 #define CAMSYS_DMA_BUF_MAX_NUM 32
197 extern unsigned int camsys_debug;
199 #define camsys_trace(level, msg, ...) \
201 if (camsys_debug >= level) \
202 printk("D%d:%s(%d): " msg "\n", level,\
203 __FUNCTION__, __LINE__, ## __VA_ARGS__); \
206 #define camsys_warn(msg, ...) \
207 printk(KERN_ERR "W:%s(%d): " msg "\n", __FUNCTION__,\
208 __LINE__, ## __VA_ARGS__)
209 #define camsys_err(msg, ...) \
210 printk(KERN_ERR "E:%s(%d): " msg "\n", __FUNCTION__,\
211 __LINE__, ## __VA_ARGS__)
213 typedef struct camsys_irqstas_s {
215 struct list_head list;
218 typedef struct camsys_irqpool_s {
220 unsigned int timeout;/* us */
223 spinlock_t lock;/* lock for list */
224 camsys_irqstas_t pool[CAMSYS_IRQPOOL_NUM];
225 struct list_head active;
226 struct list_head deactive;
228 struct list_head list;
230 wait_queue_head_t done;
233 typedef struct camsys_irq_s {
235 /* lock for timeout and irq_connect in ioctl */
237 struct list_head irq_pool;
240 typedef struct camsys_meminfo_s {
241 unsigned char name[32];
242 unsigned long phy_base;
243 unsigned long vir_base;
246 struct list_head list;
249 typedef struct camsys_devmems_s {
250 camsys_meminfo_t *registermem;
251 camsys_meminfo_t *i2cmem;
252 struct list_head memslist;
255 typedef struct camsys_regulator_s {
256 struct regulator *ldo;
259 } camsys_regulator_t;
261 typedef struct camsys_gpio_s {
265 typedef struct camsys_flash_s {
270 typedef struct camsys_extdev_s {
271 unsigned char dev_name[CAMSYS_NAME_LEN];
273 camsys_regulator_t avdd;
274 camsys_regulator_t dovdd;
275 camsys_regulator_t dvdd;
276 camsys_regulator_t afvdd;
280 camsys_gpio_t afpwrdn;
283 camsys_extdev_phy_t phy;
284 camsys_extdev_clk_t clk;
285 unsigned int dev_cfg;
286 struct platform_device *pdev;
287 struct list_head list;
288 struct list_head active;
291 typedef struct camsys_phyinfo_s {
294 camsys_meminfo_t *reg;
295 int (*clkin_cb)(void *ptr, unsigned int on);
296 int (*ops)(void *ptr, camsys_mipiphy_t *phy);
297 int (*remove)(struct platform_device *pdev);
300 typedef struct camsys_exdevs_s {
302 struct list_head list;
303 struct list_head active;
306 typedef struct camsys_dma_buf_s {
307 struct dma_buf *dma_buf;
308 struct dma_buf_attachment *attach;
309 struct sg_table *sgt;
314 typedef struct camsys_dev_s {
317 camsys_devmems_t devmems;
318 struct miscdevice miscdev;
320 camsys_phyinfo_t *mipiphy;
321 camsys_phyinfo_t cifphy;
323 camsys_exdevs_t extdevs;
324 struct list_head list;
325 struct platform_device *pdev;
329 camsys_meminfo_t *csiphy_reg;
330 camsys_meminfo_t *dsiphy_reg;
331 camsys_meminfo_t *isp0_reg;
333 unsigned long rk_grf_base;
334 unsigned long rk_cru_base;
335 unsigned long rk_isp_base;
337 struct iommu_domain *domain;
338 camsys_dma_buf_t dma_buf[CAMSYS_DMA_BUF_MAX_NUM];
341 int (*clkin_cb)(void *ptr, unsigned int on);
342 int (*clkout_cb)(void *ptr, unsigned int on, unsigned int clk);
343 int (*reset_cb)(void *ptr, unsigned int on);
346 (camsys_extdev_t *extdev,
347 camsys_sysctrl_t *devctl, void *ptr);
348 int (*iomux)(camsys_extdev_t *extdev, void *ptr);
349 int (*platform_remove)(struct platform_device *pdev);
350 int (*flash_trigger_cb)(void *ptr, int mode, unsigned int on);
351 int (*iommu_cb)(void *ptr, camsys_sysctrl_t *devctl);
355 static inline camsys_extdev_t *camsys_find_extdev(
356 unsigned int dev_id, camsys_dev_t *camsys_dev)
358 camsys_extdev_t *extdev = NULL;
360 if (!list_empty(&camsys_dev->extdevs.list)) {
361 list_for_each_entry(extdev,
362 &camsys_dev->extdevs.list, list) {
363 if (extdev->dev_id == dev_id) {
371 static inline camsys_meminfo_t *camsys_find_devmem(
372 char *name, camsys_dev_t *camsys_dev)
374 camsys_meminfo_t *devmem;
376 if (!list_empty(&camsys_dev->devmems.memslist)) {
377 list_for_each_entry(devmem,
378 &camsys_dev->devmems.memslist, list) {
379 if (strcmp(devmem->name, name) == 0) {
384 camsys_err("%s memory have not been find in %s!",
385 name, dev_name(camsys_dev->miscdev.this_device));
389 static inline int camsys_sysctl_extdev(
390 camsys_extdev_t *extdev, camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
393 camsys_regulator_t *regulator;
396 if ((devctl->ops > CamSys_Vdd_Start_Tag) &&
397 (devctl->ops < CamSys_Vdd_End_Tag)) {
398 regulator = &extdev->avdd;
399 regulator += devctl->ops-1;
401 if (!IS_ERR_OR_NULL(regulator->ldo)) {
403 err = regulator_set_voltage(
404 regulator->ldo, regulator->min_uv,
406 err |= regulator_enable(regulator->ldo);
408 "Sysctl %d success, regulator set (%d,%d) uv!",
409 devctl->ops, regulator->min_uv,
412 while (regulator_is_enabled(regulator->ldo) > 0)
413 regulator_disable(regulator->ldo);
415 "Sysctl %d success, regulator off!",
422 } else if ((devctl->ops > CamSys_Gpio_Start_Tag) &&
423 (devctl->ops < CamSys_Gpio_End_Tag)) {
424 gpio = &extdev->pwrdn;
425 gpio += devctl->ops - CamSys_Gpio_Start_Tag -1;
427 if (gpio->io != 0xffffffff) {
429 gpio_direction_output(gpio->io, gpio->active);
430 gpio_set_value(gpio->io, gpio->active);
432 "Sysctl %d success, gpio(%d) set %d",
433 devctl->ops, gpio->io, gpio->active);
435 gpio_direction_output(gpio->io, !gpio->active);
436 gpio_set_value(gpio->io, !gpio->active);
438 "Sysctl %d success, gpio(%d) set %d",
439 devctl->ops, gpio->io, !gpio->active);
442 camsys_trace(1, "Sysctl %d not do, because gpio is NULL",
447 } else if (devctl->ops == CamSys_ClkIn) {
448 if (camsys_dev->clkout_cb)
449 camsys_dev->clkout_cb
450 (camsys_dev, devctl->on,
451 extdev->clk.in_rate);
452 } else if (devctl->ops == CamSys_Phy) {
453 if (camsys_dev->phy_cb)
463 extern struct file_operations camsys_fops;