Merge branch 'linux-5.5' of git://github.com/skeggsb/linux into drm-fixes
Bunch of random nouveau fixes. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Ben Skeggs <skeggsb@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/ <CACAvsv56Am90okV334eXgxDuK228sb9UJxMiOYjNAMShvvv4cg@mail.gmail.com
This commit is contained in:
commit
cdf1d28ced
|
@ -114,6 +114,7 @@ struct nv50_head_atom {
|
|||
u8 nhsync:1;
|
||||
u8 nvsync:1;
|
||||
u8 depth:4;
|
||||
u8 bpc;
|
||||
} or;
|
||||
|
||||
/* Currently only used for MST */
|
||||
|
|
|
@ -326,9 +326,9 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
|
|||
* same size as the native one (e.g. different
|
||||
* refresh rate)
|
||||
*/
|
||||
if (adjusted_mode->hdisplay == native_mode->hdisplay &&
|
||||
adjusted_mode->vdisplay == native_mode->vdisplay &&
|
||||
adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
|
||||
if (mode->hdisplay == native_mode->hdisplay &&
|
||||
mode->vdisplay == native_mode->vdisplay &&
|
||||
mode->type & DRM_MODE_TYPE_DRIVER)
|
||||
break;
|
||||
mode = native_mode;
|
||||
asyc->scaler.full = true;
|
||||
|
@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
|
|||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct nouveau_connector *nv_connector =
|
||||
nouveau_connector(conn_state->connector);
|
||||
return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
|
||||
nv_connector->native_mode);
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (crtc_state->mode_changed || crtc_state->connectors_changed)
|
||||
asyh->or.bpc = connector->display_info.bpc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
|
|||
struct nv50_mstm *mstm = mstc->mstm;
|
||||
struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
|
||||
int slots;
|
||||
int ret;
|
||||
|
||||
ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
|
||||
mstc->native);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* When restoring duplicated states, we need to make sure that the bw
|
||||
* remains the same and avoid recalculating it, as the connector's bpc
|
||||
* may have changed after the state was duplicated
|
||||
*/
|
||||
if (!state->duplicated) {
|
||||
const int clock = crtc_state->adjusted_mode.clock;
|
||||
|
||||
if (crtc_state->mode_changed || crtc_state->connectors_changed) {
|
||||
/*
|
||||
* When restoring duplicated states, we need to make sure that
|
||||
* the bw remains the same and avoid recalculating it, as the
|
||||
* connector's bpc may have changed after the state was
|
||||
* duplicated
|
||||
* XXX: Since we don't use HDR in userspace quite yet, limit
|
||||
* the bpc to 8 to save bandwidth on the topology. In the
|
||||
* future, we'll want to properly fix this by dynamically
|
||||
* selecting the highest possible bpc that would fit in the
|
||||
* topology
|
||||
*/
|
||||
if (!state->duplicated) {
|
||||
const int bpp = connector->display_info.bpc * 3;
|
||||
const int clock = crtc_state->adjusted_mode.clock;
|
||||
|
||||
asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
|
||||
}
|
||||
|
||||
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
|
||||
mstc->port,
|
||||
asyh->dp.pbn);
|
||||
if (slots < 0)
|
||||
return slots;
|
||||
|
||||
asyh->dp.tu = slots;
|
||||
asyh->or.bpc = min(connector->display_info.bpc, 8U);
|
||||
asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
|
||||
}
|
||||
|
||||
return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
|
||||
mstc->native);
|
||||
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
|
||||
asyh->dp.pbn);
|
||||
if (slots < 0)
|
||||
return slots;
|
||||
|
||||
asyh->dp.tu = slots;
|
||||
|
||||
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
|
||||
|
@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
|
|||
struct nv50_mstm *mstm = NULL;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
u8 proto, depth;
|
||||
u8 proto;
|
||||
bool r;
|
||||
|
||||
drm_connector_list_iter_begin(encoder->dev, &conn_iter);
|
||||
|
@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
|
|||
else
|
||||
proto = 0x9;
|
||||
|
||||
switch (mstc->connector.display_info.bpc) {
|
||||
case 6: depth = 0x2; break;
|
||||
case 8: depth = 0x5; break;
|
||||
case 10:
|
||||
default: depth = 0x6; break;
|
||||
}
|
||||
|
||||
mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
|
||||
mstm->outp->update(mstm->outp, head->base.index, armh, proto,
|
||||
nv50_dp_bpc_to_depth(armh->or.bpc));
|
||||
|
||||
msto->head = head;
|
||||
msto->mstc = mstc;
|
||||
|
@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *encoder)
|
|||
lvds.lvds.script |= 0x0200;
|
||||
}
|
||||
|
||||
if (nv_connector->base.display_info.bpc == 8)
|
||||
if (asyh->or.bpc == 8)
|
||||
lvds.lvds.script |= 0x0200;
|
||||
}
|
||||
|
||||
nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
|
||||
break;
|
||||
case DCB_OUTPUT_DP:
|
||||
if (nv_connector->base.display_info.bpc == 6)
|
||||
depth = 0x2;
|
||||
else
|
||||
if (nv_connector->base.display_info.bpc == 8)
|
||||
depth = 0x5;
|
||||
else
|
||||
depth = 0x6;
|
||||
depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
|
||||
|
||||
if (nv_encoder->link & 1)
|
||||
proto = 0x8;
|
||||
|
@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *encoder)
|
|||
nv50_outp_acquire(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 8: asyh->or.depth = 0x5; break;
|
||||
case 6: asyh->or.depth = 0x2; break;
|
||||
|
|
|
@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
|
|||
struct nv50_head_atom *asyh,
|
||||
struct nouveau_conn_atom *asyc)
|
||||
{
|
||||
struct drm_connector *connector = asyc->state.connector;
|
||||
u32 mode = 0x00;
|
||||
|
||||
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;
|
||||
} else {
|
||||
mode = asyc->dither.mode;
|
||||
}
|
||||
|
||||
if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
|
||||
if (connector->display_info.bpc >= 8)
|
||||
if (asyh->or.bpc >= 8)
|
||||
mode |= DITHERING_DEPTH_8BPC;
|
||||
} else {
|
||||
mode |= asyc->dither.depth;
|
||||
|
|
|
@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
|
|||
void
|
||||
nouveau_conn_reset(struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_conn_atom *asyc;
|
||||
|
||||
if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
|
||||
return;
|
||||
if (drm_drv_uses_atomic_modeset(connector->dev)) {
|
||||
if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
|
||||
return;
|
||||
|
||||
if (connector->state)
|
||||
nouveau_conn_atomic_destroy_state(connector,
|
||||
connector->state);
|
||||
|
||||
__drm_atomic_helper_connector_reset(connector, &asyc->state);
|
||||
} else {
|
||||
asyc = &nv_connector->properties_state;
|
||||
}
|
||||
|
||||
if (connector->state)
|
||||
nouveau_conn_atomic_destroy_state(connector, connector->state);
|
||||
__drm_atomic_helper_connector_reset(connector, &asyc->state);
|
||||
asyc->dither.mode = DITHERING_MODE_AUTO;
|
||||
asyc->dither.depth = DITHERING_DEPTH_AUTO;
|
||||
asyc->scaler.mode = DRM_MODE_SCALE_NONE;
|
||||
|
@ -276,8 +284,14 @@ void
|
|||
nouveau_conn_attach_properties(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_conn_atom *armc;
|
||||
|
||||
if (drm_drv_uses_atomic_modeset(connector->dev))
|
||||
armc = nouveau_conn_atom(connector->state);
|
||||
else
|
||||
armc = &nv_connector->properties_state;
|
||||
|
||||
/* Init DVI-I specific properties. */
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
|
||||
|
@ -748,9 +762,9 @@ static int
|
|||
nouveau_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property, uint64_t value)
|
||||
{
|
||||
struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
||||
struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
|
||||
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
|
||||
int ret;
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <nvif/notify.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
@ -44,6 +45,60 @@ struct dcb_output;
|
|||
struct nouveau_backlight;
|
||||
#endif
|
||||
|
||||
#define nouveau_conn_atom(p) \
|
||||
container_of((p), struct nouveau_conn_atom, state)
|
||||
|
||||
struct nouveau_conn_atom {
|
||||
struct drm_connector_state state;
|
||||
|
||||
struct {
|
||||
/* The enum values specifically defined here match nv50/gf119
|
||||
* hw values, and the code relies on this.
|
||||
*/
|
||||
enum {
|
||||
DITHERING_MODE_OFF = 0x00,
|
||||
DITHERING_MODE_ON = 0x01,
|
||||
DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_AUTO
|
||||
} mode;
|
||||
enum {
|
||||
DITHERING_DEPTH_6BPC = 0x00,
|
||||
DITHERING_DEPTH_8BPC = 0x02,
|
||||
DITHERING_DEPTH_AUTO
|
||||
} depth;
|
||||
} dither;
|
||||
|
||||
struct {
|
||||
int mode; /* DRM_MODE_SCALE_* */
|
||||
struct {
|
||||
enum {
|
||||
UNDERSCAN_OFF,
|
||||
UNDERSCAN_ON,
|
||||
UNDERSCAN_AUTO,
|
||||
} mode;
|
||||
u32 hborder;
|
||||
u32 vborder;
|
||||
} underscan;
|
||||
bool full;
|
||||
} scaler;
|
||||
|
||||
struct {
|
||||
int color_vibrance;
|
||||
int vibrant_hue;
|
||||
} procamp;
|
||||
|
||||
union {
|
||||
struct {
|
||||
bool dither:1;
|
||||
bool scaler:1;
|
||||
bool procamp:1;
|
||||
};
|
||||
u8 mask;
|
||||
} set;
|
||||
};
|
||||
|
||||
struct nouveau_connector {
|
||||
struct drm_connector base;
|
||||
enum dcb_connector_type type;
|
||||
|
@ -63,6 +118,12 @@ struct nouveau_connector {
|
|||
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
||||
struct nouveau_backlight *backlight;
|
||||
#endif
|
||||
/*
|
||||
* Our connector property code expects a nouveau_conn_atom struct
|
||||
* even on pre-nv50 where we do not support atomic. This embedded
|
||||
* version gets used in the non atomic modeset case.
|
||||
*/
|
||||
struct nouveau_conn_atom properties_state;
|
||||
};
|
||||
|
||||
static inline struct nouveau_connector *nouveau_connector(
|
||||
|
@ -121,61 +182,6 @@ extern int nouveau_ignorelid;
|
|||
extern int nouveau_duallink;
|
||||
extern int nouveau_hdmimhz;
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#define nouveau_conn_atom(p) \
|
||||
container_of((p), struct nouveau_conn_atom, state)
|
||||
|
||||
struct nouveau_conn_atom {
|
||||
struct drm_connector_state state;
|
||||
|
||||
struct {
|
||||
/* The enum values specifically defined here match nv50/gf119
|
||||
* hw values, and the code relies on this.
|
||||
*/
|
||||
enum {
|
||||
DITHERING_MODE_OFF = 0x00,
|
||||
DITHERING_MODE_ON = 0x01,
|
||||
DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_AUTO
|
||||
} mode;
|
||||
enum {
|
||||
DITHERING_DEPTH_6BPC = 0x00,
|
||||
DITHERING_DEPTH_8BPC = 0x02,
|
||||
DITHERING_DEPTH_AUTO
|
||||
} depth;
|
||||
} dither;
|
||||
|
||||
struct {
|
||||
int mode; /* DRM_MODE_SCALE_* */
|
||||
struct {
|
||||
enum {
|
||||
UNDERSCAN_OFF,
|
||||
UNDERSCAN_ON,
|
||||
UNDERSCAN_AUTO,
|
||||
} mode;
|
||||
u32 hborder;
|
||||
u32 vborder;
|
||||
} underscan;
|
||||
bool full;
|
||||
} scaler;
|
||||
|
||||
struct {
|
||||
int color_vibrance;
|
||||
int vibrant_hue;
|
||||
} procamp;
|
||||
|
||||
union {
|
||||
struct {
|
||||
bool dither:1;
|
||||
bool scaler:1;
|
||||
bool procamp:1;
|
||||
};
|
||||
u8 mask;
|
||||
} set;
|
||||
};
|
||||
|
||||
void nouveau_conn_attach_properties(struct drm_connector *);
|
||||
void nouveau_conn_reset(struct drm_connector *);
|
||||
struct drm_connector_state *
|
||||
|
|
Loading…
Reference in a new issue