diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2018-05-31 05:11:46 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-05-31 05:11:45 -0700 |
| commit | c0a42ee0ed459c22d980d9bf706775ab987e378e (patch) | |
| tree | 1d12c1ac0600ab97b9edc02318ffd3c69194730f | |
| parent | cbeccf228abd4fd10290cb0b54aba18b57322628 (diff) | |
| parent | 1fb990c0b39798179bbc4ab8ebf4a8eb857e1d60 (diff) | |
Merge "adv7481: Add support for AVI Infoframe"
| -rw-r--r-- | drivers/media/i2c/adv7481.c | 114 | ||||
| -rw-r--r-- | drivers/media/i2c/adv7481_reg.h | 6 | ||||
| -rw-r--r-- | drivers/video/msm/ba/msm_ba.c | 18 | ||||
| -rw-r--r-- | include/uapi/media/msm_ba.h | 32 |
4 files changed, 158 insertions, 12 deletions
diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 43a5f3da5ac4..19ec11174632 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -41,28 +41,32 @@ #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" -#define I2C_RW_DELAY 1 -#define I2C_SW_RST_DELAY 5000 +#define I2C_RW_DELAY 1 +#define I2C_SW_RST_DELAY 5000 #define GPIO_HW_RST_DELAY_HI 10000 #define GPIO_HW_RST_DELAY_LOW 10000 -#define SDP_MIN_SLEEP 5000 -#define SDP_MAX_SLEEP 6000 -#define SDP_NUM_TRIES 30 -#define LOCK_MIN_SLEEP 5000 -#define LOCK_MAX_SLEEP 6000 -#define LOCK_NUM_TRIES 200 +#define SDP_MIN_SLEEP 5000 +#define SDP_MAX_SLEEP 6000 +#define SDP_NUM_TRIES 30 +#define LOCK_MIN_SLEEP 5000 +#define LOCK_MAX_SLEEP 6000 +#define LOCK_NUM_TRIES 200 #define MAX_DEFAULT_WIDTH 1280 #define MAX_DEFAULT_HEIGHT 720 #define MAX_DEFAULT_FRAME_RATE 60 #define MAX_DEFAULT_PIX_CLK_HZ 74240000 -#define ONE_MHZ_TO_HZ 1000000 -#define I2C_BLOCK_WRITE_SIZE 1024 -#define ADV_REG_STABLE_DELAY 70 /* ms*/ +#define ONE_MHZ_TO_HZ 1000000 +#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 { @@ -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; @@ -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]; @@ -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) { @@ -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) { @@ -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, @@ -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; @@ -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; @@ -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, @@ -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; diff --git a/drivers/media/i2c/adv7481_reg.h b/drivers/media/i2c/adv7481_reg.h index 76c992cf4394..3d484c6d335a 100644 --- a/drivers/media/i2c/adv7481_reg.h +++ b/drivers/media/i2c/adv7481_reg.h @@ -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 diff --git a/drivers/video/msm/ba/msm_ba.c b/drivers/video/msm/ba/msm_ba.c index 95edb5bd48a9..42a737713465 100644 --- a/drivers/video/msm/ba/msm_ba.c +++ b/drivers/video/msm/ba/msm_ba.c @@ -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; diff --git a/include/uapi/media/msm_ba.h b/include/uapi/media/msm_ba.h index 933dd85bb48b..45ddfb4c8cb9 100644 --- a/include/uapi/media/msm_ba.h +++ b/include/uapi/media/msm_ba.h @@ -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; @@ -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 |
