While we do handle the additional cursor sizes introduced in NVE4, it looks
like we accidentally broke this when converting over to use Nvidia's
display headers. Since we now use NVVAL in dispnv50/head907d.c in order to
format the value for the cursor layout and NVD9 only had one byte reserved
vs. the 2 bytes reserved in later generations, we end up accidentally
stripping the second bit in the cursor layout format parameter - causing us
to set the wrong cursor size.
This fixes that by adding our own curs_set hook for 917d which uses the
NV917D headers.
Cc: Martin Peres <martin.peres@free.fr>
Cc: Jeremy Cline <jcline@redhat.com>
Cc: Simon Ser <contact@emersion.fr>
Cc: <stable@vger.kernel.org> # v5.9+
Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: ed0b86a90b
("drm/nouveau/kms/nv50-: use NVIDIA's headers for core head_curs_set()")
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
137 lines
4.7 KiB
C
137 lines
4.7 KiB
C
/*
|
|
* Copyright 2018 Red Hat Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include "head.h"
|
|
#include "core.h"
|
|
|
|
#include "nvif/push.h"
|
|
#include <nvif/push507c.h>
|
|
|
|
#include <nvhw/class/cl917d.h>
|
|
|
|
static int
|
|
head917d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
|
|
{
|
|
struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
|
|
const int i = head->base.index;
|
|
int ret;
|
|
|
|
if ((ret = PUSH_WAIT(push, 2)))
|
|
return ret;
|
|
|
|
PUSH_MTHD(push, NV917D, HEAD_SET_DITHER_CONTROL(i),
|
|
NVVAL(NV917D, HEAD_SET_DITHER_CONTROL, ENABLE, asyh->dither.enable) |
|
|
NVVAL(NV917D, HEAD_SET_DITHER_CONTROL, BITS, asyh->dither.bits) |
|
|
NVVAL(NV917D, HEAD_SET_DITHER_CONTROL, MODE, asyh->dither.mode) |
|
|
NVVAL(NV917D, HEAD_SET_DITHER_CONTROL, PHASE, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
head917d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
|
|
{
|
|
struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
|
|
const int i = head->base.index;
|
|
u32 bounds = 0;
|
|
int ret;
|
|
|
|
if (asyh->base.cpp) {
|
|
switch (asyh->base.cpp) {
|
|
case 8: bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_64); break;
|
|
case 4: bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_32); break;
|
|
case 2: bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); break;
|
|
case 1: bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_8); break;
|
|
default:
|
|
WARN_ON(1);
|
|
break;
|
|
}
|
|
bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, USABLE, TRUE);
|
|
bounds |= NVDEF(NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, BASE_LUT, USAGE_1025);
|
|
}
|
|
|
|
if ((ret = PUSH_WAIT(push, 2)))
|
|
return ret;
|
|
|
|
PUSH_MTHD(push, NV917D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS(i), bounds);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
head917d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
|
|
{
|
|
struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
|
|
const int i = head->base.index;
|
|
int ret;
|
|
|
|
ret = PUSH_WAIT(push, 5);
|
|
if (ret)
|
|
return ret;
|
|
|
|
PUSH_MTHD(push, NV917D, HEAD_SET_CONTROL_CURSOR(i),
|
|
NVDEF(NV917D, HEAD_SET_CONTROL_CURSOR, ENABLE, ENABLE) |
|
|
NVVAL(NV917D, HEAD_SET_CONTROL_CURSOR, FORMAT, asyh->curs.format) |
|
|
NVVAL(NV917D, HEAD_SET_CONTROL_CURSOR, SIZE, asyh->curs.layout) |
|
|
NVVAL(NV917D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_X, 0) |
|
|
NVVAL(NV917D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_Y, 0) |
|
|
NVDEF(NV917D, HEAD_SET_CONTROL_CURSOR, COMPOSITION, ALPHA_BLEND),
|
|
|
|
HEAD_SET_OFFSET_CURSOR(i), asyh->curs.offset >> 8);
|
|
|
|
PUSH_MTHD(push, NV917D, HEAD_SET_CONTEXT_DMA_CURSOR(i), asyh->curs.handle);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
head917d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw,
|
|
struct nv50_head_atom *asyh)
|
|
{
|
|
switch (asyw->state.fb->width) {
|
|
case 32: asyh->curs.layout = NV917D_HEAD_SET_CONTROL_CURSOR_SIZE_W32_H32; break;
|
|
case 64: asyh->curs.layout = NV917D_HEAD_SET_CONTROL_CURSOR_SIZE_W64_H64; break;
|
|
case 128: asyh->curs.layout = NV917D_HEAD_SET_CONTROL_CURSOR_SIZE_W128_H128; break;
|
|
case 256: asyh->curs.layout = NV917D_HEAD_SET_CONTROL_CURSOR_SIZE_W256_H256; break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const struct nv50_head_func
|
|
head917d = {
|
|
.view = head907d_view,
|
|
.mode = head907d_mode,
|
|
.olut = head907d_olut,
|
|
.olut_size = 1024,
|
|
.olut_set = head907d_olut_set,
|
|
.olut_clr = head907d_olut_clr,
|
|
.core_calc = head507d_core_calc,
|
|
.core_set = head907d_core_set,
|
|
.core_clr = head907d_core_clr,
|
|
.curs_layout = head917d_curs_layout,
|
|
.curs_format = head507d_curs_format,
|
|
.curs_set = head917d_curs_set,
|
|
.curs_clr = head907d_curs_clr,
|
|
.base = head917d_base,
|
|
.ovly = head907d_ovly,
|
|
.dither = head917d_dither,
|
|
.procamp = head907d_procamp,
|
|
.or = head907d_or,
|
|
};
|