Re: [PATCH v3 6/9] drm/bridge: ti-sn65dsi86: Use 18-bit DP if we can
From: Bjorn Andersson
Date: Mon Feb 03 2020 - 18:37:17 EST
On Wed 18 Dec 14:35 PST 2019, Douglas Anderson wrote:
> The current bridge driver always forced us to use 24 bits per pixel
> over the DP link. This is a waste if you are hooked up to a panel
> that only supports 6 bits per color or fewer, since in that case you
> ran run at 18 bits per pixel and thus end up at a lower DP clock rate.
s/ran/can/
>
> Let's support this.
>
> While at it, let's clean up the math in the function to avoid rounding
> errors (and round in the correct direction when we have to round).
> Numbers are sufficiently small (because mode->clock is in kHz) that we
> don't need to worry about integer overflow.
>
> Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
> Tested-by: Rob Clark <robdclark@xxxxxxxxx>
> Reviewed-by: Rob Clark <robdclark@xxxxxxxxx>
Reviewed-by: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
> drivers/gpu/drm/bridge/ti-sn65dsi86.c | 27 ++++++++++++++++++---------
> 1 file changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 0fc9e97b2d98..d5990a0947b9 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -51,6 +51,7 @@
> #define SN_ENH_FRAME_REG 0x5A
> #define VSTREAM_ENABLE BIT(3)
> #define SN_DATA_FORMAT_REG 0x5B
> +#define BPP_18_RGB BIT(0)
> #define SN_HPD_DISABLE_REG 0x5C
> #define HPD_DISABLE BIT(0)
> #define SN_AUX_WDATA_REG(x) (0x64 + (x))
> @@ -436,6 +437,14 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn_bridge *pdata)
> regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
> }
>
> +static unsigned int ti_sn_bridge_get_bpp(struct ti_sn_bridge *pdata)
> +{
> + if (pdata->connector.display_info.bpc <= 6)
> + return 18;
> + else
> + return 24;
> +}
> +
> /**
> * LUT index corresponds to register value and
> * LUT values corresponds to dp data rate supported
> @@ -447,21 +456,17 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
>
> static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata)
> {
> - unsigned int bit_rate_mhz, dp_rate_mhz;
> + unsigned int bit_rate_khz, dp_rate_mhz;
> unsigned int i;
> struct drm_display_mode *mode =
> &pdata->bridge.encoder->crtc->state->adjusted_mode;
>
> - /*
> - * Calculate minimum bit rate based on our pixel clock. At
> - * the moment this driver never sets the DP_18BPP_EN bit in
> - * register 0x5b so we hardcode 24bpp.
> - */
> - bit_rate_mhz = (mode->clock / 1000) * 24;
> + /* Calculate minimum bit rate based on our pixel clock. */
> + bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata);
>
> /* Calculate minimum DP data rate, taking 80% as per DP spec */
> - dp_rate_mhz = ((bit_rate_mhz / pdata->dp_lanes) * DP_CLK_FUDGE_NUM) /
> - DP_CLK_FUDGE_DEN;
> + dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM,
> + 1000 * pdata->dp_lanes * DP_CLK_FUDGE_DEN);
>
> for (i = 1; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++)
> if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz)
> @@ -550,6 +555,10 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge)
> regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG,
> CHA_DSI_LANES_MASK, val);
>
> + /* Set the DP output format (18 bpp or 24 bpp) */
> + val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0;
> + regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val);
> +
> /* DP lane config */
> val = DP_NUM_LANES(min(pdata->dp_lanes, 3));
> regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK,
> --
> 2.24.1.735.g03f4e72817-goog
>