| .. | .. |
|---|
| 21 | 21 | */ |
|---|
| 22 | 22 | #include "base.h" |
|---|
| 23 | 23 | |
|---|
| 24 | | -static void |
|---|
| 24 | +#include <nvif/push507c.h> |
|---|
| 25 | + |
|---|
| 26 | +#include <nvhw/class/cl907c.h> |
|---|
| 27 | + |
|---|
| 28 | +static int |
|---|
| 25 | 29 | base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
|---|
| 26 | 30 | { |
|---|
| 27 | | - u32 *push; |
|---|
| 28 | | - if ((push = evo_wait(&wndw->wndw, 10))) { |
|---|
| 29 | | - evo_mthd(push, 0x0084, 1); |
|---|
| 30 | | - evo_data(push, asyw->image.mode << 8 | |
|---|
| 31 | | - asyw->image.interval << 4); |
|---|
| 32 | | - evo_mthd(push, 0x00c0, 1); |
|---|
| 33 | | - evo_data(push, asyw->image.handle[0]); |
|---|
| 34 | | - evo_mthd(push, 0x0400, 5); |
|---|
| 35 | | - evo_data(push, asyw->image.offset[0] >> 8); |
|---|
| 36 | | - evo_data(push, 0x00000000); |
|---|
| 37 | | - evo_data(push, asyw->image.h << 16 | asyw->image.w); |
|---|
| 38 | | - evo_data(push, asyw->image.layout << 24 | |
|---|
| 39 | | - (asyw->image.pitch[0] >> 8) << 8 | |
|---|
| 40 | | - asyw->image.blocks[0] << 8 | |
|---|
| 41 | | - asyw->image.blockh); |
|---|
| 42 | | - evo_data(push, asyw->image.format << 8); |
|---|
| 43 | | - evo_kick(push, &wndw->wndw); |
|---|
| 44 | | - } |
|---|
| 31 | + struct nvif_push *push = wndw->wndw.push; |
|---|
| 32 | + int ret; |
|---|
| 33 | + |
|---|
| 34 | + if ((ret = PUSH_WAIT(push, 10))) |
|---|
| 35 | + return ret; |
|---|
| 36 | + |
|---|
| 37 | + PUSH_MTHD(push, NV907C, SET_PRESENT_CONTROL, |
|---|
| 38 | + NVVAL(NV907C, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) | |
|---|
| 39 | + NVDEF(NV907C, SET_PRESENT_CONTROL, TIMESTAMP_MODE, DISABLE) | |
|---|
| 40 | + NVVAL(NV907C, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval)); |
|---|
| 41 | + |
|---|
| 42 | + PUSH_MTHD(push, NV907C, SET_CONTEXT_DMAS_ISO(0), asyw->image.handle, 1); |
|---|
| 43 | + |
|---|
| 44 | + PUSH_MTHD(push, NV907C, SURFACE_SET_OFFSET(0, 0), asyw->image.offset[0] >> 8, |
|---|
| 45 | + SURFACE_SET_OFFSET(0, 1), 0x00000000, |
|---|
| 46 | + |
|---|
| 47 | + SURFACE_SET_SIZE(0), |
|---|
| 48 | + NVVAL(NV907C, SURFACE_SET_SIZE, WIDTH, asyw->image.w) | |
|---|
| 49 | + NVVAL(NV907C, SURFACE_SET_SIZE, HEIGHT, asyw->image.h), |
|---|
| 50 | + |
|---|
| 51 | + SURFACE_SET_STORAGE(0), |
|---|
| 52 | + NVVAL(NV907C, SURFACE_SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh) | |
|---|
| 53 | + NVVAL(NV907C, SURFACE_SET_STORAGE, PITCH, asyw->image.pitch[0] >> 8) | |
|---|
| 54 | + NVVAL(NV907C, SURFACE_SET_STORAGE, PITCH, asyw->image.blocks[0]) | |
|---|
| 55 | + NVVAL(NV907C, SURFACE_SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout), |
|---|
| 56 | + |
|---|
| 57 | + SURFACE_SET_PARAMS(0), |
|---|
| 58 | + NVVAL(NV907C, SURFACE_SET_PARAMS, FORMAT, asyw->image.format) | |
|---|
| 59 | + NVDEF(NV907C, SURFACE_SET_PARAMS, SUPER_SAMPLE, X1_AA) | |
|---|
| 60 | + NVDEF(NV907C, SURFACE_SET_PARAMS, GAMMA, LINEAR) | |
|---|
| 61 | + NVDEF(NV907C, SURFACE_SET_PARAMS, LAYOUT, FRM)); |
|---|
| 62 | + return 0; |
|---|
| 45 | 63 | } |
|---|
| 46 | 64 | |
|---|
| 47 | | -static void |
|---|
| 65 | +static int |
|---|
| 48 | 66 | base907c_xlut_clr(struct nv50_wndw *wndw) |
|---|
| 49 | 67 | { |
|---|
| 50 | | - u32 *push; |
|---|
| 51 | | - if ((push = evo_wait(&wndw->wndw, 6))) { |
|---|
| 52 | | - evo_mthd(push, 0x00e0, 1); |
|---|
| 53 | | - evo_data(push, 0x00000000); |
|---|
| 54 | | - evo_mthd(push, 0x00e8, 1); |
|---|
| 55 | | - evo_data(push, 0x00000000); |
|---|
| 56 | | - evo_mthd(push, 0x00fc, 1); |
|---|
| 57 | | - evo_data(push, 0x00000000); |
|---|
| 58 | | - evo_kick(push, &wndw->wndw); |
|---|
| 59 | | - } |
|---|
| 68 | + struct nvif_push *push = wndw->wndw.push; |
|---|
| 69 | + int ret; |
|---|
| 70 | + |
|---|
| 71 | + if ((ret = PUSH_WAIT(push, 6))) |
|---|
| 72 | + return ret; |
|---|
| 73 | + |
|---|
| 74 | + PUSH_MTHD(push, NV907C, SET_BASE_LUT_LO, |
|---|
| 75 | + NVDEF(NV907C, SET_BASE_LUT_LO, ENABLE, DISABLE)); |
|---|
| 76 | + |
|---|
| 77 | + PUSH_MTHD(push, NV907C, SET_OUTPUT_LUT_LO, |
|---|
| 78 | + NVDEF(NV907C, SET_OUTPUT_LUT_LO, ENABLE, DISABLE)); |
|---|
| 79 | + |
|---|
| 80 | + PUSH_MTHD(push, NV907C, SET_CONTEXT_DMA_LUT, 0x00000000); |
|---|
| 81 | + return 0; |
|---|
| 60 | 82 | } |
|---|
| 61 | 83 | |
|---|
| 62 | | -static void |
|---|
| 84 | +static int |
|---|
| 63 | 85 | base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
|---|
| 64 | 86 | { |
|---|
| 65 | | - u32 *push; |
|---|
| 66 | | - if ((push = evo_wait(&wndw->wndw, 6))) { |
|---|
| 67 | | - evo_mthd(push, 0x00e0, 3); |
|---|
| 68 | | - evo_data(push, asyw->xlut.i.enable << 30 | |
|---|
| 69 | | - asyw->xlut.i.mode << 24); |
|---|
| 70 | | - evo_data(push, asyw->xlut.i.offset >> 8); |
|---|
| 71 | | - evo_data(push, 0x40000000); |
|---|
| 72 | | - evo_mthd(push, 0x00fc, 1); |
|---|
| 73 | | - evo_data(push, asyw->xlut.handle); |
|---|
| 74 | | - evo_kick(push, &wndw->wndw); |
|---|
| 87 | + struct nvif_push *push = wndw->wndw.push; |
|---|
| 88 | + int ret; |
|---|
| 89 | + |
|---|
| 90 | + if ((ret = PUSH_WAIT(push, 6))) |
|---|
| 91 | + return ret; |
|---|
| 92 | + |
|---|
| 93 | + PUSH_MTHD(push, NV907C, SET_BASE_LUT_LO, |
|---|
| 94 | + NVVAL(NV907C, SET_BASE_LUT_LO, ENABLE, asyw->xlut.i.enable) | |
|---|
| 95 | + NVVAL(NV907C, SET_BASE_LUT_LO, MODE, asyw->xlut.i.mode), |
|---|
| 96 | + |
|---|
| 97 | + SET_BASE_LUT_HI, asyw->xlut.i.offset >> 8, |
|---|
| 98 | + |
|---|
| 99 | + SET_OUTPUT_LUT_LO, |
|---|
| 100 | + NVDEF(NV907C, SET_OUTPUT_LUT_LO, ENABLE, USE_CORE_LUT)); |
|---|
| 101 | + |
|---|
| 102 | + PUSH_MTHD(push, NV907C, SET_CONTEXT_DMA_LUT, asyw->xlut.handle); |
|---|
| 103 | + return 0; |
|---|
| 104 | +} |
|---|
| 105 | + |
|---|
| 106 | +static bool |
|---|
| 107 | +base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) |
|---|
| 108 | +{ |
|---|
| 109 | + if (size != 256 && size != 1024) |
|---|
| 110 | + return false; |
|---|
| 111 | + |
|---|
| 112 | + if (size == 1024) |
|---|
| 113 | + asyw->xlut.i.mode = NV907C_SET_BASE_LUT_LO_MODE_INTERPOLATE_1025_UNITY_RANGE; |
|---|
| 114 | + else |
|---|
| 115 | + asyw->xlut.i.mode = NV907C_SET_BASE_LUT_LO_MODE_INTERPOLATE_257_UNITY_RANGE; |
|---|
| 116 | + |
|---|
| 117 | + asyw->xlut.i.enable = NV907C_SET_BASE_LUT_LO_ENABLE_ENABLE; |
|---|
| 118 | + asyw->xlut.i.load = head907d_olut_load; |
|---|
| 119 | + return true; |
|---|
| 120 | +} |
|---|
| 121 | + |
|---|
| 122 | +static inline u32 |
|---|
| 123 | +csc_drm_to_base(u64 in) |
|---|
| 124 | +{ |
|---|
| 125 | + /* base takes a 19-bit 2's complement value in S3.16 format */ |
|---|
| 126 | + bool sign = in & BIT_ULL(63); |
|---|
| 127 | + u32 integer = (in >> 32) & 0x7fffffff; |
|---|
| 128 | + u32 fraction = in & 0xffffffff; |
|---|
| 129 | + |
|---|
| 130 | + if (integer >= 4) { |
|---|
| 131 | + return (1 << 18) - (sign ? 0 : 1); |
|---|
| 132 | + } else { |
|---|
| 133 | + u32 ret = (integer << 16) | (fraction >> 16); |
|---|
| 134 | + if (sign) |
|---|
| 135 | + ret = -ret; |
|---|
| 136 | + return ret & GENMASK(18, 0); |
|---|
| 75 | 137 | } |
|---|
| 76 | 138 | } |
|---|
| 77 | 139 | |
|---|
| 78 | | -static void |
|---|
| 79 | | -base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
|---|
| 140 | +void |
|---|
| 141 | +base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, |
|---|
| 142 | + const struct drm_color_ctm *ctm) |
|---|
| 80 | 143 | { |
|---|
| 81 | | - asyw->xlut.i.mode = 7; |
|---|
| 82 | | - asyw->xlut.i.enable = 2; |
|---|
| 144 | + int i, j; |
|---|
| 145 | + |
|---|
| 146 | + for (j = 0; j < 3; j++) { |
|---|
| 147 | + for (i = 0; i < 4; i++) { |
|---|
| 148 | + u32 *val = &asyw->csc.matrix[j * 4 + i]; |
|---|
| 149 | + /* DRM does not support constant offset, while |
|---|
| 150 | + * HW CSC does. Skip it. */ |
|---|
| 151 | + if (i == 3) { |
|---|
| 152 | + *val = 0; |
|---|
| 153 | + } else { |
|---|
| 154 | + *val = csc_drm_to_base(ctm->matrix[j * 3 + i]); |
|---|
| 155 | + } |
|---|
| 156 | + } |
|---|
| 157 | + } |
|---|
| 158 | +} |
|---|
| 159 | + |
|---|
| 160 | +static int |
|---|
| 161 | +base907c_csc_clr(struct nv50_wndw *wndw) |
|---|
| 162 | +{ |
|---|
| 163 | + struct nvif_push *push = wndw->wndw.push; |
|---|
| 164 | + int ret; |
|---|
| 165 | + |
|---|
| 166 | + if ((ret = PUSH_WAIT(push, 2))) |
|---|
| 167 | + return ret; |
|---|
| 168 | + |
|---|
| 169 | + PUSH_MTHD(push, NV907C, SET_CSC_RED2RED, |
|---|
| 170 | + NVDEF(NV907C, SET_CSC_RED2RED, OWNER, CORE)); |
|---|
| 171 | + return 0; |
|---|
| 172 | +} |
|---|
| 173 | + |
|---|
| 174 | +static int |
|---|
| 175 | +base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
|---|
| 176 | +{ |
|---|
| 177 | + struct nvif_push *push = wndw->wndw.push; |
|---|
| 178 | + int ret; |
|---|
| 179 | + |
|---|
| 180 | + if ((ret = PUSH_WAIT(push, 13))) |
|---|
| 181 | + return ret; |
|---|
| 182 | + |
|---|
| 183 | + PUSH_MTHD(push, NV907C, SET_CSC_RED2RED, |
|---|
| 184 | + NVDEF(NV907C, SET_CSC_RED2RED, OWNER, BASE) | |
|---|
| 185 | + NVVAL(NV907C, SET_CSC_RED2RED, COEFF, asyw->csc.matrix[0]), |
|---|
| 186 | + |
|---|
| 187 | + SET_CSC_GRN2RED, &asyw->csc.matrix[1], 11); |
|---|
| 188 | + return 0; |
|---|
| 83 | 189 | } |
|---|
| 84 | 190 | |
|---|
| 85 | 191 | const struct nv50_wndw_func |
|---|
| .. | .. |
|---|
| 93 | 199 | .ntfy_clr = base507c_ntfy_clr, |
|---|
| 94 | 200 | .ntfy_wait_begun = base507c_ntfy_wait_begun, |
|---|
| 95 | 201 | .ilut = base907c_ilut, |
|---|
| 202 | + .csc = base907c_csc, |
|---|
| 203 | + .csc_set = base907c_csc_set, |
|---|
| 204 | + .csc_clr = base907c_csc_clr, |
|---|
| 96 | 205 | .olut_core = true, |
|---|
| 206 | + .ilut_size = 1024, |
|---|
| 97 | 207 | .xlut_set = base907c_xlut_set, |
|---|
| 98 | 208 | .xlut_clr = base907c_xlut_clr, |
|---|
| 99 | 209 | .image_set = base907c_image_set, |
|---|