From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 31 Jan 2024 03:29:01 +0000
Subject: [PATCH] add lvds1024*800

---
 kernel/drivers/gpu/drm/nouveau/dispnv50/base907c.c |  200 ++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 155 insertions(+), 45 deletions(-)

diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/kernel/drivers/gpu/drm/nouveau/dispnv50/base907c.c
index a562fc9..5396e37 100644
--- a/kernel/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+++ b/kernel/drivers/gpu/drm/nouveau/dispnv50/base907c.c
@@ -21,65 +21,171 @@
  */
 #include "base.h"
 
-static void
+#include <nvif/push507c.h>
+
+#include <nvhw/class/cl907c.h>
+
+static int
 base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
-	u32 *push;
-	if ((push = evo_wait(&wndw->wndw, 10))) {
-		evo_mthd(push, 0x0084, 1);
-		evo_data(push, asyw->image.mode << 8 |
-			       asyw->image.interval << 4);
-		evo_mthd(push, 0x00c0, 1);
-		evo_data(push, asyw->image.handle[0]);
-		evo_mthd(push, 0x0400, 5);
-		evo_data(push, asyw->image.offset[0] >> 8);
-		evo_data(push, 0x00000000);
-		evo_data(push, asyw->image.h << 16 | asyw->image.w);
-		evo_data(push, asyw->image.layout << 24 |
-			       (asyw->image.pitch[0] >> 8) << 8 |
-			       asyw->image.blocks[0] << 8 |
-			       asyw->image.blockh);
-		evo_data(push, asyw->image.format << 8);
-		evo_kick(push, &wndw->wndw);
-	}
+	struct nvif_push *push = wndw->wndw.push;
+	int ret;
+
+	if ((ret = PUSH_WAIT(push, 10)))
+		return ret;
+
+	PUSH_MTHD(push, NV907C, SET_PRESENT_CONTROL,
+		  NVVAL(NV907C, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) |
+		  NVDEF(NV907C, SET_PRESENT_CONTROL, TIMESTAMP_MODE, DISABLE) |
+		  NVVAL(NV907C, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval));
+
+	PUSH_MTHD(push, NV907C, SET_CONTEXT_DMAS_ISO(0), asyw->image.handle, 1);
+
+	PUSH_MTHD(push, NV907C, SURFACE_SET_OFFSET(0, 0), asyw->image.offset[0] >> 8,
+				SURFACE_SET_OFFSET(0, 1), 0x00000000,
+
+				SURFACE_SET_SIZE(0),
+		  NVVAL(NV907C, SURFACE_SET_SIZE, WIDTH, asyw->image.w) |
+		  NVVAL(NV907C, SURFACE_SET_SIZE, HEIGHT, asyw->image.h),
+
+				SURFACE_SET_STORAGE(0),
+		  NVVAL(NV907C, SURFACE_SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh) |
+		  NVVAL(NV907C, SURFACE_SET_STORAGE, PITCH, asyw->image.pitch[0] >> 8) |
+		  NVVAL(NV907C, SURFACE_SET_STORAGE, PITCH, asyw->image.blocks[0]) |
+		  NVVAL(NV907C, SURFACE_SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout),
+
+				SURFACE_SET_PARAMS(0),
+		  NVVAL(NV907C, SURFACE_SET_PARAMS, FORMAT, asyw->image.format) |
+		  NVDEF(NV907C, SURFACE_SET_PARAMS, SUPER_SAMPLE, X1_AA) |
+		  NVDEF(NV907C, SURFACE_SET_PARAMS, GAMMA, LINEAR) |
+		  NVDEF(NV907C, SURFACE_SET_PARAMS, LAYOUT, FRM));
+	return 0;
 }
 
-static void
+static int
 base907c_xlut_clr(struct nv50_wndw *wndw)
 {
-	u32 *push;
-	if ((push = evo_wait(&wndw->wndw, 6))) {
-		evo_mthd(push, 0x00e0, 1);
-		evo_data(push, 0x00000000);
-		evo_mthd(push, 0x00e8, 1);
-		evo_data(push, 0x00000000);
-		evo_mthd(push, 0x00fc, 1);
-		evo_data(push, 0x00000000);
-		evo_kick(push, &wndw->wndw);
-	}
+	struct nvif_push *push = wndw->wndw.push;
+	int ret;
+
+	if ((ret = PUSH_WAIT(push, 6)))
+		return ret;
+
+	PUSH_MTHD(push, NV907C, SET_BASE_LUT_LO,
+		  NVDEF(NV907C, SET_BASE_LUT_LO, ENABLE, DISABLE));
+
+	PUSH_MTHD(push, NV907C, SET_OUTPUT_LUT_LO,
+		  NVDEF(NV907C, SET_OUTPUT_LUT_LO, ENABLE, DISABLE));
+
+	PUSH_MTHD(push, NV907C, SET_CONTEXT_DMA_LUT, 0x00000000);
+	return 0;
 }
 
-static void
+static int
 base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
-	u32 *push;
-	if ((push = evo_wait(&wndw->wndw, 6))) {
-		evo_mthd(push, 0x00e0, 3);
-		evo_data(push, asyw->xlut.i.enable << 30 |
-			       asyw->xlut.i.mode << 24);
-		evo_data(push, asyw->xlut.i.offset >> 8);
-		evo_data(push, 0x40000000);
-		evo_mthd(push, 0x00fc, 1);
-		evo_data(push, asyw->xlut.handle);
-		evo_kick(push, &wndw->wndw);
+	struct nvif_push *push = wndw->wndw.push;
+	int ret;
+
+	if ((ret = PUSH_WAIT(push, 6)))
+		return ret;
+
+	PUSH_MTHD(push, NV907C, SET_BASE_LUT_LO,
+		  NVVAL(NV907C, SET_BASE_LUT_LO, ENABLE, asyw->xlut.i.enable) |
+		  NVVAL(NV907C, SET_BASE_LUT_LO, MODE, asyw->xlut.i.mode),
+
+				SET_BASE_LUT_HI, asyw->xlut.i.offset >> 8,
+
+				SET_OUTPUT_LUT_LO,
+		  NVDEF(NV907C, SET_OUTPUT_LUT_LO, ENABLE, USE_CORE_LUT));
+
+	PUSH_MTHD(push, NV907C, SET_CONTEXT_DMA_LUT, asyw->xlut.handle);
+	return 0;
+}
+
+static bool
+base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
+{
+	if (size != 256 && size != 1024)
+		return false;
+
+	if (size == 1024)
+		asyw->xlut.i.mode = NV907C_SET_BASE_LUT_LO_MODE_INTERPOLATE_1025_UNITY_RANGE;
+	else
+		asyw->xlut.i.mode = NV907C_SET_BASE_LUT_LO_MODE_INTERPOLATE_257_UNITY_RANGE;
+
+	asyw->xlut.i.enable = NV907C_SET_BASE_LUT_LO_ENABLE_ENABLE;
+	asyw->xlut.i.load = head907d_olut_load;
+	return true;
+}
+
+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_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+void
+base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+	     const struct drm_color_ctm *ctm)
 {
-	asyw->xlut.i.mode = 7;
-	asyw->xlut.i.enable = 2;
+	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 int
+base907c_csc_clr(struct nv50_wndw *wndw)
+{
+	struct nvif_push *push = wndw->wndw.push;
+	int ret;
+
+	if ((ret = PUSH_WAIT(push, 2)))
+		return ret;
+
+	PUSH_MTHD(push, NV907C, SET_CSC_RED2RED,
+		  NVDEF(NV907C, SET_CSC_RED2RED, OWNER, CORE));
+	return 0;
+}
+
+static int
+base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nvif_push *push = wndw->wndw.push;
+	int ret;
+
+	if ((ret = PUSH_WAIT(push, 13)))
+		return ret;
+
+	PUSH_MTHD(push, NV907C, SET_CSC_RED2RED,
+		  NVDEF(NV907C, SET_CSC_RED2RED, OWNER, BASE) |
+		  NVVAL(NV907C, SET_CSC_RED2RED, COEFF, asyw->csc.matrix[0]),
+
+				SET_CSC_GRN2RED, &asyw->csc.matrix[1], 11);
+	return 0;
 }
 
 const struct nv50_wndw_func
@@ -93,7 +199,11 @@
 	.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,
+	.ilut_size = 1024,
 	.xlut_set = base907c_xlut_set,
 	.xlut_clr = base907c_xlut_clr,
 	.image_set = base907c_image_set,

--
Gitblit v1.6.2