From 2980426a779f227ffcac342240b0c3ca3d386da8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 21 Oct 2019 16:34:26 +0200 Subject: drm/dp: Remove a gratuituous blank line It's idiomatic to check the return value of a function call immediately after the function call, without any blank lines in between, to make it more obvious that the two lines belong together. Reviewed-by: Lyude Paul Signed-off-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20191021143437.1477719-3-thierry.reding@gmail.com --- drivers/gpu/drm/drm_dp_helper.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/drm_dp_helper.c') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f373798d82f6..8f2d7c4850ca 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -220,7 +220,6 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, } ret = aux->transfer(aux, &msg); - if (ret >= 0) { native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK; if (native_reply == DP_AUX_NATIVE_REPLY_ACK) { -- cgit v1.2.3 From fc6b42045e51a8e2793751e03daa39dc99c25983 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 21 Oct 2019 16:34:30 +0200 Subject: drm/dp: Do not busy-loop during link training Use microsecond sleeps for the clock recovery and channel equalization delays during link training. The duration of these delays can be from 100 us up to 16 ms. It is rude to busy-loop for that amount of time. While at it, also convert to standard coding style by putting the opening braces in a function definition on a new line. Also switch to using an unsigned int for the AUX read interval to match the data type of the parameters to usleep_range(). v2: use correct multiplier for training delays (Philipp Zabel) v3: clarify data type change in commit message Signed-off-by: Thierry Reding Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191021143437.1477719-7-thierry.reding@gmail.com --- drivers/gpu/drm/drm_dp_helper.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/drm_dp_helper.c') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 8f2d7c4850ca..ac802b04f120 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -120,33 +120,39 @@ u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SI } EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis); -void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { - int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & - DP_TRAINING_AUX_RD_MASK; +void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_TRAINING_AUX_RD_MASK; if (rd_interval > 4) - DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n", + DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n", rd_interval); if (rd_interval == 0 || dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14) - udelay(100); + rd_interval = 100; else - mdelay(rd_interval * 4); + rd_interval *= 4 * USEC_PER_MSEC; + + usleep_range(rd_interval, rd_interval * 2); } EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay); -void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { - int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & - DP_TRAINING_AUX_RD_MASK; +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_TRAINING_AUX_RD_MASK; if (rd_interval > 4) - DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n", + DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n", rd_interval); if (rd_interval == 0) - udelay(400); + rd_interval = 400; else - mdelay(rd_interval * 4); + rd_interval *= 4 * USEC_PER_MSEC; + + usleep_range(rd_interval, rd_interval * 2); } EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay); -- cgit v1.2.3 From 79465e0ffeb9e4866939ea562bc55367be91e595 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 21 Oct 2019 16:34:31 +0200 Subject: drm/dp: Add helper to get post-cursor adjustments If the transmitter supports pre-emphasis post cursor2 the sink will request adjustments in a similar way to how it requests adjustments to the voltage swing and pre-emphasis settings. Add a helper to extract these adjustments on a per-lane basis from the DPCD link status. Reviewed-by: Philipp Zabel Reviewed-by: Lyude Paul Signed-off-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20191021143437.1477719-8-thierry.reding@gmail.com --- drivers/gpu/drm/drm_dp_helper.c | 10 ++++++++++ include/drm/drm_dp_helper.h | 10 ++++++++++ 2 files changed, 20 insertions(+) (limited to 'drivers/gpu/drm/drm_dp_helper.c') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ac802b04f120..f567141aff54 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -120,6 +120,16 @@ u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SI } EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis); +u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE], + unsigned int lane) +{ + unsigned int offset = DP_ADJUST_REQUEST_POST_CURSOR2; + u8 value = dp_link_status(link_status, offset); + + return (value >> (lane << 1)) & 0x3; +} +EXPORT_SYMBOL(drm_dp_get_adjust_request_post_cursor); + void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b3402cb186a4..04f6c0bb0274 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -605,6 +605,14 @@ # define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 #define DP_ADJUST_REQUEST_POST_CURSOR2 0x20c +# define DP_ADJUST_POST_CURSOR2_LANE0_MASK 0x03 +# define DP_ADJUST_POST_CURSOR2_LANE0_SHIFT 0 +# define DP_ADJUST_POST_CURSOR2_LANE1_MASK 0x0c +# define DP_ADJUST_POST_CURSOR2_LANE1_SHIFT 2 +# define DP_ADJUST_POST_CURSOR2_LANE2_MASK 0x30 +# define DP_ADJUST_POST_CURSOR2_LANE2_SHIFT 4 +# define DP_ADJUST_POST_CURSOR2_LANE3_MASK 0xc0 +# define DP_ADJUST_POST_CURSOR2_LANE3_SHIFT 6 #define DP_TEST_REQUEST 0x218 # define DP_TEST_LINK_TRAINING (1 << 0) @@ -1122,6 +1130,8 @@ u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE], int lane); u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE], int lane); +u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE], + unsigned int lane); #define DP_BRANCH_OUI_HEADER_SIZE 0xc #define DP_RECEIVER_CAP_SIZE 0xf -- cgit v1.2.3 From 9a42c7c647a9ad0f7ebb147a52eda3dcb7c84292 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 21 Oct 2019 16:34:37 +0200 Subject: drm/tegra: Move drm_dp_link helpers to Tegra DRM During the discussion of patches that enhance the drm_dp_link helpers it was concluded that these helpers aren't very useful to begin with. After all other drivers have been converted not to use these helpers anymore, move these helpers into the last remaining user: Tegra DRM. If at some point these helpers are deemed more widely useful, they can be moved out into the DRM DP helpers again. Signed-off-by: Thierry Reding Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191021143437.1477719-14-thierry.reding@gmail.com --- drivers/gpu/drm/drm_dp_helper.c | 128 -------------------------------------- drivers/gpu/drm/tegra/Makefile | 1 + drivers/gpu/drm/tegra/dp.c | 133 ++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/dp.h | 26 ++++++++ drivers/gpu/drm/tegra/dpaux.c | 1 + drivers/gpu/drm/tegra/sor.c | 1 + include/drm/drm_dp_helper.h | 16 ----- 7 files changed, 162 insertions(+), 144 deletions(-) create mode 100644 drivers/gpu/drm/tegra/dp.c create mode 100644 drivers/gpu/drm/tegra/dp.h (limited to 'drivers/gpu/drm/drm_dp_helper.c') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f567141aff54..2c7870aef469 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -351,134 +351,6 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_dpcd_read_link_status); -/** - * drm_dp_link_probe() - probe a DisplayPort link for capabilities - * @aux: DisplayPort AUX channel - * @link: pointer to structure in which to return link capabilities - * - * The structure filled in by this function can usually be passed directly - * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and - * configure the link based on the link's capabilities. - * - * Returns 0 on success or a negative error code on failure. - */ -int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link) -{ - u8 values[3]; - int err; - - memset(link, 0, sizeof(*link)); - - err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values)); - if (err < 0) - return err; - - link->revision = values[0]; - link->rate = drm_dp_bw_code_to_link_rate(values[1]); - link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK; - - if (values[2] & DP_ENHANCED_FRAME_CAP) - link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; - - return 0; -} -EXPORT_SYMBOL(drm_dp_link_probe); - -/** - * drm_dp_link_power_up() - power up a DisplayPort link - * @aux: DisplayPort AUX channel - * @link: pointer to a structure containing the link configuration - * - * Returns 0 on success or a negative error code on failure. - */ -int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link) -{ - u8 value; - int err; - - /* DP_SET_POWER register is only available on DPCD v1.1 and later */ - if (link->revision < 0x11) - return 0; - - err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); - if (err < 0) - return err; - - value &= ~DP_SET_POWER_MASK; - value |= DP_SET_POWER_D0; - - err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); - if (err < 0) - return err; - - /* - * According to the DP 1.1 specification, a "Sink Device must exit the - * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink - * Control Field" (register 0x600). - */ - usleep_range(1000, 2000); - - return 0; -} -EXPORT_SYMBOL(drm_dp_link_power_up); - -/** - * drm_dp_link_power_down() - power down a DisplayPort link - * @aux: DisplayPort AUX channel - * @link: pointer to a structure containing the link configuration - * - * Returns 0 on success or a negative error code on failure. - */ -int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link) -{ - u8 value; - int err; - - /* DP_SET_POWER register is only available on DPCD v1.1 and later */ - if (link->revision < 0x11) - return 0; - - err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); - if (err < 0) - return err; - - value &= ~DP_SET_POWER_MASK; - value |= DP_SET_POWER_D3; - - err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(drm_dp_link_power_down); - -/** - * drm_dp_link_configure() - configure a DisplayPort link - * @aux: DisplayPort AUX channel - * @link: pointer to a structure containing the link configuration - * - * Returns 0 on success or a negative error code on failure. - */ -int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) -{ - u8 values[2]; - int err; - - values[0] = drm_dp_link_rate_to_bw_code(link->rate); - values[1] = link->num_lanes; - - if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) - values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - - err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(drm_dp_link_configure); - /** * drm_dp_downstream_max_clock() - extract branch device max * pixel rate for legacy VGA diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile index 33c463e8d49f..d6cf202414f0 100644 --- a/drivers/gpu/drm/tegra/Makefile +++ b/drivers/gpu/drm/tegra/Makefile @@ -5,6 +5,7 @@ tegra-drm-y := \ drm.o \ gem.o \ fb.o \ + dp.o \ hub.o \ plane.o \ dc.o \ diff --git a/drivers/gpu/drm/tegra/dp.c b/drivers/gpu/drm/tegra/dp.c new file mode 100644 index 000000000000..50ba967ebcbd --- /dev/null +++ b/drivers/gpu/drm/tegra/dp.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2013-2019 NVIDIA Corporation + * Copyright (C) 2015 Rob Clark + */ + +#include + +#include "dp.h" + +/** + * drm_dp_link_probe() - probe a DisplayPort link for capabilities + * @aux: DisplayPort AUX channel + * @link: pointer to structure in which to return link capabilities + * + * The structure filled in by this function can usually be passed directly + * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and + * configure the link based on the link's capabilities. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link) +{ + u8 values[3]; + int err; + + memset(link, 0, sizeof(*link)); + + err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values)); + if (err < 0) + return err; + + link->revision = values[0]; + link->rate = drm_dp_bw_code_to_link_rate(values[1]); + link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK; + + if (values[2] & DP_ENHANCED_FRAME_CAP) + link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; + + return 0; +} + +/** + * drm_dp_link_power_up() - power up a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link) +{ + u8 value; + int err; + + /* DP_SET_POWER register is only available on DPCD v1.1 and later */ + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + /* + * According to the DP 1.1 specification, a "Sink Device must exit the + * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink + * Control Field" (register 0x600). + */ + usleep_range(1000, 2000); + + return 0; +} + +/** + * drm_dp_link_power_down() - power down a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link) +{ + u8 value; + int err; + + /* DP_SET_POWER register is only available on DPCD v1.1 and later */ + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D3; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + return 0; +} + +/** + * drm_dp_link_configure() - configure a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) +{ + u8 values[2]; + int err; + + values[0] = drm_dp_link_rate_to_bw_code(link->rate); + values[1] = link->num_lanes; + + if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) + values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); + if (err < 0) + return err; + + return 0; +} diff --git a/drivers/gpu/drm/tegra/dp.h b/drivers/gpu/drm/tegra/dp.h new file mode 100644 index 000000000000..88842fd25abf --- /dev/null +++ b/drivers/gpu/drm/tegra/dp.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2013-2019 NVIDIA Corporation. + * Copyright (C) 2015 Rob Clark + */ + +#ifndef DRM_TEGRA_DP_H +#define DRM_TEGRA_DP_H 1 + +struct drm_dp_aux; + +#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) + +struct drm_dp_link { + unsigned char revision; + unsigned int rate; + unsigned int num_lanes; + unsigned long capabilities; +}; + +int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); + +#endif diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index a0f6f9b0d258..1144605c9737 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -22,6 +22,7 @@ #include #include +#include "dp.h" #include "dpaux.h" #include "drm.h" #include "trace.h" diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index e1669ada0a40..fbbb974c1e1a 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -25,6 +25,7 @@ #include #include "dc.h" +#include "dp.h" #include "drm.h" #include "hda.h" #include "sor.h" diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 04f6c0bb0274..51ecb5112ef8 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1455,22 +1455,6 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, u8 status[DP_LINK_STATUS_SIZE]); -/* - * DisplayPort link - */ -#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) - -struct drm_dp_link { - unsigned char revision; - unsigned int rate; - unsigned int num_lanes; - unsigned long capabilities; -}; - -int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); -int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); -int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); -int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], -- cgit v1.2.3