Commit 6d0c3831 authored by Andrey Smirnov's avatar Andrey Smirnov Committed by Andrzej Hajda

drm/bridge: tc358767: Drop custom tc_write()/tc_read() accessors

A very unfortunate aspect of tc_write()/tc_read() macro helpers is
that they capture quite a bit of context around them and thus require
the caller to have magic variables 'ret' and 'tc' as well as label
'err'. That makes a number of code paths rather counter-intuitive and
somewhat clunky, for example tc_stream_clock_calc() ends up being like
this:

	int ret;

	tc_write(DP0_VIDMNGEN1, 32768);

	return 0;
err:
	return ret;

which is rather surprising when you read the code for the first
time. Since those helpers arguably aren't really saving that much code
and there's no way of fixing them without making them too verbose to
be worth it change the driver code to not use them at all.
Signed-off-by: default avatarAndrey Smirnov <andrew.smirnov@gmail.com>
Reviewed-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190619052716.16831-6-andrew.smirnov@gmail.com
parent 3f072c30
...@@ -271,20 +271,6 @@ static inline struct tc_data *connector_to_tc(struct drm_connector *c) ...@@ -271,20 +271,6 @@ static inline struct tc_data *connector_to_tc(struct drm_connector *c)
return container_of(c, struct tc_data, connector); return container_of(c, struct tc_data, connector);
} }
/* Simple macros to avoid repeated error checks */
#define tc_write(reg, var) \
do { \
ret = regmap_write(tc->regmap, reg, var); \
if (ret) \
goto err; \
} while (0)
#define tc_read(reg, var) \
do { \
ret = regmap_read(tc->regmap, reg, var); \
if (ret) \
goto err; \
} while (0)
static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr, static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr,
unsigned int cond_mask, unsigned int cond_mask,
unsigned int cond_value, unsigned int cond_value,
...@@ -342,7 +328,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux, ...@@ -342,7 +328,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
ret = tc_aux_wait_busy(tc, 100); ret = tc_aux_wait_busy(tc, 100);
if (ret) if (ret)
goto err; return ret;
if (request == DP_AUX_I2C_WRITE || request == DP_AUX_NATIVE_WRITE) { if (request == DP_AUX_I2C_WRITE || request == DP_AUX_NATIVE_WRITE) {
/* Store data */ /* Store data */
...@@ -353,7 +339,11 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux, ...@@ -353,7 +339,11 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
tmp = (tmp << 8) | buf[i]; tmp = (tmp << 8) | buf[i];
i++; i++;
if (((i % 4) == 0) || (i == size)) { if (((i % 4) == 0) || (i == size)) {
tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp); ret = regmap_write(tc->regmap,
DP0_AUXWDATA((i - 1) >> 2),
tmp);
if (ret)
return ret;
tmp = 0; tmp = 0;
} }
} }
...@@ -363,23 +353,32 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux, ...@@ -363,23 +353,32 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
} }
/* Store address */ /* Store address */
tc_write(DP0_AUXADDR, msg->address); ret = regmap_write(tc->regmap, DP0_AUXADDR, msg->address);
if (ret)
return ret;
/* Start transfer */ /* Start transfer */
tc_write(DP0_AUXCFG0, ((size - 1) << 8) | request); ret = regmap_write(tc->regmap, DP0_AUXCFG0,
((size - 1) << 8) | request);
if (ret)
return ret;
ret = tc_aux_wait_busy(tc, 100); ret = tc_aux_wait_busy(tc, 100);
if (ret) if (ret)
goto err; return ret;
ret = tc_aux_get_status(tc, &msg->reply); ret = tc_aux_get_status(tc, &msg->reply);
if (ret) if (ret)
goto err; return ret;
if (request == DP_AUX_I2C_READ || request == DP_AUX_NATIVE_READ) { if (request == DP_AUX_I2C_READ || request == DP_AUX_NATIVE_READ) {
/* Read data */ /* Read data */
while (i < size) { while (i < size) {
if ((i % 4) == 0) if ((i % 4) == 0) {
tc_read(DP0_AUXRDATA(i >> 2), &tmp); ret = regmap_read(tc->regmap,
DP0_AUXRDATA(i >> 2), &tmp);
if (ret)
return ret;
}
buf[i] = tmp & 0xff; buf[i] = tmp & 0xff;
tmp = tmp >> 8; tmp = tmp >> 8;
i++; i++;
...@@ -387,8 +386,6 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux, ...@@ -387,8 +386,6 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
} }
return size; return size;
err:
return ret;
} }
static const char * const training_pattern1_errors[] = { static const char * const training_pattern1_errors[] = {
...@@ -445,6 +442,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) ...@@ -445,6 +442,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
int ext_div[] = {1, 2, 3, 5, 7}; int ext_div[] = {1, 2, 3, 5, 7};
int best_pixelclock = 0; int best_pixelclock = 0;
int vco_hi = 0; int vco_hi = 0;
u32 pxl_pllparam;
dev_dbg(tc->dev, "PLL: requested %d pixelclock, ref %d\n", pixelclock, dev_dbg(tc->dev, "PLL: requested %d pixelclock, ref %d\n", pixelclock,
refclk); refclk);
...@@ -514,24 +512,29 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) ...@@ -514,24 +512,29 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
best_mul = 0; best_mul = 0;
/* Power up PLL and switch to bypass */ /* Power up PLL and switch to bypass */
tc_write(PXL_PLLCTRL, PLLBYP | PLLEN); ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN);
if (ret)
return ret;
tc_write(PXL_PLLPARAM, pxl_pllparam = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */
(vco_hi << 24) | /* For PLL VCO >= 300 MHz = 1 */ pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */
(ext_div[best_pre] << 20) | /* External Pre-divider */ pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */
(ext_div[best_post] << 16) | /* External Post-divider */ pxl_pllparam |= IN_SEL_REFCLK; /* Use RefClk as PLL input */
IN_SEL_REFCLK | /* Use RefClk as PLL input */ pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */
(best_div << 8) | /* Divider for PLL RefClk */ pxl_pllparam |= best_mul; /* Multiplier for PLL */
(best_mul << 0)); /* Multiplier for PLL */
ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam);
if (ret)
return ret;
/* Force PLL parameter update and disable bypass */ /* Force PLL parameter update and disable bypass */
tc_write(PXL_PLLCTRL, PLLUPDATE | PLLEN); ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLUPDATE | PLLEN);
if (ret)
return ret;
tc_wait_pll_lock(tc); tc_wait_pll_lock(tc);
return 0; return 0;
err:
return ret;
} }
static int tc_pxl_pll_dis(struct tc_data *tc) static int tc_pxl_pll_dis(struct tc_data *tc)
...@@ -542,7 +545,6 @@ static int tc_pxl_pll_dis(struct tc_data *tc) ...@@ -542,7 +545,6 @@ static int tc_pxl_pll_dis(struct tc_data *tc)
static int tc_stream_clock_calc(struct tc_data *tc) static int tc_stream_clock_calc(struct tc_data *tc)
{ {
int ret;
/* /*
* If the Stream clock and Link Symbol clock are * If the Stream clock and Link Symbol clock are
* asynchronous with each other, the value of M changes over * asynchronous with each other, the value of M changes over
...@@ -558,16 +560,13 @@ static int tc_stream_clock_calc(struct tc_data *tc) ...@@ -558,16 +560,13 @@ static int tc_stream_clock_calc(struct tc_data *tc)
* M/N = f_STRMCLK / f_LSCLK * M/N = f_STRMCLK / f_LSCLK
* *
*/ */
tc_write(DP0_VIDMNGEN1, 32768); return regmap_write(tc->regmap, DP0_VIDMNGEN1, 32768);
return 0;
err:
return ret;
} }
static int tc_aux_link_setup(struct tc_data *tc) static int tc_aux_link_setup(struct tc_data *tc)
{ {
unsigned long rate; unsigned long rate;
u32 dp0_auxcfg1;
u32 value; u32 value;
int ret; int ret;
...@@ -592,18 +591,26 @@ static int tc_aux_link_setup(struct tc_data *tc) ...@@ -592,18 +591,26 @@ static int tc_aux_link_setup(struct tc_data *tc)
/* Setup DP-PHY / PLL */ /* Setup DP-PHY / PLL */
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value); ret = regmap_write(tc->regmap, SYS_PLLPARAM, value);
if (ret)
tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | PHY_A0_EN); goto err;
ret = regmap_write(tc->regmap, DP_PHY_CTRL,
BGREN | PWR_SW_EN | PHY_A0_EN);
if (ret)
goto err;
/* /*
* Initially PLLs are in bypass. Force PLL parameter update, * Initially PLLs are in bypass. Force PLL parameter update,
* disable PLL bypass, enable PLL * disable PLL bypass, enable PLL
*/ */
tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN); ret = regmap_write(tc->regmap, DP0_PLLCTRL, PLLUPDATE | PLLEN);
if (ret)
goto err;
tc_wait_pll_lock(tc); tc_wait_pll_lock(tc);
tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN); ret = regmap_write(tc->regmap, DP1_PLLCTRL, PLLUPDATE | PLLEN);
if (ret)
goto err;
tc_wait_pll_lock(tc); tc_wait_pll_lock(tc);
ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000); ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
...@@ -615,9 +622,13 @@ static int tc_aux_link_setup(struct tc_data *tc) ...@@ -615,9 +622,13 @@ static int tc_aux_link_setup(struct tc_data *tc)
} }
/* Setup AUX link */ /* Setup AUX link */
tc_write(DP0_AUXCFG1, AUX_RX_FILTER_EN | dp0_auxcfg1 = AUX_RX_FILTER_EN;
(0x06 << 8) | /* Aux Bit Period Calculator Threshold */ dp0_auxcfg1 |= 0x06 << 8; /* Aux Bit Period Calculator Threshold */
(0x3f << 0)); /* Aux Response Timeout Timer */ dp0_auxcfg1 |= 0x3f << 0; /* Aux Response Timeout Timer */
ret = regmap_write(tc->regmap, DP0_AUXCFG1, dp0_auxcfg1);
if (ret)
goto err;
return 0; return 0;
err: err:
...@@ -718,48 +729,73 @@ static int tc_set_video_mode(struct tc_data *tc, ...@@ -718,48 +729,73 @@ static int tc_set_video_mode(struct tc_data *tc,
* assume we do not need any delay when DPI is a source of * assume we do not need any delay when DPI is a source of
* sync signals * sync signals
*/ */
tc_write(VPCTRL0, ret = regmap_write(tc->regmap, VPCTRL0,
FIELD_PREP(VSDELAY, 0) | FIELD_PREP(VSDELAY, 0) |
OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED); OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
tc_write(HTIM01, if (ret)
return ret;
ret = regmap_write(tc->regmap, HTIM01,
FIELD_PREP(HBPR, ALIGN(left_margin, 2)) | FIELD_PREP(HBPR, ALIGN(left_margin, 2)) |
FIELD_PREP(HPW, ALIGN(hsync_len, 2))); FIELD_PREP(HPW, ALIGN(hsync_len, 2)));
tc_write(HTIM02, if (ret)
return ret;
ret = regmap_write(tc->regmap, HTIM02,
FIELD_PREP(HDISPR, ALIGN(mode->hdisplay, 2)) | FIELD_PREP(HDISPR, ALIGN(mode->hdisplay, 2)) |
FIELD_PREP(HFPR, ALIGN(right_margin, 2))); FIELD_PREP(HFPR, ALIGN(right_margin, 2)));
tc_write(VTIM01, if (ret)
return ret;
ret = regmap_write(tc->regmap, VTIM01,
FIELD_PREP(VBPR, upper_margin) | FIELD_PREP(VBPR, upper_margin) |
FIELD_PREP(VSPR, vsync_len)); FIELD_PREP(VSPR, vsync_len));
tc_write(VTIM02, if (ret)
return ret;
ret = regmap_write(tc->regmap, VTIM02,
FIELD_PREP(VFPR, lower_margin) | FIELD_PREP(VFPR, lower_margin) |
FIELD_PREP(VDISPR, mode->vdisplay)); FIELD_PREP(VDISPR, mode->vdisplay));
tc_write(VFUEN0, VFUEN); /* update settings */ if (ret)
return ret;
ret = regmap_write(tc->regmap, VFUEN0, VFUEN); /* update settings */
if (ret)
return ret;
/* Test pattern settings */ /* Test pattern settings */
tc_write(TSTCTL, ret = regmap_write(tc->regmap, TSTCTL,
FIELD_PREP(COLOR_R, 120) | FIELD_PREP(COLOR_R, 120) |
FIELD_PREP(COLOR_G, 20) | FIELD_PREP(COLOR_G, 20) |
FIELD_PREP(COLOR_B, 99) | FIELD_PREP(COLOR_B, 99) |
ENI2CFILTER | ENI2CFILTER |
FIELD_PREP(COLOR_BAR_MODE, COLOR_BAR_MODE_BARS)); FIELD_PREP(COLOR_BAR_MODE, COLOR_BAR_MODE_BARS));
if (ret)
return ret;
/* DP Main Stream Attributes */ /* DP Main Stream Attributes */
vid_sync_dly = hsync_len + left_margin + mode->hdisplay; vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
tc_write(DP0_VIDSYNCDELAY, ret = regmap_write(tc->regmap, DP0_VIDSYNCDELAY,
FIELD_PREP(THRESH_DLY, max_tu_symbol) | FIELD_PREP(THRESH_DLY, max_tu_symbol) |
FIELD_PREP(VID_SYNC_DLY, vid_sync_dly)); FIELD_PREP(VID_SYNC_DLY, vid_sync_dly));
tc_write(DP0_TOTALVAL, ret = regmap_write(tc->regmap, DP0_TOTALVAL,
FIELD_PREP(H_TOTAL, mode->htotal) | FIELD_PREP(H_TOTAL, mode->htotal) |
FIELD_PREP(V_TOTAL, mode->vtotal)); FIELD_PREP(V_TOTAL, mode->vtotal));
if (ret)
return ret;
tc_write(DP0_STARTVAL, ret = regmap_write(tc->regmap, DP0_STARTVAL,
FIELD_PREP(H_START, left_margin + hsync_len) | FIELD_PREP(H_START, left_margin + hsync_len) |
FIELD_PREP(V_START, upper_margin + vsync_len)); FIELD_PREP(V_START, upper_margin + vsync_len));
if (ret)
return ret;
tc_write(DP0_ACTIVEVAL, ret = regmap_write(tc->regmap, DP0_ACTIVEVAL,
FIELD_PREP(V_ACT, mode->vdisplay) | FIELD_PREP(V_ACT, mode->vdisplay) |
FIELD_PREP(H_ACT, mode->hdisplay)); FIELD_PREP(H_ACT, mode->hdisplay));
if (ret)
return ret;
dp0_syncval = FIELD_PREP(VS_WIDTH, vsync_len) | dp0_syncval = FIELD_PREP(VS_WIDTH, vsync_len) |
FIELD_PREP(HS_WIDTH, hsync_len); FIELD_PREP(HS_WIDTH, hsync_len);
...@@ -770,21 +806,25 @@ static int tc_set_video_mode(struct tc_data *tc, ...@@ -770,21 +806,25 @@ static int tc_set_video_mode(struct tc_data *tc,
if (mode->flags & DRM_MODE_FLAG_NHSYNC) if (mode->flags & DRM_MODE_FLAG_NHSYNC)
dp0_syncval |= SYNCVAL_HS_POL_ACTIVE_LOW; dp0_syncval |= SYNCVAL_HS_POL_ACTIVE_LOW;
tc_write(DP0_SYNCVAL, dp0_syncval); ret = regmap_write(tc->regmap, DP0_SYNCVAL, dp0_syncval);
if (ret)
return ret;
tc_write(DPIPXLFMT, ret = regmap_write(tc->regmap, DPIPXLFMT,
VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 |
DPI_BPP_RGB888); DPI_BPP_RGB888);
if (ret)
return ret;
tc_write(DP0_MISC, ret = regmap_write(tc->regmap, DP0_MISC,
FIELD_PREP(MAX_TU_SYMBOL, max_tu_symbol) | FIELD_PREP(MAX_TU_SYMBOL, max_tu_symbol) |
FIELD_PREP(TU_SIZE, TU_SIZE_RECOMMENDED) | FIELD_PREP(TU_SIZE, TU_SIZE_RECOMMENDED) |
BPC_8); BPC_8);
if (ret)
return ret;
return 0; return 0;
err:
return ret;
} }
static int tc_wait_link_training(struct tc_data *tc) static int tc_wait_link_training(struct tc_data *tc)
...@@ -799,11 +839,11 @@ static int tc_wait_link_training(struct tc_data *tc) ...@@ -799,11 +839,11 @@ static int tc_wait_link_training(struct tc_data *tc)
return ret; return ret;
} }
tc_read(DP0_LTSTAT, &value); ret = regmap_read(tc->regmap, DP0_LTSTAT, &value);
if (ret)
return ret;
return (value >> 8) & 0x7; return (value >> 8) & 0x7;
err:
return ret;
} }
static int tc_main_link_enable(struct tc_data *tc) static int tc_main_link_enable(struct tc_data *tc)
...@@ -818,15 +858,25 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -818,15 +858,25 @@ static int tc_main_link_enable(struct tc_data *tc)
dev_dbg(tc->dev, "link enable\n"); dev_dbg(tc->dev, "link enable\n");
tc_read(DP0CTL, &value); ret = regmap_read(tc->regmap, DP0CTL, &value);
if (WARN_ON(value & DP_EN)) if (ret)
tc_write(DP0CTL, 0); return ret;
if (WARN_ON(value & DP_EN)) {
ret = regmap_write(tc->regmap, DP0CTL, 0);
if (ret)
return ret;
}
tc_write(DP0_SRCCTRL, tc_srcctrl(tc)); ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc));
if (ret)
return ret;
/* SSCG and BW27 on DP1 must be set to the same as on DP0 */ /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
tc_write(DP1_SRCCTRL, ret = regmap_write(tc->regmap, DP1_SRCCTRL,
(tc->link.spread ? DP0_SRCCTRL_SSCG : 0) | (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0)); ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
if (ret)
return ret;
rate = clk_get_rate(tc->refclk); rate = clk_get_rate(tc->refclk);
switch (rate) { switch (rate) {
...@@ -846,27 +896,36 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -846,27 +896,36 @@ static int tc_main_link_enable(struct tc_data *tc)
return -EINVAL; return -EINVAL;
} }
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value); ret = regmap_write(tc->regmap, SYS_PLLPARAM, value);
if (ret)
return ret;
/* Setup Main Link */ /* Setup Main Link */
dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN; dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
if (tc->link.base.num_lanes == 2) if (tc->link.base.num_lanes == 2)
dp_phy_ctrl |= PHY_2LANE; dp_phy_ctrl |= PHY_2LANE;
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
if (ret)
return ret;
/* PLL setup */ /* PLL setup */
tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN); ret = regmap_write(tc->regmap, DP0_PLLCTRL, PLLUPDATE | PLLEN);
if (ret)
return ret;
tc_wait_pll_lock(tc); tc_wait_pll_lock(tc);
tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN); ret = regmap_write(tc->regmap, DP1_PLLCTRL, PLLUPDATE | PLLEN);
if (ret)
return ret;
tc_wait_pll_lock(tc); tc_wait_pll_lock(tc);
/* Reset/Enable Main Links */ /* Reset/Enable Main Links */
dp_phy_ctrl |= DP_PHY_RST | PHY_M1_RST | PHY_M0_RST; dp_phy_ctrl |= DP_PHY_RST | PHY_M1_RST | PHY_M0_RST;
tc_write(DP_PHY_CTRL, dp_phy_ctrl); ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
usleep_range(100, 200); usleep_range(100, 200);
dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST); dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST);
tc_write(DP_PHY_CTRL, dp_phy_ctrl); ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000); ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
if (ret) { if (ret) {
...@@ -877,7 +936,7 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -877,7 +936,7 @@ static int tc_main_link_enable(struct tc_data *tc)
/* Set misc: 8 bits per color */ /* Set misc: 8 bits per color */
ret = regmap_update_bits(tc->regmap, DP0_MISC, BPC_8, BPC_8); ret = regmap_update_bits(tc->regmap, DP0_MISC, BPC_8, BPC_8);
if (ret) if (ret)
goto err; return ret;
/* /*
* ASSR mode * ASSR mode
...@@ -930,53 +989,71 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -930,53 +989,71 @@ static int tc_main_link_enable(struct tc_data *tc)
/* Clock-Recovery */ /* Clock-Recovery */
/* Set DPCD 0x102 for Training Pattern 1 */ /* Set DPCD 0x102 for Training Pattern 1 */
tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE | ret = regmap_write(tc->regmap, DP0_SNKLTCTRL,
DP_LINK_SCRAMBLING_DISABLE |
DP_TRAINING_PATTERN_1); DP_TRAINING_PATTERN_1);
if (ret)
return ret;
tc_write(DP0_LTLOOPCTRL, ret = regmap_write(tc->regmap, DP0_LTLOOPCTRL,
(15 << 28) | /* Defer Iteration Count */ (15 << 28) | /* Defer Iteration Count */
(15 << 24) | /* Loop Iteration Count */ (15 << 24) | /* Loop Iteration Count */
(0xd << 0)); /* Loop Timer Delay */ (0xd << 0)); /* Loop Timer Delay */
if (ret)
return ret;
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | ret = regmap_write(tc->regmap, DP0_SRCCTRL,
DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP1); tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
DP0_SRCCTRL_AUTOCORRECT |
DP0_SRCCTRL_TP1);
if (ret)
return ret;
/* Enable DP0 to start Link Training */ /* Enable DP0 to start Link Training */
tc_write(DP0CTL, ret = regmap_write(tc->regmap, DP0CTL,
((tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) | ((tc->link.base.capabilities &
DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) |
DP_EN); DP_EN);
if (ret)
return ret;
/* wait */ /* wait */
ret = tc_wait_link_training(tc); ret = tc_wait_link_training(tc);
if (ret < 0) if (ret < 0)
goto err; return ret;
if (ret) { if (ret) {
dev_err(tc->dev, "Link training phase 1 failed: %s\n", dev_err(tc->dev, "Link training phase 1 failed: %s\n",
training_pattern1_errors[ret]); training_pattern1_errors[ret]);
ret = -ENODEV; return -ENODEV;
goto err;
} }
/* Channel Equalization */ /* Channel Equalization */
/* Set DPCD 0x102 for Training Pattern 2 */ /* Set DPCD 0x102 for Training Pattern 2 */
tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE | ret = regmap_write(tc->regmap, DP0_SNKLTCTRL,
DP_LINK_SCRAMBLING_DISABLE |
DP_TRAINING_PATTERN_2); DP_TRAINING_PATTERN_2);
if (ret)
return ret;
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | ret = regmap_write(tc->regmap, DP0_SRCCTRL,
DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP2); tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
DP0_SRCCTRL_AUTOCORRECT |
DP0_SRCCTRL_TP2);
if (ret)
return ret;
/* wait */ /* wait */
ret = tc_wait_link_training(tc); ret = tc_wait_link_training(tc);
if (ret < 0) if (ret < 0)
goto err; return ret;
if (ret) { if (ret) {
dev_err(tc->dev, "Link training phase 2 failed: %s\n", dev_err(tc->dev, "Link training phase 2 failed: %s\n",
training_pattern2_errors[ret]); training_pattern2_errors[ret]);
ret = -ENODEV; return -ENODEV;
goto err;
} }
/* /*
...@@ -989,7 +1066,10 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -989,7 +1066,10 @@ static int tc_main_link_enable(struct tc_data *tc)
*/ */
/* Clear Training Pattern, set AutoCorrect Mode = 1 */ /* Clear Training Pattern, set AutoCorrect Mode = 1 */
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_AUTOCORRECT); ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc) |
DP0_SRCCTRL_AUTOCORRECT);
if (ret)
return ret;
/* Clear DPCD 0x102 */ /* Clear DPCD 0x102 */
/* Note: Can Not use DP0_SNKLTCTRL (0x06E4) short cut */ /* Note: Can Not use DP0_SNKLTCTRL (0x06E4) short cut */
...@@ -1033,7 +1113,7 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -1033,7 +1113,7 @@ static int tc_main_link_enable(struct tc_data *tc)
dev_err(dev, "0x0205 SINK_STATUS: 0x%02x\n", tmp[3]); dev_err(dev, "0x0205 SINK_STATUS: 0x%02x\n", tmp[3]);
dev_err(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n", tmp[4]); dev_err(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n", tmp[4]);
dev_err(dev, "0x0207 ADJUST_REQUEST_LANE2_3: 0x%02x\n", tmp[5]); dev_err(dev, "0x0207 ADJUST_REQUEST_LANE2_3: 0x%02x\n", tmp[5]);
goto err; return ret;
} }
return 0; return 0;
...@@ -1042,7 +1122,6 @@ static int tc_main_link_enable(struct tc_data *tc) ...@@ -1042,7 +1122,6 @@ static int tc_main_link_enable(struct tc_data *tc)
return ret; return ret;
err_dpcd_write: err_dpcd_write:
dev_err(tc->dev, "Failed to write DPCD: %d\n", ret); dev_err(tc->dev, "Failed to write DPCD: %d\n", ret);
err:
return ret; return ret;
} }
...@@ -1052,12 +1131,11 @@ static int tc_main_link_disable(struct tc_data *tc) ...@@ -1052,12 +1131,11 @@ static int tc_main_link_disable(struct tc_data *tc)
dev_dbg(tc->dev, "link disable\n"); dev_dbg(tc->dev, "link disable\n");
tc_write(DP0_SRCCTRL, 0); ret = regmap_write(tc->regmap, DP0_SRCCTRL, 0);
tc_write(DP0CTL, 0); if (ret)
return 0;
err:
return ret; return ret;
return regmap_write(tc->regmap, DP0CTL, 0);
} }
static int tc_stream_enable(struct tc_data *tc) static int tc_stream_enable(struct tc_data *tc)
...@@ -1072,7 +1150,7 @@ static int tc_stream_enable(struct tc_data *tc) ...@@ -1072,7 +1150,7 @@ static int tc_stream_enable(struct tc_data *tc)
ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk), ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk),
1000 * tc->mode.clock); 1000 * tc->mode.clock);
if (ret) if (ret)
goto err; return ret;
} }
ret = tc_set_video_mode(tc, &tc->mode); ret = tc_set_video_mode(tc, &tc->mode);
...@@ -1087,7 +1165,9 @@ static int tc_stream_enable(struct tc_data *tc) ...@@ -1087,7 +1165,9 @@ static int tc_stream_enable(struct tc_data *tc)
value = VID_MN_GEN | DP_EN; value = VID_MN_GEN | DP_EN;
if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
value |= EF_EN; value |= EF_EN;
tc_write(DP0CTL, value); ret = regmap_write(tc->regmap, DP0CTL, value);
if (ret)
return ret;
/* /*
* VID_EN assertion should be delayed by at least N * LSCLK * VID_EN assertion should be delayed by at least N * LSCLK
* cycles from the time VID_MN_GEN is enabled in order to * cycles from the time VID_MN_GEN is enabled in order to
...@@ -1097,36 +1177,35 @@ static int tc_stream_enable(struct tc_data *tc) ...@@ -1097,36 +1177,35 @@ static int tc_stream_enable(struct tc_data *tc)
*/ */
usleep_range(500, 1000); usleep_range(500, 1000);
value |= VID_EN; value |= VID_EN;
tc_write(DP0CTL, value); ret = regmap_write(tc->regmap, DP0CTL, value);
if (ret)
return ret;
/* Set input interface */ /* Set input interface */
value = DP0_AUDSRC_NO_INPUT; value = DP0_AUDSRC_NO_INPUT;
if (tc_test_pattern) if (tc_test_pattern)
value |= DP0_VIDSRC_COLOR_BAR; value |= DP0_VIDSRC_COLOR_BAR;
else else
value |= DP0_VIDSRC_DPI_RX; value |= DP0_VIDSRC_DPI_RX;
tc_write(SYSCTRL, value); ret = regmap_write(tc->regmap, SYSCTRL, value);
if (ret)
return ret;
return 0; return 0;
err:
return ret;
} }
static int tc_stream_disable(struct tc_data *tc) static int tc_stream_disable(struct tc_data *tc)
{ {
int ret; int ret;
u32 val;
dev_dbg(tc->dev, "disable video stream\n"); dev_dbg(tc->dev, "disable video stream\n");
tc_read(DP0CTL, &val); ret = regmap_update_bits(tc->regmap, DP0CTL, VID_EN, 0);
val &= ~VID_EN; if (ret)
tc_write(DP0CTL, val); return ret;
tc_pxl_pll_dis(tc); tc_pxl_pll_dis(tc);
return 0; return 0;
err:
return ret;
} }
static void tc_bridge_pre_enable(struct drm_bridge *bridge) static void tc_bridge_pre_enable(struct drm_bridge *bridge)
...@@ -1278,7 +1357,9 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne ...@@ -1278,7 +1357,9 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne
return connector_status_unknown; return connector_status_unknown;
} }
tc_read(GPIOI, &val); ret = regmap_read(tc->regmap, GPIOI, &val);
if (ret)
return connector_status_unknown;
conn = val & BIT(tc->hpd_pin); conn = val & BIT(tc->hpd_pin);
...@@ -1286,9 +1367,6 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne ...@@ -1286,9 +1367,6 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne
return connector_status_connected; return connector_status_connected;
else else
return connector_status_disconnected; return connector_status_disconnected;
err:
return connector_status_unknown;
} }
static const struct drm_connector_funcs tc_connector_funcs = { static const struct drm_connector_funcs tc_connector_funcs = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment