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

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

Merge "clk: qcom: mdss: calculate pixel clock for HDMI during handoff"

parents eeee2b62 48497b87
Loading
Loading
Loading
Loading
+94 −1
Original line number Diff line number Diff line
@@ -2265,9 +2265,102 @@ static int hdmi_8996_v3_1p8_vco_set_rate(struct clk *c, unsigned long rate)
	return hdmi_8996_vco_set_rate(c, rate, HDMI_VERSION_8996_V3_1_8);
}

static unsigned long hdmi_get_hsclk_sel_divisor(unsigned long hsclk_sel)
{
	unsigned long divisor;

	switch (hsclk_sel) {
	case 0:
		divisor = 2;
		break;
	case 1:
		divisor = 6;
		break;
	case 2:
		divisor = 10;
		break;
	case 3:
		divisor = 14;
		break;
	case 4:
		divisor = 3;
		break;
	case 5:
		divisor = 9;
		break;
	case 6:
	case 13:
		divisor = 15;
		break;
	case 7:
		divisor = 21;
		break;
	case 8:
		divisor = 4;
		break;
	case 9:
		divisor = 12;
		break;
	case 10:
		divisor = 20;
		break;
	case 11:
		divisor = 28;
		break;
	case 12:
		divisor = 5;
		break;
	case 14:
		divisor = 25;
		break;
	case 15:
		divisor = 35;
		break;
	default:
		divisor = 1;
		DEV_ERR("%s: invalid hsclk_sel value = %lu",
				__func__, hsclk_sel);
		break;
	}

	return divisor;
}

static unsigned long hdmi_8996_vco_get_rate(struct clk *c)
{
	unsigned long freq = 0;
	unsigned long freq = 0, hsclk_sel = 0, tx_band = 0, dec_start = 0,
		      div_frac_start = 0, vco_clock_freq = 0;
	struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c);
	struct mdss_pll_resources *io = vco->priv;

	if (mdss_pll_resource_enable(io, true)) {
		DEV_ERR("%s: pll resource can't be enabled\n", __func__);
		return freq;
	}

	dec_start = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEC_START_MODE0);

	div_frac_start =
		MDSS_PLL_REG_R(io->pll_base,
				QSERDES_COM_DIV_FRAC_START1_MODE0) |
		MDSS_PLL_REG_R(io->pll_base,
				QSERDES_COM_DIV_FRAC_START2_MODE0) << 8 |
		MDSS_PLL_REG_R(io->pll_base,
				QSERDES_COM_DIV_FRAC_START3_MODE0) << 16;

	vco_clock_freq = (dec_start + (div_frac_start / (1 << 20)))
		* 4 * (HDMI_REF_CLOCK);

	hsclk_sel = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_HSCLK_SEL) & 0x15;
	hsclk_sel = hdmi_get_hsclk_sel_divisor(hsclk_sel);
	tx_band = MDSS_PLL_REG_R(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
			QSERDES_TX_L0_TX_BAND) & 0x3;

	freq = vco_clock_freq / (10 * hsclk_sel * (1 << tx_band));

	mdss_pll_resource_enable(io, false);

	DEV_DBG("%s: freq = %lu\n", __func__, freq);

	return freq;
}
+4 −69
Original line number Diff line number Diff line
@@ -61,8 +61,6 @@
#define AUDIO_POLL_SLEEP_US   (5 * 1000)
#define AUDIO_POLL_TIMEOUT_US (AUDIO_POLL_SLEEP_US * 1000)

#define LPA_DMA_IDLE_MAX 200

#define IFRAME_CHECKSUM_32(d)			\
	((d & 0xff) + ((d >> 8) & 0xff) +	\
	((d >> 16) & 0xff) + ((d >> 24) & 0xff))
@@ -3907,8 +3905,9 @@ static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
		goto end;
	}

	hdmi_ctrl->panel_power_on = true;
end:
	hdmi_ctrl->panel_power_on = true;

	dss_reg_dump(io->base, io->len, "HDMI-ON: ", REG_DUMP);

	DEV_DBG("%s: Tx: %s (%s mode)\n", __func__,
@@ -4473,7 +4472,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
		break;

	case MDSS_EVENT_RESET:
		if (hdmi_ctrl->hpd_initialized) {
		if (!hdmi_ctrl->pdata.cont_splash_enabled &&
				hdmi_ctrl->hpd_initialized) {
			hdmi_tx_set_mode(hdmi_ctrl, false);
			hdmi_tx_phy_reset(hdmi_ctrl);
			hdmi_tx_set_mode(hdmi_ctrl, true);
@@ -5166,69 +5166,6 @@ error:
	return rc;
} /* hdmi_tx_get_dt_data */

static void hdmi_tx_audio_tear_down(struct hdmi_tx_ctrl *hdmi_ctrl)
{
	struct dss_io_data *io;
	u32 audio_pkt_ctrl;
	u32 audio_eng_cfg;

	if (!hdmi_ctrl) {
		DEV_ERR("%s: invalid input\n", __func__);
		return;
	}

	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
		DEV_ERR("%s: Core io is not initialized\n", __func__);
		return;
	}

	audio_pkt_ctrl = DSS_REG_R(io, HDMI_AUDIO_PKT_CTRL);
	audio_eng_cfg  = DSS_REG_R(io, HDMI_AUDIO_CFG);

	if ((audio_pkt_ctrl & BIT(0)) || (audio_eng_cfg & BIT(0))) {
		u32 lpa_dma, i = 0;

		void __iomem *lpa_base = ioremap(LPASS_LPAIF_RDDMA_CTL0, 0xFF);

		lpa_dma = readl_relaxed(lpa_base + LPASS_LPAIF_RDDMA_PER_CNT0);

		/* Disable audio packet transmission */
		DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL,
			DSS_REG_R(io, HDMI_AUDIO_PKT_CTRL) & ~BIT(0));

		/* Wait for LPA DMA Engine to be idle */
		while (i < LPA_DMA_IDLE_MAX) {
			u32 val;

			/*
			 * sleep for minimum HW recommended time
			 * for HW status to update.
			 */
			msleep(20);

			val = readl_relaxed(lpa_base +
				LPASS_LPAIF_RDDMA_PER_CNT0);
			if (val == lpa_dma)
				break;

			lpa_dma = val;
			i++;
		}

		DEV_DBG("%s: LPA DMA idle after %d ms\n", __func__, i * 20);

		/* Disable audio engine */
		DSS_REG_W(io, HDMI_AUDIO_CFG,
			DSS_REG_R(io, HDMI_AUDIO_CFG) & ~BIT(0));

		/* Disable LPA DMA Engine */
		writel_relaxed(readl_relaxed(lpa_base) & ~BIT(0), lpa_base);

		iounmap(lpa_base);
	}
}

static int hdmi_tx_probe(struct platform_device *pdev)
{
	int rc = 0, i;
@@ -5345,8 +5282,6 @@ static int hdmi_tx_probe(struct platform_device *pdev)
				hdmi_ctrl->pdata.power_data[i].clk_config,
				hdmi_ctrl->pdata.power_data[i].num_clk, 1);
		}

		hdmi_tx_audio_tear_down(hdmi_ctrl);
	}

	return rc;