media: spi: update 1608 driver

1. update safe read, limit max op size.
2. add dsp time init.
3. add dsp frame control msg.
4. support flip.
5. support file export/import, calib data read/write.
6. add align calculate func.

Signed-off-by: Zhenke Fan <fanzy.fan@rock-chips.com>
Change-Id: I714aec690d00c9aa6f7f4ef58c3616bfcbf238bb
This commit is contained in:
Zhenke Fan
2020-08-25 15:09:44 +08:00
committed by Tao Huang
parent 9e8d6dd9f8
commit bb0c5d7b4b
5 changed files with 1146 additions and 17 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,9 @@
#include <linux/version.h>
#include "rk1608_dphy.h"
#define RK1608_VERSION KERNEL_VERSION(0, 0x01, 0x03)
#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
@@ -41,7 +43,7 @@
#define RK1608_MSG_QUEUE_OK_MASK 0xffff0001
#define RK1608_MSG_QUEUE_OK_TAG 0x16080001
#define RK1608_MAX_OP_BYTES 60000
#define MSG_SYNC_TIMEOUT 50
#define MSG_SYNC_TIMEOUT 3000
#define BOOT_FLAG_CRC (0x01 << 0)
#define BOOT_FLAG_EXE (0x01 << 1)
@@ -70,6 +72,9 @@
#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
@@ -99,6 +104,7 @@ struct rk1608_state {
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;
@@ -124,6 +130,8 @@ struct rk1608_state {
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;
@@ -131,6 +139,7 @@ struct rk1608_state {
struct preisp_hdrae_exp_s hdrae_exp;
u32 set_exp_cnt;
const char *firm_name;
u8 flip;
};
struct rk1608_section {
@@ -229,7 +238,10 @@ struct msg_out_size_head {
u16 line_length_pclk;
u16 frame_length_lines;
u16 mipi_lane;
u16 reserved;
union {
u16 flip;
u16 reserved;
};
};
struct msg_set_output_size {
@@ -237,6 +249,13 @@ struct msg_set_output_size {
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,
@@ -298,6 +317,25 @@ struct msg_set_sensor_info_s {
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;
u32 calib_sn_code;
#endif
};
#define MSG_RESPONSE_ID_OFFSET 0x2ff
enum {
/* AP -> RK1608
* 1 msg of sensor
@@ -376,9 +414,93 @@ enum {
/* RK1608 -> AP
* 10 msg of xfile
*/
id_msg_xfile_import_t = 0x8000 + 0x0600,
/* 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);

View File

@@ -52,6 +52,7 @@
* extra sensor,and it is passed to the Soc through ISP.
*/
static DEFINE_MUTEX(rk1608_dphy_mutex);
static inline struct rk1608_dphy *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct rk1608_dphy, sd);
@@ -248,6 +249,23 @@ static int rk1608_s_frame_interval(struct v4l2_subdev *sd,
return 0;
}
static int rk1608_g_mbus_config(struct v4l2_subdev *sd,
struct v4l2_mbus_config *config)
{
struct rk1608_dphy *pdata = to_state(sd);
u32 val = 0;
val = 1 << (pdata->fmt_inf[pdata->fmt_inf_idx].mipi_lane - 1) |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
config->type = V4L2_MBUS_CSI2;
config->flags = val;
return 0;
}
static long rk1608_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct rk1608_dphy *pdata = to_state(sd);
@@ -255,12 +273,28 @@ static long rk1608_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
switch (cmd) {
case PREISP_CMD_SAVE_HDRAE_PARAM:
ret = v4l2_subdev_call(pdata->rk1608_sd, core, ioctl,
cmd, arg);
break;
case PREISP_CMD_SET_HDRAE_EXP:
case RKMODULE_GET_MODULE_INFO:
case RKMODULE_AWB_CFG:
case PREISP_DISP_SET_FRAME_OUTPUT:
case PREISP_DISP_SET_FRAME_FORMAT:
case PREISP_DISP_SET_FRAME_TYPE:
case PREISP_DISP_SET_PRO_TIME:
case PREISP_DISP_SET_PRO_CURRENT:
case PREISP_DISP_SET_DENOISE:
case PREISP_DISP_WRITE_EEPROM:
case PREISP_DISP_READ_EEPROM:
case PREISP_DISP_SET_LED_ON_OFF:
mutex_lock(&rk1608_dphy_mutex);
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
ret = v4l2_subdev_call(pdata->rk1608_sd, core, ioctl,
cmd, arg);
return ret;
mutex_unlock(&rk1608_dphy_mutex);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -275,6 +309,7 @@ static long rk1608_compat_ioctl32(struct v4l2_subdev *sd,
void __user *up = compat_ptr(arg);
struct preisp_hdrae_exp_s hdrae_exp;
struct rkmodule_inf *inf;
struct rkmodule_awb_cfg *cfg;
long ret;
switch (cmd) {
@@ -295,6 +330,17 @@ static long rk1608_compat_ioctl32(struct v4l2_subdev *sd,
ret = copy_to_user(up, inf, sizeof(*inf));
kfree(inf);
break;
case RKMODULE_AWB_CFG:
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
ret = -ENOMEM;
return ret;
}
if (copy_from_user(cfg, up, sizeof(cfg)))
return -EFAULT;
ret = rk1608_ioctl(sd, cmd, cfg);
kfree(cfg);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -374,7 +420,7 @@ static int rk1608_initialize_controls(struct rk1608_dphy *dphy)
{
u32 i;
int ret;
s64 pixel_rate, pixel_bit;
u64 pixel_rate, pixel_bit;
u32 idx = dphy->fmt_inf_idx;
struct v4l2_ctrl_handler *handler;
unsigned long flags = V4L2_CTRL_FLAG_VOLATILE |
@@ -465,6 +511,7 @@ static const struct v4l2_subdev_video_ops rk1608_subdev_video_ops = {
.s_stream = rk1608_s_stream,
.g_frame_interval = rk1608_g_frame_interval,
.s_frame_interval = rk1608_s_frame_interval,
.g_mbus_config = rk1608_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops rk1608_subdev_pad_ops = {

View File

@@ -34,6 +34,8 @@ struct rk1608_dphy {
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 cam_nums;
@@ -53,4 +55,6 @@ struct rk1608_dphy {
u32 fmt_inf_num;
u32 fmt_inf_idx;
struct rk1608_fmt_inf fmt_inf[RK1608_MAX_FMTINF];
bool first_stream;
};

View File

@@ -19,6 +19,33 @@
#define PREISP_CMD_SAVE_HDRAE_PARAM \
_IOW('V', BASE_VIDIOC_PRIVATE + 1, struct preisp_hdrae_para_s)
#define PREISP_DISP_SET_FRAME_OUTPUT \
_IOW('V', BASE_VIDIOC_PRIVATE + 4, int)
#define PREISP_DISP_SET_FRAME_FORMAT \
_IOW('V', BASE_VIDIOC_PRIVATE + 5, unsigned int)
#define PREISP_DISP_SET_FRAME_TYPE \
_IOW('V', BASE_VIDIOC_PRIVATE + 6, unsigned int)
#define PREISP_DISP_SET_PRO_TIME \
_IOW('V', BASE_VIDIOC_PRIVATE + 7, unsigned int)
#define PREISP_DISP_SET_PRO_CURRENT \
_IOW('V', BASE_VIDIOC_PRIVATE + 8, unsigned int)
#define PREISP_DISP_SET_DENOISE \
_IOW('V', BASE_VIDIOC_PRIVATE + 9, unsigned int[2])
#define PREISP_DISP_WRITE_EEPROM \
_IO('V', BASE_VIDIOC_PRIVATE + 10)
#define PREISP_DISP_READ_EEPROM \
_IO('V', BASE_VIDIOC_PRIVATE + 11)
#define PREISP_DISP_SET_LED_ON_OFF \
_IOW('V', BASE_VIDIOC_PRIVATE + 12, unsigned int)
#define PREISP_POWER_ON _IO('p', 1)
#define PREISP_POWER_OFF _IO('p', 2)
#define PREISP_REQUEST_SLEEP _IOW('p', 3, s32)