Skip to content

Commit

Permalink
drm/nouveau/kms/gf119-: allow both 256- and 1024-sized LUTs to be used
Browse files Browse the repository at this point in the history
The hardware supports either size. Also add checks to ensure that only
these two sizes may be used for supplying a LUT.

Signed-off-by: Ilia Mirkin <[email protected]>
Signed-off-by: Ben Skeggs <[email protected]>
  • Loading branch information
imirkin authored and Ben Skeggs committed Jan 15, 2020
1 parent 11a8630 commit 1319927
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 40 deletions.
11 changes: 8 additions & 3 deletions drivers/gpu/drm/nouveau/dispnv50/base907c.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,16 @@ base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
}
}

static void
base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
static bool
base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
{
asyw->xlut.i.mode = 7;
if (size != 256 && size != 1024)
return false;

asyw->xlut.i.mode = size == 1024 ? 4 : 7;
asyw->xlut.i.enable = 2;
asyw->xlut.i.load = head907d_olut_load;
return true;
}

static inline u32
Expand Down Expand Up @@ -160,6 +164,7 @@ base907c = {
.csc_set = base907c_csc_set,
.csc_clr = base907c_csc_clr,
.olut_core = true,
.ilut_size = 1024,
.xlut_set = base907c_xlut_set,
.xlut_clr = base907c_xlut_clr,
.image_set = base907c_image_set,
Expand Down
26 changes: 18 additions & 8 deletions drivers/gpu/drm/nouveau/dispnv50/head.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
{
struct nv50_disp *disp = nv50_disp(head->base.base.dev);
struct drm_property_blob *olut = asyh->state.gamma_lut;
int size;

/* Determine whether core output LUT should be enabled. */
if (olut) {
Expand All @@ -229,14 +230,23 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
}
}

if (!olut && !head->func->olut_identity) {
asyh->olut.handle = 0;
return 0;
if (!olut) {
if (!head->func->olut_identity) {
asyh->olut.handle = 0;
return 0;
}
size = 0;
} else {
size = drm_color_lut_size(olut);
}

if (!head->func->olut(head, asyh, size)) {
DRM_DEBUG_KMS("Invalid olut\n");
return -EINVAL;
}
asyh->olut.handle = disp->core->chan.vram.handle;
asyh->olut.buffer = !asyh->olut.buffer;
head->func->olut(head, asyh);

return 0;
}

Expand Down Expand Up @@ -510,11 +520,11 @@ nv50_head_create(struct drm_device *dev, int index)
drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane,
&nv50_head_func, "head-%d", head->base.index);
drm_crtc_helper_add(crtc, &nv50_head_help);
/* Keep the legacy gamma size at 256 to avoid compatibility issues */
drm_mode_crtc_set_gamma_size(crtc, 256);
if (disp->disp->object.oclass >= GF110_DISP)
drm_crtc_enable_color_mgmt(crtc, 256, true, 256);
else
drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
disp->disp->object.oclass >= GF110_DISP,
head->func->olut_size);

if (head->func->olut_set) {
ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/nouveau/dispnv50/head.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ void nv50_head_flush_clr(struct nv50_head *, struct nv50_head_atom *, bool y);
struct nv50_head_func {
void (*view)(struct nv50_head *, struct nv50_head_atom *);
void (*mode)(struct nv50_head *, struct nv50_head_atom *);
void (*olut)(struct nv50_head *, struct nv50_head_atom *);
bool (*olut)(struct nv50_head *, struct nv50_head_atom *, int);
bool olut_identity;
int olut_size;
void (*olut_set)(struct nv50_head *, struct nv50_head_atom *);
void (*olut_clr)(struct nv50_head *);
void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
Expand All @@ -43,7 +44,7 @@ struct nv50_head_func {
extern const struct nv50_head_func head507d;
void head507d_view(struct nv50_head *, struct nv50_head_atom *);
void head507d_mode(struct nv50_head *, struct nv50_head_atom *);
void head507d_olut(struct nv50_head *, struct nv50_head_atom *);
bool head507d_olut(struct nv50_head *, struct nv50_head_atom *, int);
void head507d_core_calc(struct nv50_head *, struct nv50_head_atom *);
void head507d_core_clr(struct nv50_head *);
int head507d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *,
Expand All @@ -60,7 +61,7 @@ extern const struct nv50_head_func head827d;
extern const struct nv50_head_func head907d;
void head907d_view(struct nv50_head *, struct nv50_head_atom *);
void head907d_mode(struct nv50_head *, struct nv50_head_atom *);
void head907d_olut(struct nv50_head *, struct nv50_head_atom *);
bool head907d_olut(struct nv50_head *, struct nv50_head_atom *, int);
void head907d_olut_set(struct nv50_head *, struct nv50_head_atom *);
void head907d_olut_clr(struct nv50_head *);
void head907d_core_set(struct nv50_head *, struct nv50_head_atom *);
Expand Down
9 changes: 7 additions & 2 deletions drivers/gpu/drm/nouveau/dispnv50/head507d.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,19 @@ head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
writew(readw(mem - 4), mem + 4);
}

void
head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
bool
head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
{
if (size != 256)
return false;

if (asyh->base.cpp == 1)
asyh->olut.mode = 0;
else
asyh->olut.mode = 1;

asyh->olut.load = head507d_olut_load;
return true;
}

void
Expand Down Expand Up @@ -328,6 +332,7 @@ head507d = {
.view = head507d_view,
.mode = head507d_mode,
.olut = head507d_olut,
.olut_size = 256,
.olut_set = head507d_olut_set,
.olut_clr = head507d_olut_clr,
.core_calc = head507d_core_calc,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/dispnv50/head827d.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ head827d = {
.view = head507d_view,
.mode = head507d_mode,
.olut = head507d_olut,
.olut_size = 256,
.olut_set = head827d_olut_set,
.olut_clr = head827d_olut_clr,
.core_calc = head507d_core_calc,
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/nouveau/dispnv50/head907d.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,15 @@ head907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
writew(readw(mem - 4), mem + 4);
}

void
head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
bool
head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
{
asyh->olut.mode = 7;
if (size != 256 && size != 1024)
return false;

asyh->olut.mode = size == 1024 ? 4 : 7;
asyh->olut.load = head907d_olut_load;
return true;
}

void
Expand Down Expand Up @@ -285,6 +289,7 @@ head907d = {
.view = head907d_view,
.mode = head907d_mode,
.olut = head907d_olut,
.olut_size = 1024,
.olut_set = head907d_olut_set,
.olut_clr = head907d_olut_clr,
.core_calc = head507d_core_calc,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/dispnv50/head917d.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ head917d = {
.view = head907d_view,
.mode = head907d_mode,
.olut = head907d_olut,
.olut_size = 1024,
.olut_set = head907d_olut_set,
.olut_clr = head907d_olut_clr,
.core_calc = head507d_core_calc,
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/nouveau/dispnv50/headc37d.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,18 @@ headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
}
}

static void
headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
static bool
headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
{
if (size != 256 && size != 1024)
return false;

asyh->olut.mode = 2;
asyh->olut.size = 0;
asyh->olut.size = size == 1024 ? 2 : 0;
asyh->olut.range = 0;
asyh->olut.output_mode = 1;
asyh->olut.load = head907d_olut_load;
return true;
}

static void
Expand Down Expand Up @@ -201,6 +205,7 @@ headc37d = {
.view = headc37d_view,
.mode = headc37d_mode,
.olut = headc37d_olut,
.olut_size = 1024,
.olut_set = headc37d_olut_set,
.olut_clr = headc37d_olut_clr,
.curs_layout = head917d_curs_layout,
Expand Down
12 changes: 8 additions & 4 deletions drivers/gpu/drm/nouveau/dispnv50/headc57d.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,20 @@ headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
writew(readw(mem - 4), mem + 4);
}

void
headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
bool
headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
{
if (size != 0 && size != 256 && size != 1024)
return false;

asyh->olut.mode = 2; /* DIRECT10 */
asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */;
asyh->olut.output_mode = 1; /* INTERPOLATE_ENABLE. */
if (asyh->state.gamma_lut &&
asyh->state.gamma_lut->length / sizeof(struct drm_color_lut) == 256)
if (size == 256)
asyh->olut.load = headc57d_olut_load_8;
else
asyh->olut.load = headc57d_olut_load;
return true;
}

static void
Expand Down Expand Up @@ -194,6 +197,7 @@ headc57d = {
.mode = headc57d_mode,
.olut = headc57d_olut,
.olut_identity = true,
.olut_size = 1024,
.olut_set = headc57d_olut_set,
.olut_clr = headc57d_olut_clr,
.curs_layout = head917d_curs_layout,
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/dispnv50/lut.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ nv50_lut_load(struct nv50_lut *lut, int buffer, struct drm_property_blob *blob,
kvfree(in);
}
} else {
load(in, blob->length / sizeof(*in), mem);
load(in, drm_color_lut_size(blob), mem);
}

return addr;
Expand Down
17 changes: 12 additions & 5 deletions drivers/gpu/drm/nouveau/dispnv50/wndw.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset,
return wndw->func->acquire(wndw, asyw, asyh);
}

static void
static int
nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
struct nv50_wndw_atom *armw,
struct nv50_wndw_atom *asyw,
Expand All @@ -340,7 +340,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
*/
if (!(ilut = asyh->state.gamma_lut)) {
asyw->visible = false;
return;
return 0;
}

if (wndw->func->ilut)
Expand All @@ -359,7 +359,10 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
/* Recalculate LUT state. */
memset(&asyw->xlut, 0x00, sizeof(asyw->xlut));
if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) {
wndw->func->ilut(wndw, asyw);
if (!wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut))) {
DRM_DEBUG_KMS("Invalid ilut\n");
return -EINVAL;
}
asyw->xlut.handle = wndw->wndw.vram.handle;
asyw->xlut.i.buffer = !asyw->xlut.i.buffer;
asyw->set.xlut = true;
Expand All @@ -384,6 +387,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,

/* Can't do an immediate flip while changing the LUT. */
asyh->state.async_flip = false;
return 0;
}

static int
Expand Down Expand Up @@ -424,8 +428,11 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
(!armw->visible ||
asyh->state.color_mgmt_changed ||
asyw->state.fb->format->format !=
armw->state.fb->format->format))
nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh);
armw->state.fb->format->format)) {
ret = nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh);
if (ret)
return ret;
}

/* Calculate new window state. */
if (asyw->visible) {
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/dispnv50/wndw.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ struct nv50_wndw_func {
void (*ntfy_clr)(struct nv50_wndw *);
int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
struct nvif_device *);
void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
bool (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *, int);
void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *,
const struct drm_color_ctm *);
void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*csc_clr)(struct nv50_wndw *);
bool ilut_identity;
int ilut_size;
bool olut_core;
void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*xlut_clr)(struct nv50_wndw *);
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,18 @@ wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
}
}

static void
wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
static bool
wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
{
if (size != 256 && size != 1024)
return false;

asyw->xlut.i.mode = 2;
asyw->xlut.i.size = 0;
asyw->xlut.i.size = size == 1024 ? 2 : 0;
asyw->xlut.i.range = 0;
asyw->xlut.i.output_mode = 1;
asyw->xlut.i.load = head907d_olut_load;
return true;
}

void
Expand Down Expand Up @@ -261,6 +265,7 @@ wndwc37e = {
.ntfy_reset = corec37d_ntfy_init,
.ntfy_wait_begun = base507c_ntfy_wait_begun,
.ilut = wndwc37e_ilut,
.ilut_size = 1024,
.xlut_set = wndwc37e_ilut_set,
.xlut_clr = wndwc37e_ilut_clr,
.csc = base907c_csc,
Expand Down
11 changes: 7 additions & 4 deletions drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,21 @@ wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
writew(readw(mem - 4), mem + 4);
}

static void
wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
static bool
wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
{
u16 size = asyw->ilut->length / sizeof(struct drm_color_lut);
if (size = size ? size : 1024, size != 256 && size != 1024)
return false;

if (size == 256) {
asyw->xlut.i.mode = 1; /* DIRECT8. */
} else {
asyw->xlut.i.mode = 2; /* DIRECT10. */
size = 1024;
}
asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
asyw->xlut.i.load = wndwc57e_ilut_load;
return true;
}

static const struct nv50_wndw_func
Expand All @@ -183,6 +185,7 @@ wndwc57e = {
.ntfy_wait_begun = base507c_ntfy_wait_begun,
.ilut = wndwc57e_ilut,
.ilut_identity = true,
.ilut_size = 1024,
.xlut_set = wndwc57e_ilut_set,
.xlut_clr = wndwc57e_ilut_clr,
.csc = base907c_csc,
Expand Down

0 comments on commit 1319927

Please sign in to comment.