Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0a42ee0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "adv7481: Add support for AVI Infoframe"

parents cbeccf22 1fb990c0
Loading
Loading
Loading
Loading
+102 −12
Original line number Diff line number Diff line
@@ -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"

@@ -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,
@@ -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;

+6 −0
Original line number Diff line number Diff line
@@ -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
+18 −0
Original line number Diff line number Diff line
@@ -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;
+32 −0
Original line number Diff line number Diff line
@@ -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