drm/nouveau/kms/gf119-: add ctm property support
This adds support on GF119:GV100 (exclusive) for CTM (aka CSC). Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
This commit is contained in:
parent
7c844e9d95
commit
88b703527b
drivers/gpu/drm/nouveau/dispnv50
@ -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 *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user