root/drivers/gpu/drm/nouveau/dispnv50/head507d.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. head507d_procamp
  2. head507d_dither
  3. head507d_ovly
  4. head507d_base
  5. head507d_curs_clr
  6. head507d_curs_set
  7. head507d_curs_format
  8. head507d_curs_layout
  9. head507d_core_clr
  10. head507d_core_set
  11. head507d_core_calc
  12. head507d_olut_clr
  13. head507d_olut_set
  14. head507d_olut_load
  15. head507d_olut
  16. head507d_mode
  17. head507d_view

   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 "head.h"
  23 #include "core.h"
  24 
  25 void
  26 head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
  27 {
  28         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
  29         u32 *push;
  30         if ((push = evo_wait(core, 2))) {
  31                 evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
  32                 evo_data(push, asyh->procamp.sat.sin << 20 |
  33                                asyh->procamp.sat.cos << 8);
  34                 evo_kick(push, core);
  35         }
  36 }
  37 
  38 void
  39 head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
  40 {
  41         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
  42         u32 *push;
  43         if ((push = evo_wait(core, 2))) {
  44                 evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
  45                 evo_data(push, asyh->dither.mode << 3 |
  46                                asyh->dither.bits << 1 |
  47                                asyh->dither.enable);
  48                 evo_kick(push, core);
  49         }
  50 }
  51 
  52 void
  53 head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
  54 {
  55         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
  56         u32 bounds = 0;
  57         u32 *push;
  58 
  59         if (asyh->ovly.cpp) {
  60                 switch (asyh->ovly.cpp) {
  61                 case 4: bounds |= 0x00000300; break;
  62                 case 2: bounds |= 0x00000100; break;
  63                 default:
  64                         WARN_ON(1);
  65                         break;
  66                 }
  67                 bounds |= 0x00000001;
  68         } else {
  69                 bounds |= 0x00000100;
  70         }
  71 
  72         if ((push = evo_wait(core, 2))) {
  73                 evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
  74                 evo_data(push, bounds);
  75                 evo_kick(push, core);
  76         }
  77 }
  78 
  79 void
  80 head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
  81 {
  82         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
  83         u32 bounds = 0;
  84         u32 *push;
  85 
  86         if (asyh->base.cpp) {
  87                 switch (asyh->base.cpp) {
  88                 case 8: bounds |= 0x00000500; break;
  89                 case 4: bounds |= 0x00000300; break;
  90                 case 2: bounds |= 0x00000100; break;
  91                 case 1: bounds |= 0x00000000; break;
  92                 default:
  93                         WARN_ON(1);
  94                         break;
  95                 }
  96                 bounds |= 0x00000001;
  97         }
  98 
  99         if ((push = evo_wait(core, 2))) {
 100                 evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
 101                 evo_data(push, bounds);
 102                 evo_kick(push, core);
 103         }
 104 }
 105 
 106 static void
 107 head507d_curs_clr(struct nv50_head *head)
 108 {
 109         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 110         u32 *push;
 111         if ((push = evo_wait(core, 2))) {
 112                 evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
 113                 evo_data(push, 0x05000000);
 114                 evo_kick(push, core);
 115         }
 116 }
 117 
 118 static void
 119 head507d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 120 {
 121         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 122         u32 *push;
 123         if ((push = evo_wait(core, 3))) {
 124                 evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
 125                 evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
 126                                             asyh->curs.format << 24);
 127                 evo_data(push, asyh->curs.offset >> 8);
 128                 evo_kick(push, core);
 129         }
 130 }
 131 
 132 int
 133 head507d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
 134                      struct nv50_head_atom *asyh)
 135 {
 136         switch (asyw->image.format) {
 137         case 0xcf: asyh->curs.format = 1; break;
 138         default:
 139                 WARN_ON(1);
 140                 return -EINVAL;
 141         }
 142         return 0;
 143 }
 144 
 145 int
 146 head507d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw,
 147                      struct nv50_head_atom *asyh)
 148 {
 149         switch (asyw->image.w) {
 150         case 32: asyh->curs.layout = 0; break;
 151         case 64: asyh->curs.layout = 1; break;
 152         default:
 153                 return -EINVAL;
 154         }
 155         return 0;
 156 }
 157 
 158 void
 159 head507d_core_clr(struct nv50_head *head)
 160 {
 161         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 162         u32 *push;
 163         if ((push = evo_wait(core, 2))) {
 164                 evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
 165                 evo_data(push, 0x00000000);
 166                 evo_kick(push, core);
 167         }
 168 }
 169 
 170 static void
 171 head507d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 172 {
 173         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 174         u32 *push;
 175         if ((push = evo_wait(core, 9))) {
 176                 evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
 177                 evo_data(push, asyh->core.offset >> 8);
 178                 evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
 179                 evo_data(push, asyh->core.h << 16 | asyh->core.w);
 180                 evo_data(push, asyh->core.layout << 20 |
 181                                (asyh->core.pitch >> 8) << 8 |
 182                                asyh->core.blocks << 8 |
 183                                asyh->core.blockh);
 184                 evo_data(push, asyh->core.kind << 16 |
 185                                asyh->core.format << 8);
 186                 evo_data(push, asyh->core.handle);
 187                 evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
 188                 evo_data(push, asyh->core.y << 16 | asyh->core.x);
 189                 evo_kick(push, core);
 190 
 191                 /* EVO will complain with INVALID_STATE if we have an
 192                  * active cursor and (re)specify HeadSetContextDmaIso
 193                  * without also updating HeadSetOffsetCursor.
 194                  */
 195                 asyh->set.curs = asyh->curs.visible;
 196                 asyh->set.olut = asyh->olut.handle != 0;
 197         }
 198 }
 199 
 200 void
 201 head507d_core_calc(struct nv50_head *head, struct nv50_head_atom *asyh)
 202 {
 203         struct nv50_disp *disp = nv50_disp(head->base.base.dev);
 204         if ((asyh->core.visible = (asyh->base.cpp != 0))) {
 205                 asyh->core.x = asyh->base.x;
 206                 asyh->core.y = asyh->base.y;
 207                 asyh->core.w = asyh->base.w;
 208                 asyh->core.h = asyh->base.h;
 209         } else
 210         if ((asyh->core.visible = (asyh->ovly.cpp != 0)) ||
 211             (asyh->core.visible = asyh->curs.visible)) {
 212                 /*XXX: We need to either find some way of having the
 213                  *     primary base layer appear black, while still
 214                  *     being able to display the other layers, or we
 215                  *     need to allocate a dummy black surface here.
 216                  */
 217                 asyh->core.x = 0;
 218                 asyh->core.y = 0;
 219                 asyh->core.w = asyh->state.mode.hdisplay;
 220                 asyh->core.h = asyh->state.mode.vdisplay;
 221         }
 222         asyh->core.handle = disp->core->chan.vram.handle;
 223         asyh->core.offset = 0;
 224         asyh->core.format = 0xcf;
 225         asyh->core.kind = 0;
 226         asyh->core.layout = 1;
 227         asyh->core.blockh = 0;
 228         asyh->core.blocks = 0;
 229         asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
 230 }
 231 
 232 static void
 233 head507d_olut_clr(struct nv50_head *head)
 234 {
 235         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 236         u32 *push;
 237         if ((push = evo_wait(core, 2))) {
 238                 evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
 239                 evo_data(push, 0x00000000);
 240                 evo_kick(push, core);
 241         }
 242 }
 243 
 244 static void
 245 head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 246 {
 247         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 248         u32 *push;
 249         if ((push = evo_wait(core, 3))) {
 250                 evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
 251                 evo_data(push, 0x80000000 | asyh->olut.mode << 30);
 252                 evo_data(push, asyh->olut.offset >> 8);
 253                 evo_kick(push, core);
 254         }
 255 }
 256 
 257 static void
 258 head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
 259 {
 260         for (; size--; in++, mem += 8) {
 261                 writew(drm_color_lut_extract(in->  red, 11) << 3, mem + 0);
 262                 writew(drm_color_lut_extract(in->green, 11) << 3, mem + 2);
 263                 writew(drm_color_lut_extract(in-> blue, 11) << 3, mem + 4);
 264         }
 265 
 266         /* INTERPOLATE modes require a "next" entry to interpolate with,
 267          * so we replicate the last entry to deal with this for now.
 268          */
 269         writew(readw(mem - 8), mem + 0);
 270         writew(readw(mem - 6), mem + 2);
 271         writew(readw(mem - 4), mem + 4);
 272 }
 273 
 274 void
 275 head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
 276 {
 277         if (asyh->base.cpp == 1)
 278                 asyh->olut.mode = 0;
 279         else
 280                 asyh->olut.mode = 1;
 281 
 282         asyh->olut.load = head507d_olut_load;
 283 }
 284 
 285 void
 286 head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
 287 {
 288         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 289         struct nv50_head_mode *m = &asyh->mode;
 290         u32 *push;
 291         if ((push = evo_wait(core, 13))) {
 292                 evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
 293                 evo_data(push, 0x00800000 | m->clock);
 294                 evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
 295                 evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
 296                 evo_data(push, 0x00000000);
 297                 evo_data(push, m->v.active  << 16 | m->h.active );
 298                 evo_data(push, m->v.synce   << 16 | m->h.synce  );
 299                 evo_data(push, m->v.blanke  << 16 | m->h.blanke );
 300                 evo_data(push, m->v.blanks  << 16 | m->h.blanks );
 301                 evo_data(push, m->v.blank2e << 16 | m->v.blank2s);
 302                 evo_data(push, asyh->mode.v.blankus);
 303                 evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
 304                 evo_data(push, 0x00000000);
 305                 evo_kick(push, core);
 306         }
 307 }
 308 
 309 void
 310 head507d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
 311 {
 312         struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
 313         u32 *push;
 314         if ((push = evo_wait(core, 7))) {
 315                 evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
 316                 evo_data(push, 0x00000000);
 317                 evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
 318                 evo_data(push, asyh->view.iH << 16 | asyh->view.iW);
 319                 evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
 320                 evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
 321                 evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
 322                 evo_kick(push, core);
 323         }
 324 }
 325 
 326 const struct nv50_head_func
 327 head507d = {
 328         .view = head507d_view,
 329         .mode = head507d_mode,
 330         .olut = head507d_olut,
 331         .olut_set = head507d_olut_set,
 332         .olut_clr = head507d_olut_clr,
 333         .core_calc = head507d_core_calc,
 334         .core_set = head507d_core_set,
 335         .core_clr = head507d_core_clr,
 336         .curs_layout = head507d_curs_layout,
 337         .curs_format = head507d_curs_format,
 338         .curs_set = head507d_curs_set,
 339         .curs_clr = head507d_curs_clr,
 340         .base = head507d_base,
 341         .ovly = head507d_ovly,
 342         .dither = head507d_dither,
 343         .procamp = head507d_procamp,
 344 };

/* [<][>][^][v][top][bottom][index][help] */