/* SPDX-License-Identifier: GPL-2.0 */ /** * Rockchip rk1608 driver * * Copyright (C) 2017-2018 Rockchip Electronics Co., Ltd. * */ #ifndef __RK1608_CORE_H__ #define __RK1608_CORE_H__ #include #include #include #include #include "rk1608_dphy.h" #define RK1608_VERSION KERNEL_VERSION(0, 0x01, 0x04) #define UPDATE_REF_DATA_FROM_EEPROM (1) #define RK1608_OP_TRY_MAX 3 #define RK1608_OP_TRY_DELAY 10 #define RK1608_CMD_WRITE 0x00000011 #define RK1608_CMD_WRITE_REG0 0X00010011 #define RK1608_CMD_WRITE_REG1 0X00020011 #define RK1608_CMD_READ 0x00000077 #define RK1608_CMD_READ_BEGIN 0x000000aa #define RK1608_CMD_QUERY 0x000000ff #define RK1608_CMD_QUERY_REG2 0x000001ff #define RK1608_STATE_ID_MASK 0xffff0000 #define RK1608_STATE_ID 0X16080000 #define RK1608_STATE_MASK 0x0000ffff #define APB_CMD_WRITE_REG1 0X00020011 #define RK1608_R_MSG_QUEUE_ADDR 0x60050000 #define RK1608_IRQ_TYPE_MSG 0x12345678 #define BOOT_REQUEST_ADDR 0x18000010 #define RK1608_HEAD_ADDR 0x60000000 #define RK1608_FW_NAME "rk1608.rkl" #define RK1608_S_MSG_QUEUE_ADDR 0x60050010 #define RK1608_PMU_SYS_REG0 0x120000f0 #define RK1608_MSG_QUEUE_OK_MASK 0xffff0001 #define RK1608_MSG_QUEUE_OK_TAG 0x16080001 #define RK1608_MAX_OP_BYTES 60000 #define MSG_SYNC_TIMEOUT 3000 #define BOOT_FLAG_CRC (0x01 << 0) #define BOOT_FLAG_EXE (0x01 << 1) #define BOOT_FLAG_LOAD_PMEM (0x01 << 2) #define BOOT_FLAG_ACK (0x01 << 3) #define BOOT_FLAG_READ_WAIT (0x01 << 4) #define BOOT_FLAG_BOOT_REQUEST (0x01 << 5) #define DEBUG_DUMP_ALL_SEND_RECV_MSG 0 #define RK1608_MCLK_RATE (24 * 1000 * 1000ul) #define SENSOR_TIMEOUT 1000 #define OPM_SLAVE_MODE 0x100000 #define RSD_SEL_2CYC 0x008000 #define DFS_SEL_16BIT 0x000002 #define SPI_CTRL0 0x11060000 #define SPI_ENR 0x11060008 #define CRUPMU_CLKSEL14_CON 0x12008098 #define PMUGRF_GPIO1A_E 0x12030040 #define PMUGRF_GPIO1B_E 0x12030044 #define BIT7_6_SEL_8MA 0xf000a000 #define BIT1_0_SEL_8MA 0x000f000a #define SPI0_PLL_SEL_APLL 0xff004000 #define INVALID_ID -1 #define RK1608_MAX_SEC_NUM 10 #define ISP_DSP_HDRAE_MAXGRIDITEMS 225 #define MIRROR_BIT_MASK BIT(0) #define FLIP_BIT_MASK BIT(1) #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MSB2LSB32 #define MSB2LSB32(x) ((((u32)(x) & 0x80808080) >> 7) | \ (((u32)(x) & 0x40404040) >> 5) | \ (((u32)(x) & 0x20202020) >> 3) | \ (((u32)(x) & 0x10101010) >> 1) | \ (((u32)(x) & 0x08080808) << 1) | \ (((u32)(x) & 0x04040404) << 3) | \ (((u32)(x) & 0x02020202) << 5) | \ (((u32)(x) & 0x01010101) << 7)) #endif struct rk1608_client_list { struct mutex mutex; /* protect clients */ struct list_head list; }; struct rk1608_state { struct v4l2_subdev sd; struct rk1608_dphy *dphy[2]; struct mutex lock; /* protect resource */ struct mutex sensor_lock; /* protect sensor */ struct mutex send_msg_lock; /* protect msg */ struct mutex spi2apb_lock; /* protect spi2apb write/read */ spinlock_t hdrae_lock; /* protect hdrae parameter */ struct gpio_desc *reset_gpio; struct gpio_desc *pwren_gpio; struct gpio_desc *irq_gpio; int irq; struct gpio_desc *wakeup_gpio; struct gpio_desc *aesync_gpio; struct v4l2_subdev *sensor[4]; struct device *dev; struct spi_device *spi; struct clk *mclk; struct miscdevice misc; struct rk1608_client_list clients; int log_level; int power_count; int msg_num; u32 link_nums; u32 sensor_cnt; u32 sensor_nums[2]; u32 msg_done[8]; wait_queue_head_t msg_wait; struct media_pad pad; struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; struct v4l2_ctrl *exposure; struct v4l2_ctrl *gain; struct v4l2_ctrl *h_flip; struct v4l2_ctrl *v_flip; struct v4l2_ctrl_handler ctrl_handler; u32 max_speed_hz; u32 min_speed_hz; struct preisp_hdrae_para_s hdrae_para; struct preisp_hdrae_exp_s hdrae_exp; u32 set_exp_cnt; const char *firm_name; u8 flip; }; struct rk1608_section { union { u32 offset; u32 wait_value; }; u32 size; union { u32 load_addr; u32 wait_addr; }; u16 wait_time; u16 timeout; u16 crc_16; u8 flag; u8 type; }; struct rk1608_header { char version[32]; u32 header_size; u32 section_count; struct rk1608_section sections[RK1608_MAX_SEC_NUM]; }; struct rk1608_boot_req { u32 flag; u32 load_addr; u32 boot_len; u8 status; u8 dummy[2]; u8 cmd; }; struct rk1608_msg_queue { u32 buf_head; /* msg buffer head */ u32 buf_tail; /* msg buffer tail */ u32 cur_send; /* current msg send position */ u32 cur_recv; /* current msg receive position */ }; enum _log_level { LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, }; struct msg { u32 size; /* unit 4 bytes */ u16 type; union { u8 camera_id; u8 core_id; } id; union { u8 sync; u8 log_level; s8 err; } mux; }; struct msg_init { struct msg msg_head; u32 i2c_bus; u32 i2c_clk; s8 in_mipi_phy; s8 out_mipi_phy; s8 mipi_lane; s8 bayer; u8 sensor_name[32]; u8 i2c_slave_addr; u8 sub_sensor_num; }; struct preisp_vc_cfg { s8 data_id; s8 decode_format; s8 flag; s8 unused; u16 width; u16 height; }; struct msg_in_size { struct msg msg_head; struct preisp_vc_cfg channel[4]; }; struct msg_out_size_head { struct msg msg_head; u16 width; u16 height; u32 mipi_clk; u16 line_length_pclk; u16 frame_length_lines; u16 mipi_lane; union { u16 flip; u16 reserved; }; }; struct msg_set_output_size { struct msg_out_size_head head; struct preisp_vc_cfg channel[4]; }; struct msg_init_dsp_time { struct msg msg_head; u16 t_ms; s32 tv_sec; s32 tv_usec; }; enum ISP_AE_Bayer_Mode_e { BAYER_MODE_MIN = 0, BAYER_MODE_BGGR = 1, BAYER_MODE_GRBG = 2, BAYER_MODE_GBRG = 3, BAYER_MODE_RGGB = 4, BAYER_MODE_MAX = 5 }; struct ISP_AE_YCOEFF_s { int rcoef; int gcoef; int bcoef; int offset; }; enum ISP_AE_Hist_Mode_e { AE_HISTSTATICMODE_INVALID = 0, AE_HISTSTATICMODE_Y, AE_HISTSTATICMODE_R, AE_HISTSTATICMODE_G, AE_HISTSTATICMODE_B, AE_HISTSTATICMODE_MAX }; enum ISP_AE_Grid_Mode_e { AE_MEASURE_GRID_INVALID = 0, AE_MEASURE_GRID_1X1, AE_MEASURE_GRID_5X5, AE_MEASURE_GRID_9X9, AE_MEASURE_GRID_15X15, AE_MEASURE_GRID_MAX }; struct ISP_DSP_hdrae_cfg_s { enum ISP_AE_Bayer_Mode_e bayer_mode; enum ISP_AE_Grid_Mode_e grid_mode; u8 weight[ISP_DSP_HDRAE_MAXGRIDITEMS]; enum ISP_AE_Hist_Mode_e hist_mode; struct ISP_AE_YCOEFF_s ycoeff; u8 imgbits; u16 width; u16 height; u16 frames; }; struct msg_set_sensor_info_s { struct msg msg_head; u32 set_exp_cnt; u16 r_gain; u16 b_gain; u16 gr_gain; u16 gb_gain; u32 exp_time[3]; u32 exp_gain[3]; u32 reg_exp_time[3]; u32 reg_exp_gain[3]; s32 lsc_table[17 * 17]; struct ISP_DSP_hdrae_cfg_s dsp_hdrae; }; struct msg_calib_temp { u32 size; // unit 4 bytes u16 type; // msg identification s8 camera_id; s8 sync; u32 temp; u32 calib_version; #if UPDATE_REF_DATA_FROM_EEPROM u32 calib_exist; u32 calib_sn_size; u32 calib_sn_offset; u8 calib_sn_code[64]; #endif }; #define MSG_RESPONSE_ID_OFFSET 0x2ff enum { /* AP -> RK1608 * 1 msg of sensor */ id_msg_init_sensor_t = 0x0001, id_msg_set_input_size_t, id_msg_set_output_size_t, id_msg_set_stream_in_on_t, id_msg_set_stream_in_off_t, id_msg_set_stream_out_on_t, id_msg_set_stream_out_off_t, /* AP -> RK1608 * 2 msg of take picture */ id_msg_take_picture_t = 0x0021, id_msg_take_picture_done_t, /* AP -> RK1608 * 3 msg of realtime parameter */ id_msg_rt_args_t = 0x0031, id_msg_set_sensor_info_t, /* AP -> RK1608 * 4 msg of power manager */ id_msg_set_sys_mode_bypass_t = 0x0200, id_msg_set_sys_mode_standby_t, id_msg_set_sys_mode_idle_enable_t, id_msg_set_sys_mode_idle_disable_t, id_msg_set_sys_mode_slave_dsp_on_t, id_msg_set_sys_mode_slave_dsp_off_t, /* AP -> RK1608 * 5 msg of debug config */ id_msg_set_log_level_t = 0x0250, /* RK1608 -> AP * 6 response of sensor msg */ id_msg_init_sensor_ret_t = 0x0300, id_msg_set_input_size_ret_t, id_msg_set_output_size_ret_t, id_msg_set_stream_in_on_ret_t, id_msg_set_stream_in_off_ret_t, id_msg_set_stream_out_on_ret_t, id_msg_set_stream_out_off_ret_t, /* RK1608 -> AP * 7 response of take picture msg */ id_msg_take_picture_ret_t = 0x0320, id_msg_take_picture_done_ret_t, /* RK1608 -> AP * 8 response of realtime parameter msg */ id_msg_rt_args_ret_t = 0x0330, /* rk1608 -> AP */ id_msg_do_i2c_t = 0x0390, /* AP -> rk1608 */ id_msg_do_i2c_ret_t, /* RK1608 -> AP * 9 msg of print log */ id_msg_rk1608_log_t = 0x0400, /* dsi2csi dump */ id_msg_dsi2sci_rgb_dump_t = 0x6000, id_msg_dsi2sci_nv12_dump_t = 0x6001, /* RK1608 -> AP * 10 msg of xfile */ /* id_msg_xfile_import_t = 0x8000 + 0x0600, * id_msg_xfile_export_t, * id_msg_xfile_mkdir_t */ /* for dsp time. */ id_msg_frame_time_t = 0x1000, id_msg_sys_time_set_t, //calib temperature and version id_msg_temperature_t = 0x1002, id_msg_temperature_req_t = 0x1302, id_msg_calib_temperature_t = 0x1004, id_msg_calib_temperature_req_t = 0x1303, id_msg_calibration_write_req_t = 0x1050, id_msg_calibration_write_done_t, id_msg_calibration_read_req_t = 0x1052, id_msg_calibration_read_done_t, id_msg_calibration_write_req_mode2_t = 0x1054, id_msg_calibration_read_req_mode2_t, id_msg_calibration_write_req_ret_t = 0x1050 + MSG_RESPONSE_ID_OFFSET, id_msg_calibration_write_done_ret_t = 0x1051 + MSG_RESPONSE_ID_OFFSET, id_msg_calibration_read_req_ret_t = 0x1052 + MSG_RESPONSE_ID_OFFSET, id_msg_calibration_read_done_ret_t = 0x1053 + MSG_RESPONSE_ID_OFFSET, /* 1808 for disp control */ id_msg_disp_set_frame_output_t = 0x1070, id_msg_disp_set_frame_format_t, id_msg_disp_set_frame_type_t, id_msg_disp_set_pro_time_t, id_msg_disp_set_pro_current_t, id_msg_disp_set_denoise_t, id_msg_disp_set_led_on_off_t, /* 0xf000 ~ 0xfdff id reversed. */ id_msg_xfile_import_t = 0xfe00, id_msg_xfile_export_t, id_msg_xfile_mkdir_t }; #define PREISP_CALIB_ITEM_NUM 24 #define PREISP_CALIB_MAGIC "#SLM_CALIB_DATA#" struct calib_item { unsigned char name[48]; unsigned int offset; unsigned int size; unsigned int temp; unsigned int crc32; }; struct calib_head { unsigned char magic[16]; unsigned int version; unsigned int head_size; unsigned int image_size; unsigned int items_number; unsigned char reserved0[32]; unsigned int hash_len; unsigned char hash[32]; unsigned char reserved1[28]; unsigned int sign_tag; unsigned int sign_len; unsigned char rsa_hash[256]; unsigned char reserved2[120]; struct calib_item item[PREISP_CALIB_ITEM_NUM]; }; #define XFILE_MAX_PATH 256 struct msg_xfile { u32 size; u16 type; s8 camera_id; union { s8 sync; s8 ret; }; u32 addr; u32 data_size; u32 cb; u32 args; char path[XFILE_MAX_PATH]; }; int rk1608_send_msg_to_dsp(struct rk1608_state *pdata, struct msg *m); /** * rk1608_write - RK1608 synchronous write * * @spi: spi device * @addr: resource address * @data: data buffer * @data_len: data buffer size, in bytes * Context: can sleep * * It returns zero on success, else a negative error code. */ int rk1608_write(struct spi_device *spi, s32 addr, const s32 *data, size_t data_len); /** * rk1608_safe_write - RK1608 synchronous write with state check * * @spi: spi device * @addr: resource address * @data: data buffer * @data_len: data buffer size, in bytes * Context: can sleep * * It returns zero on success, else operation state code. */ int rk1608_safe_write(struct rk1608_state *rk1608, struct spi_device *spi, s32 addr, const s32 *data, size_t data_len); /** * rk1608_read - RK1608 synchronous read * * @spi: spi device * @addr: resource address * @data: data buffer [out] * @data_len: data buffer size, in bytes * Context: can sleep * * It returns zero on success, else a negative error code. */ int rk1608_read(struct spi_device *spi, s32 addr, s32 *data, size_t data_len); /** * rk1608_safe_read - RK1608 synchronous read with state check * * @spi: spi device * @addr: resource address * @data: data buffer [out] * @data_len: data buffer size, in bytes * Context: can sleep * * It returns zero on success, else operation state code. */ int rk1608_safe_read(struct rk1608_state *rk1608, struct spi_device *spi, s32 addr, s32 *data, size_t data_len); /** * rk1608_operation_query - RK1608 last operation state query * * @spi: spi device * @state: last operation state [out] * Context: can sleep * * It returns zero on success, else a negative error code. */ int rk1608_operation_query(struct spi_device *spi, s32 *state); /** * rk1608_state_query - RK1608 system state query * * @spi: spi device * @state: system state [out] * Context: can sleep * * It returns zero on success, else a negative error code. */ int rk1608_state_query(struct spi_device *spi, int32_t *state); /** * rk1608_interrupt_request - RK1608 request a rk1608 interrupt * * @spi: spi device * @interrupt_num: interrupt identification * Context: can sleep * * It returns zero on success, else a negative error code. */ int rk1608_interrupt_request(struct spi_device *spi, s32 interrupt_num); /** * rk1608_download_fw: - rk1608 firmware download through spi * * @spi: spi device * @fw_name: name of firmware file, NULL for default firmware name * Context: can sleep * * It returns zero on success, else a negative error code. **/ int rk1608_download_fw(struct rk1608_state *rk1608, struct spi_device *spi, const char *fw_name); /** * rk1608_msq_recv_msg - receive a msg from RK1608 -> AP msg queue * * @spi: spi device * @m: a msg pointer buf [out] * * need call rk1608_msq_free_received_msg to free msg after msg use done * * It returns zero on success, else a negative error code. */ int rk1608_msq_recv_msg(struct rk1608_state *rk1608, struct spi_device *spi, struct msg **m); /* * rk1608_msq_send_msg - send a msg from AP -> RK1608 msg queue * * @spi: spi device * @m: a msg to send * * It returns zero on success, else a negative error code. */ int rk1608_msq_send_msg(struct rk1608_state *rk1608, struct spi_device *spi, struct msg *m); int rk1608_set_power(struct rk1608_state *pdata, int on); void rk1608_set_spi_speed(struct rk1608_state *pdata, u32 hz); int rk1608_set_log_level(struct rk1608_state *pdata, int level); int rk1608_get_dcrop_cfg(struct v4l2_rect *crop_in, struct v4l2_rect *crop_out); #endif