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

Commit cbfe7a87 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: dp: Update late_phy seq and reg for 10nm targets"

parents 06ee4c17 6b11a6e8
Loading
Loading
Loading
Loading
+46 −100
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */


@@ -74,6 +74,34 @@ static u8 const vm_voltage_swing[4][4] = {
	{0xFF, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2 v, optional */
};

static u8 const vm_pre_emphasis_hbr3_hbr2[4][4] = {
	{0x00, 0x0C, 0x15, 0x1A},
	{0x02, 0x0E, 0x16, 0xFF},
	{0x02, 0x11, 0xFF, 0xFF},
	{0x04, 0xFF, 0xFF, 0xFF}
};

static u8 const vm_voltage_swing_hbr3_hbr2[4][4] = {
	{0x02, 0x12, 0x16, 0x1A},
	{0x09, 0x19, 0x1F, 0xFF},
	{0x10, 0x1F, 0xFF, 0xFF},
	{0x1F, 0xFF, 0xFF, 0xFF}
};

static u8 const vm_pre_emphasis_hbr_rbr[4][4] = {
	{0x00, 0x0C, 0x14, 0x19},
	{0x00, 0x0B, 0x12, 0xFF},
	{0x00, 0x0B, 0xFF, 0xFF},
	{0x04, 0xFF, 0xFF, 0xFF}
};

static u8 const vm_voltage_swing_hbr_rbr[4][4] = {
	{0x08, 0x0F, 0x16, 0x1F},
	{0x11, 0x1E, 0x1F, 0xFF},
	{0x19, 0x1F, 0xFF, 0xFF},
	{0x1F, 0xFF, 0xFF, 0xFF}
};

enum dp_flush_bit {
	DP_PPS_FLUSH,
	DP_DHDR_FLUSH,
@@ -419,107 +447,11 @@ static void dp_catalog_aux_get_irq(struct dp_catalog_aux *aux, bool cmd_busy)
	dp_write(DP_INTR_STATUS, ack);
}

static bool dp_catalog_ctrl_wait_for_phy_ready(
		struct dp_catalog_private *catalog)
{
	u32 reg = DP_PHY_STATUS, state;
	void __iomem *base = catalog->io.dp_phy->io.base;
	bool success = true;
	u32 const poll_sleep_us = 500;
	u32 const pll_timeout_us = 10000;

	if (readl_poll_timeout_atomic((base + reg), state,
			((state & DP_PHY_READY) > 0),
			poll_sleep_us, pll_timeout_us)) {
		DP_ERR("PHY status failed, status=%x\n", state);

		success = false;
	}

	return success;
}

/* controller related catalog functions */
static int dp_catalog_ctrl_late_phy_init(struct dp_catalog_ctrl *ctrl,
					u8 lane_cnt, bool flipped)
{
	int rc = 0;
	u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;

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

	catalog = dp_catalog_get_priv(ctrl);

	switch (lane_cnt) {
	case 1:
		drvr0_en = flipped ? 0x13 : 0x10;
		bias0_en = flipped ? 0x3E : 0x15;
		drvr1_en = flipped ? 0x10 : 0x13;
		bias1_en = flipped ? 0x15 : 0x3E;
		break;
	case 2:
		drvr0_en = flipped ? 0x10 : 0x10;
		bias0_en = flipped ? 0x3F : 0x15;
		drvr1_en = flipped ? 0x10 : 0x10;
		bias1_en = flipped ? 0x15 : 0x3F;
		break;
	case 4:
	default:
		drvr0_en = 0x10;
		bias0_en = 0x3F;
		drvr1_en = 0x10;
		bias1_en = 0x3F;
		break;
	}

	io_data = catalog->io.dp_ln_tx0;
	dp_write(TXn_HIGHZ_DRVR_EN_V420, drvr0_en);
	dp_write(TXn_TRANSCEIVER_BIAS_EN_V420, bias0_en);

	io_data = catalog->io.dp_ln_tx1;
	dp_write(TXn_HIGHZ_DRVR_EN_V420, drvr1_en);
	dp_write(TXn_TRANSCEIVER_BIAS_EN_V420, bias1_en);

	io_data = catalog->io.dp_phy;
	dp_write(DP_PHY_CFG, 0x18);
	/* add hardware recommended delay */
	udelay(2000);
	dp_write(DP_PHY_CFG, 0x19);

	/*
	 * Make sure all the register writes are completed before
	 * doing any other operation
	 */
	wmb();

	if (!dp_catalog_ctrl_wait_for_phy_ready(catalog)) {
		rc = -EINVAL;
		goto lock_err;
	}

	io_data = catalog->io.dp_ln_tx0;
	dp_write(TXn_TX_POL_INV_V420, 0x0a);
	io_data = catalog->io.dp_ln_tx1;
	dp_write(TXn_TX_POL_INV_V420, 0x0a);

	io_data = catalog->io.dp_ln_tx0;
	dp_write(TXn_TX_DRV_LVL_V420, 0x27);
	io_data = catalog->io.dp_ln_tx1;
	dp_write(TXn_TX_DRV_LVL_V420, 0x27);

	io_data = catalog->io.dp_ln_tx0;
	dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
	io_data = catalog->io.dp_ln_tx1;
	dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
	/* Make sure the PHY register writes are done */
	wmb();
lock_err:
	return rc;
	return 0;
}

static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl)
@@ -1721,6 +1653,7 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl,
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u8 value0, value1;
	u32 version;

	if (!ctrl) {
		DP_ERR("invalid input\n");
@@ -1731,8 +1664,21 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl,

	DP_DEBUG("hw: v=%d p=%d\n", v_level, p_level);

	io_data = catalog->io.dp_ahb;
	version = dp_read(DP_HW_VERSION);

	if (version == 0x10020004) {
		if (high) {
			value0 = vm_voltage_swing_hbr3_hbr2[v_level][p_level];
			value1 = vm_pre_emphasis_hbr3_hbr2[v_level][p_level];
		} else {
			value0 = vm_voltage_swing_hbr_rbr[v_level][p_level];
			value1 = vm_pre_emphasis_hbr_rbr[v_level][p_level];
		}
	} else {
		value0 = vm_voltage_swing[v_level][p_level];
		value1 = vm_pre_emphasis[v_level][p_level];
	}

	/* program default setting first */

+106 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/iopoll.h>
#include <linux/iopoll.h>

#include "dp_catalog.h"
#include "dp_reg.h"
@@ -23,6 +25,7 @@
	catalog->sub.write(catalog->dpc, io_data, x, y); \
})

#define DP_PHY_READY BIT(1)
#define MAX_VOLTAGE_LEVELS 4
#define MAX_PRE_EMP_LEVELS 4

@@ -294,6 +297,108 @@ static void dp_catalog_ctrl_update_vx_px_v420(struct dp_catalog_ctrl *ctrl,
	}
}

static bool dp_catalog_ctrl_wait_for_phy_ready_v420(
		struct dp_catalog_private_v420 *catalog)
{
	u32 reg = DP_PHY_STATUS_V420, state;
	void __iomem *base = catalog->io->dp_phy->io.base;
	bool success = true;
	u32 const poll_sleep_us = 500;
	u32 const pll_timeout_us = 10000;

	if (readl_poll_timeout_atomic((base + reg), state,
			((state & DP_PHY_READY) > 0),
			poll_sleep_us, pll_timeout_us)) {
		DP_ERR("PHY status failed, status=%x\n", state);

		success = false;
	}

	return success;
}

static int dp_catalog_ctrl_late_phy_init_v420(struct dp_catalog_ctrl *ctrl,
					u8 lane_cnt, bool flipped)
{
	int rc = 0;
	u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
	struct dp_catalog_private_v420 *catalog;
	struct dp_io_data *io_data;

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

	catalog = dp_catalog_get_priv_v420(ctrl);

	switch (lane_cnt) {
	case 1:
		drvr0_en = flipped ? 0x13 : 0x10;
		bias0_en = flipped ? 0x3E : 0x15;
		drvr1_en = flipped ? 0x10 : 0x13;
		bias1_en = flipped ? 0x15 : 0x3E;
		break;
	case 2:
		drvr0_en = flipped ? 0x10 : 0x10;
		bias0_en = flipped ? 0x3F : 0x15;
		drvr1_en = flipped ? 0x10 : 0x10;
		bias1_en = flipped ? 0x15 : 0x3F;
		break;
	case 4:
	default:
		drvr0_en = 0x10;
		bias0_en = 0x3F;
		drvr1_en = 0x10;
		bias1_en = 0x3F;
		break;
	}

	io_data = catalog->io->dp_ln_tx0;
	dp_write(TXn_HIGHZ_DRVR_EN_V420, drvr0_en);
	dp_write(TXn_TRANSCEIVER_BIAS_EN_V420, bias0_en);

	io_data = catalog->io->dp_ln_tx1;
	dp_write(TXn_HIGHZ_DRVR_EN_V420, drvr1_en);
	dp_write(TXn_TRANSCEIVER_BIAS_EN_V420, bias1_en);

	io_data = catalog->io->dp_phy;
	dp_write(DP_PHY_CFG, 0x18);
	/* add hardware recommended delay */
	udelay(2000);
	dp_write(DP_PHY_CFG, 0x19);

	/*
	 * Make sure all the register writes are completed before
	 * doing any other operation
	 */
	wmb();

	if (!dp_catalog_ctrl_wait_for_phy_ready_v420(catalog)) {
		rc = -EINVAL;
		goto lock_err;
	}

	io_data = catalog->io->dp_ln_tx0;
	dp_write(TXn_TX_POL_INV_V420, 0x0a);
	io_data = catalog->io->dp_ln_tx1;
	dp_write(TXn_TX_POL_INV_V420, 0x0a);

	io_data = catalog->io->dp_ln_tx0;
	dp_write(TXn_TX_DRV_LVL_V420, 0x27);
	io_data = catalog->io->dp_ln_tx1;
	dp_write(TXn_TX_DRV_LVL_V420, 0x27);

	io_data = catalog->io->dp_ln_tx0;
	dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
	io_data = catalog->io->dp_ln_tx1;
	dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
	/* Make sure the PHY register writes are done */
	wmb();
lock_err:
	return rc;
}

static void dp_catalog_ctrl_lane_pnswap_v420(struct dp_catalog_ctrl *ctrl,
						u8 ln_pnswap)
{
@@ -356,6 +461,7 @@ struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev,
	catalog->ctrl.phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg_v420;
	catalog->ctrl.update_vx_px = dp_catalog_ctrl_update_vx_px_v420;
	catalog->ctrl.lane_pnswap = dp_catalog_ctrl_lane_pnswap_v420;
	catalog->ctrl.late_phy_init = dp_catalog_ctrl_late_phy_init_v420;

	return &catalog_priv->sub;
}
+4 −4
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _DP_REG_H_
@@ -377,7 +377,7 @@
#define TXn_TRANSCEIVER_BIAS_EN			(0x005C)
#define TXn_HIGHZ_DRVR_EN			(0x0060)

#define DP_PHY_STATUS				(0x00DC)
#define DP_PHY_STATUS_V420			(0x00DC)
#define DP_PHY_AUX_INTERRUPT_MASK_V420		(0x0054)
#define DP_PHY_AUX_INTERRUPT_CLEAR_V420		(0x0058)
#define DP_PHY_AUX_INTERRUPT_STATUS_V420	(0x00D8)
@@ -392,8 +392,8 @@
/* DP MMSS_CC registers */
#define MMSS_DP_LINK_CMD_RCGR			(0x0138)
#define MMSS_DP_LINK_CFG_RCGR			(0x013C)
#define MMSS_DP_PIXEL_M				(0x01B4)
#define MMSS_DP_PIXEL_N				(0x01B8)
#define MMSS_DP_PIXEL_M				(0x0134)
#define MMSS_DP_PIXEL_N				(0x0138)
#define MMSS_DP_PIXEL1_M			(0x01CC)
#define MMSS_DP_PIXEL1_N			(0x01D0)
#define MMSS_DP_PIXEL_M_V200			(0x0130)