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

Commit e0ec36aa authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

msm: mdss: hdmi: fix scrambling interrupt handling



Use proper timeout values for polling scrambling status from sink.
Clear the interrupts and stop polling after timeout if scrambling
status is not updated by sink indicating it has not detected
scrambling signal.

Change-Id: I3cac01ef261ee958fd0bbecf88edde5305b20ee7
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 985edcd0
Loading
Loading
Loading
Loading
+22 −37
Original line number Diff line number Diff line
@@ -36,9 +36,6 @@

#define HDCP2P2_LINK_CHECK_TIME_MS 900 /* link check within 1 sec */

#define HDCP2P2_SEC_TO_US 1000000
#define HDCP2P2_MS_TO_US  1000
#define HDCP2P2_KHZ_TO_HZ 1000
#define HDCP2P2_DEFAULT_TIMEOUT 500

/*
@@ -600,15 +597,12 @@ exit:
static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
{
	int rc = 0;
	u32 fps, v_total;
	u32 time_taken_by_one_line_us;
	u32 lines_needed_for_given_time;
	int timeout_hsync;
	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 *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};

	if (!ctrl) {
@@ -635,27 +629,21 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)

	memset(ddc_data, 0, sizeof(*ddc_data));

	timing = ctrl->init_data.timing;
	timeout_hsync = hdmi_utils_get_timeout_in_hysnc(
		ctrl->init_data.timing, ctrl->timeout);

	fps = timing->refresh_rate / HDCP2P2_KHZ_TO_HZ;
	v_total = hdmi_tx_get_v_total(timing);

	/*
	 * pixel clock  = h_total * v_total * fps
	 * 1 sec = pixel clock number of pixels are transmitted.
	 * time taken by one line (h_total) = 1 / (v_total * fps).
	 */
	time_taken_by_one_line_us = HDCP2P2_SEC_TO_US / (v_total * fps);
	lines_needed_for_given_time = (ctrl->timeout * HDCP2P2_MS_TO_US) /
		time_taken_by_one_line_us;
	if (timeout_hsync <= 0) {
		pr_err("err in timeout hsync calc\n");
		timeout_hsync = HDMI_DEFAULT_TIMEOUT_HSYNC;
	}

	pr_debug("timeout for rxstatus %dms, %d hsyncs\n",
		ctrl->timeout, lines_needed_for_given_time);
	pr_debug("timeout for rxstatus %dms, %d hsync\n",
		ctrl->timeout, timeout_hsync);

	ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE;
	ddc_data->timeout_ms = ctrl->timeout;
	ddc_data->timeout_hsync = lines_needed_for_given_time;
	ddc_data->periodic_timer_hsync = lines_needed_for_given_time / 20;
	ddc_data->timeout_hsync = timeout_hsync;
	ddc_data->periodic_timer_hsync = timeout_hsync / 20;
	ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;

	rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, true);
@@ -704,10 +692,7 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
{
	struct hdmi_tx_ddc_ctrl *ddc_ctrl;
	struct hdmi_tx_hdcp2p2_ddc_data *ddc_data;
	struct msm_hdmi_mode_timing_info *timing;
	u32 fps, v_total;
	u32 time_taken_by_one_line_us;
	u32 lines_needed_for_given_time;
	int timeout_hsync;

	ddc_ctrl = ctrl->init_data.ddc_ctrl;
	if (!ddc_ctrl)
@@ -719,20 +704,20 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)

	memset(ddc_data, 0, sizeof(*ddc_data));

	timing = ctrl->init_data.timing;
	fps = timing->refresh_rate / HDCP2P2_KHZ_TO_HZ;
	v_total = hdmi_tx_get_v_total(timing);
	time_taken_by_one_line_us = HDCP2P2_SEC_TO_US / (v_total * fps);
	lines_needed_for_given_time = (jiffies_to_msecs((HZ / 2) + (HZ / 4)) *
		HDCP2P2_MS_TO_US) / time_taken_by_one_line_us;
	timeout_hsync = hdmi_utils_get_timeout_in_hysnc(
		ctrl->init_data.timing,
		jiffies_to_msecs((HZ / 2) + (HZ / 4)));

	pr_debug("timeout for rxstatus %d hsyncs\n",
		lines_needed_for_given_time);
	if (timeout_hsync <= 0) {
		pr_err("err in timeout hsync calc\n");
		timeout_hsync = HDMI_DEFAULT_TIMEOUT_HSYNC;
	}
	pr_debug("timeout for rxstatus %d hsyncs\n", timeout_hsync);

	ddc_data->intr_mask = RXSTATUS_READY | RXSTATUS_MESSAGE_SIZE |
		RXSTATUS_REAUTH_REQ;
	ddc_data->timeout_hsync = lines_needed_for_given_time;
	ddc_data->periodic_timer_hsync = lines_needed_for_given_time;
	ddc_data->timeout_hsync = timeout_hsync;
	ddc_data->periodic_timer_hsync = timeout_hsync;
	ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;

	return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, false);
+17 −20
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@
#define HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1

#define HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ 340000
#define HDMI_TX_SCRAMBLER_TIMEOUT_USEC 200000
#define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200

#define HDMI_TX_KHZ_TO_HZ 1000
#define HDMI_TX_MHZ_TO_HZ 1000000
@@ -3228,6 +3228,7 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
	struct dss_io_data *io = NULL;
	struct msm_hdmi_mode_timing_info *timing = NULL;
	void *edid_data = NULL;
	int timeout_hsync;

	if (!hdmi_ctrl) {
		DEV_ERR("%s: Bad input parameters\n", __func__);
@@ -3254,9 +3255,6 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
		return 0;
	}

	if (!hdmi_edid_get_scdc_support(edid_data))
		DEV_WARN("%s: sink didn't provide scdc support\n", __func__);

	rate = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl);

	if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
@@ -3268,9 +3266,6 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
	}

	if (scrambler_on) {
		u64 mult;
		u64 div;

		rc = hdmi_scdc_write(&hdmi_ctrl->ddc_ctrl,
			HDMI_TX_SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE,
			tmds_clock_ratio);
@@ -3300,24 +3295,26 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
		 * status bit on the sink. Sink should set this bit
		 * with in 200ms after scrambler is enabled.
		 */
		mult = HDMI_TX_SCRAMBLER_TIMEOUT_USEC *
			((u64)timing->pixel_freq * HDMI_TX_KHZ_TO_HZ);
		div = hdmi_tx_get_v_total(timing) * HDMI_TX_MHZ_TO_HZ;
		if (div)
			do_div(mult, div);
		else
			mult = 0;
		timeout_hsync = hdmi_utils_get_timeout_in_hysnc(
					&hdmi_ctrl->vid_cfg.timing,
					HDMI_TX_SCRAMBLER_TIMEOUT_MSEC);

		if (timeout_hsync <= 0) {
			DEV_ERR("%s: err in timeout hsync calc\n", __func__);
			timeout_hsync = HDMI_DEFAULT_TIMEOUT_HSYNC;
		}

		pr_debug("timeout for scrambling en: %d hsyncs\n",
			timeout_hsync);

		rc = hdmi_setup_ddc_timers(&hdmi_ctrl->ddc_ctrl,
			HDMI_TX_DDC_TIMER_SCRAMBLER_STATUS, (u32)mult);
			HDMI_TX_DDC_TIMER_SCRAMBLER_STATUS, timeout_hsync);
	} else {
		if (hdmi_ctrl->scrambler_enabled) {
		hdmi_scdc_write(&hdmi_ctrl->ddc_ctrl,
			HDMI_TX_SCDC_SCRAMBLING_ENABLE, 0x0);

		hdmi_ctrl->scrambler_enabled = false;
	}
	}

	return rc;
}
+171 −112
Original line number Diff line number Diff line
@@ -19,37 +19,117 @@

#define RESOLUTION_NAME_STR_LEN 30
#define HDMI_SEC_TO_MS 1000
#define HDMI_MS_TO_US 1000
#define HDMI_SEC_TO_US (HDMI_SEC_TO_MS * HDMI_MS_TO_US)
#define HDMI_KHZ_TO_HZ 1000

#define HDMI_SCDC_UNKNOWN_REGISTER        "Unknown register"

static char res_buf[RESOLUTION_NAME_STR_LEN];

int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing,
	u32 timeout_ms)
{
	u32 fps, v_total;
	u32 time_taken_by_one_line_us, lines_needed_for_given_time;

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

	fps = timing->refresh_rate / HDMI_KHZ_TO_HZ;
	v_total = hdmi_tx_get_v_total(timing);

	/*
	 * pixel clock  = h_total * v_total * fps
	 * 1 sec = pixel clock number of pixels are transmitted.
	 * time taken by one line (h_total) = 1 / (v_total * fps).
	 */
	time_taken_by_one_line_us = HDMI_SEC_TO_US / (v_total * fps);
	lines_needed_for_given_time = (timeout_ms * HDMI_MS_TO_US) /
		time_taken_by_one_line_us;

	return lines_needed_for_given_time;
}

static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
	char *what)
{
	u32 ddc_int_ctrl, ddc_status, in_use, timeout;
	u32 sw_done_mask = BIT(2);
	u32 sw_done_ack  = BIT(1);
	u32 hw_done_mask = BIT(6);
	u32 hw_done_ack  = BIT(5);
	u32 in_use_by_sw = BIT(0);
	u32 in_use_by_hw = BIT(1);

	if (!ddc_ctrl || !ddc_ctrl->io) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	/* clear and enable interrutps */
	ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack;

	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl);

	/* wait until DDC HW is free */
	timeout = 100;
	do {
		ddc_status = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_HW_STATUS);
		in_use = ddc_status & (in_use_by_sw | in_use_by_hw);
		if (in_use) {
			pr_debug("ddc is in use by %s, timeout(%d)\n",
				ddc_status & in_use_by_sw ? "sw" : "hw",
				timeout);
			udelay(100);
		}
	} while (in_use && --timeout);

	if (!timeout) {
		pr_err("%s: timedout\n", what);
		return -ETIMEDOUT;
	}

	return 0;
}

static void hdmi_scrambler_status_timer_setup(struct hdmi_tx_ddc_ctrl *ctrl,
					     u32 to_in_num_lines)
		u32 timeout_hsync)
{
	u32 reg_val;
	struct dss_io_data *io = NULL;

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

	DSS_REG_W(ctrl->io, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL,
						to_in_num_lines);
	DSS_REG_W(ctrl->io, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL2,
						0xFFFF);
	reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL5);
	io = ctrl->io;

	hdmi_ddc_clear_irq(ctrl, "scrambler");

	DSS_REG_W(io, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL, timeout_hsync);
	DSS_REG_W(io, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL2, timeout_hsync);

	reg_val = DSS_REG_R(io, HDMI_DDC_INT_CTRL5);
	reg_val |= BIT(10);
	DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL5, reg_val);
	DSS_REG_W(io, HDMI_DDC_INT_CTRL5, reg_val);

	reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL2);
	reg_val = DSS_REG_R(io, HDMI_DDC_INT_CTRL2);
	/* Trigger interrupt if scrambler status is 0 or DDC failure */
	reg_val |= BIT(10);
	reg_val &= 0x18000;
	reg_val |= (0x2 << 15);
	DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL2, reg_val);
	reg_val &= ~(BIT(15) | BIT(16));
	reg_val |= BIT(16);
	DSS_REG_W(io, HDMI_DDC_INT_CTRL2, reg_val);

	/* Enable DDC access */
	reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL);
	reg_val = DSS_REG_R(io, HDMI_HW_DDC_CTRL);

	reg_val &= ~0x300;
	reg_val |= (0x1 << 8);
	DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
	reg_val &= ~(BIT(8) | BIT(9));
	reg_val |= BIT(8);
	DSS_REG_W(io, HDMI_HW_DDC_CTRL, reg_val);
}

static inline char *hdmi_scdc_reg2string(u32 type)
@@ -499,47 +579,6 @@ static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data)
		ddc_data->retry, ddc_data->what);
} /* hdmi_ddc_print_data */

static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
	char *what)
{
	u32 ddc_int_ctrl, ddc_status, in_use, timeout;
	u32 sw_done_mask = BIT(2);
	u32 sw_done_ack  = BIT(1);
	u32 hw_done_mask = BIT(6);
	u32 hw_done_ack  = BIT(5);
	u32 in_use_by_sw = BIT(0);
	u32 in_use_by_hw = BIT(1);

	if (!ddc_ctrl || !ddc_ctrl->io) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	/* clear and enable interrutps */
	ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack;

	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl);

	/* wait until DDC HW is free */
	timeout = 100;
	do {
		ddc_status = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_HW_STATUS);
		in_use = ddc_status & (in_use_by_sw | in_use_by_hw);
		if (in_use) {
			pr_debug("ddc is in use by %s\n",
				ddc_status & in_use_by_sw ? "sw" : "hw");
			udelay(100);
		}
	} while (in_use && --timeout);

	if (!timeout) {
		pr_err("%s: timedout\n", what);
		return -ETIMEDOUT;
	}

	return 0;
} /*hdmi_ddc_clear_irq */

static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
{
	u32 reg_val, ndx, time_out_count, wait_time;
@@ -796,23 +835,19 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
	struct hdmi_tx_hdcp2p2_ddc_data *data;
	u32 intr0, intr2;

	if (!ddc_ctrl) {
	if (!ddc_ctrl || !ddc_ctrl->io) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	io = ddc_ctrl->io;
	if (!io) {
		pr_err("invalid io data\n");
		return -EINVAL;
	}

	data = &ddc_ctrl->hdcp2p2_ddc_data;

	intr2 = DSS_REG_R(io, HDMI_HDCP_INT_CTRL2);
	intr0 = DSS_REG_R(io, HDMI_DDC_INT_CTRL0);

	pr_debug("ctl0: 0x%x, ctl1: 0x%x\n", intr0, intr2);
	pr_debug("intr0: 0x%x, intr2: 0x%x\n", intr0, intr2);

	/* check for encryption ready interrupt */
	if (intr2 & BIT(2)) {
@@ -848,7 +883,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
		}
	}

	DSS_REG_W_ND(ddc_ctrl->io, HDMI_HDCP_INT_CTRL2, intr2);
	DSS_REG_W_ND(io, HDMI_HDCP_INT_CTRL2, intr2);

	/* check for message size interrupt */
	if (intr0 & BIT(31)) {
@@ -913,7 +948,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
		data->ddc_read_req = (intr0 & BIT(0)) ? true : false;
	}

	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL0, intr0);
	DSS_REG_W_ND(io, HDMI_DDC_INT_CTRL0, intr0);

	if (data->message_size || data->ready || data->reauth_req) {
		if (!completion_done(&ddc_ctrl->rxstatus_completion))
@@ -923,69 +958,97 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
	return 0;
}

int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
static int hdmi_ddc_scrambling_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
{
	u32 ddc_int_ctrl;
	u32 ddc_timer_int;
	struct dss_io_data *io;
	bool scrambler_timer_off = false;
	u32 intr2, intr5;

	if (!ddc_ctrl || !ddc_ctrl->io) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	ddc_int_ctrl = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
	if ((ddc_int_ctrl & BIT(2)) && (ddc_int_ctrl & BIT(0))) {
		/* SW_DONE INT occurred, clr it */
		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
			ddc_int_ctrl | BIT(1));
		complete(&ddc_ctrl->ddc_sw_done);
	io = ddc_ctrl->io;

	intr2 = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2);
	pr_debug("ddc_int_ctrl2=0x%x\n", intr2);

	if (intr2 & BIT(12)) {
		pr_err("SCRAMBLER_STATUS_NOT\n");

		intr2 |= BIT(14);

		scrambler_timer_off = true;
	}

	if ((ddc_int_ctrl & BIT(6)) && (ddc_int_ctrl & BIT(4))) {
		/* HW_DONE INT occurred, clr it */
		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
			ddc_int_ctrl | BIT(5));
	}

	pr_debug("ddc_int_ctrl=%04x\n", ddc_int_ctrl);
	if (version < HDMI_TX_SCRAMBLER_MIN_TX_VERSION)
		goto end;

	ddc_timer_int = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2);
	if (ddc_timer_int & BIT(12)) {
		/* DDC_INT_CTRL2.SCRAMBLER_STATUS_NOT is set */
		pr_err("Sink cannot descramble the signal\n");
		/* Clear interrupt */
		ddc_timer_int |= BIT(14);
		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2,
							ddc_timer_int);
	if (intr2 & BIT(8)) {
		pr_err("SCRAMBLER_STATUS_DDC_FAILED\n");

		intr2 |= BIT(9);

		scrambler_timer_off = true;
	}
	DSS_REG_W_ND(io, HDMI_DDC_INT_CTRL2, intr2);

	intr5 = DSS_REG_R_ND(io, HDMI_DDC_INT_CTRL5);
	pr_debug("ddc_int_ctrl5=0x%x\n", intr5);

	if (intr5 & BIT(8)) {
		pr_err("SCRAMBLER_STATUS_DDC_REQ_TIMEOUT\n");

		intr5 |= BIT(9);

	ddc_timer_int = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL5);
	if (ddc_timer_int & BIT(8)) {
		/*
		 * DDC_INT_CTRL5.SCRAMBLER_STATUS_DDC_REQ_TIMEOUT
		 * is set
		 */
		pr_err("DDC timeout while reading SCRAMBLER STATUS\n");
		ddc_timer_int |= BIT(13);
		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL5,
							ddc_timer_int);
		scrambler_timer_off = true;
	}
	DSS_REG_W_ND(io, HDMI_DDC_INT_CTRL5, intr5);

	/* Disable scrambler status timer if it has been acknowledged */
	if (scrambler_timer_off) {
		u32 regval = DSS_REG_R_ND(ddc_ctrl->io,
						HDMI_HW_DDC_CTRL);
		regval &= 0x300;
		DSS_REG_W_ND(ddc_ctrl->io, HDMI_HW_DDC_CTRL, regval);
		u32 reg_val = DSS_REG_R_ND(io, HDMI_HW_DDC_CTRL);

		reg_val &= ~(BIT(8) | BIT(9));
		DSS_REG_W_ND(io, HDMI_HW_DDC_CTRL, reg_val);
	}
end:
	hdmi_ddc_hdcp2p2_isr(ddc_ctrl);

	return 0;
}

int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
{
	u32 ddc_int_ctrl, ret = 0;

	if (!ddc_ctrl || !ddc_ctrl->io) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	ddc_int_ctrl = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
	pr_debug("ddc_int_ctrl=0x%x\n", ddc_int_ctrl);

	if ((ddc_int_ctrl & BIT(2)) && (ddc_int_ctrl & BIT(0))) {
		pr_debug("ddc sw done\n");

		ddc_int_ctrl |= BIT(1);
		complete(&ddc_ctrl->ddc_sw_done);
	}

	if ((ddc_int_ctrl & BIT(6)) && (ddc_int_ctrl & BIT(4))) {
		pr_debug("ddc hw done\n");
		ddc_int_ctrl |= BIT(5);
	}
	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl);

	if (version >= HDMI_TX_SCRAMBLER_MIN_TX_VERSION) {
		ret = hdmi_ddc_scrambling_isr(ddc_ctrl);
		if (ret)
			pr_err("err in scrambling isr\n");
	}

	ret = hdmi_ddc_hdcp2p2_isr(ddc_ctrl);
	if (ret)
		pr_err("err in hdcp2p2 isr\n");

	return ret;
} /* hdmi_ddc_isr */

int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
@@ -1127,8 +1190,6 @@ again:
	time_out_count = wait_for_completion_timeout(
		&ddc_ctrl->ddc_sw_done, HZ/2);

	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
	if (!time_out_count) {
		if (ddc_data->retry-- > 0) {
			pr_debug("failed timout, retry=%d\n", ddc_data->retry);
@@ -1305,8 +1366,6 @@ again:

	pr_debug("DDC write done at %dms\n", jiffies_to_msecs(jiffies));

	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
	if (!time_out_count) {
		if (retry-- > 0) {
			pr_debug("%s: failed timout, retry=%d\n",
+5 −0
Original line number Diff line number Diff line
@@ -364,6 +364,9 @@
#define HDCP2P2_RXSTATUS_HW_DDC_FORCE_LOOP          2
#define HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER          3

/* default hsyncs for 4k@60 for 200ms */
#define HDMI_DEFAULT_TIMEOUT_HSYNC 28571

enum hdmi_tx_feature_type {
	HDMI_TX_FEAT_EDID,
	HDMI_TX_FEAT_HDCP,
@@ -496,5 +499,7 @@ void hdmi_hdcp2p2_ddc_reset(struct hdmi_tx_ddc_ctrl *ctrl);
void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl);
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait);
int hdmi_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl);
int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing,
	u32 timeout_ms);

#endif /* __HDMI_UTIL_H__ */