162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2013 Samsung Electronics Co., Ltd. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Younghwan Joo <yhwan.joo@samsung.com> 862306a36Sopenharmony_ci * Sylwester Nawrocki <s.nawrocki@samsung.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#ifndef FIMC_IS_H_ 1162306a36Sopenharmony_ci#define FIMC_IS_H_ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <asm/barrier.h> 1462306a36Sopenharmony_ci#include <linux/clk.h> 1562306a36Sopenharmony_ci#include <linux/device.h> 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/sizes.h> 1962306a36Sopenharmony_ci#include <linux/spinlock.h> 2062306a36Sopenharmony_ci#include <linux/types.h> 2162306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h> 2262306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "fimc-isp.h" 2562306a36Sopenharmony_ci#include "fimc-is-command.h" 2662306a36Sopenharmony_ci#include "fimc-is-sensor.h" 2762306a36Sopenharmony_ci#include "fimc-is-param.h" 2862306a36Sopenharmony_ci#include "fimc-is-regs.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define FIMC_IS_DRV_NAME "exynos4-fimc-is" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" 3362306a36Sopenharmony_ci#define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ 3662306a36Sopenharmony_ci#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define FIMC_IS_SENSORS_NUM 2 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* Memory definitions */ 4162306a36Sopenharmony_ci#define FIMC_IS_CPU_MEM_SIZE (0xa00000) 4262306a36Sopenharmony_ci#define FIMC_IS_CPU_BASE_MASK ((1 << 26) - 1) 4362306a36Sopenharmony_ci#define FIMC_IS_REGION_SIZE 0x5000 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define FIMC_IS_DEBUG_REGION_OFFSET 0x0084b000 4662306a36Sopenharmony_ci#define FIMC_IS_SHARED_REGION_OFFSET 0x008c0000 4762306a36Sopenharmony_ci#define FIMC_IS_FW_INFO_LEN 31 4862306a36Sopenharmony_ci#define FIMC_IS_FW_VER_LEN 7 4962306a36Sopenharmony_ci#define FIMC_IS_FW_DESC_LEN (FIMC_IS_FW_INFO_LEN + \ 5062306a36Sopenharmony_ci FIMC_IS_FW_VER_LEN) 5162306a36Sopenharmony_ci#define FIMC_IS_SETFILE_INFO_LEN 39 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define FIMC_IS_EXTRA_MEM_SIZE (FIMC_IS_EXTRA_FW_SIZE + \ 5462306a36Sopenharmony_ci FIMC_IS_EXTRA_SETFILE_SIZE + 0x1000) 5562306a36Sopenharmony_ci#define FIMC_IS_EXTRA_FW_SIZE 0x180000 5662306a36Sopenharmony_ci#define FIMC_IS_EXTRA_SETFILE_SIZE 0x4b000 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* TODO: revisit */ 5962306a36Sopenharmony_ci#define FIMC_IS_FW_ADDR_MASK ((1 << 26) - 1) 6062306a36Sopenharmony_ci#define FIMC_IS_FW_SIZE_MAX (SZ_4M) 6162306a36Sopenharmony_ci#define FIMC_IS_FW_SIZE_MIN (SZ_32K) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define ATCLK_MCUISP_FREQUENCY 100000000UL 6462306a36Sopenharmony_ci#define ACLK_AXI_FREQUENCY 100000000UL 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cienum { 6762306a36Sopenharmony_ci ISS_CLK_PPMUISPX, 6862306a36Sopenharmony_ci ISS_CLK_PPMUISPMX, 6962306a36Sopenharmony_ci ISS_CLK_LITE0, 7062306a36Sopenharmony_ci ISS_CLK_LITE1, 7162306a36Sopenharmony_ci ISS_CLK_MPLL, 7262306a36Sopenharmony_ci ISS_CLK_ISP, 7362306a36Sopenharmony_ci ISS_CLK_DRC, 7462306a36Sopenharmony_ci ISS_CLK_FD, 7562306a36Sopenharmony_ci ISS_CLK_MCUISP, 7662306a36Sopenharmony_ci ISS_CLK_GICISP, 7762306a36Sopenharmony_ci ISS_CLK_PWM_ISP, 7862306a36Sopenharmony_ci ISS_CLK_MCUCTL_ISP, 7962306a36Sopenharmony_ci ISS_CLK_UART, 8062306a36Sopenharmony_ci ISS_GATE_CLKS_MAX, 8162306a36Sopenharmony_ci ISS_CLK_ISP_DIV0 = ISS_GATE_CLKS_MAX, 8262306a36Sopenharmony_ci ISS_CLK_ISP_DIV1, 8362306a36Sopenharmony_ci ISS_CLK_MCUISP_DIV0, 8462306a36Sopenharmony_ci ISS_CLK_MCUISP_DIV1, 8562306a36Sopenharmony_ci ISS_CLK_ACLK200, 8662306a36Sopenharmony_ci ISS_CLK_ACLK200_DIV, 8762306a36Sopenharmony_ci ISS_CLK_ACLK400MCUISP, 8862306a36Sopenharmony_ci ISS_CLK_ACLK400MCUISP_DIV, 8962306a36Sopenharmony_ci ISS_CLKS_MAX 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* The driver's internal state flags */ 9362306a36Sopenharmony_cienum { 9462306a36Sopenharmony_ci IS_ST_IDLE, 9562306a36Sopenharmony_ci IS_ST_PWR_ON, 9662306a36Sopenharmony_ci IS_ST_A5_PWR_ON, 9762306a36Sopenharmony_ci IS_ST_FW_LOADED, 9862306a36Sopenharmony_ci IS_ST_OPEN_SENSOR, 9962306a36Sopenharmony_ci IS_ST_SETFILE_LOADED, 10062306a36Sopenharmony_ci IS_ST_INIT_DONE, 10162306a36Sopenharmony_ci IS_ST_STREAM_ON, 10262306a36Sopenharmony_ci IS_ST_STREAM_OFF, 10362306a36Sopenharmony_ci IS_ST_CHANGE_MODE, 10462306a36Sopenharmony_ci IS_ST_BLOCK_CMD_CLEARED, 10562306a36Sopenharmony_ci IS_ST_SET_ZOOM, 10662306a36Sopenharmony_ci IS_ST_PWR_SUBIP_ON, 10762306a36Sopenharmony_ci IS_ST_END, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cienum af_state { 11162306a36Sopenharmony_ci FIMC_IS_AF_IDLE = 0, 11262306a36Sopenharmony_ci FIMC_IS_AF_SETCONFIG = 1, 11362306a36Sopenharmony_ci FIMC_IS_AF_RUNNING = 2, 11462306a36Sopenharmony_ci FIMC_IS_AF_LOCK = 3, 11562306a36Sopenharmony_ci FIMC_IS_AF_ABORT = 4, 11662306a36Sopenharmony_ci FIMC_IS_AF_FAILED = 5, 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cienum af_lock_state { 12062306a36Sopenharmony_ci FIMC_IS_AF_UNLOCKED = 0, 12162306a36Sopenharmony_ci FIMC_IS_AF_LOCKED = 2 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cienum ae_lock_state { 12562306a36Sopenharmony_ci FIMC_IS_AE_UNLOCKED = 0, 12662306a36Sopenharmony_ci FIMC_IS_AE_LOCKED = 1 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cienum awb_lock_state { 13062306a36Sopenharmony_ci FIMC_IS_AWB_UNLOCKED = 0, 13162306a36Sopenharmony_ci FIMC_IS_AWB_LOCKED = 1 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cienum { 13562306a36Sopenharmony_ci IS_METERING_CONFIG_CMD, 13662306a36Sopenharmony_ci IS_METERING_CONFIG_WIN_POS_X, 13762306a36Sopenharmony_ci IS_METERING_CONFIG_WIN_POS_Y, 13862306a36Sopenharmony_ci IS_METERING_CONFIG_WIN_WIDTH, 13962306a36Sopenharmony_ci IS_METERING_CONFIG_WIN_HEIGHT, 14062306a36Sopenharmony_ci IS_METERING_CONFIG_MAX 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistruct is_setfile { 14462306a36Sopenharmony_ci const struct firmware *info; 14562306a36Sopenharmony_ci int state; 14662306a36Sopenharmony_ci u32 sub_index; 14762306a36Sopenharmony_ci u32 base; 14862306a36Sopenharmony_ci size_t size; 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistruct is_fd_result_header { 15262306a36Sopenharmony_ci u32 offset; 15362306a36Sopenharmony_ci u32 count; 15462306a36Sopenharmony_ci u32 index; 15562306a36Sopenharmony_ci u32 curr_index; 15662306a36Sopenharmony_ci u32 width; 15762306a36Sopenharmony_ci u32 height; 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistruct is_af_info { 16162306a36Sopenharmony_ci u16 mode; 16262306a36Sopenharmony_ci u32 af_state; 16362306a36Sopenharmony_ci u32 af_lock_state; 16462306a36Sopenharmony_ci u32 ae_lock_state; 16562306a36Sopenharmony_ci u32 awb_lock_state; 16662306a36Sopenharmony_ci u16 pos_x; 16762306a36Sopenharmony_ci u16 pos_y; 16862306a36Sopenharmony_ci u16 prev_pos_x; 16962306a36Sopenharmony_ci u16 prev_pos_y; 17062306a36Sopenharmony_ci u16 use_af; 17162306a36Sopenharmony_ci}; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistruct fimc_is_firmware { 17462306a36Sopenharmony_ci const struct firmware *f_w; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci dma_addr_t addr; 17762306a36Sopenharmony_ci void *vaddr; 17862306a36Sopenharmony_ci unsigned int size; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci char info[FIMC_IS_FW_INFO_LEN + 1]; 18162306a36Sopenharmony_ci char version[FIMC_IS_FW_VER_LEN + 1]; 18262306a36Sopenharmony_ci char setfile_info[FIMC_IS_SETFILE_INFO_LEN + 1]; 18362306a36Sopenharmony_ci u8 state; 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistruct fimc_is_memory { 18762306a36Sopenharmony_ci /* DMA base address */ 18862306a36Sopenharmony_ci dma_addr_t addr; 18962306a36Sopenharmony_ci /* virtual base address */ 19062306a36Sopenharmony_ci void *vaddr; 19162306a36Sopenharmony_ci /* total length */ 19262306a36Sopenharmony_ci unsigned int size; 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#define FIMC_IS_I2H_MAX_ARGS 12 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistruct i2h_cmd { 19862306a36Sopenharmony_ci u32 cmd; 19962306a36Sopenharmony_ci u32 sensor_id; 20062306a36Sopenharmony_ci u16 num_args; 20162306a36Sopenharmony_ci u32 args[FIMC_IS_I2H_MAX_ARGS]; 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistruct h2i_cmd { 20562306a36Sopenharmony_ci u16 cmd_type; 20662306a36Sopenharmony_ci u32 entry_id; 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define FIMC_IS_DEBUG_MSG 0x3f 21062306a36Sopenharmony_ci#define FIMC_IS_DEBUG_LEVEL 3 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistruct fimc_is_setfile { 21362306a36Sopenharmony_ci const struct firmware *info; 21462306a36Sopenharmony_ci unsigned int state; 21562306a36Sopenharmony_ci unsigned int size; 21662306a36Sopenharmony_ci u32 sub_index; 21762306a36Sopenharmony_ci u32 base; 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistruct chain_config { 22162306a36Sopenharmony_ci struct global_param global; 22262306a36Sopenharmony_ci struct sensor_param sensor; 22362306a36Sopenharmony_ci struct isp_param isp; 22462306a36Sopenharmony_ci struct drc_param drc; 22562306a36Sopenharmony_ci struct fd_param fd; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci unsigned long p_region_index[2]; 22862306a36Sopenharmony_ci}; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/** 23162306a36Sopenharmony_ci * struct fimc_is - fimc-is data structure 23262306a36Sopenharmony_ci * @pdev: pointer to FIMC-IS platform device 23362306a36Sopenharmony_ci * @v4l2_dev: pointer to the top level v4l2_device 23462306a36Sopenharmony_ci * @fw: data structure describing the FIMC-IS firmware binary 23562306a36Sopenharmony_ci * @memory: memory region assigned for the FIMC-IS (firmware) 23662306a36Sopenharmony_ci * @isp: the ISP block data structure 23762306a36Sopenharmony_ci * @sensor: fimc-is sensor subdevice array 23862306a36Sopenharmony_ci * @setfile: descriptor of the imaging pipeline calibration data 23962306a36Sopenharmony_ci * @ctrl_handler: the v4l2 controls handler 24062306a36Sopenharmony_ci * @lock: mutex serializing video device and the subdev operations 24162306a36Sopenharmony_ci * @slock: spinlock protecting this data structure and the hw registers 24262306a36Sopenharmony_ci * @clocks: FIMC-LITE gate clock 24362306a36Sopenharmony_ci * @regs: MCUCTL mmapped registers region 24462306a36Sopenharmony_ci * @pmu_regs: PMU ISP mmapped registers region 24562306a36Sopenharmony_ci * @irq: FIMC-IS interrupt 24662306a36Sopenharmony_ci * @irq_queue: interrupt handling waitqueue 24762306a36Sopenharmony_ci * @lpm: low power mode flag 24862306a36Sopenharmony_ci * @state: internal driver's state flags 24962306a36Sopenharmony_ci * @sensor_index: image sensor index for the firmware 25062306a36Sopenharmony_ci * @i2h_cmd: FIMC-IS to the host (CPU) mailbox command data structure 25162306a36Sopenharmony_ci * @h2i_cmd: the host (CPU) to FIMC-IS mailbox command data structure 25262306a36Sopenharmony_ci * @fd_header: the face detection result data structure 25362306a36Sopenharmony_ci * @config: shared HW pipeline configuration data 25462306a36Sopenharmony_ci * @config_index: index to the @config entry currently in use 25562306a36Sopenharmony_ci * @is_p_region: pointer to the shared parameter memory region 25662306a36Sopenharmony_ci * @is_dma_p_region: DMA address of the shared parameter memory region 25762306a36Sopenharmony_ci * @is_shared_region: pointer to the IS shared region data structure 25862306a36Sopenharmony_ci * @af: auto focus data 25962306a36Sopenharmony_ci * @debugfs_entry: debugfs entry for the firmware log 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_cistruct fimc_is { 26262306a36Sopenharmony_ci struct platform_device *pdev; 26362306a36Sopenharmony_ci struct v4l2_device *v4l2_dev; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci struct fimc_is_firmware fw; 26662306a36Sopenharmony_ci struct fimc_is_memory memory; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci struct fimc_isp isp; 26962306a36Sopenharmony_ci struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM]; 27062306a36Sopenharmony_ci struct fimc_is_setfile setfile; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci struct v4l2_ctrl_handler ctrl_handler; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci struct mutex lock; 27562306a36Sopenharmony_ci spinlock_t slock; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci struct clk *clocks[ISS_CLKS_MAX]; 27862306a36Sopenharmony_ci void __iomem *regs; 27962306a36Sopenharmony_ci void __iomem *pmu_regs; 28062306a36Sopenharmony_ci int irq; 28162306a36Sopenharmony_ci wait_queue_head_t irq_queue; 28262306a36Sopenharmony_ci u8 lpm; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci unsigned long state; 28562306a36Sopenharmony_ci unsigned int sensor_index; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci struct i2h_cmd i2h_cmd; 28862306a36Sopenharmony_ci struct h2i_cmd h2i_cmd; 28962306a36Sopenharmony_ci struct is_fd_result_header fd_header; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci struct chain_config config[IS_SC_MAX]; 29262306a36Sopenharmony_ci unsigned config_index; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci struct is_region *is_p_region; 29562306a36Sopenharmony_ci dma_addr_t is_dma_p_region; 29662306a36Sopenharmony_ci struct is_share_region *is_shared_region; 29762306a36Sopenharmony_ci struct is_af_info af; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci struct dentry *debugfs_entry; 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci return container_of(isp, struct fimc_is, isp); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic inline struct chain_config *__get_curr_is_config(struct fimc_is *is) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci return &is->config[is->config_index]; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic inline void fimc_is_mem_barrier(void) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci mb(); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic inline void fimc_is_set_param_bit(struct fimc_is *is, int num) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci struct chain_config *cfg = &is->config[is->config_index]; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci set_bit(num, &cfg->p_region_index[0]); 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci is->is_p_region->parameter.isp.control.cmd = cmd; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic inline void mcuctl_write(u32 v, struct fimc_is *is, unsigned int offset) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci writel(v, is->regs + offset); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic inline u32 mcuctl_read(struct fimc_is *is, unsigned int offset) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci return readl(is->regs + offset); 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic inline void pmuisp_write(u32 v, struct fimc_is *is, unsigned int offset) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci writel(v, is->pmu_regs + offset); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic inline u32 pmuisp_read(struct fimc_is *is, unsigned int offset) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci return readl(is->pmu_regs + offset); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciint fimc_is_wait_event(struct fimc_is *is, unsigned long bit, 35062306a36Sopenharmony_ci unsigned int state, unsigned int timeout); 35162306a36Sopenharmony_ciint fimc_is_cpu_set_power(struct fimc_is *is, int on); 35262306a36Sopenharmony_ciint fimc_is_start_firmware(struct fimc_is *is); 35362306a36Sopenharmony_ciint fimc_is_hw_initialize(struct fimc_is *is); 35462306a36Sopenharmony_civoid fimc_is_log_dump(const char *level, const void *buf, size_t len); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci#endif /* FIMC_IS_H_ */ 357