1 /* 2 * Copyright 2018 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 #include "wndw.h" 23 #include "atom.h" 24 25 #include <drm/drm_atomic_helper.h> 26 #include <drm/drm_plane_helper.h> 27 #include <nouveau_bo.h> 28 29 #include <nvif/clc37e.h> 30 #include <nvif/pushc37b.h> 31 32 #include <nvhw/class/clc37e.h> 33 34 static int 35 wndwc37e_csc_clr(struct nv50_wndw *wndw) 36 { 37 return 0; 38 } 39 40 static int 41 wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 42 { 43 struct nvif_push *push = wndw->wndw.push; 44 int ret; 45 46 if ((ret = PUSH_WAIT(push, 13))) 47 return ret; 48 49 PUSH_MTHD(push, NVC37E, SET_CSC_RED2RED, asyw->csc.matrix, 12); 50 return 0; 51 } 52 53 static int 54 wndwc37e_ilut_clr(struct nv50_wndw *wndw) 55 { 56 struct nvif_push *push = wndw->wndw.push; 57 int ret; 58 59 if ((ret = PUSH_WAIT(push, 2))) 60 return ret; 61 62 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_INPUT_LUT, 0x00000000); 63 return 0; 64 } 65 66 static int 67 wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 68 { 69 struct nvif_push *push = wndw->wndw.push; 70 int ret; 71 72 if ((ret = PUSH_WAIT(push, 4))) 73 return ret; 74 75 PUSH_MTHD(push, NVC37E, SET_CONTROL_INPUT_LUT, 76 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, OUTPUT_MODE, asyw->xlut.i.output_mode) | 77 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, RANGE, asyw->xlut.i.range) | 78 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, SIZE, asyw->xlut.i.size), 79 80 SET_OFFSET_INPUT_LUT, asyw->xlut.i.offset >> 8, 81 SET_CONTEXT_DMA_INPUT_LUT, asyw->xlut.handle); 82 return 0; 83 } 84 85 static void 86 wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) 87 { 88 asyw->xlut.i.size = size == 1024 ? NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_1025 : 89 NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_257; 90 asyw->xlut.i.range = NVC37E_SET_CONTROL_INPUT_LUT_RANGE_UNITY; 91 asyw->xlut.i.output_mode = NVC37E_SET_CONTROL_INPUT_LUT_OUTPUT_MODE_INTERPOLATE; 92 asyw->xlut.i.load = head907d_olut_load; 93 } 94 95 int 96 wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 97 { 98 struct nvif_push *push = wndw->wndw.push; 99 int ret; 100 101 if ((ret = PUSH_WAIT(push, 8))) 102 return ret; 103 104 PUSH_MTHD(push, NVC37E, SET_COMPOSITION_CONTROL, 105 NVDEF(NVC37E, SET_COMPOSITION_CONTROL, COLOR_KEY_SELECT, DISABLE) | 106 NVVAL(NVC37E, SET_COMPOSITION_CONTROL, DEPTH, asyw->blend.depth), 107 108 SET_COMPOSITION_CONSTANT_ALPHA, 109 NVVAL(NVC37E, SET_COMPOSITION_CONSTANT_ALPHA, K1, asyw->blend.k1) | 110 NVVAL(NVC37E, SET_COMPOSITION_CONSTANT_ALPHA, K2, 0), 111 112 SET_COMPOSITION_FACTOR_SELECT, 113 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, SRC_COLOR_FACTOR_MATCH_SELECT, 114 asyw->blend.src_color) | 115 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, SRC_COLOR_FACTOR_NO_MATCH_SELECT, 116 asyw->blend.src_color) | 117 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, DST_COLOR_FACTOR_MATCH_SELECT, 118 asyw->blend.dst_color) | 119 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, DST_COLOR_FACTOR_NO_MATCH_SELECT, 120 asyw->blend.dst_color), 121 122 SET_KEY_ALPHA, 123 NVVAL(NVC37E, SET_KEY_ALPHA, MIN, 0x0000) | 124 NVVAL(NVC37E, SET_KEY_ALPHA, MAX, 0xffff), 125 126 SET_KEY_RED_CR, 127 NVVAL(NVC37E, SET_KEY_RED_CR, MIN, 0x0000) | 128 NVVAL(NVC37E, SET_KEY_RED_CR, MAX, 0xffff), 129 130 SET_KEY_GREEN_Y, 131 NVVAL(NVC37E, SET_KEY_GREEN_Y, MIN, 0x0000) | 132 NVVAL(NVC37E, SET_KEY_GREEN_Y, MAX, 0xffff), 133 134 SET_KEY_BLUE_CB, 135 NVVAL(NVC37E, SET_KEY_BLUE_CB, MIN, 0x0000) | 136 NVVAL(NVC37E, SET_KEY_BLUE_CB, MAX, 0xffff)); 137 return 0; 138 } 139 140 int 141 wndwc37e_image_clr(struct nv50_wndw *wndw) 142 { 143 struct nvif_push *push = wndw->wndw.push; 144 int ret; 145 146 if ((ret = PUSH_WAIT(push, 4))) 147 return ret; 148 149 PUSH_MTHD(push, NVC37E, SET_PRESENT_CONTROL, 150 NVVAL(NVC37E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, 0) | 151 NVDEF(NVC37E, SET_PRESENT_CONTROL, BEGIN_MODE, NON_TEARING)); 152 153 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_ISO(0), 0x00000000); 154 return 0; 155 } 156 157 static int 158 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 159 { 160 struct nvif_push *push = wndw->wndw.push; 161 int ret; 162 163 if ((ret = PUSH_WAIT(push, 17))) 164 return ret; 165 166 PUSH_MTHD(push, NVC37E, SET_PRESENT_CONTROL, 167 NVVAL(NVC37E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval) | 168 NVVAL(NVC37E, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) | 169 NVDEF(NVC37E, SET_PRESENT_CONTROL, TIMESTAMP_MODE, DISABLE)); 170 171 PUSH_MTHD(push, NVC37E, SET_SIZE, 172 NVVAL(NVC37E, SET_SIZE, WIDTH, asyw->image.w) | 173 NVVAL(NVC37E, SET_SIZE, HEIGHT, asyw->image.h), 174 175 SET_STORAGE, 176 NVVAL(NVC37E, SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh) | 177 NVVAL(NVC37E, SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout), 178 179 SET_PARAMS, 180 NVVAL(NVC37E, SET_PARAMS, FORMAT, asyw->image.format) | 181 NVVAL(NVC37E, SET_PARAMS, COLOR_SPACE, asyw->image.colorspace) | 182 NVDEF(NVC37E, SET_PARAMS, INPUT_RANGE, BYPASS) | 183 NVDEF(NVC37E, SET_PARAMS, UNDERREPLICATE, DISABLE) | 184 NVDEF(NVC37E, SET_PARAMS, DE_GAMMA, NONE) | 185 NVVAL(NVC37E, SET_PARAMS, CSC, asyw->csc.valid) | 186 NVDEF(NVC37E, SET_PARAMS, CLAMP_BEFORE_BLEND, DISABLE) | 187 NVDEF(NVC37E, SET_PARAMS, SWAP_UV, DISABLE), 188 189 SET_PLANAR_STORAGE(0), 190 NVVAL(NVC37E, SET_PLANAR_STORAGE, PITCH, asyw->image.blocks[0]) | 191 NVVAL(NVC37E, SET_PLANAR_STORAGE, PITCH, asyw->image.pitch[0] >> 6)); 192 193 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_ISO(0), asyw->image.handle, 1); 194 PUSH_MTHD(push, NVC37E, SET_OFFSET(0), asyw->image.offset[0] >> 8); 195 196 PUSH_MTHD(push, NVC37E, SET_POINT_IN(0), 197 NVVAL(NVC37E, SET_POINT_IN, X, asyw->state.src_x >> 16) | 198 NVVAL(NVC37E, SET_POINT_IN, Y, asyw->state.src_y >> 16)); 199 200 PUSH_MTHD(push, NVC37E, SET_SIZE_IN, 201 NVVAL(NVC37E, SET_SIZE_IN, WIDTH, asyw->state.src_w >> 16) | 202 NVVAL(NVC37E, SET_SIZE_IN, HEIGHT, asyw->state.src_h >> 16)); 203 204 PUSH_MTHD(push, NVC37E, SET_SIZE_OUT, 205 NVVAL(NVC37E, SET_SIZE_OUT, WIDTH, asyw->state.crtc_w) | 206 NVVAL(NVC37E, SET_SIZE_OUT, HEIGHT, asyw->state.crtc_h)); 207 return 0; 208 } 209 210 int 211 wndwc37e_ntfy_clr(struct nv50_wndw *wndw) 212 { 213 struct nvif_push *push = wndw->wndw.push; 214 int ret; 215 216 if ((ret = PUSH_WAIT(push, 2))) 217 return ret; 218 219 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_NOTIFIER, 0x00000000); 220 return 0; 221 } 222 223 int 224 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 225 { 226 struct nvif_push *push = wndw->wndw.push; 227 int ret; 228 229 if ((ret = PUSH_WAIT(push, 3))) 230 return ret; 231 232 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_NOTIFIER, asyw->ntfy.handle, 233 234 SET_NOTIFIER_CONTROL, 235 NVVAL(NVC37E, SET_NOTIFIER_CONTROL, MODE, asyw->ntfy.awaken) | 236 NVVAL(NVC37E, SET_NOTIFIER_CONTROL, OFFSET, asyw->ntfy.offset >> 4)); 237 return 0; 238 } 239 240 int 241 wndwc37e_sema_clr(struct nv50_wndw *wndw) 242 { 243 struct nvif_push *push = wndw->wndw.push; 244 int ret; 245 246 if ((ret = PUSH_WAIT(push, 2))) 247 return ret; 248 249 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_SEMAPHORE, 0x00000000); 250 return 0; 251 } 252 253 int 254 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 255 { 256 struct nvif_push *push = wndw->wndw.push; 257 int ret; 258 259 if ((ret = PUSH_WAIT(push, 5))) 260 return ret; 261 262 PUSH_MTHD(push, NVC37E, SET_SEMAPHORE_CONTROL, asyw->sema.offset, 263 SET_SEMAPHORE_ACQUIRE, asyw->sema.acquire, 264 SET_SEMAPHORE_RELEASE, asyw->sema.release, 265 SET_CONTEXT_DMA_SEMAPHORE, asyw->sema.handle); 266 return 0; 267 } 268 269 int 270 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock) 271 { 272 struct nvif_push *push = wndw->wndw.push; 273 int ret; 274 275 if ((ret = PUSH_WAIT(push, 5))) 276 return ret; 277 278 PUSH_MTHD(push, NVC37E, SET_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_CURS] << 1 | 279 interlock[NV50_DISP_INTERLOCK_CORE], 280 SET_WINDOW_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_WNDW]); 281 282 PUSH_MTHD(push, NVC37E, UPDATE, 0x00000001 | 283 NVVAL(NVC37E, UPDATE, INTERLOCK_WITH_WIN_IMM, 284 !!(interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data))); 285 286 return PUSH_KICK(push); 287 } 288 289 void 290 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, 291 struct nv50_head_atom *asyh) 292 { 293 } 294 295 int 296 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, 297 struct nv50_head_atom *asyh) 298 { 299 return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, 300 DRM_PLANE_HELPER_NO_SCALING, 301 DRM_PLANE_HELPER_NO_SCALING, 302 true, true); 303 } 304 305 static const u32 306 wndwc37e_format[] = { 307 DRM_FORMAT_C8, 308 DRM_FORMAT_YUYV, 309 DRM_FORMAT_UYVY, 310 DRM_FORMAT_XRGB8888, 311 DRM_FORMAT_ARGB8888, 312 DRM_FORMAT_RGB565, 313 DRM_FORMAT_XRGB1555, 314 DRM_FORMAT_ARGB1555, 315 DRM_FORMAT_XBGR2101010, 316 DRM_FORMAT_ABGR2101010, 317 DRM_FORMAT_XBGR8888, 318 DRM_FORMAT_ABGR8888, 319 DRM_FORMAT_XRGB2101010, 320 DRM_FORMAT_ARGB2101010, 321 DRM_FORMAT_XBGR16161616F, 322 DRM_FORMAT_ABGR16161616F, 323 0 324 }; 325 326 static const struct nv50_wndw_func 327 wndwc37e = { 328 .acquire = wndwc37e_acquire, 329 .release = wndwc37e_release, 330 .sema_set = wndwc37e_sema_set, 331 .sema_clr = wndwc37e_sema_clr, 332 .ntfy_set = wndwc37e_ntfy_set, 333 .ntfy_clr = wndwc37e_ntfy_clr, 334 .ntfy_reset = corec37d_ntfy_init, 335 .ntfy_wait_begun = base507c_ntfy_wait_begun, 336 .ilut = wndwc37e_ilut, 337 .ilut_size = 1024, 338 .xlut_set = wndwc37e_ilut_set, 339 .xlut_clr = wndwc37e_ilut_clr, 340 .csc = base907c_csc, 341 .csc_set = wndwc37e_csc_set, 342 .csc_clr = wndwc37e_csc_clr, 343 .image_set = wndwc37e_image_set, 344 .image_clr = wndwc37e_image_clr, 345 .blend_set = wndwc37e_blend_set, 346 .update = wndwc37e_update, 347 }; 348 349 int 350 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, 351 enum drm_plane_type type, int index, s32 oclass, u32 heads, 352 struct nv50_wndw **pwndw) 353 { 354 struct nvc37e_window_channel_dma_v0 args = { 355 .pushbuf = 0xb0007e00 | index, 356 .index = index, 357 }; 358 struct nv50_disp *disp = nv50_disp(drm->dev); 359 struct nv50_wndw *wndw; 360 int ret; 361 362 ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index, 363 wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW, 364 BIT(index), &wndw); 365 if (*pwndw = wndw, ret) 366 return ret; 367 368 ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, 369 &oclass, 0, &args, sizeof(args), 370 disp->sync->offset, &wndw->wndw); 371 if (ret) { 372 NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret); 373 return ret; 374 } 375 376 wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id); 377 wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id); 378 wndw->data = 0x00000000; 379 return 0; 380 } 381 382 int 383 wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index, 384 s32 oclass, struct nv50_wndw **pwndw) 385 { 386 return wndwc37e_new_(&wndwc37e, drm, type, index, oclass, 387 BIT(index >> 1), pwndw); 388 } 389