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 >