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 void
  86wndwc37e_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
  95int
  96wndwc37e_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
 140int
 141wndwc37e_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
 157static int
 158wndwc37e_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
 210int
 211wndwc37e_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
 223int
 224wndwc37e_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
 240int
 241wndwc37e_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
 253int
 254wndwc37e_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
 269int
 270wndwc37e_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
 289void
 290wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
 291                 struct nv50_head_atom *asyh)
 292{
 293}
 294
 295int
 296wndwc37e_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
 305static const u32
 306wndwc37e_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
 326static const struct nv50_wndw_func
 327wndwc37e = {
 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
 349int
 350wndwc37e_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
 382int
 383wndwc37e_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