Karol Herbst
2023-Mar-30 22:39 UTC
[Nouveau] [PATCH] drm/nouveau/disp: Support more modes by checking with lower bpc
This allows us to advertise more modes especially on HDR displays. Fixes using 4K at 60 modes on my TV and main display both using a HDMI to DP adapter. Also fixes similiar issues for users running into this. Cc: stable at vger.kernel.org # 5.10+ Signed-off-by: Karol Herbst <kherbst at redhat.com> --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 32 +++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_dp.c | 8 ++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index ed9d374147b8d..f28e47c161dd9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder, return 0; } +static void +nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state) +{ + struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_display_mode *mode = &asyh->state.adjusted_mode; + unsigned int max_rate, mode_rate; + + switch (nv_encoder->dcb->type) { + case DCB_OUTPUT_DP: + max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw; + + /* we don't support more than 10 anyway */ + asyh->or.bpc = max_t(u8, asyh->or.bpc, 10); + + /* reduce the bpc until it works out */ + while (asyh->or.bpc > 6) { + mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8); + if (mode_rate <= max_rate) + break; + + asyh->or.bpc -= 2; + } + break; + default: + break; + } +} + static int nv50_outp_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, if (crtc_state->mode_changed || crtc_state->connectors_changed) asyh->or.bpc = connector->display_info.bpc; + /* We might have to reduce the bpc */ + nv50_outp_atomic_fix_depth(encoder, crtc_state); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index e00876f92aeea..d49b4875fc3c9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work) } /* TODO: - * - Use the minimum possible BPC here, once we add support for the max bpc - * property. * - Validate against the DP caps advertised by the GPU (we don't check these * yet) */ @@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector, { const unsigned int min_clock = 25000; unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock; - const u8 bpp = connector->display_info.bpc * 3; + /* Check with the minmum bpc always, so we can advertise better modes. + * In particlar not doing this causes modes to be dropped on HDR + * displays as we might check with a bpc of 16 even. + */ + const u8 bpp = 6 * 3; if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) return MODE_NO_INTERLACE; -- 2.39.2
Lyude Paul
2023-Mar-31 20:51 UTC
[Nouveau] [PATCH] drm/nouveau/disp: Support more modes by checking with lower bpc
Reviewed-by: Lyude Paul <lyude at redhat.com> On Fri, 2023-03-31 at 00:39 +0200, Karol Herbst wrote:> This allows us to advertise more modes especially on HDR displays. > > Fixes using 4K at 60 modes on my TV and main display both using a HDMI to DP > adapter. Also fixes similiar issues for users running into this. > > Cc: stable at vger.kernel.org # 5.10+ > Signed-off-by: Karol Herbst <kherbst at redhat.com> > --- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 32 +++++++++++++++++++++++++ > drivers/gpu/drm/nouveau/nouveau_dp.c | 8 ++++--- > 2 files changed, 37 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index ed9d374147b8d..f28e47c161dd9 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder, > return 0; > } > > +static void > +nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state) > +{ > + struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); > + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); > + struct drm_display_mode *mode = &asyh->state.adjusted_mode; > + unsigned int max_rate, mode_rate; > + > + switch (nv_encoder->dcb->type) { > + case DCB_OUTPUT_DP: > + max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw; > + > + /* we don't support more than 10 anyway */ > + asyh->or.bpc = max_t(u8, asyh->or.bpc, 10); > + > + /* reduce the bpc until it works out */ > + while (asyh->or.bpc > 6) { > + mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8); > + if (mode_rate <= max_rate) > + break; > + > + asyh->or.bpc -= 2; > + } > + break; > + default: > + break; > + } > +} > + > static int > nv50_outp_atomic_check(struct drm_encoder *encoder, > struct drm_crtc_state *crtc_state, > @@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, > if (crtc_state->mode_changed || crtc_state->connectors_changed) > asyh->or.bpc = connector->display_info.bpc; > > + /* We might have to reduce the bpc */ > + nv50_outp_atomic_fix_depth(encoder, crtc_state); > + > return 0; > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c > index e00876f92aeea..d49b4875fc3c9 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_dp.c > +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c > @@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work) > } > > /* TODO: > - * - Use the minimum possible BPC here, once we add support for the max bpc > - * property. > * - Validate against the DP caps advertised by the GPU (we don't check these > * yet) > */ > @@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector, > { > const unsigned int min_clock = 25000; > unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock; > - const u8 bpp = connector->display_info.bpc * 3; > + /* Check with the minmum bpc always, so we can advertise better modes. > + * In particlar not doing this causes modes to be dropped on HDR > + * displays as we might check with a bpc of 16 even. > + */ > + const u8 bpp = 6 * 3; > > if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) > return MODE_NO_INTERLACE;-- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
Karol Herbst
2023-Apr-01 00:19 UTC
[Nouveau] [PATCH] drm/nouveau/disp: Support more modes by checking with lower bpc
On Fri, Mar 31, 2023 at 12:39?AM Karol Herbst <kherbst at redhat.com> wrote:> > This allows us to advertise more modes especially on HDR displays. > > Fixes using 4K at 60 modes on my TV and main display both using a HDMI to DP > adapter. Also fixes similiar issues for users running into this. > > Cc: stable at vger.kernel.org # 5.10+ > Signed-off-by: Karol Herbst <kherbst at redhat.com> > --- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 32 +++++++++++++++++++++++++ > drivers/gpu/drm/nouveau/nouveau_dp.c | 8 ++++--- > 2 files changed, 37 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index ed9d374147b8d..f28e47c161dd9 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder, > return 0; > } > > +static void > +nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state) > +{ > + struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); > + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); > + struct drm_display_mode *mode = &asyh->state.adjusted_mode; > + unsigned int max_rate, mode_rate; > + > + switch (nv_encoder->dcb->type) { > + case DCB_OUTPUT_DP: > + max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw; > + > + /* we don't support more than 10 anyway */ > + asyh->or.bpc = max_t(u8, asyh->or.bpc, 10);luckily I didn't push yet, but this has to be `min_t` :)> + > + /* reduce the bpc until it works out */ > + while (asyh->or.bpc > 6) { > + mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8); > + if (mode_rate <= max_rate) > + break; > + > + asyh->or.bpc -= 2; > + } > + break; > + default: > + break; > + } > +} > + > static int > nv50_outp_atomic_check(struct drm_encoder *encoder, > struct drm_crtc_state *crtc_state, > @@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, > if (crtc_state->mode_changed || crtc_state->connectors_changed) > asyh->or.bpc = connector->display_info.bpc; > > + /* We might have to reduce the bpc */ > + nv50_outp_atomic_fix_depth(encoder, crtc_state); > + > return 0; > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c > index e00876f92aeea..d49b4875fc3c9 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_dp.c > +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c > @@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work) > } > > /* TODO: > - * - Use the minimum possible BPC here, once we add support for the max bpc > - * property. > * - Validate against the DP caps advertised by the GPU (we don't check these > * yet) > */ > @@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector, > { > const unsigned int min_clock = 25000; > unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock; > - const u8 bpp = connector->display_info.bpc * 3; > + /* Check with the minmum bpc always, so we can advertise better modes. > + * In particlar not doing this causes modes to be dropped on HDR > + * displays as we might check with a bpc of 16 even. > + */ > + const u8 bpp = 6 * 3; > > if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) > return MODE_NO_INTERLACE; > -- > 2.39.2 >
Maybe Matching Threads
- [PATCH v2 1/2] drm/nouveau/kms/nv50-: Get rid of bogus nouveau_conn_mode_valid()
- [PATCH 0/2] drm/nouveau: Stable backport of DP clock fixes for v5.9
- [PATCH 0/3] MST BPC fixes for nouveau
- [PATCH v2 0/5] drm/nouveau: DP interlace fixes
- [PATCH v3 0/5] drm/nouveau: DP interlace fixes