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