| .. | .. |
|---|
| 21 | 21 | */ |
|---|
| 22 | 22 | #include "wndw.h" |
|---|
| 23 | 23 | #include "wimm.h" |
|---|
| 24 | +#include "handles.h" |
|---|
| 24 | 25 | |
|---|
| 25 | 26 | #include <nvif/class.h> |
|---|
| 26 | 27 | #include <nvif/cl0002.h> |
|---|
| 27 | 28 | |
|---|
| 29 | +#include <nvhw/class/cl507c.h> |
|---|
| 30 | +#include <nvhw/class/cl507e.h> |
|---|
| 31 | +#include <nvhw/class/clc37e.h> |
|---|
| 32 | + |
|---|
| 28 | 33 | #include <drm/drm_atomic_helper.h> |
|---|
| 34 | +#include <drm/drm_fourcc.h> |
|---|
| 35 | + |
|---|
| 29 | 36 | #include "nouveau_bo.h" |
|---|
| 37 | +#include "nouveau_gem.h" |
|---|
| 30 | 38 | |
|---|
| 31 | 39 | static void |
|---|
| 32 | 40 | nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma) |
|---|
| 33 | 41 | { |
|---|
| 34 | | - nvif_object_fini(&ctxdma->object); |
|---|
| 42 | + nvif_object_dtor(&ctxdma->object); |
|---|
| 35 | 43 | list_del(&ctxdma->head); |
|---|
| 36 | 44 | kfree(ctxdma); |
|---|
| 37 | 45 | } |
|---|
| 38 | 46 | |
|---|
| 39 | 47 | static struct nv50_wndw_ctxdma * |
|---|
| 40 | | -nv50_wndw_ctxdma_new(struct nv50_wndw *wndw, struct nouveau_framebuffer *fb) |
|---|
| 48 | +nv50_wndw_ctxdma_new(struct nv50_wndw *wndw, struct drm_framebuffer *fb) |
|---|
| 41 | 49 | { |
|---|
| 42 | | - struct nouveau_drm *drm = nouveau_drm(fb->base.dev); |
|---|
| 50 | + struct nouveau_drm *drm = nouveau_drm(fb->dev); |
|---|
| 43 | 51 | struct nv50_wndw_ctxdma *ctxdma; |
|---|
| 44 | | - const u8 kind = fb->nvbo->kind; |
|---|
| 45 | | - const u32 handle = 0xfb000000 | kind; |
|---|
| 52 | + u32 handle; |
|---|
| 53 | + u32 unused; |
|---|
| 54 | + u8 kind; |
|---|
| 46 | 55 | struct { |
|---|
| 47 | 56 | struct nv_dma_v0 base; |
|---|
| 48 | 57 | union { |
|---|
| .. | .. |
|---|
| 53 | 62 | } args = {}; |
|---|
| 54 | 63 | u32 argc = sizeof(args.base); |
|---|
| 55 | 64 | int ret; |
|---|
| 65 | + |
|---|
| 66 | + nouveau_framebuffer_get_layout(fb, &unused, &kind); |
|---|
| 67 | + handle = NV50_DISP_HANDLE_WNDW_CTX(kind); |
|---|
| 56 | 68 | |
|---|
| 57 | 69 | list_for_each_entry(ctxdma, &wndw->ctxdma.list, head) { |
|---|
| 58 | 70 | if (ctxdma->object.handle == handle) |
|---|
| .. | .. |
|---|
| 86 | 98 | argc += sizeof(args.gf119); |
|---|
| 87 | 99 | } |
|---|
| 88 | 100 | |
|---|
| 89 | | - ret = nvif_object_init(wndw->ctxdma.parent, handle, NV_DMA_IN_MEMORY, |
|---|
| 90 | | - &args, argc, &ctxdma->object); |
|---|
| 101 | + ret = nvif_object_ctor(wndw->ctxdma.parent, "kmsFbCtxDma", handle, |
|---|
| 102 | + NV_DMA_IN_MEMORY, &args, argc, &ctxdma->object); |
|---|
| 91 | 103 | if (ret) { |
|---|
| 92 | 104 | nv50_wndw_ctxdma_del(ctxdma); |
|---|
| 93 | 105 | return ERR_PTR(ret); |
|---|
| .. | .. |
|---|
| 118 | 130 | if (clr.sema ) wndw->func-> sema_clr(wndw); |
|---|
| 119 | 131 | if (clr.ntfy ) wndw->func-> ntfy_clr(wndw); |
|---|
| 120 | 132 | if (clr.xlut ) wndw->func-> xlut_clr(wndw); |
|---|
| 133 | + if (clr.csc ) wndw->func-> csc_clr(wndw); |
|---|
| 121 | 134 | if (clr.image) wndw->func->image_clr(wndw); |
|---|
| 122 | 135 | |
|---|
| 123 | 136 | interlock[wndw->interlock.type] |= wndw->interlock.data; |
|---|
| .. | .. |
|---|
| 127 | 140 | nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock, |
|---|
| 128 | 141 | struct nv50_wndw_atom *asyw) |
|---|
| 129 | 142 | { |
|---|
| 130 | | - if (interlock) { |
|---|
| 131 | | - asyw->image.mode = 0; |
|---|
| 143 | + if (interlock[NV50_DISP_INTERLOCK_CORE]) { |
|---|
| 144 | + asyw->image.mode = NV507C_SET_PRESENT_CONTROL_BEGIN_MODE_NON_TEARING; |
|---|
| 132 | 145 | asyw->image.interval = 1; |
|---|
| 133 | 146 | } |
|---|
| 134 | 147 | |
|---|
| .. | .. |
|---|
| 139 | 152 | if (asyw->set.xlut ) { |
|---|
| 140 | 153 | if (asyw->ilut) { |
|---|
| 141 | 154 | asyw->xlut.i.offset = |
|---|
| 142 | | - nv50_lut_load(&wndw->ilut, |
|---|
| 143 | | - asyw->xlut.i.mode <= 1, |
|---|
| 144 | | - asyw->xlut.i.buffer, |
|---|
| 145 | | - asyw->ilut); |
|---|
| 155 | + nv50_lut_load(&wndw->ilut, asyw->xlut.i.buffer, |
|---|
| 156 | + asyw->ilut, asyw->xlut.i.load); |
|---|
| 146 | 157 | } |
|---|
| 147 | 158 | wndw->func->xlut_set(wndw, asyw); |
|---|
| 148 | 159 | } |
|---|
| 149 | 160 | |
|---|
| 161 | + if (asyw->set.csc ) wndw->func->csc_set (wndw, asyw); |
|---|
| 150 | 162 | if (asyw->set.scale) wndw->func->scale_set(wndw, asyw); |
|---|
| 163 | + if (asyw->set.blend) wndw->func->blend_set(wndw, asyw); |
|---|
| 151 | 164 | if (asyw->set.point) { |
|---|
| 152 | 165 | if (asyw->set.point = false, asyw->set.mask) |
|---|
| 153 | 166 | interlock[wndw->interlock.type] |= wndw->interlock.data; |
|---|
| .. | .. |
|---|
| 184 | 197 | wndw->func->release(wndw, asyw, asyh); |
|---|
| 185 | 198 | asyw->ntfy.handle = 0; |
|---|
| 186 | 199 | asyw->sema.handle = 0; |
|---|
| 200 | + asyw->xlut.handle = 0; |
|---|
| 201 | + memset(asyw->image.handle, 0x00, sizeof(asyw->image.handle)); |
|---|
| 187 | 202 | } |
|---|
| 188 | 203 | |
|---|
| 189 | 204 | static int |
|---|
| 190 | 205 | nv50_wndw_atomic_check_acquire_yuv(struct nv50_wndw_atom *asyw) |
|---|
| 191 | 206 | { |
|---|
| 192 | 207 | switch (asyw->state.fb->format->format) { |
|---|
| 193 | | - case DRM_FORMAT_YUYV: asyw->image.format = 0x28; break; |
|---|
| 194 | | - case DRM_FORMAT_UYVY: asyw->image.format = 0x29; break; |
|---|
| 208 | + case DRM_FORMAT_YUYV: |
|---|
| 209 | + asyw->image.format = NV507E_SURFACE_SET_PARAMS_FORMAT_VE8YO8UE8YE8; |
|---|
| 210 | + break; |
|---|
| 211 | + case DRM_FORMAT_UYVY: |
|---|
| 212 | + asyw->image.format = NV507E_SURFACE_SET_PARAMS_FORMAT_YO8VE8YE8UE8; |
|---|
| 213 | + break; |
|---|
| 195 | 214 | default: |
|---|
| 196 | 215 | WARN_ON(1); |
|---|
| 197 | 216 | return -EINVAL; |
|---|
| 198 | 217 | } |
|---|
| 199 | | - asyw->image.colorspace = 1; |
|---|
| 218 | + |
|---|
| 219 | + asyw->image.colorspace = NV507E_SURFACE_SET_PARAMS_COLOR_SPACE_YUV_601; |
|---|
| 200 | 220 | return 0; |
|---|
| 201 | 221 | } |
|---|
| 202 | 222 | |
|---|
| .. | .. |
|---|
| 204 | 224 | nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw) |
|---|
| 205 | 225 | { |
|---|
| 206 | 226 | switch (asyw->state.fb->format->format) { |
|---|
| 207 | | - case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break; |
|---|
| 208 | | - case DRM_FORMAT_XRGB8888 : |
|---|
| 209 | | - case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break; |
|---|
| 210 | | - case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break; |
|---|
| 211 | | - case DRM_FORMAT_XRGB1555 : |
|---|
| 212 | | - case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break; |
|---|
| 227 | + case DRM_FORMAT_C8: |
|---|
| 228 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_I8; |
|---|
| 229 | + break; |
|---|
| 230 | + case DRM_FORMAT_XRGB8888: |
|---|
| 231 | + case DRM_FORMAT_ARGB8888: |
|---|
| 232 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_A8R8G8B8; |
|---|
| 233 | + break; |
|---|
| 234 | + case DRM_FORMAT_RGB565: |
|---|
| 235 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_R5G6B5; |
|---|
| 236 | + break; |
|---|
| 237 | + case DRM_FORMAT_XRGB1555: |
|---|
| 238 | + case DRM_FORMAT_ARGB1555: |
|---|
| 239 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_A1R5G5B5; |
|---|
| 240 | + break; |
|---|
| 213 | 241 | case DRM_FORMAT_XBGR2101010: |
|---|
| 214 | | - case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break; |
|---|
| 215 | | - case DRM_FORMAT_XBGR8888 : |
|---|
| 216 | | - case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break; |
|---|
| 242 | + case DRM_FORMAT_ABGR2101010: |
|---|
| 243 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_A2B10G10R10; |
|---|
| 244 | + break; |
|---|
| 245 | + case DRM_FORMAT_XBGR8888: |
|---|
| 246 | + case DRM_FORMAT_ABGR8888: |
|---|
| 247 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_A8B8G8R8; |
|---|
| 248 | + break; |
|---|
| 217 | 249 | case DRM_FORMAT_XRGB2101010: |
|---|
| 218 | | - case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break; |
|---|
| 250 | + case DRM_FORMAT_ARGB2101010: |
|---|
| 251 | + asyw->image.format = NVC37E_SET_PARAMS_FORMAT_A2R10G10B10; |
|---|
| 252 | + break; |
|---|
| 253 | + case DRM_FORMAT_XBGR16161616F: |
|---|
| 254 | + case DRM_FORMAT_ABGR16161616F: |
|---|
| 255 | + asyw->image.format = NV507C_SURFACE_SET_PARAMS_FORMAT_RF16_GF16_BF16_AF16; |
|---|
| 256 | + break; |
|---|
| 219 | 257 | default: |
|---|
| 220 | 258 | return -EINVAL; |
|---|
| 221 | 259 | } |
|---|
| 222 | | - asyw->image.colorspace = 0; |
|---|
| 260 | + |
|---|
| 261 | + asyw->image.colorspace = NV507E_SURFACE_SET_PARAMS_COLOR_SPACE_RGB; |
|---|
| 223 | 262 | return 0; |
|---|
| 224 | 263 | } |
|---|
| 225 | 264 | |
|---|
| .. | .. |
|---|
| 229 | 268 | struct nv50_wndw_atom *asyw, |
|---|
| 230 | 269 | struct nv50_head_atom *asyh) |
|---|
| 231 | 270 | { |
|---|
| 232 | | - struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb); |
|---|
| 271 | + struct drm_framebuffer *fb = asyw->state.fb; |
|---|
| 233 | 272 | struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev); |
|---|
| 273 | + uint8_t kind; |
|---|
| 274 | + uint32_t tile_mode; |
|---|
| 234 | 275 | int ret; |
|---|
| 235 | 276 | |
|---|
| 236 | 277 | NV_ATOMIC(drm, "%s acquire\n", wndw->plane.name); |
|---|
| 237 | 278 | |
|---|
| 238 | | - if (asyw->state.fb != armw->state.fb || !armw->visible || modeset) { |
|---|
| 239 | | - asyw->image.w = fb->base.width; |
|---|
| 240 | | - asyw->image.h = fb->base.height; |
|---|
| 241 | | - asyw->image.kind = fb->nvbo->kind; |
|---|
| 279 | + if (fb != armw->state.fb || !armw->visible || modeset) { |
|---|
| 280 | + nouveau_framebuffer_get_layout(fb, &tile_mode, &kind); |
|---|
| 281 | + |
|---|
| 282 | + asyw->image.w = fb->width; |
|---|
| 283 | + asyw->image.h = fb->height; |
|---|
| 284 | + asyw->image.kind = kind; |
|---|
| 242 | 285 | |
|---|
| 243 | 286 | ret = nv50_wndw_atomic_check_acquire_rgb(asyw); |
|---|
| 244 | 287 | if (ret) { |
|---|
| .. | .. |
|---|
| 248 | 291 | } |
|---|
| 249 | 292 | |
|---|
| 250 | 293 | if (asyw->image.kind) { |
|---|
| 251 | | - asyw->image.layout = 0; |
|---|
| 294 | + asyw->image.layout = NV507C_SURFACE_SET_STORAGE_MEMORY_LAYOUT_BLOCKLINEAR; |
|---|
| 252 | 295 | if (drm->client.device.info.chipset >= 0xc0) |
|---|
| 253 | | - asyw->image.blockh = fb->nvbo->mode >> 4; |
|---|
| 296 | + asyw->image.blockh = tile_mode >> 4; |
|---|
| 254 | 297 | else |
|---|
| 255 | | - asyw->image.blockh = fb->nvbo->mode; |
|---|
| 256 | | - asyw->image.blocks[0] = fb->base.pitches[0] / 64; |
|---|
| 298 | + asyw->image.blockh = tile_mode; |
|---|
| 299 | + asyw->image.blocks[0] = fb->pitches[0] / 64; |
|---|
| 257 | 300 | asyw->image.pitch[0] = 0; |
|---|
| 258 | 301 | } else { |
|---|
| 259 | | - asyw->image.layout = 1; |
|---|
| 260 | | - asyw->image.blockh = 0; |
|---|
| 302 | + asyw->image.layout = NV507C_SURFACE_SET_STORAGE_MEMORY_LAYOUT_PITCH; |
|---|
| 303 | + asyw->image.blockh = NV507C_SURFACE_SET_STORAGE_BLOCK_HEIGHT_ONE_GOB; |
|---|
| 261 | 304 | asyw->image.blocks[0] = 0; |
|---|
| 262 | | - asyw->image.pitch[0] = fb->base.pitches[0]; |
|---|
| 305 | + asyw->image.pitch[0] = fb->pitches[0]; |
|---|
| 263 | 306 | } |
|---|
| 264 | 307 | |
|---|
| 265 | | - if (!(asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)) |
|---|
| 308 | + if (!asyh->state.async_flip) |
|---|
| 266 | 309 | asyw->image.interval = 1; |
|---|
| 267 | 310 | else |
|---|
| 268 | 311 | asyw->image.interval = 0; |
|---|
| 269 | | - asyw->image.mode = asyw->image.interval ? 0 : 1; |
|---|
| 312 | + |
|---|
| 313 | + if (asyw->image.interval) |
|---|
| 314 | + asyw->image.mode = NV507C_SET_PRESENT_CONTROL_BEGIN_MODE_NON_TEARING; |
|---|
| 315 | + else |
|---|
| 316 | + asyw->image.mode = NV507C_SET_PRESENT_CONTROL_BEGIN_MODE_IMMEDIATE; |
|---|
| 317 | + |
|---|
| 270 | 318 | asyw->set.image = wndw->func->image_set != NULL; |
|---|
| 271 | 319 | } |
|---|
| 272 | 320 | |
|---|
| .. | .. |
|---|
| 281 | 329 | asyw->set.scale = true; |
|---|
| 282 | 330 | } |
|---|
| 283 | 331 | |
|---|
| 332 | + if (wndw->func->blend_set) { |
|---|
| 333 | + asyw->blend.depth = 255 - asyw->state.normalized_zpos; |
|---|
| 334 | + asyw->blend.k1 = asyw->state.alpha >> 8; |
|---|
| 335 | + switch (asyw->state.pixel_blend_mode) { |
|---|
| 336 | + case DRM_MODE_BLEND_PREMULTI: |
|---|
| 337 | + asyw->blend.src_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_SRC_COLOR_FACTOR_MATCH_SELECT_K1; |
|---|
| 338 | + asyw->blend.dst_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_DST_COLOR_FACTOR_MATCH_SELECT_NEG_K1_TIMES_SRC; |
|---|
| 339 | + break; |
|---|
| 340 | + case DRM_MODE_BLEND_COVERAGE: |
|---|
| 341 | + asyw->blend.src_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_SRC_COLOR_FACTOR_MATCH_SELECT_K1_TIMES_SRC; |
|---|
| 342 | + asyw->blend.dst_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_DST_COLOR_FACTOR_MATCH_SELECT_NEG_K1_TIMES_SRC; |
|---|
| 343 | + break; |
|---|
| 344 | + case DRM_MODE_BLEND_PIXEL_NONE: |
|---|
| 345 | + default: |
|---|
| 346 | + asyw->blend.src_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_SRC_COLOR_FACTOR_MATCH_SELECT_K1; |
|---|
| 347 | + asyw->blend.dst_color = NVC37E_SET_COMPOSITION_FACTOR_SELECT_DST_COLOR_FACTOR_MATCH_SELECT_NEG_K1; |
|---|
| 348 | + break; |
|---|
| 349 | + } |
|---|
| 350 | + if (memcmp(&armw->blend, &asyw->blend, sizeof(asyw->blend))) |
|---|
| 351 | + asyw->set.blend = true; |
|---|
| 352 | + } |
|---|
| 353 | + |
|---|
| 284 | 354 | if (wndw->immd) { |
|---|
| 285 | 355 | asyw->point.x = asyw->state.crtc_x; |
|---|
| 286 | 356 | asyw->point.y = asyw->state.crtc_y; |
|---|
| .. | .. |
|---|
| 291 | 361 | return wndw->func->acquire(wndw, asyw, asyh); |
|---|
| 292 | 362 | } |
|---|
| 293 | 363 | |
|---|
| 294 | | -static void |
|---|
| 364 | +static int |
|---|
| 295 | 365 | nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, |
|---|
| 296 | 366 | struct nv50_wndw_atom *armw, |
|---|
| 297 | 367 | struct nv50_wndw_atom *asyw, |
|---|
| .. | .. |
|---|
| 313 | 383 | */ |
|---|
| 314 | 384 | if (!(ilut = asyh->state.gamma_lut)) { |
|---|
| 315 | 385 | asyw->visible = false; |
|---|
| 316 | | - return; |
|---|
| 386 | + return 0; |
|---|
| 317 | 387 | } |
|---|
| 318 | 388 | |
|---|
| 319 | 389 | if (wndw->func->ilut) |
|---|
| .. | .. |
|---|
| 322 | 392 | asyh->wndw.olut &= ~BIT(wndw->id); |
|---|
| 323 | 393 | } |
|---|
| 324 | 394 | |
|---|
| 395 | + if (!ilut && wndw->func->ilut_identity && |
|---|
| 396 | + asyw->state.fb->format->format != DRM_FORMAT_XBGR16161616F && |
|---|
| 397 | + asyw->state.fb->format->format != DRM_FORMAT_ABGR16161616F) { |
|---|
| 398 | + static struct drm_property_blob dummy = {}; |
|---|
| 399 | + ilut = &dummy; |
|---|
| 400 | + } |
|---|
| 401 | + |
|---|
| 325 | 402 | /* Recalculate LUT state. */ |
|---|
| 326 | 403 | memset(&asyw->xlut, 0x00, sizeof(asyw->xlut)); |
|---|
| 327 | 404 | if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) { |
|---|
| 328 | | - wndw->func->ilut(wndw, asyw); |
|---|
| 405 | + if (!wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut))) { |
|---|
| 406 | + DRM_DEBUG_KMS("Invalid ilut\n"); |
|---|
| 407 | + return -EINVAL; |
|---|
| 408 | + } |
|---|
| 329 | 409 | asyw->xlut.handle = wndw->wndw.vram.handle; |
|---|
| 330 | 410 | asyw->xlut.i.buffer = !asyw->xlut.i.buffer; |
|---|
| 331 | 411 | asyw->set.xlut = true; |
|---|
| 412 | + } else { |
|---|
| 413 | + asyw->clr.xlut = armw->xlut.handle != 0; |
|---|
| 332 | 414 | } |
|---|
| 333 | 415 | |
|---|
| 334 | 416 | /* Handle setting base SET_OUTPUT_LUT_LO_ENABLE_USE_CORE_LUT. */ |
|---|
| .. | .. |
|---|
| 336 | 418 | (!armw->visible || (armw->xlut.handle && !asyw->xlut.handle))) |
|---|
| 337 | 419 | asyw->set.xlut = true; |
|---|
| 338 | 420 | |
|---|
| 421 | + if (wndw->func->csc && asyh->state.ctm) { |
|---|
| 422 | + const struct drm_color_ctm *ctm = asyh->state.ctm->data; |
|---|
| 423 | + wndw->func->csc(wndw, asyw, ctm); |
|---|
| 424 | + asyw->csc.valid = true; |
|---|
| 425 | + asyw->set.csc = true; |
|---|
| 426 | + } else { |
|---|
| 427 | + asyw->csc.valid = false; |
|---|
| 428 | + asyw->clr.csc = armw->csc.valid; |
|---|
| 429 | + } |
|---|
| 430 | + |
|---|
| 339 | 431 | /* Can't do an immediate flip while changing the LUT. */ |
|---|
| 340 | | - asyh->state.pageflip_flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; |
|---|
| 432 | + asyh->state.async_flip = false; |
|---|
| 433 | + return 0; |
|---|
| 341 | 434 | } |
|---|
| 342 | 435 | |
|---|
| 343 | 436 | static int |
|---|
| .. | .. |
|---|
| 378 | 471 | (!armw->visible || |
|---|
| 379 | 472 | asyh->state.color_mgmt_changed || |
|---|
| 380 | 473 | asyw->state.fb->format->format != |
|---|
| 381 | | - armw->state.fb->format->format)) |
|---|
| 382 | | - nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh); |
|---|
| 474 | + armw->state.fb->format->format)) { |
|---|
| 475 | + ret = nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh); |
|---|
| 476 | + if (ret) |
|---|
| 477 | + return ret; |
|---|
| 478 | + } |
|---|
| 383 | 479 | |
|---|
| 384 | 480 | /* Calculate new window state. */ |
|---|
| 385 | 481 | if (asyw->visible) { |
|---|
| .. | .. |
|---|
| 407 | 503 | asyw->clr.xlut = armw->xlut.handle != 0; |
|---|
| 408 | 504 | if (asyw->clr.xlut && asyw->visible) |
|---|
| 409 | 505 | asyw->set.xlut = asyw->xlut.handle != 0; |
|---|
| 506 | + asyw->clr.csc = armw->csc.valid; |
|---|
| 410 | 507 | if (wndw->func->image_clr) |
|---|
| 411 | 508 | asyw->clr.image = armw->image.handle[0] != 0; |
|---|
| 412 | 509 | } |
|---|
| .. | .. |
|---|
| 417 | 514 | static void |
|---|
| 418 | 515 | nv50_wndw_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) |
|---|
| 419 | 516 | { |
|---|
| 420 | | - struct nouveau_framebuffer *fb = nouveau_framebuffer(old_state->fb); |
|---|
| 421 | 517 | struct nouveau_drm *drm = nouveau_drm(plane->dev); |
|---|
| 518 | + struct nouveau_bo *nvbo; |
|---|
| 422 | 519 | |
|---|
| 423 | 520 | NV_ATOMIC(drm, "%s cleanup: %p\n", plane->name, old_state->fb); |
|---|
| 424 | 521 | if (!old_state->fb) |
|---|
| 425 | 522 | return; |
|---|
| 426 | 523 | |
|---|
| 427 | | - nouveau_bo_unpin(fb->nvbo); |
|---|
| 524 | + nvbo = nouveau_gem_object(old_state->fb->obj[0]); |
|---|
| 525 | + nouveau_bo_unpin(nvbo); |
|---|
| 428 | 526 | } |
|---|
| 429 | 527 | |
|---|
| 430 | 528 | static int |
|---|
| 431 | 529 | nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) |
|---|
| 432 | 530 | { |
|---|
| 433 | | - struct nouveau_framebuffer *fb = nouveau_framebuffer(state->fb); |
|---|
| 531 | + struct drm_framebuffer *fb = state->fb; |
|---|
| 434 | 532 | struct nouveau_drm *drm = nouveau_drm(plane->dev); |
|---|
| 435 | 533 | struct nv50_wndw *wndw = nv50_wndw(plane); |
|---|
| 436 | 534 | struct nv50_wndw_atom *asyw = nv50_wndw_atom(state); |
|---|
| 535 | + struct nouveau_bo *nvbo; |
|---|
| 437 | 536 | struct nv50_head_atom *asyh; |
|---|
| 438 | 537 | struct nv50_wndw_ctxdma *ctxdma; |
|---|
| 439 | 538 | int ret; |
|---|
| 440 | 539 | |
|---|
| 441 | | - NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, state->fb); |
|---|
| 540 | + NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, fb); |
|---|
| 442 | 541 | if (!asyw->state.fb) |
|---|
| 443 | 542 | return 0; |
|---|
| 444 | 543 | |
|---|
| 445 | | - ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM, true); |
|---|
| 544 | + nvbo = nouveau_gem_object(fb->obj[0]); |
|---|
| 545 | + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, true); |
|---|
| 446 | 546 | if (ret) |
|---|
| 447 | 547 | return ret; |
|---|
| 448 | 548 | |
|---|
| 449 | 549 | if (wndw->ctxdma.parent) { |
|---|
| 450 | 550 | ctxdma = nv50_wndw_ctxdma_new(wndw, fb); |
|---|
| 451 | 551 | if (IS_ERR(ctxdma)) { |
|---|
| 452 | | - nouveau_bo_unpin(fb->nvbo); |
|---|
| 552 | + nouveau_bo_unpin(nvbo); |
|---|
| 453 | 553 | return PTR_ERR(ctxdma); |
|---|
| 454 | 554 | } |
|---|
| 455 | 555 | |
|---|
| 456 | | - asyw->image.handle[0] = ctxdma->object.handle; |
|---|
| 556 | + if (asyw->visible) |
|---|
| 557 | + asyw->image.handle[0] = ctxdma->object.handle; |
|---|
| 457 | 558 | } |
|---|
| 458 | 559 | |
|---|
| 459 | | - asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv); |
|---|
| 460 | | - asyw->image.offset[0] = fb->nvbo->bo.offset; |
|---|
| 560 | + asyw->state.fence = dma_resv_get_excl_rcu(nvbo->bo.base.resv); |
|---|
| 561 | + asyw->image.offset[0] = nvbo->offset; |
|---|
| 461 | 562 | |
|---|
| 462 | 563 | if (wndw->func->prepare) { |
|---|
| 463 | 564 | asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc); |
|---|
| .. | .. |
|---|
| 498 | 599 | asyw->ntfy = armw->ntfy; |
|---|
| 499 | 600 | asyw->ilut = NULL; |
|---|
| 500 | 601 | asyw->xlut = armw->xlut; |
|---|
| 602 | + asyw->csc = armw->csc; |
|---|
| 501 | 603 | asyw->image = armw->image; |
|---|
| 502 | 604 | asyw->point = armw->point; |
|---|
| 503 | 605 | asyw->clr.mask = 0; |
|---|
| 504 | 606 | asyw->set.mask = 0; |
|---|
| 505 | 607 | return &asyw->state; |
|---|
| 608 | +} |
|---|
| 609 | + |
|---|
| 610 | +static int |
|---|
| 611 | +nv50_wndw_zpos_default(struct drm_plane *plane) |
|---|
| 612 | +{ |
|---|
| 613 | + return (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : |
|---|
| 614 | + (plane->type == DRM_PLANE_TYPE_OVERLAY) ? 1 : 255; |
|---|
| 506 | 615 | } |
|---|
| 507 | 616 | |
|---|
| 508 | 617 | static void |
|---|
| .. | .. |
|---|
| 515 | 624 | |
|---|
| 516 | 625 | if (plane->state) |
|---|
| 517 | 626 | plane->funcs->atomic_destroy_state(plane, plane->state); |
|---|
| 518 | | - plane->state = &asyw->state; |
|---|
| 519 | | - plane->state->plane = plane; |
|---|
| 520 | | - plane->state->rotation = DRM_MODE_ROTATE_0; |
|---|
| 627 | + |
|---|
| 628 | + __drm_atomic_helper_plane_reset(plane, &asyw->state); |
|---|
| 629 | + plane->state->zpos = nv50_wndw_zpos_default(plane); |
|---|
| 630 | + plane->state->normalized_zpos = nv50_wndw_zpos_default(plane); |
|---|
| 521 | 631 | } |
|---|
| 522 | 632 | |
|---|
| 523 | 633 | static void |
|---|
| .. | .. |
|---|
| 530 | 640 | nv50_wndw_ctxdma_del(ctxdma); |
|---|
| 531 | 641 | } |
|---|
| 532 | 642 | |
|---|
| 533 | | - nvif_notify_fini(&wndw->notify); |
|---|
| 643 | + nvif_notify_dtor(&wndw->notify); |
|---|
| 534 | 644 | nv50_dmac_destroy(&wndw->wimm); |
|---|
| 535 | 645 | nv50_dmac_destroy(&wndw->wndw); |
|---|
| 536 | 646 | |
|---|
| .. | .. |
|---|
| 538 | 648 | |
|---|
| 539 | 649 | drm_plane_cleanup(&wndw->plane); |
|---|
| 540 | 650 | kfree(wndw); |
|---|
| 651 | +} |
|---|
| 652 | + |
|---|
| 653 | +/* This function assumes the format has already been validated against the plane |
|---|
| 654 | + * and the modifier was validated against the device-wides modifier list at FB |
|---|
| 655 | + * creation time. |
|---|
| 656 | + */ |
|---|
| 657 | +static bool nv50_plane_format_mod_supported(struct drm_plane *plane, |
|---|
| 658 | + u32 format, u64 modifier) |
|---|
| 659 | +{ |
|---|
| 660 | + struct nouveau_drm *drm = nouveau_drm(plane->dev); |
|---|
| 661 | + uint8_t i; |
|---|
| 662 | + |
|---|
| 663 | + if (drm->client.device.info.chipset < 0xc0) { |
|---|
| 664 | + const struct drm_format_info *info = drm_format_info(format); |
|---|
| 665 | + const uint8_t kind = (modifier >> 12) & 0xff; |
|---|
| 666 | + |
|---|
| 667 | + if (!format) return false; |
|---|
| 668 | + |
|---|
| 669 | + for (i = 0; i < info->num_planes; i++) |
|---|
| 670 | + if ((info->cpp[i] != 4) && kind != 0x70) return false; |
|---|
| 671 | + } |
|---|
| 672 | + |
|---|
| 673 | + return true; |
|---|
| 541 | 674 | } |
|---|
| 542 | 675 | |
|---|
| 543 | 676 | const struct drm_plane_funcs |
|---|
| .. | .. |
|---|
| 548 | 681 | .reset = nv50_wndw_reset, |
|---|
| 549 | 682 | .atomic_duplicate_state = nv50_wndw_atomic_duplicate_state, |
|---|
| 550 | 683 | .atomic_destroy_state = nv50_wndw_atomic_destroy_state, |
|---|
| 684 | + .format_mod_supported = nv50_plane_format_mod_supported, |
|---|
| 551 | 685 | }; |
|---|
| 552 | 686 | |
|---|
| 553 | 687 | static int |
|---|
| .. | .. |
|---|
| 568 | 702 | nvif_notify_get(&wndw->notify); |
|---|
| 569 | 703 | } |
|---|
| 570 | 704 | |
|---|
| 705 | +static const u64 nv50_cursor_format_modifiers[] = { |
|---|
| 706 | + DRM_FORMAT_MOD_LINEAR, |
|---|
| 707 | + DRM_FORMAT_MOD_INVALID, |
|---|
| 708 | +}; |
|---|
| 709 | + |
|---|
| 571 | 710 | int |
|---|
| 572 | 711 | nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, |
|---|
| 573 | 712 | enum drm_plane_type type, const char *name, int index, |
|---|
| .. | .. |
|---|
| 579 | 718 | struct nvif_mmu *mmu = &drm->client.mmu; |
|---|
| 580 | 719 | struct nv50_disp *disp = nv50_disp(dev); |
|---|
| 581 | 720 | struct nv50_wndw *wndw; |
|---|
| 721 | + const u64 *format_modifiers; |
|---|
| 582 | 722 | int nformat; |
|---|
| 583 | 723 | int ret; |
|---|
| 584 | 724 | |
|---|
| .. | .. |
|---|
| 594 | 734 | |
|---|
| 595 | 735 | for (nformat = 0; format[nformat]; nformat++); |
|---|
| 596 | 736 | |
|---|
| 597 | | - ret = drm_universal_plane_init(dev, &wndw->plane, heads, &nv50_wndw, |
|---|
| 598 | | - format, nformat, NULL, |
|---|
| 599 | | - type, "%s-%d", name, index); |
|---|
| 737 | + if (type == DRM_PLANE_TYPE_CURSOR) |
|---|
| 738 | + format_modifiers = nv50_cursor_format_modifiers; |
|---|
| 739 | + else |
|---|
| 740 | + format_modifiers = nouveau_display(dev)->format_modifiers; |
|---|
| 741 | + |
|---|
| 742 | + ret = drm_universal_plane_init(dev, &wndw->plane, heads, &nv50_wndw, format, nformat, |
|---|
| 743 | + format_modifiers, type, "%s-%d", name, index); |
|---|
| 600 | 744 | if (ret) { |
|---|
| 601 | 745 | kfree(*pwndw); |
|---|
| 602 | 746 | *pwndw = NULL; |
|---|
| .. | .. |
|---|
| 612 | 756 | } |
|---|
| 613 | 757 | |
|---|
| 614 | 758 | wndw->notify.func = nv50_wndw_notify; |
|---|
| 759 | + |
|---|
| 760 | + if (wndw->func->blend_set) { |
|---|
| 761 | + ret = drm_plane_create_zpos_property(&wndw->plane, |
|---|
| 762 | + nv50_wndw_zpos_default(&wndw->plane), 0, 254); |
|---|
| 763 | + if (ret) |
|---|
| 764 | + return ret; |
|---|
| 765 | + |
|---|
| 766 | + ret = drm_plane_create_alpha_property(&wndw->plane); |
|---|
| 767 | + if (ret) |
|---|
| 768 | + return ret; |
|---|
| 769 | + |
|---|
| 770 | + ret = drm_plane_create_blend_mode_property(&wndw->plane, |
|---|
| 771 | + BIT(DRM_MODE_BLEND_PIXEL_NONE) | |
|---|
| 772 | + BIT(DRM_MODE_BLEND_PREMULTI) | |
|---|
| 773 | + BIT(DRM_MODE_BLEND_COVERAGE)); |
|---|
| 774 | + if (ret) |
|---|
| 775 | + return ret; |
|---|
| 776 | + } else { |
|---|
| 777 | + ret = drm_plane_create_zpos_immutable_property(&wndw->plane, |
|---|
| 778 | + nv50_wndw_zpos_default(&wndw->plane)); |
|---|
| 779 | + if (ret) |
|---|
| 780 | + return ret; |
|---|
| 781 | + } |
|---|
| 782 | + |
|---|
| 615 | 783 | return 0; |
|---|
| 616 | 784 | } |
|---|
| 617 | 785 | |
|---|
| .. | .. |
|---|
| 625 | 793 | int (*new)(struct nouveau_drm *, enum drm_plane_type, |
|---|
| 626 | 794 | int, s32, struct nv50_wndw **); |
|---|
| 627 | 795 | } wndws[] = { |
|---|
| 796 | + { TU102_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new }, |
|---|
| 628 | 797 | { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new }, |
|---|
| 629 | 798 | {} |
|---|
| 630 | 799 | }; |
|---|