Loading drivers/media/i2c/adv7481.c +102 −12 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ #include "msm_camera_i2c.h" #include "msm_camera_io_util.h" #include "msm_camera_dt_util.h" #include "linux/hdmi.h" #define DRIVER_NAME "adv7481" Loading @@ -64,6 +65,9 @@ #define I2C_BLOCK_WRITE_SIZE 1024 #define ADV_REG_STABLE_DELAY 70 /* ms*/ #define AVI_INFOFRAME_SIZE 31 #define INFOFRAME_DATA_SIZE 28 enum adv7481_gpio_t { CCI_I2C_SDA = 0, Loading Loading @@ -120,6 +124,7 @@ struct adv7481_state { uint8_t i2c_csi_txa_addr; uint8_t i2c_csi_txb_addr; uint8_t i2c_hdmi_addr; uint8_t i2c_hdmi_inf_addr; uint8_t i2c_edid_addr; uint8_t i2c_cp_addr; uint8_t i2c_sdp_addr; Loading @@ -141,6 +146,9 @@ struct adv7481_state { int csib_src; int mode; /* AVI Infoframe Params */ struct avi_infoframe_params hdmi_avi_infoframe; /* resolution configuration */ struct resolution_config res_configs[RES_MAX]; Loading Loading @@ -304,6 +312,14 @@ static int32_t adv7481_cci_i2c_read(struct msm_camera_i2c_client *i2c_client, data, data_type); } static int32_t adv7481_cci_i2c_read_seq( struct msm_camera_i2c_client *i2c_client, uint8_t reg, uint8_t *data, uint32_t size) { return i2c_client->i2c_func_tbl->i2c_read_seq(i2c_client, reg, data, size); } static int32_t adv7481_wr_byte(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg, uint8_t data) { Loading Loading @@ -334,6 +350,20 @@ static int32_t adv7481_wr_block(struct msm_camera_i2c_client *c_i2c_client, return ret; } static int32_t adv7481_rd_block(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg, uint8_t *data, uint32_t size) { int ret = 0; c_i2c_client->cci_client->sid = sid; ret = adv7481_cci_i2c_read_seq(c_i2c_client, reg, data, size); if (ret < 0) pr_err("Error %d reading cci i2c block data\n", ret); return ret; } static uint8_t adv7481_rd_byte(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg) { Loading Loading @@ -392,6 +422,7 @@ static int adv7481_set_irq(struct adv7481_state *state) ADV_REG_SETFIELD(1, IO_CP_UNLOCK_CP_MB1) | ADV_REG_SETFIELD(1, IO_VMUTE_REQUEST_HDMI_MB1) | ADV_REG_SETFIELD(1, IO_INT_SD_MB1)); /* Set cable detect */ ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_LVL_INT_MASKB_3_ADDR, Loading Loading @@ -801,6 +832,7 @@ static int adv7481_dev_init(struct adv7481_state *state) state->i2c_csi_txb_addr = IO_REG_CSI_TXB_SADDR >> 1; state->i2c_cp_addr = IO_REG_CP_SADDR >> 1; state->i2c_hdmi_addr = IO_REG_HDMI_SADDR >> 1; state->i2c_hdmi_inf_addr = IO_REG_HDMI_INF_SADDR >> 1; state->i2c_edid_addr = IO_REG_EDID_SADDR >> 1; state->i2c_sdp_addr = IO_REG_SDP_SADDR >> 1; state->i2c_rep_addr = IO_REG_HDMI_REP_SADDR >> 1; Loading Loading @@ -1035,10 +1067,16 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct adv7481_vid_params vid_params; struct adv7481_hdmi_params hdmi_params; struct device *dev = state->dev; union hdmi_infoframe hdmi_info_frame; uint8_t inf_buffer[AVI_INFOFRAME_SIZE]; pr_debug("Enter %s with command: 0x%x", __func__, cmd); memset(&vid_params, 0, sizeof(struct adv7481_vid_params)); memset(&hdmi_params, 0, sizeof(struct adv7481_hdmi_params)); memset(&hdmi_info_frame, 0, sizeof(union hdmi_infoframe)); memset(inf_buffer, 0, AVI_INFOFRAME_SIZE); if (!sd) return -EINVAL; Loading Loading @@ -1091,6 +1129,58 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } break; } case VIDIOC_G_AVI_INFOFRAME: { int int_raw = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_EDG_RAW_STATUS_1_ADDR); adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_EDG_INT_CLEAR_1_ADDR, int_raw); if (ADV_REG_GETFIELD(int_raw, IO_NEW_AVI_INFO_RAW)) { inf_buffer[0] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_PACKET_ID_ADDR); inf_buffer[1] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_VERS_ADDR); inf_buffer[2] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_LEN_ADDR); ret = adv7481_rd_block(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_PB_ADDR, &inf_buffer[3], INFOFRAME_DATA_SIZE); if (ret) { pr_err("%s:Error in VIDIOC_G_AVI_INFOFRAME\n", __func__); return -EINVAL; } if (hdmi_infoframe_unpack(&hdmi_info_frame, (void *)inf_buffer) < 0) { pr_err("%s: infoframe unpack fail\n", __func__); return -EINVAL; } hdmi_infoframe_log(KERN_ERR, dev, &hdmi_info_frame); state->hdmi_avi_infoframe.picture_aspect = (enum picture_aspect_ratio) hdmi_info_frame.avi.picture_aspect; state->hdmi_avi_infoframe.active_aspect = (enum active_format_aspect_ratio) hdmi_info_frame.avi.active_aspect; state->hdmi_avi_infoframe.video_code = hdmi_info_frame.avi.video_code; } else { pr_err("%s: No new AVI Infoframe\n", __func__); } if (copy_to_user((void __user *)adv_arg.ptr, (void *)&state->hdmi_avi_infoframe, sizeof(struct avi_infoframe_params))) { pr_err("%s: Failed to copy Infoframe\n", __func__); return -EINVAL; } break; } case VIDIOC_G_FIELD_INFO: /* Select SDP read-only Map 1 */ adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, Loading Loading @@ -2628,7 +2718,7 @@ static int adv7481_probe(struct platform_device *pdev) goto err_media_entity; } enable_irq(state->irq); pr_debug("Probe successful!\n"); pr_info("ADV7481 Probe successful!\n"); return ret; Loading drivers/media/i2c/adv7481_reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,12 @@ #define HDMI_EDID_A_ENABLE_BMSK 0x0001 #define HDMI_EDID_A_ENABLE_SHFT 0 /* HDMI RX INFOFRAME Map Registers (Read Only) */ #define HDMI_REG_AVI_INF_PB_ADDR 0x00 #define HDMI_REG_AVI_PACKET_ID_ADDR 0xE0 #define HDMI_REG_AVI_INF_VERS_ADDR 0xE1 #define HDMI_REG_AVI_INF_LEN_ADDR 0xE2 /* CEC Map Registers */ #define CEC_REG_LOG_ADDR_MASK_ADDR 0x27 #define CEC_REG_LOG_ADDR_MASK2_BMSK 0x0040 Loading drivers/video/msm/ba/msm_ba.c +18 −0 Original line number Diff line number Diff line Loading @@ -574,6 +574,24 @@ long msm_ba_private_ioctl(void *instance, int cmd, void *arg) } } break; case VIDIOC_G_AVI_INFOFRAME: { dprintk(BA_DBG, "VIDIOC_G_AVI_INFOFRAME\n"); sd = inst->sd; if (!sd) { dprintk(BA_ERR, "No sd registered"); return -EINVAL; } if (arg) { rc = v4l2_subdev_call(sd, core, ioctl, cmd, arg); if (rc) dprintk(BA_ERR, "%s failed: %ld on cmd: 0x%x", __func__, rc, cmd); } else { dprintk(BA_ERR, "%s: NULL argument provided", __func__); rc = -EINVAL; } } break; case VIDIOC_G_FIELD_INFO: { dprintk(BA_DBG, "VIDIOC_G_FIELD_INFO"); sd = inst->sd; Loading include/uapi/media/msm_ba.h +32 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,35 @@ struct csi_ctrl_params { uint32_t lane_count; }; /* AVI Infoframe params */ enum picture_aspect_ratio { PICTURE_ASPECT_RATIO_NONE, PICTURE_ASPECT_RATIO_4_3, PICTURE_ASPECT_RATIO_16_9, PICTURE_ASPECT_RATIO_64_27, PICTURE_ASPECT_RATIO_256_135, PICTURE_ASPECT_RATIO_RESERVED, }; enum active_format_aspect_ratio { ACTIVE_ASPECT_RATIO_16_9_TOP = 2, ACTIVE_ASPECT_RATIO_14_9_TOP = 3, ACTIVE_ASPECT_RATIO_16_9_CENTER = 4, ACTIVE_ASPECT_RATIO_PICTURE = 8, ACTIVE_ASPECT_RATIO_4_3 = 9, ACTIVE_ASPECT_RATIO_16_9 = 10, ACTIVE_ASPECT_RATIO_14_9 = 11, ACTIVE_ASPECT_RATIO_4_3_SP_14_9 = 13, ACTIVE_ASPECT_RATIO_16_9_SP_14_9 = 14, ACTIVE_ASPECT_RATIO_16_9_SP_4_3 = 15, }; struct avi_infoframe_params { enum picture_aspect_ratio picture_aspect; enum active_format_aspect_ratio active_aspect; unsigned char video_code; }; /* Field info params */ struct field_info_params { bool even_field; Loading @@ -41,5 +70,8 @@ struct msm_ba_v4l2_ioctl_t { /* ADV7481 private ioctls for field info query */ #define VIDIOC_G_FIELD_INFO \ _IOWR('V', BASE_VIDIOC_PRIVATE + 40, struct msm_ba_v4l2_ioctl_t) /* ADV7481 private ioctl for AVI Infoframe query */ #define VIDIOC_G_AVI_INFOFRAME \ _IOWR('V', BASE_VIDIOC_PRIVATE + 41, struct msm_ba_v4l2_ioctl_t) #endif Loading
drivers/media/i2c/adv7481.c +102 −12 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ #include "msm_camera_i2c.h" #include "msm_camera_io_util.h" #include "msm_camera_dt_util.h" #include "linux/hdmi.h" #define DRIVER_NAME "adv7481" Loading @@ -64,6 +65,9 @@ #define I2C_BLOCK_WRITE_SIZE 1024 #define ADV_REG_STABLE_DELAY 70 /* ms*/ #define AVI_INFOFRAME_SIZE 31 #define INFOFRAME_DATA_SIZE 28 enum adv7481_gpio_t { CCI_I2C_SDA = 0, Loading Loading @@ -120,6 +124,7 @@ struct adv7481_state { uint8_t i2c_csi_txa_addr; uint8_t i2c_csi_txb_addr; uint8_t i2c_hdmi_addr; uint8_t i2c_hdmi_inf_addr; uint8_t i2c_edid_addr; uint8_t i2c_cp_addr; uint8_t i2c_sdp_addr; Loading @@ -141,6 +146,9 @@ struct adv7481_state { int csib_src; int mode; /* AVI Infoframe Params */ struct avi_infoframe_params hdmi_avi_infoframe; /* resolution configuration */ struct resolution_config res_configs[RES_MAX]; Loading Loading @@ -304,6 +312,14 @@ static int32_t adv7481_cci_i2c_read(struct msm_camera_i2c_client *i2c_client, data, data_type); } static int32_t adv7481_cci_i2c_read_seq( struct msm_camera_i2c_client *i2c_client, uint8_t reg, uint8_t *data, uint32_t size) { return i2c_client->i2c_func_tbl->i2c_read_seq(i2c_client, reg, data, size); } static int32_t adv7481_wr_byte(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg, uint8_t data) { Loading Loading @@ -334,6 +350,20 @@ static int32_t adv7481_wr_block(struct msm_camera_i2c_client *c_i2c_client, return ret; } static int32_t adv7481_rd_block(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg, uint8_t *data, uint32_t size) { int ret = 0; c_i2c_client->cci_client->sid = sid; ret = adv7481_cci_i2c_read_seq(c_i2c_client, reg, data, size); if (ret < 0) pr_err("Error %d reading cci i2c block data\n", ret); return ret; } static uint8_t adv7481_rd_byte(struct msm_camera_i2c_client *c_i2c_client, uint8_t sid, uint8_t reg) { Loading Loading @@ -392,6 +422,7 @@ static int adv7481_set_irq(struct adv7481_state *state) ADV_REG_SETFIELD(1, IO_CP_UNLOCK_CP_MB1) | ADV_REG_SETFIELD(1, IO_VMUTE_REQUEST_HDMI_MB1) | ADV_REG_SETFIELD(1, IO_INT_SD_MB1)); /* Set cable detect */ ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_LVL_INT_MASKB_3_ADDR, Loading Loading @@ -801,6 +832,7 @@ static int adv7481_dev_init(struct adv7481_state *state) state->i2c_csi_txb_addr = IO_REG_CSI_TXB_SADDR >> 1; state->i2c_cp_addr = IO_REG_CP_SADDR >> 1; state->i2c_hdmi_addr = IO_REG_HDMI_SADDR >> 1; state->i2c_hdmi_inf_addr = IO_REG_HDMI_INF_SADDR >> 1; state->i2c_edid_addr = IO_REG_EDID_SADDR >> 1; state->i2c_sdp_addr = IO_REG_SDP_SADDR >> 1; state->i2c_rep_addr = IO_REG_HDMI_REP_SADDR >> 1; Loading Loading @@ -1035,10 +1067,16 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct adv7481_vid_params vid_params; struct adv7481_hdmi_params hdmi_params; struct device *dev = state->dev; union hdmi_infoframe hdmi_info_frame; uint8_t inf_buffer[AVI_INFOFRAME_SIZE]; pr_debug("Enter %s with command: 0x%x", __func__, cmd); memset(&vid_params, 0, sizeof(struct adv7481_vid_params)); memset(&hdmi_params, 0, sizeof(struct adv7481_hdmi_params)); memset(&hdmi_info_frame, 0, sizeof(union hdmi_infoframe)); memset(inf_buffer, 0, AVI_INFOFRAME_SIZE); if (!sd) return -EINVAL; Loading Loading @@ -1091,6 +1129,58 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } break; } case VIDIOC_G_AVI_INFOFRAME: { int int_raw = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_EDG_RAW_STATUS_1_ADDR); adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_HDMI_EDG_INT_CLEAR_1_ADDR, int_raw); if (ADV_REG_GETFIELD(int_raw, IO_NEW_AVI_INFO_RAW)) { inf_buffer[0] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_PACKET_ID_ADDR); inf_buffer[1] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_VERS_ADDR); inf_buffer[2] = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_LEN_ADDR); ret = adv7481_rd_block(&state->i2c_client, state->i2c_hdmi_inf_addr, HDMI_REG_AVI_INF_PB_ADDR, &inf_buffer[3], INFOFRAME_DATA_SIZE); if (ret) { pr_err("%s:Error in VIDIOC_G_AVI_INFOFRAME\n", __func__); return -EINVAL; } if (hdmi_infoframe_unpack(&hdmi_info_frame, (void *)inf_buffer) < 0) { pr_err("%s: infoframe unpack fail\n", __func__); return -EINVAL; } hdmi_infoframe_log(KERN_ERR, dev, &hdmi_info_frame); state->hdmi_avi_infoframe.picture_aspect = (enum picture_aspect_ratio) hdmi_info_frame.avi.picture_aspect; state->hdmi_avi_infoframe.active_aspect = (enum active_format_aspect_ratio) hdmi_info_frame.avi.active_aspect; state->hdmi_avi_infoframe.video_code = hdmi_info_frame.avi.video_code; } else { pr_err("%s: No new AVI Infoframe\n", __func__); } if (copy_to_user((void __user *)adv_arg.ptr, (void *)&state->hdmi_avi_infoframe, sizeof(struct avi_infoframe_params))) { pr_err("%s: Failed to copy Infoframe\n", __func__); return -EINVAL; } break; } case VIDIOC_G_FIELD_INFO: /* Select SDP read-only Map 1 */ adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, Loading Loading @@ -2628,7 +2718,7 @@ static int adv7481_probe(struct platform_device *pdev) goto err_media_entity; } enable_irq(state->irq); pr_debug("Probe successful!\n"); pr_info("ADV7481 Probe successful!\n"); return ret; Loading
drivers/media/i2c/adv7481_reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,12 @@ #define HDMI_EDID_A_ENABLE_BMSK 0x0001 #define HDMI_EDID_A_ENABLE_SHFT 0 /* HDMI RX INFOFRAME Map Registers (Read Only) */ #define HDMI_REG_AVI_INF_PB_ADDR 0x00 #define HDMI_REG_AVI_PACKET_ID_ADDR 0xE0 #define HDMI_REG_AVI_INF_VERS_ADDR 0xE1 #define HDMI_REG_AVI_INF_LEN_ADDR 0xE2 /* CEC Map Registers */ #define CEC_REG_LOG_ADDR_MASK_ADDR 0x27 #define CEC_REG_LOG_ADDR_MASK2_BMSK 0x0040 Loading
drivers/video/msm/ba/msm_ba.c +18 −0 Original line number Diff line number Diff line Loading @@ -574,6 +574,24 @@ long msm_ba_private_ioctl(void *instance, int cmd, void *arg) } } break; case VIDIOC_G_AVI_INFOFRAME: { dprintk(BA_DBG, "VIDIOC_G_AVI_INFOFRAME\n"); sd = inst->sd; if (!sd) { dprintk(BA_ERR, "No sd registered"); return -EINVAL; } if (arg) { rc = v4l2_subdev_call(sd, core, ioctl, cmd, arg); if (rc) dprintk(BA_ERR, "%s failed: %ld on cmd: 0x%x", __func__, rc, cmd); } else { dprintk(BA_ERR, "%s: NULL argument provided", __func__); rc = -EINVAL; } } break; case VIDIOC_G_FIELD_INFO: { dprintk(BA_DBG, "VIDIOC_G_FIELD_INFO"); sd = inst->sd; Loading
include/uapi/media/msm_ba.h +32 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,35 @@ struct csi_ctrl_params { uint32_t lane_count; }; /* AVI Infoframe params */ enum picture_aspect_ratio { PICTURE_ASPECT_RATIO_NONE, PICTURE_ASPECT_RATIO_4_3, PICTURE_ASPECT_RATIO_16_9, PICTURE_ASPECT_RATIO_64_27, PICTURE_ASPECT_RATIO_256_135, PICTURE_ASPECT_RATIO_RESERVED, }; enum active_format_aspect_ratio { ACTIVE_ASPECT_RATIO_16_9_TOP = 2, ACTIVE_ASPECT_RATIO_14_9_TOP = 3, ACTIVE_ASPECT_RATIO_16_9_CENTER = 4, ACTIVE_ASPECT_RATIO_PICTURE = 8, ACTIVE_ASPECT_RATIO_4_3 = 9, ACTIVE_ASPECT_RATIO_16_9 = 10, ACTIVE_ASPECT_RATIO_14_9 = 11, ACTIVE_ASPECT_RATIO_4_3_SP_14_9 = 13, ACTIVE_ASPECT_RATIO_16_9_SP_14_9 = 14, ACTIVE_ASPECT_RATIO_16_9_SP_4_3 = 15, }; struct avi_infoframe_params { enum picture_aspect_ratio picture_aspect; enum active_format_aspect_ratio active_aspect; unsigned char video_code; }; /* Field info params */ struct field_info_params { bool even_field; Loading @@ -41,5 +70,8 @@ struct msm_ba_v4l2_ioctl_t { /* ADV7481 private ioctls for field info query */ #define VIDIOC_G_FIELD_INFO \ _IOWR('V', BASE_VIDIOC_PRIVATE + 40, struct msm_ba_v4l2_ioctl_t) /* ADV7481 private ioctl for AVI Infoframe query */ #define VIDIOC_G_AVI_INFOFRAME \ _IOWR('V', BASE_VIDIOC_PRIVATE + 41, struct msm_ba_v4l2_ioctl_t) #endif