Commit ac2d9275 authored by Lyude Paul's avatar Lyude Paul Committed by Ben Skeggs

drm/nouveau/kms/nv50-: Store the bpc we're using in nv50_head_atom

In order to be able to use bpc values that are different from what the
connector reports, we want to be able to store the bpc value we decide
on using for an atomic state in nv50_head_atom and refer to that instead
of simply using the value that the connector reports throughout the
whole atomic check phase and commit phase. This will let us (eventually)
implement the max bpc connector property, and will also be needed for
limiting the bpc we use on MST displays to 8 in the next commit.
Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Fixes: 232c9eec ("drm/nouveau: Use atomic VCPI helpers for MST")
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: David Airlie <airlied@redhat.com>
Cc: Jerry Zuo <Jerry.Zuo@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Juston Li <juston.li@intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: <stable@vger.kernel.org> # v5.1+
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 310d3577
...@@ -114,6 +114,7 @@ struct nv50_head_atom { ...@@ -114,6 +114,7 @@ struct nv50_head_atom {
u8 nhsync:1; u8 nhsync:1;
u8 nvsync:1; u8 nvsync:1;
u8 depth:4; u8 depth:4;
u8 bpc;
} or; } or;
/* Currently only used for MST */ /* Currently only used for MST */
......
...@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, ...@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state) struct drm_connector_state *conn_state)
{ {
struct nouveau_connector *nv_connector = struct drm_connector *connector = conn_state->connector;
nouveau_connector(conn_state->connector); struct nouveau_connector *nv_connector = nouveau_connector(connector);
return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
int ret;
ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
nv_connector->native_mode); nv_connector->native_mode);
if (ret)
return ret;
if (crtc_state->mode_changed || crtc_state->connectors_changed)
asyh->or.bpc = connector->display_info.bpc;
return 0;
} }
/****************************************************************************** /******************************************************************************
...@@ -786,10 +796,10 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, ...@@ -786,10 +796,10 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
* may have changed after the state was duplicated * may have changed after the state was duplicated
*/ */
if (!state->duplicated) { if (!state->duplicated) {
const int bpp = connector->display_info.bpc * 3;
const int clock = crtc_state->adjusted_mode.clock; const int clock = crtc_state->adjusted_mode.clock;
asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp); asyh->or.bpc = connector->display_info.bpc;
asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
} }
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
...@@ -802,6 +812,17 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, ...@@ -802,6 +812,17 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
return 0; return 0;
} }
static u8
nv50_dp_bpc_to_depth(unsigned int bpc)
{
switch (bpc) {
case 6: return 0x2;
case 8: return 0x5;
case 10: /* fall-through */
default: return 0x6;
}
}
static void static void
nv50_msto_enable(struct drm_encoder *encoder) nv50_msto_enable(struct drm_encoder *encoder)
{ {
...@@ -812,7 +833,7 @@ nv50_msto_enable(struct drm_encoder *encoder) ...@@ -812,7 +833,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
struct nv50_mstm *mstm = NULL; struct nv50_mstm *mstm = NULL;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
u8 proto, depth; u8 proto;
bool r; bool r;
drm_connector_list_iter_begin(encoder->dev, &conn_iter); drm_connector_list_iter_begin(encoder->dev, &conn_iter);
...@@ -841,14 +862,8 @@ nv50_msto_enable(struct drm_encoder *encoder) ...@@ -841,14 +862,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
else else
proto = 0x9; proto = 0x9;
switch (mstc->connector.display_info.bpc) { mstm->outp->update(mstm->outp, head->base.index, armh, proto,
case 6: depth = 0x2; break; nv50_dp_bpc_to_depth(armh->or.bpc));
case 8: depth = 0x5; break;
case 10:
default: depth = 0x6; break;
}
mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
msto->head = head; msto->head = head;
msto->mstc = mstc; msto->mstc = mstc;
...@@ -1502,20 +1517,14 @@ nv50_sor_enable(struct drm_encoder *encoder) ...@@ -1502,20 +1517,14 @@ nv50_sor_enable(struct drm_encoder *encoder)
lvds.lvds.script |= 0x0200; lvds.lvds.script |= 0x0200;
} }
if (nv_connector->base.display_info.bpc == 8) if (asyh->or.bpc == 8)
lvds.lvds.script |= 0x0200; lvds.lvds.script |= 0x0200;
} }
nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds)); nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
break; break;
case DCB_OUTPUT_DP: case DCB_OUTPUT_DP:
if (nv_connector->base.display_info.bpc == 6) depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
depth = 0x2;
else
if (nv_connector->base.display_info.bpc == 8)
depth = 0x5;
else
depth = 0x6;
if (nv_encoder->link & 1) if (nv_encoder->link & 1)
proto = 0x8; proto = 0x8;
...@@ -1666,7 +1675,7 @@ nv50_pior_enable(struct drm_encoder *encoder) ...@@ -1666,7 +1675,7 @@ nv50_pior_enable(struct drm_encoder *encoder)
nv50_outp_acquire(nv_encoder); nv50_outp_acquire(nv_encoder);
nv_connector = nouveau_encoder_connector_get(nv_encoder); nv_connector = nouveau_encoder_connector_get(nv_encoder);
switch (nv_connector->base.display_info.bpc) { switch (asyh->or.bpc) {
case 10: asyh->or.depth = 0x6; break; case 10: asyh->or.depth = 0x6; break;
case 8: asyh->or.depth = 0x5; break; case 8: asyh->or.depth = 0x5; break;
case 6: asyh->or.depth = 0x2; break; case 6: asyh->or.depth = 0x2; break;
......
...@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh, ...@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
struct nv50_head_atom *asyh, struct nv50_head_atom *asyh,
struct nouveau_conn_atom *asyc) struct nouveau_conn_atom *asyc)
{ {
struct drm_connector *connector = asyc->state.connector;
u32 mode = 0x00; u32 mode = 0x00;
if (asyc->dither.mode == DITHERING_MODE_AUTO) { if (asyc->dither.mode == DITHERING_MODE_AUTO) {
if (asyh->base.depth > connector->display_info.bpc * 3) if (asyh->base.depth > asyh->or.bpc * 3)
mode = DITHERING_MODE_DYNAMIC2X2; mode = DITHERING_MODE_DYNAMIC2X2;
} else { } else {
mode = asyc->dither.mode; mode = asyc->dither.mode;
} }
if (asyc->dither.depth == DITHERING_DEPTH_AUTO) { if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
if (connector->display_info.bpc >= 8) if (asyh->or.bpc >= 8)
mode |= DITHERING_DEPTH_8BPC; mode |= DITHERING_DEPTH_8BPC;
} else { } else {
mode |= asyc->dither.depth; mode |= asyc->dither.depth;
......
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