| /* |
| * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver |
| * |
| * Copyright (C) 2013 Samsung Electronics Co., Ltd. |
| * |
| * Authors: Younghwan Joo <yhwan.joo@samsung.com> |
| * Sylwester Nawrocki <s.nawrocki@samsung.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| #ifndef FIMC_IS_H_ |
| #define FIMC_IS_H_ |
| |
| #include <asm/barrier.h> |
| #include <linux/clk.h> |
| #include <linux/device.h> |
| #include <linux/kernel.h> |
| #include <linux/pinctrl/consumer.h> |
| #include <linux/platform_device.h> |
| #include <linux/sizes.h> |
| #include <linux/spinlock.h> |
| #include <linux/types.h> |
| #include <media/videobuf2-v4l2.h> |
| #include <media/v4l2-ctrls.h> |
| |
| #include "fimc-isp.h" |
| #include "fimc-is-command.h" |
| #include "fimc-is-sensor.h" |
| #include "fimc-is-param.h" |
| #include "fimc-is-regs.h" |
| |
| #define FIMC_IS_DRV_NAME "exynos4-fimc-is" |
| |
| #define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" |
| #define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" |
| |
| #define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ |
| #define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ |
| |
| #define FIMC_IS_SENSORS_NUM 2 |
| |
| /* Memory definitions */ |
| #define FIMC_IS_CPU_MEM_SIZE (0xa00000) |
| #define FIMC_IS_CPU_BASE_MASK ((1 << 26) - 1) |
| #define FIMC_IS_REGION_SIZE 0x5000 |
| |
| #define FIMC_IS_DEBUG_REGION_OFFSET 0x0084b000 |
| #define FIMC_IS_SHARED_REGION_OFFSET 0x008c0000 |
| #define FIMC_IS_FW_INFO_LEN 31 |
| #define FIMC_IS_FW_VER_LEN 7 |
| #define FIMC_IS_FW_DESC_LEN (FIMC_IS_FW_INFO_LEN + \ |
| FIMC_IS_FW_VER_LEN) |
| #define FIMC_IS_SETFILE_INFO_LEN 39 |
| |
| #define FIMC_IS_EXTRA_MEM_SIZE (FIMC_IS_EXTRA_FW_SIZE + \ |
| FIMC_IS_EXTRA_SETFILE_SIZE + 0x1000) |
| #define FIMC_IS_EXTRA_FW_SIZE 0x180000 |
| #define FIMC_IS_EXTRA_SETFILE_SIZE 0x4b000 |
| |
| /* TODO: revisit */ |
| #define FIMC_IS_FW_ADDR_MASK ((1 << 26) - 1) |
| #define FIMC_IS_FW_SIZE_MAX (SZ_4M) |
| #define FIMC_IS_FW_SIZE_MIN (SZ_32K) |
| |
| #define ATCLK_MCUISP_FREQUENCY 100000000UL |
| #define ACLK_AXI_FREQUENCY 100000000UL |
| |
| enum { |
| ISS_CLK_PPMUISPX, |
| ISS_CLK_PPMUISPMX, |
| ISS_CLK_LITE0, |
| ISS_CLK_LITE1, |
| ISS_CLK_MPLL, |
| ISS_CLK_ISP, |
| ISS_CLK_DRC, |
| ISS_CLK_FD, |
| ISS_CLK_MCUISP, |
| ISS_CLK_UART, |
| ISS_GATE_CLKS_MAX, |
| ISS_CLK_ISP_DIV0 = ISS_GATE_CLKS_MAX, |
| ISS_CLK_ISP_DIV1, |
| ISS_CLK_MCUISP_DIV0, |
| ISS_CLK_MCUISP_DIV1, |
| ISS_CLK_ACLK200, |
| ISS_CLK_ACLK200_DIV, |
| ISS_CLK_ACLK400MCUISP, |
| ISS_CLK_ACLK400MCUISP_DIV, |
| ISS_CLKS_MAX |
| }; |
| |
| /* The driver's internal state flags */ |
| enum { |
| IS_ST_IDLE, |
| IS_ST_PWR_ON, |
| IS_ST_A5_PWR_ON, |
| IS_ST_FW_LOADED, |
| IS_ST_OPEN_SENSOR, |
| IS_ST_SETFILE_LOADED, |
| IS_ST_INIT_DONE, |
| IS_ST_STREAM_ON, |
| IS_ST_STREAM_OFF, |
| IS_ST_CHANGE_MODE, |
| IS_ST_BLOCK_CMD_CLEARED, |
| IS_ST_SET_ZOOM, |
| IS_ST_PWR_SUBIP_ON, |
| IS_ST_END, |
| }; |
| |
| enum af_state { |
| FIMC_IS_AF_IDLE = 0, |
| FIMC_IS_AF_SETCONFIG = 1, |
| FIMC_IS_AF_RUNNING = 2, |
| FIMC_IS_AF_LOCK = 3, |
| FIMC_IS_AF_ABORT = 4, |
| FIMC_IS_AF_FAILED = 5, |
| }; |
| |
| enum af_lock_state { |
| FIMC_IS_AF_UNLOCKED = 0, |
| FIMC_IS_AF_LOCKED = 2 |
| }; |
| |
| enum ae_lock_state { |
| FIMC_IS_AE_UNLOCKED = 0, |
| FIMC_IS_AE_LOCKED = 1 |
| }; |
| |
| enum awb_lock_state { |
| FIMC_IS_AWB_UNLOCKED = 0, |
| FIMC_IS_AWB_LOCKED = 1 |
| }; |
| |
| enum { |
| IS_METERING_CONFIG_CMD, |
| IS_METERING_CONFIG_WIN_POS_X, |
| IS_METERING_CONFIG_WIN_POS_Y, |
| IS_METERING_CONFIG_WIN_WIDTH, |
| IS_METERING_CONFIG_WIN_HEIGHT, |
| IS_METERING_CONFIG_MAX |
| }; |
| |
| struct is_setfile { |
| const struct firmware *info; |
| int state; |
| u32 sub_index; |
| u32 base; |
| size_t size; |
| }; |
| |
| struct is_fd_result_header { |
| u32 offset; |
| u32 count; |
| u32 index; |
| u32 curr_index; |
| u32 width; |
| u32 height; |
| }; |
| |
| struct is_af_info { |
| u16 mode; |
| u32 af_state; |
| u32 af_lock_state; |
| u32 ae_lock_state; |
| u32 awb_lock_state; |
| u16 pos_x; |
| u16 pos_y; |
| u16 prev_pos_x; |
| u16 prev_pos_y; |
| u16 use_af; |
| }; |
| |
| struct fimc_is_firmware { |
| const struct firmware *f_w; |
| |
| dma_addr_t paddr; |
| void *vaddr; |
| unsigned int size; |
| |
| char info[FIMC_IS_FW_INFO_LEN + 1]; |
| char version[FIMC_IS_FW_VER_LEN + 1]; |
| char setfile_info[FIMC_IS_SETFILE_INFO_LEN + 1]; |
| u8 state; |
| }; |
| |
| struct fimc_is_memory { |
| /* physical base address */ |
| dma_addr_t paddr; |
| /* virtual base address */ |
| void *vaddr; |
| /* total length */ |
| unsigned int size; |
| }; |
| |
| #define FIMC_IS_I2H_MAX_ARGS 12 |
| |
| struct i2h_cmd { |
| u32 cmd; |
| u32 sensor_id; |
| u16 num_args; |
| u32 args[FIMC_IS_I2H_MAX_ARGS]; |
| }; |
| |
| struct h2i_cmd { |
| u16 cmd_type; |
| u32 entry_id; |
| }; |
| |
| #define FIMC_IS_DEBUG_MSG 0x3f |
| #define FIMC_IS_DEBUG_LEVEL 3 |
| |
| struct fimc_is_setfile { |
| const struct firmware *info; |
| unsigned int state; |
| unsigned int size; |
| u32 sub_index; |
| u32 base; |
| }; |
| |
| struct chain_config { |
| struct global_param global; |
| struct sensor_param sensor; |
| struct isp_param isp; |
| struct drc_param drc; |
| struct fd_param fd; |
| |
| unsigned long p_region_index[2]; |
| }; |
| |
| /** |
| * struct fimc_is - fimc-is data structure |
| * @pdev: pointer to FIMC-IS platform device |
| * @pctrl: pointer to pinctrl structure for this device |
| * @v4l2_dev: pointer to top the level v4l2_device |
| * @alloc_ctx: videobuf2 memory allocator context |
| * @lock: mutex serializing video device and the subdev operations |
| * @slock: spinlock protecting this data structure and the hw registers |
| * @clocks: FIMC-LITE gate clock |
| * @regs: MCUCTL mmapped registers region |
| * @pmu_regs: PMU ISP mmapped registers region |
| * @irq_queue: interrupt handling waitqueue |
| * @lpm: low power mode flag |
| * @state: internal driver's state flags |
| */ |
| struct fimc_is { |
| struct platform_device *pdev; |
| struct pinctrl *pctrl; |
| struct v4l2_device *v4l2_dev; |
| |
| struct fimc_is_firmware fw; |
| struct fimc_is_memory memory; |
| struct firmware *f_w; |
| |
| struct fimc_isp isp; |
| struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM]; |
| struct fimc_is_setfile setfile; |
| |
| struct vb2_alloc_ctx *alloc_ctx; |
| struct v4l2_ctrl_handler ctrl_handler; |
| |
| struct mutex lock; |
| spinlock_t slock; |
| |
| struct clk *clocks[ISS_CLKS_MAX]; |
| void __iomem *regs; |
| void __iomem *pmu_regs; |
| int irq; |
| wait_queue_head_t irq_queue; |
| u8 lpm; |
| |
| unsigned long state; |
| unsigned int sensor_index; |
| |
| struct i2h_cmd i2h_cmd; |
| struct h2i_cmd h2i_cmd; |
| struct is_fd_result_header fd_header; |
| |
| struct chain_config config[IS_SC_MAX]; |
| unsigned config_index; |
| |
| struct is_region *is_p_region; |
| dma_addr_t is_dma_p_region; |
| struct is_share_region *is_shared_region; |
| struct is_af_info af; |
| |
| struct dentry *debugfs_entry; |
| }; |
| |
| static inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp) |
| { |
| return container_of(isp, struct fimc_is, isp); |
| } |
| |
| static inline struct chain_config *__get_curr_is_config(struct fimc_is *is) |
| { |
| return &is->config[is->config_index]; |
| } |
| |
| static inline void fimc_is_mem_barrier(void) |
| { |
| mb(); |
| } |
| |
| static inline void fimc_is_set_param_bit(struct fimc_is *is, int num) |
| { |
| struct chain_config *cfg = &is->config[is->config_index]; |
| |
| set_bit(num, &cfg->p_region_index[0]); |
| } |
| |
| static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) |
| { |
| is->is_p_region->parameter.isp.control.cmd = cmd; |
| } |
| |
| static inline void mcuctl_write(u32 v, struct fimc_is *is, unsigned int offset) |
| { |
| writel(v, is->regs + offset); |
| } |
| |
| static inline u32 mcuctl_read(struct fimc_is *is, unsigned int offset) |
| { |
| return readl(is->regs + offset); |
| } |
| |
| static inline void pmuisp_write(u32 v, struct fimc_is *is, unsigned int offset) |
| { |
| writel(v, is->pmu_regs + offset); |
| } |
| |
| static inline u32 pmuisp_read(struct fimc_is *is, unsigned int offset) |
| { |
| return readl(is->pmu_regs + offset); |
| } |
| |
| int fimc_is_wait_event(struct fimc_is *is, unsigned long bit, |
| unsigned int state, unsigned int timeout); |
| int fimc_is_cpu_set_power(struct fimc_is *is, int on); |
| int fimc_is_start_firmware(struct fimc_is *is); |
| int fimc_is_hw_initialize(struct fimc_is *is); |
| void fimc_is_log_dump(const char *level, const void *buf, size_t len); |
| |
| #endif /* FIMC_IS_H_ */ |