linux/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.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
  31static void
  32wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
  33{
  34        u32 *push;
  35
  36        if (!(push = evo_wait(&wndw->wndw, 17)))
  37                return;
  38
  39        evo_mthd(push, 0x0308, 1);
  40        evo_data(push, asyw->image.mode << 4 | asyw->image.interval);
  41        evo_mthd(push, 0x0224, 4);
  42        evo_data(push, asyw->image.h << 16 | asyw->image.w);
  43        evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
  44        evo_data(push, asyw->image.colorspace << 8 |
  45                       asyw->image.format);
  46        evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
  47        evo_mthd(push, 0x0240, 1);
  48        evo_data(push, asyw->image.handle[0]);
  49        evo_mthd(push, 0x0260, 1);
  50        evo_data(push, asyw->image.offset[0] >> 8);
  51        evo_mthd(push, 0x0290, 1);
  52        evo_data(push, (asyw->state.src_y >> 16) << 16 |
  53                       (asyw->state.src_x >> 16));
  54        evo_mthd(push, 0x0298, 1);
  55        evo_data(push, (asyw->state.src_h >> 16) << 16 |
  56                       (asyw->state.src_w >> 16));
  57        evo_mthd(push, 0x02a4, 1);
  58        evo_data(push, asyw->state.crtc_h << 16 |
  59                       asyw->state.crtc_w);
  60        evo_kick(push, &wndw->wndw);
  61}
  62
  63static void
  64wndwc57e_csc_clr(struct nv50_wndw *wndw)
  65{
  66        u32 *push;
  67        if ((push = evo_wait(&wndw->wndw, 13))) {
  68                 evo_mthd(push, 0x0400, 12);
  69                 evo_data(push, 0x00010000);
  70                 evo_data(push, 0x00000000);
  71                 evo_data(push, 0x00000000);
  72                 evo_data(push, 0x00000000);
  73                 evo_data(push, 0x00000000);
  74                 evo_data(push, 0x00010000);
  75                 evo_data(push, 0x00000000);
  76                 evo_data(push, 0x00000000);
  77                 evo_data(push, 0x00000000);
  78                 evo_data(push, 0x00000000);
  79                 evo_data(push, 0x00010000);
  80                 evo_data(push, 0x00000000);
  81                 evo_kick(push, &wndw->wndw);
  82        }
  83}
  84
  85static void
  86wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
  87{
  88        u32 *push, i;
  89        if ((push = evo_wait(&wndw->wndw, 13))) {
  90                 evo_mthd(push, 0x0400, 12);
  91                 for (i = 0; i < 12; i++)
  92                          evo_data(push, asyw->csc.matrix[i]);
  93                 evo_kick(push, &wndw->wndw);
  94        }
  95}
  96
  97static void
  98wndwc57e_ilut_clr(struct nv50_wndw *wndw)
  99{
 100        u32 *push;
 101        if ((push = evo_wait(&wndw->wndw, 2))) {
 102                evo_mthd(push, 0x0444, 1);
 103                evo_data(push, 0x00000000);
 104                evo_kick(push, &wndw->wndw);
 105        }
 106}
 107
 108static void
 109wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 110{
 111        u32 *push;
 112        if ((push = evo_wait(&wndw->wndw, 4))) {
 113                evo_mthd(push, 0x0440, 3);
 114                evo_data(push, asyw->xlut.i.size << 8 |
 115                               asyw->xlut.i.mode << 2 |
 116                               asyw->xlut.i.output_mode);
 117                evo_data(push, asyw->xlut.handle);
 118                evo_data(push, asyw->xlut.i.offset >> 8);
 119                evo_kick(push, &wndw->wndw);
 120        }
 121}
 122
 123static u16
 124fixedU0_16_FP16(u16 fixed)
 125{
 126        int sign = 0, exp = 0, man = 0;
 127        if (fixed) {
 128                while (--exp && !(fixed & 0x8000))
 129                        fixed <<= 1;
 130                man = ((fixed << 1) & 0xffc0) >> 6;
 131                exp += 15;
 132        }
 133        return (sign << 15) | (exp << 10) | man;
 134}
 135
 136static void
 137wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
 138{
 139        memset_io(mem, 0x00, 0x20); /* VSS header. */
 140        mem += 0x20;
 141
 142        for (; size--; in++, mem += 0x08) {
 143                u16 r = fixedU0_16_FP16(drm_color_lut_extract(in->  red, 16));
 144                u16 g = fixedU0_16_FP16(drm_color_lut_extract(in->green, 16));
 145                u16 b = fixedU0_16_FP16(drm_color_lut_extract(in-> blue, 16));
 146                writew(r, mem + 0);
 147                writew(g, mem + 2);
 148                writew(b, mem + 4);
 149        }
 150
 151        /* INTERPOLATE modes require a "next" entry to interpolate with,
 152         * so we replicate the last entry to deal with this for now.
 153         */
 154        writew(readw(mem - 8), mem + 0);
 155        writew(readw(mem - 6), mem + 2);
 156        writew(readw(mem - 4), mem + 4);
 157}
 158
 159static void
 160wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 161{
 162        u16 size = asyw->ilut->length / sizeof(struct drm_color_lut);
 163        if (size == 256) {
 164                asyw->xlut.i.mode = 1; /* DIRECT8. */
 165        } else {
 166                asyw->xlut.i.mode = 2; /* DIRECT10. */
 167                size = 1024;
 168        }
 169        asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
 170        asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
 171        asyw->xlut.i.load = wndwc57e_ilut_load;
 172}
 173
 174static const struct nv50_wndw_func
 175wndwc57e = {
 176        .acquire = wndwc37e_acquire,
 177        .release = wndwc37e_release,
 178        .sema_set = wndwc37e_sema_set,
 179        .sema_clr = wndwc37e_sema_clr,
 180        .ntfy_set = wndwc37e_ntfy_set,
 181        .ntfy_clr = wndwc37e_ntfy_clr,
 182        .ntfy_reset = corec37d_ntfy_init,
 183        .ntfy_wait_begun = base507c_ntfy_wait_begun,
 184        .ilut = wndwc57e_ilut,
 185        .ilut_identity = true,
 186        .xlut_set = wndwc57e_ilut_set,
 187        .xlut_clr = wndwc57e_ilut_clr,
 188        .csc = base907c_csc,
 189        .csc_set = wndwc57e_csc_set,
 190        .csc_clr = wndwc57e_csc_clr,
 191        .image_set = wndwc57e_image_set,
 192        .image_clr = wndwc37e_image_clr,
 193        .blend_set = wndwc37e_blend_set,
 194        .update = wndwc37e_update,
 195};
 196
 197int
 198wndwc57e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
 199             s32 oclass, struct nv50_wndw **pwndw)
 200{
 201        return wndwc37e_new_(&wndwc57e, drm, type, index, oclass,
 202                             BIT(index >> 1), pwndw);
 203}
 204