]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/nouveau/kms/gf119-: add ctm property support
authorIlia Mirkin <imirkin@alum.mit.edu>
Wed, 12 Jun 2019 02:40:36 +0000 (22:40 -0400)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 23 Aug 2019 02:55:32 +0000 (12:55 +1000)
This adds support on GF119:GV100 (exclusive) for CTM (aka CSC).

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
drivers/gpu/drm/nouveau/dispnv50/atom.h
drivers/gpu/drm/nouveau/dispnv50/base907c.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/dispnv50/wndw.h

index b5fae5ab3fa8cf44b301941b4d921e04fb193ca2..75bda111da1032afe267e22661530f2a78393912 100644 (file)
@@ -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;
index 049ce6da321c3fa3e102b1b1773122ea02b9566d..fd0c1d84730b071f009b40db6c69818c15d7c653 100644 (file)
@@ -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,
index dd01ea21da97322c67623d33d0da61f934fd8183..c8d0786297222e1eec86962dcfb34bec8f0f561f 100644 (file)
@@ -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;
index 03f3d8dc235a70cb5d15670c687b427c5c665319..1e781d80c990a7669dafcd202d834d2f825c145b 100644 (file)
@@ -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 *);