summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-05-31 05:11:46 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-05-31 05:11:45 -0700
commitc0a42ee0ed459c22d980d9bf706775ab987e378e (patch)
tree1d12c1ac0600ab97b9edc02318ffd3c69194730f
parentcbeccf228abd4fd10290cb0b54aba18b57322628 (diff)
parent1fb990c0b39798179bbc4ab8ebf4a8eb857e1d60 (diff)
Merge "adv7481: Add support for AVI Infoframe"
-rw-r--r--drivers/media/i2c/adv7481.c114
-rw-r--r--drivers/media/i2c/adv7481_reg.h6
-rw-r--r--drivers/video/msm/ba/msm_ba.c18
-rw-r--r--include/uapi/media/msm_ba.h32
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