drm/nouveau/kms/nv50-: split core implementation by hardware class

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2018-05-08 20:39:47 +10:00
parent 1590700d94
commit 09e1b78aab
19 changed files with 903 additions and 333 deletions

View File

@ -2,15 +2,23 @@ nouveau-y += dispnv50/disp.o
nouveau-y += dispnv50/core.o nouveau-y += dispnv50/core.o
nouveau-y += dispnv50/core507d.o nouveau-y += dispnv50/core507d.o
nouveau-y += dispnv50/core827d.o
nouveau-y += dispnv50/core907d.o
nouveau-y += dispnv50/core917d.o
nouveau-y += dispnv50/dac507d.o nouveau-y += dispnv50/dac507d.o
nouveau-y += dispnv50/dac907d.o
nouveau-y += dispnv50/pior507d.o nouveau-y += dispnv50/pior507d.o
nouveau-y += dispnv50/sor507d.o nouveau-y += dispnv50/sor507d.o
nouveau-y += dispnv50/sor907d.o
nouveau-y += dispnv50/head.o nouveau-y += dispnv50/head.o
nouveau-y += dispnv50/head507d.o nouveau-y += dispnv50/head507d.o
nouveau-y += dispnv50/head827d.o
nouveau-y += dispnv50/head907d.o
nouveau-y += dispnv50/head917d.o
nouveau-y += dispnv50/wndw.o nouveau-y += dispnv50/wndw.o

View File

@ -42,17 +42,17 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
int version; int version;
int (*new)(struct nouveau_drm *, s32, struct nv50_core **); int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
} cores[] = { } cores[] = {
{ GP102_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GP100_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GM200_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GM200_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GM107_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GM107_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GK110_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GK110_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GK104_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GK104_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GF110_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GF110_DISP_CORE_CHANNEL_DMA, 0, core907d_new },
{ GT214_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GT214_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
{ GT206_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GT206_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
{ GT200_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { GT200_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
{ G82_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { G82_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
{ NV50_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, { NV50_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
{} {}
}; };

View File

@ -12,6 +12,12 @@ int nv50_core_new(struct nouveau_drm *, struct nv50_core **);
void nv50_core_del(struct nv50_core **); void nv50_core_del(struct nv50_core **);
struct nv50_core_func { struct nv50_core_func {
void (*init)(struct nv50_core *);
void (*ntfy_init)(struct nouveau_bo *, u32 offset);
int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset,
struct nvif_device *);
void (*update)(struct nv50_core *, u32 interlock, bool ntfy);
const struct nv50_head_func *head; const struct nv50_head_func *head;
const struct nv50_outp_func { const struct nv50_outp_func {
void (*ctrl)(struct nv50_core *, int or, u32 ctrl, void (*ctrl)(struct nv50_core *, int or, u32 ctrl,
@ -20,7 +26,21 @@ struct nv50_core_func {
}; };
int core507d_new(struct nouveau_drm *, s32, struct nv50_core **); int core507d_new(struct nouveau_drm *, s32, struct nv50_core **);
int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
struct nv50_core **);
void core507d_init(struct nv50_core *);
void core507d_ntfy_init(struct nouveau_bo *, u32);
int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
void core507d_update(struct nv50_core *, u32, bool);
extern const struct nv50_outp_func dac507d; extern const struct nv50_outp_func dac507d;
extern const struct nv50_outp_func sor507d; extern const struct nv50_outp_func sor507d;
extern const struct nv50_outp_func pior507d; extern const struct nv50_outp_func pior507d;
int core827d_new(struct nouveau_drm *, s32, struct nv50_core **);
int core907d_new(struct nouveau_drm *, s32, struct nv50_core **);
extern const struct nv50_outp_func dac907d;
extern const struct nv50_outp_func sor907d;
int core917d_new(struct nouveau_drm *, s32, struct nv50_core **);
#endif #endif

View File

@ -26,15 +26,64 @@
#include "nouveau_bo.h" #include "nouveau_bo.h"
void
core507d_update(struct nv50_core *core, u32 interlock, bool ntfy)
{
u32 *push;
if ((push = evo_wait(&core->chan, 5))) {
if (ntfy) {
evo_mthd(push, 0x0084, 1);
evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY);
}
evo_mthd(push, 0x0080, 2);
evo_data(push, interlock);
evo_data(push, 0x00000000);
evo_kick(push, &core->chan);
}
}
int
core507d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
struct nvif_device *device)
{
s64 time = nvif_msec(device, 2000ULL,
if (nouveau_bo_rd32(bo, offset / 4))
break;
usleep_range(1, 2);
);
return time < 0 ? time : 0;
}
void
core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
{
nouveau_bo_wr32(bo, offset / 4, 0x00000000);
}
void
core507d_init(struct nv50_core *core)
{
u32 *push;
if ((push = evo_wait(&core->chan, 2))) {
evo_mthd(push, 0x0088, 1);
evo_data(push, core->chan.sync.handle);
evo_kick(push, &core->chan);
}
}
static const struct nv50_core_func static const struct nv50_core_func
core507d = { core507d = {
.init = core507d_init,
.ntfy_init = core507d_ntfy_init,
.ntfy_wait_done = core507d_ntfy_wait_done,
.update = core507d_update,
.head = &head507d, .head = &head507d,
.dac = &dac507d, .dac = &dac507d,
.sor = &sor507d, .sor = &sor507d,
.pior = &pior507d, .pior = &pior507d,
}; };
static int int
core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm, core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
s32 oclass, struct nv50_core **pcore) s32 oclass, struct nv50_core **pcore)
{ {

View File

@ -0,0 +1,41 @@
/*
* 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 "core.h"
#include "head.h"
static const struct nv50_core_func
core827d = {
.init = core507d_init,
.ntfy_init = core507d_ntfy_init,
.ntfy_wait_done = core507d_ntfy_wait_done,
.update = core507d_update,
.head = &head827d,
.dac = &dac507d,
.sor = &sor507d,
.pior = &pior507d,
};
int
core827d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
{
return core507d_new_(&core827d, drm, oclass, pcore);
}

View File

@ -0,0 +1,40 @@
/*
* 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 "core.h"
#include "head.h"
static const struct nv50_core_func
core907d = {
.init = core507d_init,
.ntfy_init = core507d_ntfy_init,
.ntfy_wait_done = core507d_ntfy_wait_done,
.update = core507d_update,
.head = &head907d,
.dac = &dac907d,
.sor = &sor907d,
};
int
core907d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
{
return core507d_new_(&core907d, drm, oclass, pcore);
}

View File

@ -0,0 +1,40 @@
/*
* 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 "core.h"
#include "head.h"
static const struct nv50_core_func
core917d = {
.init = core507d_init,
.ntfy_init = core507d_ntfy_init,
.ntfy_wait_done = core507d_ntfy_wait_done,
.update = core507d_update,
.head = &head917d,
.dac = &dac907d,
.sor = &sor907d,
};
int
core917d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
{
return core507d_new_(&core917d, drm, oclass, pcore);
}

View File

@ -21,26 +21,19 @@
*/ */
#include "core.h" #include "core.h"
#include <nvif/class.h>
static void static void
dac507d_ctrl(struct nv50_core *core, int or, u32 ctrl, dac507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
u32 *push, sync = 0; u32 *push, sync = 0;
if ((push = evo_wait(&core->chan, 3))) { if ((push = evo_wait(&core->chan, 3))) {
if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { if (asyh) {
if (asyh) { sync |= asyh->or.nvsync << 1;
sync |= asyh->or.nvsync << 1; sync |= asyh->or.nhsync;
sync |= asyh->or.nhsync;
}
evo_mthd(push, 0x0400 + (or * 0x080), 2);
evo_data(push, ctrl);
evo_data(push, sync);
} else {
evo_mthd(push, 0x0180 + (or * 0x020), 1);
evo_data(push, ctrl);
} }
evo_mthd(push, 0x0400 + (or * 0x080), 2);
evo_data(push, ctrl);
evo_data(push, sync);
evo_kick(push, &core->chan); evo_kick(push, &core->chan);
} }
} }

View File

@ -0,0 +1,39 @@
/*
* 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 "core.h"
static void
dac907d_ctrl(struct nv50_core *core, int or, u32 ctrl,
struct nv50_head_atom *asyh)
{
u32 *push;
if ((push = evo_wait(&core->chan, 2))) {
evo_mthd(push, 0x0180 + (or * 0x020), 1);
evo_data(push, ctrl);
evo_kick(push, &core->chan);
}
}
const struct nv50_outp_func
dac907d = {
.ctrl = dac907d_ctrl,
};

View File

@ -1587,10 +1587,9 @@ static void
nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock) nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
{ {
struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_disp *disp = nv50_disp(drm->dev);
struct nv50_dmac *core = &disp->core->chan; struct nv50_core *core = disp->core;
struct nv50_mstm *mstm; struct nv50_mstm *mstm;
struct drm_encoder *encoder; struct drm_encoder *encoder;
u32 *push;
NV_ATOMIC(drm, "commit core %08x\n", interlock); NV_ATOMIC(drm, "commit core %08x\n", interlock);
@ -1602,21 +1601,11 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
} }
} }
if ((push = evo_wait(core, 5))) { core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY);
evo_mthd(push, 0x0084, 1); core->func->update(core, interlock, true);
evo_data(push, 0x80000000); if (core->func->ntfy_wait_done(disp->sync, NV50_DISP_CORE_NTFY,
evo_mthd(push, 0x0080, 2); disp->core->chan.base.device))
evo_data(push, interlock); NV_ERROR(drm, "core notifier timeout\n");
evo_data(push, 0x00000000);
nouveau_bo_wr32(disp->sync, 0, 0x00000000);
evo_kick(push, core);
if (nvif_msec(&drm->client.device, 2000ULL,
if (nouveau_bo_rd32(disp->sync, 0))
break;
usleep_range(1, 2);
) < 0)
NV_ERROR(drm, "EVO timeout\n");
}
drm_for_each_encoder(encoder, drm->dev) { drm_for_each_encoder(encoder, drm->dev) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
@ -1770,16 +1759,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
/* Flush update. */ /* Flush update. */
if (interlock_core) { if (interlock_core) {
if (!interlock_chan && atom->state.legacy_cursor_update) { if (interlock_chan || !atom->state.legacy_cursor_update)
u32 *push = evo_wait(&disp->core->chan, 2);
if (push) {
evo_mthd(push, 0x0080, 1);
evo_data(push, 0x00000000);
evo_kick(push, &disp->core->chan);
}
} else {
nv50_disp_atomic_commit_core(drm, interlock_chan); nv50_disp_atomic_commit_core(drm, interlock_chan);
} else
disp->core->func->update(disp->core, 0, false);
} }
if (atom->lock_core) if (atom->lock_core)
@ -2079,18 +2062,11 @@ nv50_display_fini(struct drm_device *dev)
int int
nv50_display_init(struct drm_device *dev) nv50_display_init(struct drm_device *dev)
{ {
struct nv50_dmac *core = &nv50_disp(dev)->core->chan; struct nv50_core *core = nv50_disp(dev)->core;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_plane *plane; struct drm_plane *plane;
u32 *push;
push = evo_wait(core, 32); core->func->init(core);
if (!push)
return -EBUSY;
evo_mthd(push, 0x0088, 1);
evo_data(push, core->sync.handle);
evo_kick(push, core);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {

View File

@ -324,7 +324,6 @@ static int
nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
{ {
struct nouveau_drm *drm = nouveau_drm(crtc->dev); struct nouveau_drm *drm = nouveau_drm(crtc->dev);
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nv50_head *head = nv50_head(crtc); struct nv50_head *head = nv50_head(crtc);
struct nv50_head_atom *armh = nv50_head_atom(crtc->state); struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
struct nv50_head_atom *asyh = nv50_head_atom(state); struct nv50_head_atom *asyh = nv50_head_atom(state);
@ -373,31 +372,9 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
nv50_head_atomic_check_procamp(armh, asyh, asyc); nv50_head_atomic_check_procamp(armh, asyh, asyc);
} }
if ((asyh->core.visible = (asyh->base.cpp != 0))) { if (head->func->core_calc)
asyh->core.x = asyh->base.x; head->func->core_calc(head, asyh);
asyh->core.y = asyh->base.y;
asyh->core.w = asyh->base.w;
asyh->core.h = asyh->base.h;
} else
if ((asyh->core.visible = asyh->curs.visible) ||
(asyh->core.visible = asyh->ilut.visible)) {
/*XXX: We need to either find some way of having the
* primary base layer appear black, while still
* being able to display the other layers, or we
* need to allocate a dummy black surface here.
*/
asyh->core.x = 0;
asyh->core.y = 0;
asyh->core.w = asyh->state.mode.hdisplay;
asyh->core.h = asyh->state.mode.vdisplay;
}
asyh->core.handle = disp->core->chan.vram.handle;
asyh->core.offset = 0;
asyh->core.format = 0xcf;
asyh->core.kind = 0;
asyh->core.layout = 1;
asyh->core.block = 0;
asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
asyh->set.base = armh->base.cpp != asyh->base.cpp; asyh->set.base = armh->base.cpp != asyh->base.cpp;
asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp; asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp;
} else { } else {

View File

@ -24,6 +24,7 @@ struct nv50_head_func {
void (*mode)(struct nv50_head *, struct nv50_head_atom *); void (*mode)(struct nv50_head *, struct nv50_head_atom *);
void (*ilut_set)(struct nv50_head *, struct nv50_head_atom *); void (*ilut_set)(struct nv50_head *, struct nv50_head_atom *);
void (*ilut_clr)(struct nv50_head *); void (*ilut_clr)(struct nv50_head *);
void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
void (*core_set)(struct nv50_head *, struct nv50_head_atom *); void (*core_set)(struct nv50_head *, struct nv50_head_atom *);
void (*core_clr)(struct nv50_head *); void (*core_clr)(struct nv50_head *);
void (*curs_set)(struct nv50_head *, struct nv50_head_atom *); void (*curs_set)(struct nv50_head *, struct nv50_head_atom *);
@ -36,4 +37,30 @@ struct nv50_head_func {
}; };
extern const struct nv50_head_func head507d; extern const struct nv50_head_func head507d;
void head507d_view(struct nv50_head *, struct nv50_head_atom *);
void head507d_mode(struct nv50_head *, struct nv50_head_atom *);
void head507d_core_calc(struct nv50_head *, struct nv50_head_atom *);
void head507d_core_clr(struct nv50_head *);
void head507d_base(struct nv50_head *, struct nv50_head_atom *);
void head507d_ovly(struct nv50_head *, struct nv50_head_atom *);
void head507d_dither(struct nv50_head *, struct nv50_head_atom *);
void head507d_procamp(struct nv50_head *, struct nv50_head_atom *);
extern const struct nv50_head_func head827d;
extern const struct nv50_head_func head907d;
void head907d_view(struct nv50_head *, struct nv50_head_atom *);
void head907d_mode(struct nv50_head *, struct nv50_head_atom *);
void head907d_ilut_set(struct nv50_head *, struct nv50_head_atom *);
void head907d_ilut_clr(struct nv50_head *);
void head907d_core_set(struct nv50_head *, struct nv50_head_atom *);
void head907d_core_clr(struct nv50_head *);
void head907d_curs_set(struct nv50_head *, struct nv50_head_atom *);
void head907d_curs_clr(struct nv50_head *);
void head907d_base(struct nv50_head *, struct nv50_head_atom *);
void head907d_ovly(struct nv50_head *, struct nv50_head_atom *);
void head907d_procamp(struct nv50_head *, struct nv50_head_atom *);
void head907d_or(struct nv50_head *, struct nv50_head_atom *);
extern const struct nv50_head_func head917d;
#endif #endif

View File

@ -22,62 +22,34 @@
#include "head.h" #include "head.h"
#include "core.h" #include "core.h"
#include <nvif/class.h> void
static void
head907d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if (core->base.user.oclass >= GF110_DISP_CORE_CHANNEL_DMA &&
(push = evo_wait(core, 3))) {
evo_mthd(push, 0x0404 + (head->base.index * 0x300), 2);
evo_data(push, 0x00000001 | (asyh->or.depth << 6) |
(asyh->or.nvsync << 4) |
(asyh->or.nhsync << 3));
evo_data(push, 0x31ec6000 | (head->base.index << 25) |
asyh->mode.interlace);
evo_kick(push, core);
}
}
static void
head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 2))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1); evo_data(push, asyh->procamp.sat.sin << 20 |
else asyh->procamp.sat.cos << 8);
evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1);
evo_data(push, (asyh->procamp.sat.sin << 20) |
(asyh->procamp.sat.cos << 8));
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 2))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1); evo_data(push, asyh->dither.mode << 3 |
else asyh->dither.bits << 1 |
if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA) asyh->dither.enable);
evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
else
evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
evo_data(push, (asyh->dither.mode << 3) |
(asyh->dither.bits << 1) |
asyh->dither.enable);
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@ -97,16 +69,13 @@ head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
if ((push = evo_wait(core, 2))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
else
evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
evo_data(push, bounds); evo_data(push, bounds);
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@ -127,10 +96,7 @@ head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
if ((push = evo_wait(core, 2))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
else
evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
evo_data(push, bounds); evo_data(push, bounds);
evo_kick(push, core); evo_kick(push, core);
} }
@ -141,22 +107,9 @@ head507d_curs_clr(struct nv50_head *head)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 4))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_mthd(push, 0x0880 + head->base.index * 0x400, 1); evo_data(push, 0x05000000);
evo_data(push, 0x05000000);
} else
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, 0x00000000);
} else {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, 0x00000000);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
@ -166,42 +119,22 @@ head507d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 5))) { if ((push = evo_wait(core, 3))) {
if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) { evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
evo_mthd(push, 0x0880 + head->base.index * 0x400, 2); evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) | asyh->curs.format << 24);
(asyh->curs.format << 24)); evo_data(push, asyh->curs.offset >> 8);
evo_data(push, asyh->curs.offset >> 8);
} else
if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
(asyh->curs.format << 24));
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, asyh->curs.handle);
} else {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
(asyh->curs.format << 24));
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, asyh->curs.handle);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_core_clr(struct nv50_head *head) head507d_core_clr(struct nv50_head *head)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 2))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
else
evo_mthd(push, 0x0474 + head->base.index * 0x300, 1);
evo_data(push, 0x00000000); evo_data(push, 0x00000000);
evo_kick(push, core); evo_kick(push, core);
} }
@ -213,75 +146,67 @@ head507d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 9))) { if ((push = evo_wait(core, 9))) {
if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
evo_mthd(push, 0x0860 + head->base.index * 0x400, 1); evo_data(push, asyh->core.offset >> 8);
evo_data(push, asyh->core.offset >> 8); evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
evo_mthd(push, 0x0868 + head->base.index * 0x400, 4); evo_data(push, asyh->core.h << 16 | asyh->core.w);
evo_data(push, (asyh->core.h << 16) | asyh->core.w); evo_data(push, asyh->core.layout << 20 |
evo_data(push, asyh->core.layout << 20 | asyh->core.pitch >> 8 << 8 |
(asyh->core.pitch >> 8) << 8 | asyh->core.block);
asyh->core.block); evo_data(push, asyh->core.kind << 16 |
evo_data(push, asyh->core.kind << 16 | asyh->core.format << 8);
asyh->core.format << 8); evo_data(push, asyh->core.handle);
evo_data(push, asyh->core.handle); evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1); evo_data(push, asyh->core.y << 16 | asyh->core.x);
evo_data(push, (asyh->core.y << 16) | asyh->core.x);
/* EVO will complain with INVALID_STATE if we have an
* active cursor and (re)specify HeadSetContextDmaIso
* without also updating HeadSetOffsetCursor.
*/
asyh->set.curs = asyh->curs.visible;
} else
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
evo_data(push, asyh->core.offset >> 8);
evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
evo_data(push, (asyh->core.h << 16) | asyh->core.w);
evo_data(push, asyh->core.layout << 20 |
(asyh->core.pitch >> 8) << 8 |
asyh->core.block);
evo_data(push, asyh->core.format << 8);
evo_data(push, asyh->core.handle);
evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
evo_data(push, (asyh->core.y << 16) | asyh->core.x);
} else {
evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
evo_data(push, asyh->core.offset >> 8);
evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
evo_data(push, (asyh->core.h << 16) | asyh->core.w);
evo_data(push, asyh->core.layout << 24 |
(asyh->core.pitch >> 8) << 8 |
asyh->core.block);
evo_data(push, asyh->core.format << 8);
evo_data(push, asyh->core.handle);
evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
evo_data(push, (asyh->core.y << 16) | asyh->core.x);
}
evo_kick(push, core); evo_kick(push, core);
/* EVO will complain with INVALID_STATE if we have an
* active cursor and (re)specify HeadSetContextDmaIso
* without also updating HeadSetOffsetCursor.
*/
asyh->set.curs = asyh->curs.visible;
} }
} }
void
head507d_core_calc(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_disp *disp = nv50_disp(head->base.base.dev);
if ((asyh->core.visible = (asyh->base.cpp != 0))) {
asyh->core.x = asyh->base.x;
asyh->core.y = asyh->base.y;
asyh->core.w = asyh->base.w;
asyh->core.h = asyh->base.h;
} else
if ((asyh->core.visible = asyh->curs.visible) ||
(asyh->core.visible = asyh->ilut.visible)) {
/*XXX: We need to either find some way of having the
* primary base layer appear black, while still
* being able to display the other layers, or we
* need to allocate a dummy black surface here.
*/
asyh->core.x = 0;
asyh->core.y = 0;
asyh->core.w = asyh->state.mode.hdisplay;
asyh->core.h = asyh->state.mode.vdisplay;
}
asyh->core.handle = disp->core->chan.vram.handle;
asyh->core.offset = 0;
asyh->core.format = 0xcf;
asyh->core.kind = 0;
asyh->core.layout = 1;
asyh->core.block = 0;
asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
}
static void static void
head507d_ilut_clr(struct nv50_head *head) head507d_ilut_clr(struct nv50_head *head)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 4))) { if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1); evo_data(push, 0x40000000);
evo_data(push, 0x40000000);
} else
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
evo_data(push, 0x40000000);
evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
evo_data(push, 0x00000000);
} else {
evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
evo_data(push, 0x03000000);
evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
evo_data(push, 0x00000000);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
@ -291,96 +216,51 @@ head507d_ilut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 7))) { if ((push = evo_wait(core, 3))) {
if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2); evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
evo_data(push, 0x80000000 | asyh->ilut.mode << 30); evo_data(push, asyh->ilut.offset >> 8);
evo_data(push, asyh->ilut.offset >> 8);
} else
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
evo_data(push, asyh->ilut.offset >> 8);
evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
evo_data(push, asyh->ilut.handle);
} else {
evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
evo_data(push, 0x80000000 | asyh->ilut.mode << 24);
evo_data(push, asyh->ilut.offset >> 8);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
evo_data(push, asyh->ilut.handle);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
struct nv50_head_mode *m = &asyh->mode; struct nv50_head_mode *m = &asyh->mode;
u32 *push; u32 *push;
if ((push = evo_wait(core, 14))) { if ((push = evo_wait(core, 13))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2); evo_data(push, 0x00800000 | m->clock);
evo_data(push, 0x00800000 | m->clock); evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
evo_data(push, m->interlace ? 0x00000002 : 0x00000000); evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7); evo_data(push, 0x00000000);
evo_data(push, 0x00000000); evo_data(push, m->v.active << 16 | m->h.active );
evo_data(push, (m->v.active << 16) | m->h.active ); evo_data(push, m->v.synce << 16 | m->h.synce );
evo_data(push, (m->v.synce << 16) | m->h.synce ); evo_data(push, m->v.blanke << 16 | m->h.blanke );
evo_data(push, (m->v.blanke << 16) | m->h.blanke ); evo_data(push, m->v.blanks << 16 | m->h.blanks );
evo_data(push, (m->v.blanks << 16) | m->h.blanks ); evo_data(push, m->v.blank2e << 16 | m->v.blank2s);
evo_data(push, (m->v.blank2e << 16) | m->v.blank2s); evo_data(push, asyh->mode.v.blankus);
evo_data(push, asyh->mode.v.blankus); evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
evo_mthd(push, 0x082c + (head->base.index * 0x400), 1); evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
} else {
evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
evo_data(push, 0x00000000);
evo_data(push, (m->v.active << 16) | m->h.active );
evo_data(push, (m->v.synce << 16) | m->h.synce );
evo_data(push, (m->v.blanke << 16) | m->h.blanke );
evo_data(push, (m->v.blanks << 16) | m->h.blanks );
evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
evo_mthd(push, 0x042c + (head->base.index * 0x300), 2);
evo_data(push, 0x00000000); /* ??? */
evo_data(push, 0xffffff00);
evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
evo_data(push, m->clock * 1000);
evo_data(push, 0x00200000); /* ??? */
evo_data(push, m->clock * 1000);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
static void void
head507d_view(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push; u32 *push;
if ((push = evo_wait(core, 10))) { if ((push = evo_wait(core, 7))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1); evo_data(push, 0x00000000);
evo_data(push, 0x00000000); evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1); evo_data(push, asyh->view.iH << 16 | asyh->view.iW);
evo_data(push, (asyh->view.iH << 16) | asyh->view.iW); evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2); evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
evo_data(push, (asyh->view.oH << 16) | asyh->view.oW); evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
} else {
evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
evo_data(push, 0x00000000);
evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
}
evo_kick(push, core); evo_kick(push, core);
} }
} }
@ -391,6 +271,7 @@ head507d = {
.mode = head507d_mode, .mode = head507d_mode,
.ilut_set = head507d_ilut_set, .ilut_set = head507d_ilut_set,
.ilut_clr = head507d_ilut_clr, .ilut_clr = head507d_ilut_clr,
.core_calc = head507d_core_calc,
.core_set = head507d_core_set, .core_set = head507d_core_set,
.core_clr = head507d_core_clr, .core_clr = head507d_core_clr,
.curs_set = head507d_curs_set, .curs_set = head507d_curs_set,
@ -399,5 +280,4 @@ head507d = {
.ovly = head507d_ovly, .ovly = head507d_ovly,
.dither = head507d_dither, .dither = head507d_dither,
.procamp = head507d_procamp, .procamp = head507d_procamp,
.or = head907d_or,
}; };

View File

@ -0,0 +1,120 @@
/*
* 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"
static void
head827d_curs_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 4))) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
static void
head827d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 5))) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
asyh->curs.format << 24);
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, asyh->curs.handle);
evo_kick(push, core);
}
}
static void
head827d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 9))) {
evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
evo_data(push, asyh->core.offset >> 8);
evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
evo_data(push, asyh->core.h << 16 | asyh->core.w);
evo_data(push, asyh->core.layout << 20 |
(asyh->core.pitch >> 8) << 8 |
asyh->core.block);
evo_data(push, asyh->core.format << 8);
evo_data(push, asyh->core.handle);
evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
evo_data(push, asyh->core.y << 16 | asyh->core.x);
evo_kick(push, core);
}
}
static void
head827d_ilut_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 4))) {
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
evo_data(push, 0x40000000);
evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
static void
head827d_ilut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 5))) {
evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
evo_data(push, asyh->ilut.offset >> 8);
evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
evo_data(push, asyh->ilut.handle);
evo_kick(push, core);
}
}
const struct nv50_head_func
head827d = {
.view = head507d_view,
.mode = head507d_mode,
.ilut_set = head827d_ilut_set,
.ilut_clr = head827d_ilut_clr,
.core_calc = head507d_core_calc,
.core_set = head827d_core_set,
.core_clr = head507d_core_clr,
.curs_set = head827d_curs_set,
.curs_clr = head827d_curs_clr,
.base = head507d_base,
.ovly = head507d_ovly,
.dither = head507d_dither,
.procamp = head507d_procamp,
};

View File

@ -0,0 +1,274 @@
/*
* 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"
void
head907d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 3))) {
evo_mthd(push, 0x0404 + (head->base.index * 0x300), 2);
evo_data(push, 0x00000001 | asyh->or.depth << 6 |
asyh->or.nvsync << 4 |
asyh->or.nhsync << 3);
evo_data(push, 0x31ec6000 | head->base.index << 25 |
asyh->mode.interlace);
evo_kick(push, core);
}
}
void
head907d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1);
evo_data(push, asyh->procamp.sat.sin << 20 |
asyh->procamp.sat.cos << 8);
evo_kick(push, core);
}
}
static void
head907d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
evo_data(push, asyh->dither.mode << 3 |
asyh->dither.bits << 1 |
asyh->dither.enable);
evo_kick(push, core);
}
}
void
head907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 bounds = 0;
u32 *push;
if (asyh->ovly.cpp) {
switch (asyh->ovly.cpp) {
case 8: bounds |= 0x00000500; break;
case 4: bounds |= 0x00000300; break;
case 2: bounds |= 0x00000100; break;
default:
WARN_ON(1);
break;
}
bounds |= 0x00000001;
}
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
evo_data(push, bounds);
evo_kick(push, core);
}
}
void
head907d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 bounds = 0;
u32 *push;
if (asyh->base.cpp) {
switch (asyh->base.cpp) {
case 8: bounds |= 0x00000500; break;
case 4: bounds |= 0x00000300; break;
case 2: bounds |= 0x00000100; break;
case 1: bounds |= 0x00000000; break;
default:
WARN_ON(1);
break;
}
bounds |= 0x00000001;
}
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
evo_data(push, bounds);
evo_kick(push, core);
}
}
void
head907d_curs_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 4))) {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
void
head907d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 5))) {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
asyh->curs.format << 24);
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, asyh->curs.handle);
evo_kick(push, core);
}
}
void
head907d_core_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x0474 + head->base.index * 0x300, 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
void
head907d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 9))) {
evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
evo_data(push, asyh->core.offset >> 8);
evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
evo_data(push, asyh->core.h << 16 | asyh->core.w);
evo_data(push, asyh->core.layout << 24 |
(asyh->core.pitch >> 8) << 8 |
asyh->core.block);
evo_data(push, asyh->core.format << 8);
evo_data(push, asyh->core.handle);
evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
evo_data(push, asyh->core.y << 16 | asyh->core.x);
evo_kick(push, core);
}
}
void
head907d_ilut_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 4))) {
evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
evo_data(push, 0x03000000);
evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
void
head907d_ilut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 7))) {
evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
evo_data(push, 0x80000000 | asyh->ilut.mode << 24);
evo_data(push, asyh->ilut.offset >> 8);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
evo_data(push, asyh->ilut.handle);
evo_kick(push, core);
}
}
void
head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
struct nv50_head_mode *m = &asyh->mode;
u32 *push;
if ((push = evo_wait(core, 14))) {
evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
evo_data(push, 0x00000000);
evo_data(push, m->v.active << 16 | m->h.active );
evo_data(push, m->v.synce << 16 | m->h.synce );
evo_data(push, m->v.blanke << 16 | m->h.blanke );
evo_data(push, m->v.blanks << 16 | m->h.blanks );
evo_data(push, m->v.blank2e << 16 | m->v.blank2s);
evo_mthd(push, 0x042c + (head->base.index * 0x300), 2);
evo_data(push, 0x00000000); /* ??? */
evo_data(push, 0xffffff00);
evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
evo_data(push, m->clock * 1000);
evo_data(push, 0x00200000); /* ??? */
evo_data(push, m->clock * 1000);
evo_kick(push, core);
}
}
void
head907d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 8))) {
evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
evo_data(push, 0x00000000);
evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
evo_data(push, asyh->view.iH << 16 | asyh->view.iW);
evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
evo_kick(push, core);
}
}
const struct nv50_head_func
head907d = {
.view = head907d_view,
.mode = head907d_mode,
.ilut_set = head907d_ilut_set,
.ilut_clr = head907d_ilut_clr,
.core_calc = head507d_core_calc,
.core_set = head907d_core_set,
.core_clr = head907d_core_clr,
.curs_set = head907d_curs_set,
.curs_clr = head907d_curs_clr,
.base = head907d_base,
.ovly = head907d_ovly,
.dither = head907d_dither,
.procamp = head907d_procamp,
.or = head907d_or,
};

View File

@ -0,0 +1,55 @@
/*
* 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"
static void
head917d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
evo_data(push, asyh->dither.mode << 3 |
asyh->dither.bits << 1 |
asyh->dither.enable);
evo_kick(push, core);
}
}
const struct nv50_head_func
head917d = {
.view = head907d_view,
.mode = head907d_mode,
.ilut_set = head907d_ilut_set,
.ilut_clr = head907d_ilut_clr,
.core_calc = head507d_core_calc,
.core_set = head907d_core_set,
.core_clr = head907d_core_clr,
.curs_set = head907d_curs_set,
.curs_clr = head907d_curs_clr,
.base = head907d_base,
.ovly = head907d_ovly,
.dither = head917d_dither,
.procamp = head907d_procamp,
.or = head907d_or,
};

View File

@ -21,23 +21,19 @@
*/ */
#include "core.h" #include "core.h"
#include <nvif/class.h>
static void static void
pior507d_ctrl(struct nv50_core *core, int or, u32 ctrl, pior507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
u32 *push; u32 *push;
if ((push = evo_wait(&core->chan, 8))) { if ((push = evo_wait(&core->chan, 2))) {
if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { if (asyh) {
if (asyh) { ctrl |= asyh->or.depth << 16;
ctrl |= asyh->or.depth << 16; ctrl |= asyh->or.nvsync << 13;
ctrl |= asyh->or.nvsync << 13; ctrl |= asyh->or.nhsync << 12;
ctrl |= asyh->or.nhsync << 12;
}
evo_mthd(push, 0x0700 + (or * 0x040), 1);
evo_data(push, ctrl);
} }
evo_mthd(push, 0x0700 + (or * 0x040), 1);
evo_data(push, ctrl);
evo_kick(push, &core->chan); evo_kick(push, &core->chan);
} }
} }

View File

@ -21,24 +21,18 @@
*/ */
#include "core.h" #include "core.h"
#include <nvif/class.h>
static void static void
sor507d_ctrl(struct nv50_core *core, int or, u32 ctrl, sor507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
u32 *push; u32 *push;
if ((push = evo_wait(&core->chan, 6))) { if ((push = evo_wait(&core->chan, 2))) {
if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { if (asyh) {
if (asyh) { ctrl |= asyh->or.depth << 16;
ctrl |= asyh->or.depth << 16; ctrl |= asyh->or.nvsync << 13;
ctrl |= asyh->or.nvsync << 13; ctrl |= asyh->or.nhsync << 12;
ctrl |= asyh->or.nhsync << 12;
}
evo_mthd(push, 0x0600 + (or * 0x40), 1);
} else {
evo_mthd(push, 0x0200 + (or * 0x20), 1);
} }
evo_mthd(push, 0x0600 + (or * 0x40), 1);
evo_data(push, ctrl); evo_data(push, ctrl);
evo_kick(push, &core->chan); evo_kick(push, &core->chan);
} }

View File

@ -0,0 +1,41 @@
/*
* 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 "core.h"
#include <nvif/class.h>
static void
sor907d_ctrl(struct nv50_core *core, int or, u32 ctrl,
struct nv50_head_atom *asyh)
{
u32 *push;
if ((push = evo_wait(&core->chan, 2))) {
evo_mthd(push, 0x0200 + (or * 0x20), 1);
evo_data(push, ctrl);
evo_kick(push, &core->chan);
}
}
const struct nv50_outp_func
sor907d = {
.ctrl = sor907d_ctrl,
};