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