diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2018-05-08 20:39:47 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2018-05-18 15:01:28 +1000 |
commit | 09e1b78aab5715eacab02e4047c7a47d72f6a1e9 (patch) | |
tree | d889f7568557a7d0121c6138b223d5952bfb1e99 /drivers/gpu | |
parent | 1590700d94ac53772491ed3103a4e8b8de01640a (diff) |
drm/nouveau/kms/nv50-: split core implementation by hardware class
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
19 files changed, 903 insertions, 333 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild index f3877d2d8840..cde3ae98191a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild @@ -2,15 +2,23 @@ nouveau-y += dispnv50/disp.o nouveau-y += dispnv50/core.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/dac907d.o nouveau-y += dispnv50/pior507d.o nouveau-y += dispnv50/sor507d.o +nouveau-y += dispnv50/sor907d.o nouveau-y += dispnv50/head.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 diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.c b/drivers/gpu/drm/nouveau/dispnv50/core.c index b12899fe052a..f87cbaa4f8ec 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core.c @@ -42,17 +42,17 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore) int version; int (*new)(struct nouveau_drm *, s32, struct nv50_core **); } cores[] = { - { GP102_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GP100_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GM200_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GM107_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GK110_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GK104_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GF110_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GT214_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GT206_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { GT200_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, - { G82_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, + { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GM200_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GM107_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GK110_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GK104_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, + { GF110_DISP_CORE_CHANNEL_DMA, 0, core907d_new }, + { GT214_DISP_CORE_CHANNEL_DMA, 0, core827d_new }, + { GT206_DISP_CORE_CHANNEL_DMA, 0, core827d_new }, + { GT200_DISP_CORE_CHANNEL_DMA, 0, core827d_new }, + { G82_DISP_CORE_CHANNEL_DMA, 0, core827d_new }, { NV50_DISP_CORE_CHANNEL_DMA, 0, core507d_new }, {} }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.h b/drivers/gpu/drm/nouveau/dispnv50/core.h index 3cd54469311a..5fd7ddd31e5e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core.h +++ b/drivers/gpu/drm/nouveau/dispnv50/core.h @@ -12,6 +12,12 @@ int nv50_core_new(struct nouveau_drm *, struct nv50_core **); void nv50_core_del(struct nv50_core **); 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_outp_func { 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_(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 sor507d; 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 diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c index b0325f69a26f..96d7d8fde669 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c @@ -26,15 +26,64 @@ #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 core507d = { + .init = core507d_init, + .ntfy_init = core507d_ntfy_init, + .ntfy_wait_done = core507d_ntfy_wait_done, + .update = core507d_update, .head = &head507d, .dac = &dac507d, .sor = &sor507d, .pior = &pior507d, }; -static int +int core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/core827d.c b/drivers/gpu/drm/nouveau/dispnv50/core827d.c new file mode 100644 index 000000000000..6123a068f836 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/core827d.c @@ -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); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/core907d.c b/drivers/gpu/drm/nouveau/dispnv50/core907d.c new file mode 100644 index 000000000000..ef822f813435 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/core907d.c @@ -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); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/core917d.c b/drivers/gpu/drm/nouveau/dispnv50/core917d.c new file mode 100644 index 000000000000..392338df5bfd --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/core917d.c @@ -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); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/dac507d.c b/drivers/gpu/drm/nouveau/dispnv50/dac507d.c index 28b6025a80f3..2a10ef7d30a8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/dac507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/dac507d.c @@ -21,26 +21,19 @@ */ #include "core.h" -#include <nvif/class.h> - static void dac507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { u32 *push, sync = 0; if ((push = evo_wait(&core->chan, 3))) { - if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { - if (asyh) { - sync |= asyh->or.nvsync << 1; - 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); + if (asyh) { + sync |= asyh->or.nvsync << 1; + sync |= asyh->or.nhsync; } + evo_mthd(push, 0x0400 + (or * 0x080), 2); + evo_data(push, ctrl); + evo_data(push, sync); evo_kick(push, &core->chan); } } diff --git a/drivers/gpu/drm/nouveau/dispnv50/dac907d.c b/drivers/gpu/drm/nouveau/dispnv50/dac907d.c new file mode 100644 index 000000000000..11e87fa53fac --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/dac907d.c @@ -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, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index a8367c5d4691..6136beeba3fc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1587,10 +1587,9 @@ static void nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock) { 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 drm_encoder *encoder; - u32 *push; 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))) { - evo_mthd(push, 0x0084, 1); - evo_data(push, 0x80000000); - evo_mthd(push, 0x0080, 2); - evo_data(push, interlock); - 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"); - } + core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY); + core->func->update(core, interlock, true); + if (core->func->ntfy_wait_done(disp->sync, NV50_DISP_CORE_NTFY, + disp->core->chan.base.device)) + NV_ERROR(drm, "core notifier timeout\n"); drm_for_each_encoder(encoder, drm->dev) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { @@ -1770,16 +1759,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) /* Flush update. */ if (interlock_core) { - 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 { + if (interlock_chan || !atom->state.legacy_cursor_update) nv50_disp_atomic_commit_core(drm, interlock_chan); - } + else + disp->core->func->update(disp->core, 0, false); } if (atom->lock_core) @@ -2079,18 +2062,11 @@ nv50_display_fini(struct drm_device *dev) int 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_plane *plane; - u32 *push; - - push = evo_wait(core, 32); - if (!push) - return -EBUSY; - evo_mthd(push, 0x0088, 1); - evo_data(push, core->sync.handle); - evo_kick(push, core); + core->func->init(core); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 6a809ff24e14..1335c00500d1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -324,7 +324,6 @@ static int nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { 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_atom *armh = nv50_head_atom(crtc->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); } - 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; + if (head->func->core_calc) + head->func->core_calc(head, asyh); + asyh->set.base = armh->base.cpp != asyh->base.cpp; asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp; } else { diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h index 23099a82883b..d00cebdbd260 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.h +++ b/drivers/gpu/drm/nouveau/dispnv50/head.h @@ -24,6 +24,7 @@ struct nv50_head_func { void (*mode)(struct nv50_head *, struct nv50_head_atom *); void (*ilut_set)(struct nv50_head *, struct nv50_head_atom *); 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_clr)(struct nv50_head *); 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; +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 diff --git a/drivers/gpu/drm/nouveau/dispnv50/head507d.c b/drivers/gpu/drm/nouveau/dispnv50/head507d.c index 92fa249ba72f..5f06fa174832 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head507d.c @@ -22,62 +22,34 @@ #include "head.h" #include "core.h" -#include <nvif/class.h> - -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 +void head507d_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))) { - if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) - evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1); - else - evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1); - evo_data(push, (asyh->procamp.sat.sin << 20) | - (asyh->procamp.sat.cos << 8)); + evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1); + evo_data(push, asyh->procamp.sat.sin << 20 | + asyh->procamp.sat.cos << 8); evo_kick(push, core); } } -static void +void head507d_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))) { - if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) - evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1); - else - if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA) - 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_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1); + evo_data(push, asyh->dither.mode << 3 | + asyh->dither.bits << 1 | + asyh->dither.enable); evo_kick(push, core); } } -static void +void head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) { 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 (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) - evo_mthd(push, 0x0904 + head->base.index * 0x400, 1); - else - evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1); + evo_mthd(push, 0x0904 + head->base.index * 0x400, 1); evo_data(push, bounds); evo_kick(push, core); } } -static void +void head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh) { 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 (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) - evo_mthd(push, 0x0900 + head->base.index * 0x400, 1); - else - evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1); + evo_mthd(push, 0x0900 + head->base.index * 0x400, 1); evo_data(push, bounds); 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; u32 *push; - if ((push = evo_wait(core, 4))) { - if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { - evo_mthd(push, 0x0880 + head->base.index * 0x400, 1); - 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); - } + if ((push = evo_wait(core, 2))) { + evo_mthd(push, 0x0880 + head->base.index * 0x400, 1); + evo_data(push, 0x05000000); 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; u32 *push; - if ((push = evo_wait(core, 5))) { - if (core->base.user.oclass < G82_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); - } 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); - } + if ((push = evo_wait(core, 3))) { + 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_kick(push, core); } } -static void +void head507d_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))) { - if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) - evo_mthd(push, 0x0874 + head->base.index * 0x400, 1); - else - evo_mthd(push, 0x0474 + head->base.index * 0x300, 1); + evo_mthd(push, 0x0874 + head->base.index * 0x400, 1); evo_data(push, 0x00000000); evo_kick(push, core); } @@ -213,52 +146,57 @@ head507d_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))) { - if (core->base.user.oclass < G82_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.kind << 16 | - 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 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_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.kind << 16 | + 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); + + /* 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 @@ -266,22 +204,9 @@ head507d_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))) { - if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { - evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1); - 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); - } + if ((push = evo_wait(core, 2))) { + evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1); + evo_data(push, 0x40000000); 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; u32 *push; - if ((push = evo_wait(core, 7))) { - if (core->base.user.oclass < G82_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); - } 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); - } + if ((push = evo_wait(core, 3))) { + 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_kick(push, core); } } -static void +void 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_head_mode *m = &asyh->mode; u32 *push; - if ((push = evo_wait(core, 14))) { - if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { - evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2); - evo_data(push, 0x00800000 | m->clock); - evo_data(push, m->interlace ? 0x00000002 : 0x00000000); - evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7); - 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_data(push, asyh->mode.v.blankus); - evo_mthd(push, 0x082c + (head->base.index * 0x400), 1); - 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); - } + if ((push = evo_wait(core, 13))) { + evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2); + evo_data(push, 0x00800000 | m->clock); + evo_data(push, m->interlace ? 0x00000002 : 0x00000000); + evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7); + 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_data(push, asyh->mode.v.blankus); + evo_mthd(push, 0x082c + (head->base.index * 0x400), 1); + evo_data(push, 0x00000000); evo_kick(push, core); } } -static void +void head507d_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, 10))) { - if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { - evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1); - evo_data(push, 0x00000000); - evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1); - evo_data(push, (asyh->view.iH << 16) | asyh->view.iW); - 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); - } 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); - } + if ((push = evo_wait(core, 7))) { + evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1); + evo_data(push, 0x00000000); + evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1); + evo_data(push, asyh->view.iH << 16 | asyh->view.iW); + 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_kick(push, core); } } @@ -391,6 +271,7 @@ head507d = { .mode = head507d_mode, .ilut_set = head507d_ilut_set, .ilut_clr = head507d_ilut_clr, + .core_calc = head507d_core_calc, .core_set = head507d_core_set, .core_clr = head507d_core_clr, .curs_set = head507d_curs_set, @@ -399,5 +280,4 @@ head507d = { .ovly = head507d_ovly, .dither = head507d_dither, .procamp = head507d_procamp, - .or = head907d_or, }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head827d.c b/drivers/gpu/drm/nouveau/dispnv50/head827d.c new file mode 100644 index 000000000000..84ce595fbe79 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/head827d.c @@ -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, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c new file mode 100644 index 000000000000..0035eccd62d6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c @@ -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, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c new file mode 100644 index 000000000000..5341ea3bc7b6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c @@ -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, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/pior507d.c b/drivers/gpu/drm/nouveau/dispnv50/pior507d.c index a99ba6a7216f..d2bac6a341dc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/pior507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/pior507d.c @@ -21,23 +21,19 @@ */ #include "core.h" -#include <nvif/class.h> - static void pior507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { u32 *push; - if ((push = evo_wait(&core->chan, 8))) { - if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { - if (asyh) { - ctrl |= asyh->or.depth << 16; - ctrl |= asyh->or.nvsync << 13; - ctrl |= asyh->or.nhsync << 12; - } - evo_mthd(push, 0x0700 + (or * 0x040), 1); - evo_data(push, ctrl); + if ((push = evo_wait(&core->chan, 2))) { + if (asyh) { + ctrl |= asyh->or.depth << 16; + ctrl |= asyh->or.nvsync << 13; + ctrl |= asyh->or.nhsync << 12; } + evo_mthd(push, 0x0700 + (or * 0x040), 1); + evo_data(push, ctrl); evo_kick(push, &core->chan); } } diff --git a/drivers/gpu/drm/nouveau/dispnv50/sor507d.c b/drivers/gpu/drm/nouveau/dispnv50/sor507d.c index 2d540de27f59..5222fe6a9b21 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/sor507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/sor507d.c @@ -21,24 +21,18 @@ */ #include "core.h" -#include <nvif/class.h> - static void sor507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { u32 *push; - if ((push = evo_wait(&core->chan, 6))) { - if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { - if (asyh) { - ctrl |= asyh->or.depth << 16; - ctrl |= asyh->or.nvsync << 13; - ctrl |= asyh->or.nhsync << 12; - } - evo_mthd(push, 0x0600 + (or * 0x40), 1); - } else { - evo_mthd(push, 0x0200 + (or * 0x20), 1); + if ((push = evo_wait(&core->chan, 2))) { + if (asyh) { + ctrl |= asyh->or.depth << 16; + ctrl |= asyh->or.nvsync << 13; + ctrl |= asyh->or.nhsync << 12; } + evo_mthd(push, 0x0600 + (or * 0x40), 1); evo_data(push, ctrl); evo_kick(push, &core->chan); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/sor907d.c b/drivers/gpu/drm/nouveau/dispnv50/sor907d.c new file mode 100644 index 000000000000..b0314ec11fb3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/sor907d.c @@ -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, +}; |