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

Commit 7d374c04 authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

msm: mdss: hdmi: cleanup ddc usage



Check for all possible DDC errors and clear the corresponding
acknowledge bit. Properly enable or disable the DDC interrupts
based on the requirements. Optimize DDC data structure by
removing unnecessary variables and keeping different DDC related
data under common structure. Move all DDC implementations to one
place.

Change-Id: If63479d5bc263db63e62d1846ab13a2659a83a68
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 1838c9d2
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -333,6 +333,7 @@ struct hdcp_lib_handle {
	uint32_t tz_ctxhandle;
	uint32_t hdcp_timeout;
	bool no_stored_km_flag;
	bool feature_supported;
	void *client_ctx;
	struct hdcp_client_ops *client_ops;
	struct mutex hdcp_lock;
@@ -745,9 +746,15 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext)
		goto exit;
	}

	if (handle->feature_supported) {
		supported = true;
		goto exit;
	}

	rc = hdcp_lib_library_load(handle);
	if (!rc) {
		pr_debug("HDCP2p2 supported\n");
		handle->feature_supported = true;
		hdcp_lib_library_unload(handle);
		supported = true;
	}
@@ -769,7 +776,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)

	handle->wakeup_cmd = data->cmd;

	pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
	pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));

	if (data->recvd_msg_len) {
		handle->last_msg_recvd_len = data->recvd_msg_len;
+32 −9
Original line number Diff line number Diff line
@@ -366,7 +366,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.retry = 5;
	ddc_data.what = "Bcaps";
	ddc_data.no_align = true;
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);

	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
			HDCP_STATE_NAME);
@@ -529,7 +532,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.data_buf = an;
	ddc_data.data_len = 8;
	ddc_data.what = "An";
	rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME);
		goto error;
@@ -542,7 +547,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.data_buf = aksv;
	ddc_data.data_len = 5;
	ddc_data.what = "Aksv";
	rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: AKSV write failed\n", __func__,
			HDCP_STATE_NAME);
@@ -561,7 +568,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.retry = 5;
	ddc_data.what = "Bksv";
	ddc_data.no_align = true;
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);

	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: BKSV read failed\n", __func__,
			HDCP_STATE_NAME);
@@ -633,7 +643,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.retry = 5;
	ddc_data.what = "R0'";
	ddc_data.no_align = true;
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);

	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME);
		goto error;
@@ -684,7 +697,8 @@ do { \
	ddc_data.offset = (off); \
	memset(what, 0, sizeof(what)); \
	snprintf(what, sizeof(what), (name)); \
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); \
	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; \
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); \
	if (rc) { \
		DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \
			what); \
@@ -868,7 +882,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
		ddc_data.retry = 5;
		ddc_data.what = "Bcaps";
		ddc_data.no_align = false;
		rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);

		hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

		rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
		if (rc) {
			DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
				HDCP_STATE_NAME);
@@ -887,7 +904,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.retry = 5;
	ddc_data.what = "Bstatuss";
	ddc_data.no_align = false;
	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);

	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
	if (rc) {
		DEV_ERR("%s: %s: BSTATUS read failed\n", __func__,
			HDCP_STATE_NAME);
@@ -979,9 +999,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
	ddc_data.retry = 5;
	ddc_data.what = "KSV FIFO";
	ddc_data.no_align = true;

	hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	cnt = 0;
	do {
		rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
		rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
		if (rc) {
			DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__,
				HDCP_STATE_NAME);
+43 −96
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)

	mutex_lock(&ctrl->wakeup_mutex);

	pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
	pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));

	ctrl->wakeup_cmd = data->cmd;
	ctrl->timeout = data->timeout;
@@ -310,6 +310,10 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl,
	struct hdmi_tx_ddc_data ddc_data;
	int rc;

	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
		pr_err("hdcp is off\n");
		return -EINVAL;
	}
	memset(&ddc_data, 0, sizeof(ddc_data));
	ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR;
	ddc_data.offset = HDCP_SINK_DDC_HDCP2_READ_MESSAGE;
@@ -320,7 +324,9 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl,
	ddc_data.hard_timeout = timeout;
	ddc_data.what = "HDCP2ReadMessage";

	rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data);
	ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl);
	if (rc)
		pr_err("Cannot read HDCP message register\n");
	return rc;
@@ -340,24 +346,14 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl,
	ddc_data.retry = 1;
	ddc_data.what = "HDCP2WriteMessage";

	rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl, &ddc_data);
	ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl);
	if (rc)
		pr_err("Cannot write HDCP message register");
	return rc;
}

static void hdmi_hdcp2p2_ddc_abort(struct hdmi_hdcp2p2_ctrl *ctrl)
{
	/* Abort any ongoing DDC transactions */
	struct hdmi_tx_ddc_data ddc_data;

	memset(&ddc_data, 0, sizeof(ddc_data));
	ddc_data.retry = 1;
	ddc_data.what = "HDCPAbortTransaction";
	hdmi_ddc_abort_transaction(ctrl->init_data.ddc_ctrl,
		&ddc_data);
}

static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl,
		u8 *hdcp2version)
{
@@ -373,7 +369,9 @@ static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl,
	ddc_data.retry = 1;
	ddc_data.what = "HDCP2Version";

	rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data);
	ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;

	rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl);
	if (rc) {
		pr_err("Cannot read HDCP2Version register");
		return rc;
@@ -424,44 +422,6 @@ static struct attribute_group hdmi_hdcp2p2_fs_attr_group = {
	.attrs = hdmi_hdcp2p2_fs_attrs,
};

static int hdmi_hdcp2p2_isr(void *input)
{
	struct hdmi_hdcp2p2_ctrl *ctrl = input;
	u32 reg_val;

	if (!ctrl) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	pr_debug("INT_CTRL0 is 0x%x\n",
		DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0));
	reg_val = DSS_REG_R(ctrl->init_data.core_io,
			HDMI_HDCP_INT_CTRL2);
	if (reg_val & BIT(0)) {
		pr_debug("HDCP 2.2 Encryption is enabled\n");
		reg_val |= BIT(1);
		DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2,
			reg_val);
	}

	reg_val = DSS_REG_R(ctrl->init_data.core_io,
							HDMI_DDC_INT_CTRL0);
	if (reg_val & HDCP2P2_RXSTATUS_MESSAGE_SIZE_MASK) {
		DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0,
						reg_val & ~(BIT(31)));
		if (!completion_done(&ctrl->rxstatus_completion))
			complete_all(&ctrl->rxstatus_completion);
	} else if (reg_val & BIT(8)) {
		DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0,
						reg_val & ~(BIT(9) | BIT(10)));
		if (!completion_done(&ctrl->rxstatus_completion))
			complete_all(&ctrl->rxstatus_completion);
	}

	return 0;
}

static bool hdmi_hdcp2p2_feature_supported(void *input)
{
	struct hdmi_hdcp2p2_ctrl *ctrl = input;
@@ -525,12 +485,12 @@ exit:

static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
{
	int rc = 0, msg_size = 0, retries = 5;
	int rc = 0;
	u64 mult;
	char *recvd_msg_buf = NULL;
	struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
		struct hdmi_hdcp2p2_ctrl, recv_msg);
	struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data;
	struct hdmi_tx_hdcp2p2_ddc_data *ddc_data;
	struct hdmi_tx_ddc_ctrl *ddc_ctrl;
	struct msm_hdmi_mode_timing_info *timing;
	struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
@@ -550,59 +510,47 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
	}

	ddc_ctrl = ctrl->init_data.ddc_ctrl;
	if (!ddc_ctrl)
		goto exit;

	do {
		timing = ctrl->init_data.timing;
	hdmi_ddc_config(ddc_ctrl);

		mult = hdmi_tx_get_v_total(timing) / 20;
		memset(&hdcp2p2_ddc_data, 0, sizeof(hdcp2p2_ddc_data));
		hdcp2p2_ddc_data.ddc_data.what = "HDCP2RxStatus";
		hdcp2p2_ddc_data.ddc_data.data_buf = (u8 *)&msg_size;
		hdcp2p2_ddc_data.ddc_data.data_len = sizeof(msg_size);
		hdcp2p2_ddc_data.rxstatus_field = RXSTATUS_MESSAGE_SIZE;
		hdcp2p2_ddc_data.timer_delay_lines = (u32)mult;
		hdcp2p2_ddc_data.irq_wait_count = 100;
		hdcp2p2_ddc_data.poll_sink = false;
	ddc_data = &ddc_ctrl->hdcp2p2_ddc_data;

		hdmi_ddc_config(ddc_ctrl);
		pr_debug("Reading rxstatus, timer delay %u\n", (u32)mult);
	memset(ddc_data, 0, sizeof(*ddc_data));

		rc = hdmi_hdcp2p2_ddc_read_rxstatus(
			ddc_ctrl, &hdcp2p2_ddc_data,
			&ctrl->rxstatus_completion);
	timing = ctrl->init_data.timing;
	mult = hdmi_tx_get_v_total(timing) / 20;
	ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE;
	ddc_data->timer_delay_lines = (u32)mult;
	ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;

	rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl);
	if (rc) {
			pr_err("Could not read rxstatus from sink\n");
			continue;
		pr_err("error reading rxstatus %d\n", rc);
		goto exit;
	}

		if (!msg_size) {
	if (!ddc_data->message_size) {
		pr_err("recvd invalid message size\n");
		rc = -EINVAL;
			continue;
		}
	} while (rc && (retries-- > 0));

	if (rc) {
		pr_err("error reading valid rxstatus data\n");
		goto exit;
	}

	recvd_msg_buf = kzalloc(msg_size, GFP_KERNEL);
	pr_debug("rxstatus msg size %d\n", ddc_data->message_size);

	recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL);
	if (!recvd_msg_buf)
		goto exit;

	rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf,
		msg_size, ctrl->timeout);
		ddc_data->message_size, ctrl->timeout);
	if (rc)
		pr_err("ERROR reading message from sink\n");

	hdmi_hdcp2p2_ddc_abort(ctrl);
	hdmi_hdcp2p2_ddc_reset(ddc_ctrl);
	hdmi_hdcp2p2_ddc_disable(ddc_ctrl);
		pr_err("error reading message %d\n", rc);

	cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
	cdata.recvd_msg_buf = recvd_msg_buf;
	cdata.recvd_msg_len = msg_size;
	cdata.recvd_msg_len = ddc_data->message_size;
exit:
	if (rc == -ETIMEDOUT)
		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
@@ -707,7 +655,6 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
	struct hdmi_hdcp2p2_ctrl *ctrl;
	int rc;
	static struct hdmi_hdcp_ops ops = {
		.hdmi_hdcp_isr = hdmi_hdcp2p2_isr,
		.hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate,
		.hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate,
		.feature_supported = hdmi_hdcp2p2_feature_supported,
+15 −6
Original line number Diff line number Diff line
@@ -1291,11 +1291,13 @@ static u32 hdmi_tx_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
			ddc_data.what        = "EDID";
			ddc_data.no_align    = false;

			ddc_ctrl->ddc_data = ddc_data;

			/* Read EDID twice with 32bit alighnment too */
			if (block < 2)
				status = hdmi_ddc_read(ddc_ctrl, &ddc_data);
				status = hdmi_ddc_read(ddc_ctrl);
			else
				status = hdmi_ddc_read_seg(ddc_ctrl, &ddc_data);
				status = hdmi_ddc_read_seg(ddc_ctrl);

			if (status)
				break;
@@ -3777,10 +3779,14 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data)
		if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]))
			DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);

	if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data)
	if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) {
		if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) {
			if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr(
				hdmi_ctrl->hdcp_feature_data))
			DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__);
				DEV_ERR("%s: hdmi_hdcp_isr failed\n",
					 __func__);
		}
	}
end:
	return IRQ_HANDLED;
} /* hdmi_tx_isr */
@@ -3865,6 +3871,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)

	hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO];
	init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
	init_completion(&hdmi_ctrl->ddc_ctrl.rxstatus_completion);

	hdmi_ctrl->panel_power_on = false;
	hdmi_ctrl->panel_suspend = false;
@@ -4080,6 +4087,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
			hdmi_ctrl->hdcp_ops->hdmi_hdcp_off(
				hdmi_ctrl->hdcp_feature_data);

			hdmi_ctrl->hdcp_ops = NULL;

			rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM,
				false);
			if (rc)
+315 −215

File changed.

Preview size limit exceeded, changes collapsed.

Loading