linux/drivers/gpu/drm/nouveau/dispnv50/base507c.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 "base.h"
  23
  24#include <nvif/cl507c.h>
  25#include <nvif/event.h>
  26
  27#include <drm/drm_atomic_helper.h>
  28#include <drm/drm_plane_helper.h>
  29#include "nouveau_bo.h"
  30
  31void
  32base507c_update(struct nv50_wndw *wndw, u32 *interlock)
  33{
  34        u32 *push;
  35        if ((push = evo_wait(&wndw->wndw, 2))) {
  36                evo_mthd(push, 0x0080, 1);
  37                evo_data(push, interlock[NV50_DISP_INTERLOCK_CORE]);
  38                evo_kick(push, &wndw->wndw);
  39        }
  40}
  41
  42void
  43base507c_image_clr(struct nv50_wndw *wndw)
  44{
  45        u32 *push;
  46        if ((push = evo_wait(&wndw->wndw, 4))) {
  47                evo_mthd(push, 0x0084, 1);
  48                evo_data(push, 0x00000000);
  49                evo_mthd(push, 0x00c0, 1);
  50                evo_data(push, 0x00000000);
  51                evo_kick(push, &wndw->wndw);
  52        }
  53}
  54
  55static void
  56base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
  57{
  58        u32 *push;
  59        if ((push = evo_wait(&wndw->wndw, 10))) {
  60                evo_mthd(push, 0x0084, 1);
  61                evo_data(push, asyw->image.mode << 8 |
  62                               asyw->image.interval << 4);
  63                evo_mthd(push, 0x00c0, 1);
  64                evo_data(push, asyw->image.handle[0]);
  65                evo_mthd(push, 0x0800, 5);
  66                evo_data(push, asyw->image.offset[0] >> 8);
  67                evo_data(push, 0x00000000);
  68                evo_data(push, asyw->image.h << 16 | asyw->image.w);
  69                evo_data(push, asyw->image.layout << 20 |
  70                               (asyw->image.pitch[0] >> 8) << 8 |
  71                               asyw->image.blocks[0] << 8 |
  72                               asyw->image.blockh);
  73                evo_data(push, asyw->image.kind << 16 |
  74                               asyw->image.format << 8);
  75                evo_kick(push, &wndw->wndw);
  76        }
  77}
  78
  79void
  80base507c_xlut_clr(struct nv50_wndw *wndw)
  81{
  82        u32 *push;
  83        if ((push = evo_wait(&wndw->wndw, 2))) {
  84                evo_mthd(push, 0x00e0, 1);
  85                evo_data(push, 0x00000000);
  86                evo_kick(push, &wndw->wndw);
  87        }
  88}
  89
  90void
  91base507c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
  92{
  93        u32 *push;
  94        if ((push = evo_wait(&wndw->wndw, 2))) {
  95                evo_mthd(push, 0x00e0, 1);
  96                evo_data(push, 0x40000000);
  97                evo_kick(push, &wndw->wndw);
  98        }
  99}
 100
 101int
 102base507c_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset,
 103                         struct nvif_device *device)
 104{
 105        s64 time = nvif_msec(device, 2000ULL,
 106                u32 data = nouveau_bo_rd32(bo, offset / 4);
 107                if ((data & 0xc0000000) == 0x40000000)
 108                        break;
 109                usleep_range(1, 2);
 110        );
 111        return time < 0 ? time : 0;
 112}
 113
 114void
 115base507c_ntfy_clr(struct nv50_wndw *wndw)
 116{
 117        u32 *push;
 118        if ((push = evo_wait(&wndw->wndw, 2))) {
 119                evo_mthd(push, 0x00a4, 1);
 120                evo_data(push, 0x00000000);
 121                evo_kick(push, &wndw->wndw);
 122        }
 123}
 124
 125void
 126base507c_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 127{
 128        u32 *push;
 129        if ((push = evo_wait(&wndw->wndw, 3))) {
 130                evo_mthd(push, 0x00a0, 2);
 131                evo_data(push, asyw->ntfy.awaken << 30 | asyw->ntfy.offset);
 132                evo_data(push, asyw->ntfy.handle);
 133                evo_kick(push, &wndw->wndw);
 134        }
 135}
 136
 137void
 138base507c_ntfy_reset(struct nouveau_bo *bo, u32 offset)
 139{
 140        nouveau_bo_wr32(bo, offset / 4, 0x00000000);
 141}
 142
 143void
 144base507c_sema_clr(struct nv50_wndw *wndw)
 145{
 146        u32 *push;
 147        if ((push = evo_wait(&wndw->wndw, 2))) {
 148                evo_mthd(push, 0x0094, 1);
 149                evo_data(push, 0x00000000);
 150                evo_kick(push, &wndw->wndw);
 151        }
 152}
 153
 154void
 155base507c_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 156{
 157        u32 *push;
 158        if ((push = evo_wait(&wndw->wndw, 5))) {
 159                evo_mthd(push, 0x0088, 4);
 160                evo_data(push, asyw->sema.offset);
 161                evo_data(push, asyw->sema.acquire);
 162                evo_data(push, asyw->sema.release);
 163                evo_data(push, asyw->sema.handle);
 164                evo_kick(push, &wndw->wndw);
 165        }
 166}
 167
 168void
 169base507c_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
 170                 struct nv50_head_atom *asyh)
 171{
 172        asyh->base.cpp = 0;
 173}
 174
 175int
 176base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
 177                 struct nv50_head_atom *asyh)
 178{
 179        const struct drm_framebuffer *fb = asyw->state.fb;
 180        int ret;
 181
 182        if (!fb->format->depth)
 183                return -EINVAL;
 184
 185        ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
 186                                                  DRM_PLANE_HELPER_NO_SCALING,
 187                                                  DRM_PLANE_HELPER_NO_SCALING,
 188                                                  false, true);
 189        if (ret)
 190                return ret;
 191
 192        if (!wndw->func->ilut) {
 193                if ((asyh->base.cpp != 1) ^ (fb->format->cpp[0] != 1))
 194                        asyh->state.color_mgmt_changed = true;
 195        }
 196
 197        asyh->base.depth = fb->format->depth;
 198        asyh->base.cpp = fb->format->cpp[0];
 199        asyh->base.x = asyw->state.src.x1 >> 16;
 200        asyh->base.y = asyw->state.src.y1 >> 16;
 201        asyh->base.w = asyw->state.fb->width;
 202        asyh->base.h = asyw->state.fb->height;
 203        return 0;
 204}
 205
 206const u32
 207base507c_format[] = {
 208        DRM_FORMAT_C8,
 209        DRM_FORMAT_RGB565,
 210        DRM_FORMAT_XRGB1555,
 211        DRM_FORMAT_ARGB1555,
 212        DRM_FORMAT_XRGB8888,
 213        DRM_FORMAT_ARGB8888,
 214        DRM_FORMAT_XBGR2101010,
 215        DRM_FORMAT_ABGR2101010,
 216        DRM_FORMAT_XBGR8888,
 217        DRM_FORMAT_ABGR8888,
 218        0
 219};
 220
 221static const struct nv50_wndw_func
 222base507c = {
 223        .acquire = base507c_acquire,
 224        .release = base507c_release,
 225        .sema_set = base507c_sema_set,
 226        .sema_clr = base507c_sema_clr,
 227        .ntfy_reset = base507c_ntfy_reset,
 228        .ntfy_set = base507c_ntfy_set,
 229        .ntfy_clr = base507c_ntfy_clr,
 230        .ntfy_wait_begun = base507c_ntfy_wait_begun,
 231        .olut_core = 1,
 232        .xlut_set = base507c_xlut_set,
 233        .xlut_clr = base507c_xlut_clr,
 234        .image_set = base507c_image_set,
 235        .image_clr = base507c_image_clr,
 236        .update = base507c_update,
 237};
 238
 239int
 240base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
 241              struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data,
 242              struct nv50_wndw **pwndw)
 243{
 244        struct nv50_disp_base_channel_dma_v0 args = {
 245                .head = head,
 246        };
 247        struct nv50_disp *disp = nv50_disp(drm->dev);
 248        struct nv50_wndw *wndw;
 249        int ret;
 250
 251        ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_PRIMARY,
 252                             "base", head, format, BIT(head),
 253                             NV50_DISP_INTERLOCK_BASE, interlock_data, &wndw);
 254        if (*pwndw = wndw, ret)
 255                return ret;
 256
 257        ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
 258                               &oclass, head, &args, sizeof(args),
 259                               disp->sync->bo.offset, &wndw->wndw);
 260        if (ret) {
 261                NV_ERROR(drm, "base%04x allocation failed: %d\n", oclass, ret);
 262                return ret;
 263        }
 264
 265        ret = nvif_notify_init(&wndw->wndw.base.user, wndw->notify.func,
 266                               false, NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT,
 267                               &(struct nvif_notify_uevent_req) {},
 268                               sizeof(struct nvif_notify_uevent_req),
 269                               sizeof(struct nvif_notify_uevent_rep),
 270                               &wndw->notify);
 271        if (ret)
 272                return ret;
 273
 274        wndw->ntfy = NV50_DISP_BASE_NTFY(wndw->id);
 275        wndw->sema = NV50_DISP_BASE_SEM0(wndw->id);
 276        wndw->data = 0x00000000;
 277        return 0;
 278}
 279
 280int
 281base507c_new(struct nouveau_drm *drm, int head, s32 oclass,
 282             struct nv50_wndw **pwndw)
 283{
 284        return base507c_new_(&base507c, base507c_format, drm, head, oclass,
 285                             0x00000002 << (head * 8), pwndw);
 286}
 287