Commit 88b70352 authored by Ilia Mirkin's avatar Ilia Mirkin Committed by Ben Skeggs

drm/nouveau/kms/gf119-: add ctm property support

This adds support on GF119:GV100 (exclusive) for CTM (aka CSC).
Signed-off-by: default avatarIlia Mirkin <imirkin@alum.mit.edu>
parent 7c844e9d
......@@ -184,6 +184,11 @@ struct nv50_wndw_atom {
} i;
} xlut;
struct {
u32 matrix[12];
bool valid;
} csc;
struct {
u8 mode:2;
u8 interval:4;
......@@ -221,6 +226,7 @@ struct nv50_wndw_atom {
bool ntfy:1;
bool sema:1;
bool xlut:1;
bool csc:1;
bool image:1;
bool scale:1;
bool point:1;
......
......@@ -83,6 +83,68 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
asyw->xlut.i.load = head907d_olut_load;
}
static inline u32
csc_drm_to_base(u64 in)
{
/* base takes a 19-bit 2's complement value in S3.16 format */
bool sign = in & BIT_ULL(63);
u32 integer = (in >> 32) & 0x7fffffff;
u32 fraction = in & 0xffffffff;
if (integer >= 4) {
return (1 << 18) - (sign ? 0 : 1);
} else {
u32 ret = (integer << 16) | (fraction >> 16);
if (sign)
ret = -ret;
return ret & GENMASK(18, 0);
}
}
static void
base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
const struct drm_color_ctm *ctm)
{
int i, j;
for (j = 0; j < 3; j++) {
for (i = 0; i < 4; i++) {
u32 *val = &asyw->csc.matrix[j * 4 + i];
/* DRM does not support constant offset, while
* HW CSC does. Skip it. */
if (i == 3) {
*val = 0;
} else {
*val = csc_drm_to_base(ctm->matrix[j * 3 + i]);
}
}
}
}
static void
base907c_csc_clr(struct nv50_wndw *wndw)
{
u32 *push;
if ((push = evo_wait(&wndw->wndw, 2))) {
evo_mthd(push, 0x0140, 1);
evo_data(push, 0x00000000);
evo_kick(push, &wndw->wndw);
}
}
static void
base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u32 *push, i;
if ((push = evo_wait(&wndw->wndw, 13))) {
evo_mthd(push, 0x0140, 12);
evo_data(push, asyw->csc.matrix[0] | 0x80000000);
for (i = 1; i < 12; i++)
evo_data(push, asyw->csc.matrix[i]);
evo_kick(push, &wndw->wndw);
}
}
const struct nv50_wndw_func
base907c = {
.acquire = base507c_acquire,
......@@ -94,6 +156,9 @@ base907c = {
.ntfy_clr = base507c_ntfy_clr,
.ntfy_wait_begun = base507c_ntfy_wait_begun,
.ilut = base907c_ilut,
.csc = base907c_csc,
.csc_set = base907c_csc_set,
.csc_clr = base907c_csc_clr,
.olut_core = true,
.xlut_set = base907c_xlut_set,
.xlut_clr = base907c_xlut_clr,
......
......@@ -120,6 +120,7 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush,
if (clr.sema ) wndw->func-> sema_clr(wndw);
if (clr.ntfy ) wndw->func-> ntfy_clr(wndw);
if (clr.xlut ) wndw->func-> xlut_clr(wndw);
if (clr.csc ) wndw->func-> csc_clr(wndw);
if (clr.image) wndw->func->image_clr(wndw);
interlock[wndw->interlock.type] |= wndw->interlock.data;
......@@ -147,6 +148,7 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
wndw->func->xlut_set(wndw, asyw);
}
if (asyw->set.csc ) wndw->func->csc_set (wndw, asyw);
if (asyw->set.scale) wndw->func->scale_set(wndw, asyw);
if (asyw->set.point) {
if (asyw->set.point = false, asyw->set.mask)
......@@ -347,6 +349,16 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
(!armw->visible || (armw->xlut.handle && !asyw->xlut.handle)))
asyw->set.xlut = true;
if (wndw->func->csc && asyh->state.ctm) {
const struct drm_color_ctm *ctm = asyh->state.ctm->data;
wndw->func->csc(wndw, asyw, ctm);
asyw->csc.valid = true;
asyw->set.csc = true;
} else {
asyw->csc.valid = false;
asyw->clr.csc = armw->csc.valid;
}
/* Can't do an immediate flip while changing the LUT. */
asyh->state.pageflip_flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
}
......@@ -416,6 +428,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
asyw->clr.ntfy = armw->ntfy.handle != 0;
asyw->clr.sema = armw->sema.handle != 0;
asyw->clr.xlut = armw->xlut.handle != 0;
asyw->clr.csc = armw->csc.valid;
if (wndw->func->image_clr)
asyw->clr.image = armw->image.handle[0] != 0;
}
......@@ -507,6 +520,7 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
asyw->ntfy = armw->ntfy;
asyw->ilut = NULL;
asyw->xlut = armw->xlut;
asyw->csc = armw->csc;
asyw->image = armw->image;
asyw->point = armw->point;
asyw->clr.mask = 0;
......
......@@ -65,6 +65,10 @@ struct nv50_wndw_func {
int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
struct nvif_device *);
void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
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;
bool olut_core;
void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
......
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