diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-03 19:52:08 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-03 19:52:08 -0700 |
commit | b44f2fd87919b5ae6e1756d4c7ba2cbba22238e1 (patch) | |
tree | 01ce17e44375c3f7707640bb44d6e012bab878c4 /drivers/gpu/drm/nouveau | |
parent | 12b68040a5e468068fd7f4af1150eab8f6e96235 (diff) | |
parent | 5493ee1919eae4f49d62276cf5986b7f7c7aa8f6 (diff) | |
download | linux-b44f2fd87919b5ae6e1756d4c7ba2cbba22238e1.tar.bz2 |
Merge tag 'drm-next-2022-08-03' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"Highlights:
- New driver for logicvc - which is a display IP core.
- EDID parser rework to add new extensions
- fbcon scrolling improvements
- i915 has some more DG2 work but not enabled by default, but should
have enough features for userspace to work now.
Otherwise it's lots of work all over the place. Detailed summary:
New driver:
- logicvc
vfio:
- use aperture API
core:
- of: Add data-lane helpers and convert drivers
- connector: Remove deprecated ida_simple_get()
media:
- Add various RGB666 and RGB888 format constants
panel:
- Add HannStar HSD101PWW
- Add ETML0700Y5DHA
dma-buf:
- add sync-file API
- set dma mask for udmabuf devices
fbcon:
- Improve scrolling performance
- Sanitize input
fbdev:
- device unregistering fixes
- vesa: Support COMPILE_TEST
- Disable firmware-device registration when first native driver loads
aperture:
- fix segfault during hot-unplug
- export for use with other subsystems
client:
- use driver validated modes
dp:
- aux: make probing more reliable
- mst: Read extended DPCD capabilities during system resume
- Support waiting for HDP signal
- Port-validation fixes
edid:
- CEA data-block iterators
- struct drm_edid introduction
- implement HF-EEODB extension
gem:
- don't use fb format non-existing planes
probe-helper:
- use 640x480 as displayport fallback
scheduler:
- don't kill jobs in interrupt context
bridge:
- Add support for i.MX8qxp and i.MX8qm
- lots of fixes/cleanups
- Add TI-DLPC3433
- fy07024di26a30d: Optional GPIO reset
- ldb: Add reg and reg-name properties to bindings, Kconfig fixes
- lt9611: Fix display sensing;
- tc358767: DSI/DPI refactoring and DSI-to-eDP support, DSI lane handling
- tc358775: Fix clock settings
- ti-sn65dsi83: Allow GPIO to sleep
- adv7511: I2C fixes
- anx7625: Fix error handling; DPI fixes; Implement HDP timeout via callback
- fsl-ldb: Drop DE flip
- ti-sn65dsi86: Convert to atomic modesetting
amdgpu:
- use atomic fence helpers in DM
- fix VRAM address calculations
- export CRTC bpc via debugfs
- Initial devcoredump support
- Enable high priority gfx queue on asics which support it
- Adjust GART size on newer APUs for S/G display
- Soft reset for GFX 11 / SDMA 6
- Add gfxoff status query for vangogh
- Fix timestamps for cursor only commits
- Adjust GART size on newer APUs for S/G display
- fix buddy memory corruption
amdkfd:
- MMU notifier fixes
- P2P DMA support using dma-buf
- Add available memory IOCTL
- HMM profiler support
- Simplify GPUVM validation
- Unified memory for CWSR save/restore area
i915:
- General driver clean-up
- DG2 enabling (still under force probe)
- DG2 small BAR memory support
- HuC loading support
- DG2 workarounds
- DG2/ATS-M device IDs added
- Ponte Vecchio prep work and new blitter engines
- add Meteorlake support
- Fix sparse warnings
- DMC MMIO range checks
- Audio related fixes
- Runtime PM fixes
- PSR fixes
- Media freq factor and per-gt enhancements
- DSI fixes for ICL+
- Disable DMC flip queue handlers
- ADL_P voltage swing updates
- Use more the VBT for panel information
- Fix on Type-C ports with TBT mode
- Improve fastset and allow seamless M/N changes
- Accept more fixed modes with VRR/DMRRS panels
- Disable connector polling for a headless SKU
- ADL-S display PLL w/a
- Enable THP on Icelake and beyond
- Fix i915_gem_object_ggtt_pin_ww regression on old platforms
- Expose per tile media freq factor in sysfs
- Fix dma_resv fence handling in multi-batch execbuf
- Improve on suspend / resume time with VT-d enabled
- export CRTC bpc settings via debugfs
msm:
- gpu: a619 support
- gpu: Fix for unclocked GMU register access
- gpu: Devcore dump enhancements
- client utilization via fdinfo support
- fix fence rollover issue
- gem: Lockdep false-positive warning fix
- gem: Switch to pfn mappings
- WB support on sc7180
- dp: dropped custom bulk clock implementation
- fix link retraining on resolution change
- hdmi: dropped obsolete GPIO support
tegra:
- context isolation for host1x engines
- tegra234 soc support
mediatek:
- add vdosys0/1 for mt8195
- add MT8195 dp_intf driver
exynos:
- Fix resume function issue of exynos decon driver by calling
clk_disable_unprepare() properly if clk_prepare_enable() failed.
nouveau:
- set of misc fixes/cleanups
- display cleanups
gma500:
- Cleanup connector I2C handling
hyperv:
- Unify VRAM allocation of Gen1 and Gen2
meson:
- Support YUV422 output; Refcount fixes
mgag200:
- Support damage clipping
- Support gamma handling
- Protect concurrent HW access
- Fixes to connector
- Store model-specific limits in device-info structure
- fix PCI register init
panfrost:
- Valhall support
r128:
- Fix bit-shift overflow
rockchip:
- Locking fixes in error path
ssd130x:
- Fix built-in linkage
udl:
- Always advertize VGA connector
ast:
- Support multiple outputs
- fix black screen on resume
sun4i:
- HDMI PHY cleanups
vc4:
- Add support for BCM2711
vkms:
- Allocate output buffer with vmalloc()
mcde:
- Fix ref-count leak
mxsfb/lcdif:
- Support i.MX8MP LCD controller
stm/ltdc:
- Support dynamic Z order
- Support mirroring
ingenic:
- Fix display at maximum resolution"
* tag 'drm-next-2022-08-03' of git://anongit.freedesktop.org/drm/drm: (1480 commits)
drm/amd/display: Fix a compilation failure on PowerPC caused by FPU code
drm/amdgpu: enable support for psp 13.0.4 block
drm/amdgpu: add files for PSP 13.0.4
drm/amdgpu: add header files for MP 13.0.4
drm/amdgpu: correct RLC_RLCS_BOOTLOAD_STATUS offset and index
drm/amdgpu: send msg to IMU for the front-door loading
drm/amdkfd: use time_is_before_jiffies(a + b) to replace "jiffies - a > b"
drm/amdgpu: fix hive reference leak when reflecting psp topology info
drm/amd/pm: enable GFX ULV feature support for SMU13.0.0
drm/amd/pm: update driver if header for SMU 13.0.0
drm/amdgpu: move mes self test after drm sched re-started
drm/amdgpu: drop non-necessary call trace dump
drm/amdgpu: enable VCN cg and JPEG cg/pg
drm/amdgpu: vcn_4_0_2 video codec query
drm/amdgpu: add VCN_4_0_2 firmware support
drm/amdgpu: add VCN function in NBIO v7.7
drm/amdgpu: fix a vcn4 boot poll bug in emulation mode
drm/amd/amdgpu: add memory training support for PSP_V13
drm/amdkfd: remove an unnecessary amdgpu_bo_ref
drm/amd/pm: Add get_gfx_off_status interface for yellow carp
...
Diffstat (limited to 'drivers/gpu/drm/nouveau')
201 files changed, 6529 insertions, 9436 deletions
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 34760164c271..03d12caf9e26 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -11,7 +11,6 @@ config DRM_NOUVEAU select DRM_TTM select DRM_TTM_HELPER select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT - select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT select X86_PLATFORM_DEVICES if ACPI && X86 select ACPI_WMI if ACPI && X86 select MXM_WMI if ACPI && X86 diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index 788db043a342..cad5a646983a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -21,8 +21,7 @@ */ #include "base.h" -#include <nvif/cl507c.h> -#include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvif/timer.h> @@ -306,8 +305,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_base_channel_dma_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nouveau_display *disp = nouveau_display(drm->dev); struct nv50_disp *disp50 = nv50_disp(drm->dev); @@ -328,16 +327,6 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, return ret; } - ret = nvif_notify_ctor(&wndw->wndw.base.user, "kmsBaseNtfy", - wndw->notify.func, false, - NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT, - &(struct nvif_notify_uevent_req) {}, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &wndw->notify); - if (ret) - return ret; - wndw->ntfy = NV50_DISP_BASE_NTFY(wndw->id); wndw->sema = NV50_DISP_BASE_SEM0(wndw->id); wndw->data = 0x00000000; diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c index 1a1d806e0b01..e5bb5ca950c8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c @@ -22,7 +22,7 @@ #include "core.h" #include "head.h" -#include <nvif/cl507d.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvif/timer.h> @@ -157,7 +157,7 @@ int core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore) { - struct nv50_disp_core_channel_dma_v0 args = {}; + struct nvif_disp_chan_v0 args = {}; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_core *core; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c index 00e19fd959ea..cd2c79e4b7af 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c +++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c @@ -23,7 +23,7 @@ #include "core.h" #include "head.h" -#include <nvif/cl507a.h> +#include <nvif/if0014.h> #include <nvif/timer.h> #include <nvhw/class/cl507a.h> @@ -150,8 +150,8 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_cursor_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 4347f0b61797..a53d685a77eb 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -48,8 +48,8 @@ #include <nvif/class.h> #include <nvif/cl0002.h> #include <nvif/cl5070.h> -#include <nvif/cl507d.h> #include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/timer.h> #include <nvhw/class/cl507c.h> @@ -231,7 +231,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, struct nv50_dmac *dmac) { struct nouveau_cli *cli = (void *)device->object.client; - struct nv50_disp_core_channel_dma_v0 *args = data; + struct nvif_disp_chan_v0 *args = data; u8 type = NVIF_MEM_COHERENT; int ret; @@ -529,24 +529,15 @@ static enum drm_connector_status nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_dac_load_v0 load; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_DAC_LOAD, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - }; + u32 loadval; int ret; - args.load.data = nouveau_drm(encoder->dev)->vbios.dactestval; - if (args.load.data == 0) - args.load.data = 340; + loadval = nouveau_drm(encoder->dev)->vbios.dactestval; + if (loadval == 0) + loadval = 340; - ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); - if (ret || !args.load.load) + ret = nvif_outp_load_detect(&nv_encoder->outp, loadval); + if (ret <= 0) return connector_status_disconnected; return connector_status_connected; @@ -563,6 +554,10 @@ nv50_dac_help = { static void nv50_dac_destroy(struct drm_encoder *encoder) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + drm_encoder_cleanup(encoder); kfree(encoder); } @@ -576,6 +571,7 @@ static int nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct nv50_disp *disp = nv50_disp(connector->dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); struct nvkm_i2c_bus *bus; struct nouveau_encoder *nv_encoder; @@ -599,7 +595,7 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) drm_encoder_helper_add(encoder, &nv50_dac_help); drm_connector_attach_encoder(connector, encoder); - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /* @@ -1822,6 +1818,9 @@ static void nv50_sor_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + nv50_mstm_del(&nv_encoder->dp.mstm); drm_encoder_cleanup(encoder); @@ -1918,7 +1917,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) nv_encoder->i2c = &bus->i2c; } - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /****************************************************************************** @@ -1999,6 +1998,10 @@ nv50_pior_help = { static void nv50_pior_destroy(struct drm_encoder *encoder) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + drm_encoder_cleanup(encoder); kfree(encoder); } @@ -2056,7 +2059,7 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) disp->core->func->pior->get_caps(disp, nv_encoder, ffs(dcbe->or) - 1); nv50_outp_dump_caps(drm, nv_encoder); - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /****************************************************************************** @@ -2623,14 +2626,6 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) { struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder *encoder; - struct drm_plane *plane; - - drm_for_each_plane(plane, dev) { - struct nv50_wndw *wndw = nv50_wndw(plane); - if (plane->funcs != &nv50_wndw) - continue; - nv50_wndw_fini(wndw); - } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) @@ -2646,7 +2641,6 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) { struct nv50_core *core = nv50_disp(dev)->core; struct drm_encoder *encoder; - struct drm_plane *plane; if (resume || runtime) core->func->init(core); @@ -2659,13 +2653,6 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) } } - drm_for_each_plane(plane, dev) { - struct nv50_wndw *wndw = nv50_wndw(plane); - if (plane->funcs != &nv50_wndw) - continue; - nv50_wndw_init(wndw); - } - return 0; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c index a6c3a9b95bdb..752318cf3cf1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c @@ -21,14 +21,14 @@ */ #include "oimm.h" -#include <nvif/cl507b.h> +#include <nvif/if0014.h> static int oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { - struct nv50_disp_overlay_v0 args = { - .head = wndw->id, + struct nvif_disp_chan_v0 args = { + .id = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index afd6c7271de1..d4af69e903ad 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -26,8 +26,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> -#include <nvif/cl507e.h> -#include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvhw/class/cl507e.h> @@ -147,8 +146,8 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_overlay_channel_dma_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; @@ -169,16 +168,6 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, return ret; } - ret = nvif_notify_ctor(&wndw->wndw.base.user, "kmsOvlyNtfy", - wndw->notify.func, false, - NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT, - &(struct nvif_notify_uevent_req) {}, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &wndw->notify); - if (ret) - return ret; - wndw->ntfy = NV50_DISP_OVLY_NTFY(wndw->id); wndw->sema = NV50_DISP_OVLY_SEM0(wndw->id); wndw->data = 0x00000000; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c index b390029c69ec..ee76b091d4ef 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c @@ -23,7 +23,7 @@ #include "atom.h" #include "wndw.h" -#include <nvif/clc37b.h> +#include <nvif/if0014.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc37b.h> @@ -68,9 +68,8 @@ static int wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { - struct nvc37b_window_imm_channel_dma_v0 args = { - .pushbuf = 0xb0007b00 | wndw->id, - .index = wndw->id, + struct nvif_disp_chan_v0 args = { + .id = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index bb8a4601e0d9..7a2cceaee6e9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -32,6 +32,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_fourcc.h> @@ -643,7 +644,6 @@ nv50_wndw_destroy(struct drm_plane *plane) nv50_wndw_ctxdma_del(ctxdma); } - nvif_notify_dtor(&wndw->notify); nv50_dmac_destroy(&wndw->wimm); nv50_dmac_destroy(&wndw->wndw); @@ -687,24 +687,6 @@ nv50_wndw = { .format_mod_supported = nv50_plane_format_mod_supported, }; -static int -nv50_wndw_notify(struct nvif_notify *notify) -{ - return NVIF_NOTIFY_KEEP; -} - -void -nv50_wndw_fini(struct nv50_wndw *wndw) -{ - nvif_notify_put(&wndw->notify); -} - -void -nv50_wndw_init(struct nv50_wndw *wndw) -{ - nvif_notify_get(&wndw->notify); -} - static const u64 nv50_cursor_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID, @@ -758,8 +740,6 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, return ret; } - wndw->notify.func = nv50_wndw_notify; - if (wndw->func->blend_set) { ret = drm_plane_create_zpos_property(&wndw->plane, nv50_wndw_zpos_default(&wndw->plane), 0, 254); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 9c9f2c2a71a5..591c852f326b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -5,8 +5,6 @@ #include "atom.h" #include "lut.h" -#include <nvif/notify.h> - struct nv50_wndw_ctxdma { struct list_head head; struct nvif_object object; @@ -30,7 +28,6 @@ struct nv50_wndw { struct nv50_dmac wndw; struct nv50_dmac wimm; - struct nvif_notify notify; u16 ntfy; u16 sema; u32 data; @@ -40,8 +37,6 @@ int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *name, int index, const u32 *format, enum nv50_disp_interlock_type, u32 interlock_data, u32 heads, struct nv50_wndw **); -void nv50_wndw_init(struct nv50_wndw *); -void nv50_wndw_fini(struct nv50_wndw *); void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock, struct nv50_wndw_atom *); void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush, diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index 183d2c0e65b6..082a66d59506 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -26,7 +26,7 @@ #include <drm/drm_plane_helper.h> #include <nouveau_bo.h> -#include <nvif/clc37e.h> +#include <nvif/if0014.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc37e.h> @@ -351,9 +351,8 @@ wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, enum drm_plane_type type, int index, s32 oclass, u32 heads, struct nv50_wndw **pwndw) { - struct nvc37e_window_channel_dma_v0 args = { - .pushbuf = 0xb0007e00 | index, - .index = index, + struct nvif_disp_chan_v0 args = { + .id = index, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index 37f6da8b3f2a..31167c398708 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -26,7 +26,6 @@ #include <drm/drm_plane_helper.h> #include <nouveau_bo.h> -#include <nvif/clc37e.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc57e.h> diff --git a/drivers/gpu/drm/nouveau/include/nvhw/drf.h b/drivers/gpu/drm/nouveau/include/nvhw/drf.h index bd0fc41446e2..d6969c0e2f29 100644 --- a/drivers/gpu/drm/nouveau/include/nvhw/drf.h +++ b/drivers/gpu/drm/nouveau/include/nvhw/drf.h @@ -190,7 +190,7 @@ #define DRF_MD_(X,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,IMPL,...) IMPL #define DRF_MD(A...) DRF_MD_(X, ##A, DRF_MD_I, DRF_MD_N)(X, ##A) -/* Helper for testing against field value in aribtrary object */ +/* Helper for testing against field value in arbitrary object */ #define DRF_TV_N(X,e,p,o,d,r, f,cmp,v) \ NVVAL_TEST_X(DRF_RD_X(e, (p), (o), d##_##r ), d##_##r##_##f, cmp, (v)) #define DRF_TV_I(X,e,p,o,d,r,i,f,cmp,v) \ @@ -198,7 +198,7 @@ #define DRF_TV_(X,_1,_2,_3,_4,_5,_6,_7,_8,_9,IMPL,...) IMPL #define DRF_TV(A...) DRF_TV_(X, ##A, DRF_TV_I, DRF_TV_N)(X, ##A) -/* Helper for testing against field definition in aribtrary object */ +/* Helper for testing against field definition in arbitrary object */ #define DRF_TD_N(X,e,p,o,d,r, f,cmp,v) \ NVVAL_TEST_X(DRF_RD_X(e, (p), (o), d##_##r ), d##_##r##_##f, cmp, d##_##r##_##f##_##v) #define DRF_TD_I(X,e,p,o,d,r,i,f,cmp,v) \ diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 53800fb46582..56affb606adf 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -30,7 +30,6 @@ struct nv50_disp_mthd_v1 { __u8 version; #define NV50_DISP_MTHD_V1_ACQUIRE 0x01 #define NV50_DISP_MTHD_V1_RELEASE 0x02 -#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11 #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 @@ -50,13 +49,6 @@ struct nv50_disp_acquire_v0 { __u8 pad04[4]; }; -struct nv50_disp_dac_load_v0 { - __u8 version; - __u8 load; - __u8 pad02[2]; - __u32 data; -}; - struct nv50_disp_sor_hda_eld_v0 { __u8 version; __u8 pad01[7]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h deleted file mode 100644 index 3b2a9809b8ce..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507A_H__ -#define __NVIF_CL507A_H__ - -struct nv50_disp_cursor_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h deleted file mode 100644 index 0f3d05581ea5..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507B_H__ -#define __NVIF_CL507B_H__ - -struct nv50_disp_overlay_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h deleted file mode 100644 index 7da8813f4f5c..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507C_H__ -#define __NVIF_CL507C_H__ - -struct nv50_disp_base_channel_dma_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h deleted file mode 100644 index 4a56e42d8bc9..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507D_H__ -#define __NVIF_CL507D_H__ - -struct nv50_disp_core_channel_dma_v0 { - __u8 version; - __u8 pad01[7]; - __u64 pushbuf; -}; - -#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h deleted file mode 100644 index 633936cb6313..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507E_H__ -#define __NVIF_CL507E_H__ - -struct nv50_disp_overlay_channel_dma_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index a582c0cb0cb0..8641db649f48 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -32,6 +32,11 @@ #define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d #define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d +#define NVIF_CLASS_DISP /* if0010.h */ 0x80000010 +#define NVIF_CLASS_CONN /* if0011.h */ 0x80000011 +#define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012 +#define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014 + /* the below match nvidia-assigned (either in hw, or sw) class numbers */ #define NV_NULL_CLASS 0x00000030 @@ -73,21 +78,21 @@ #define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f #define AMPERE_CHANNEL_GPFIFO_B /* clc36f.h */ 0x0000c76f -#define NV50_DISP /* cl5070.h */ 0x00005070 -#define G82_DISP /* cl5070.h */ 0x00008270 -#define GT200_DISP /* cl5070.h */ 0x00008370 -#define GT214_DISP /* cl5070.h */ 0x00008570 -#define GT206_DISP /* cl5070.h */ 0x00008870 -#define GF110_DISP /* cl5070.h */ 0x00009070 -#define GK104_DISP /* cl5070.h */ 0x00009170 -#define GK110_DISP /* cl5070.h */ 0x00009270 -#define GM107_DISP /* cl5070.h */ 0x00009470 -#define GM200_DISP /* cl5070.h */ 0x00009570 -#define GP100_DISP /* cl5070.h */ 0x00009770 -#define GP102_DISP /* cl5070.h */ 0x00009870 -#define GV100_DISP /* cl5070.h */ 0x0000c370 -#define TU102_DISP /* cl5070.h */ 0x0000c570 -#define GA102_DISP /* cl5070.h */ 0x0000c670 +#define NV50_DISP /* if0010.h */ 0x00005070 +#define G82_DISP /* if0010.h */ 0x00008270 +#define GT200_DISP /* if0010.h */ 0x00008370 +#define GT214_DISP /* if0010.h */ 0x00008570 +#define GT206_DISP /* if0010.h */ 0x00008870 +#define GF110_DISP /* if0010.h */ 0x00009070 +#define GK104_DISP /* if0010.h */ 0x00009170 +#define GK110_DISP /* if0010.h */ 0x00009270 +#define GM107_DISP /* if0010.h */ 0x00009470 +#define GM200_DISP /* if0010.h */ 0x00009570 +#define GP100_DISP /* if0010.h */ 0x00009770 +#define GP102_DISP /* if0010.h */ 0x00009870 +#define GV100_DISP /* if0010.h */ 0x0000c370 +#define TU102_DISP /* if0010.h */ 0x0000c570 +#define GA102_DISP /* if0010.h */ 0x0000c670 #define GV100_DISP_CAPS 0x0000c373 @@ -96,59 +101,59 @@ #define NV74_VP2 0x00007476 -#define NV50_DISP_CURSOR /* cl507a.h */ 0x0000507a -#define G82_DISP_CURSOR /* cl507a.h */ 0x0000827a -#define GT214_DISP_CURSOR /* cl507a.h */ 0x0000857a -#define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a -#define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a -#define GV100_DISP_CURSOR /* cl507a.h */ 0x0000c37a -#define TU102_DISP_CURSOR /* cl507a.h */ 0x0000c57a -#define GA102_DISP_CURSOR /* cl507a.h */ 0x0000c67a - -#define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b -#define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b -#define GT214_DISP_OVERLAY /* cl507b.h */ 0x0000857b -#define GF110_DISP_OVERLAY /* cl507b.h */ 0x0000907b -#define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b - -#define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c37b -#define TU102_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c57b -#define GA102_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c67b - -#define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c -#define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c -#define GT200_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000837c -#define GT214_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000857c -#define GF110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000907c -#define GK104_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000917c -#define GK110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000927c - -#define NV50_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000507d -#define G82_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000827d -#define GT200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000837d -#define GT214_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000857d -#define GT206_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000887d -#define GF110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000907d -#define GK104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000917d -#define GK110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000927d -#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d -#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d -#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d -#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d -#define GV100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c37d -#define TU102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c57d -#define GA102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c67d - -#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e -#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e -#define GT200_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000837e -#define GT214_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000857e -#define GF110_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000907e -#define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e - -#define GV100_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c37e -#define TU102_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c57e -#define GA102_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c67e +#define NV50_DISP_CURSOR /* if0014.h */ 0x0000507a +#define G82_DISP_CURSOR /* if0014.h */ 0x0000827a +#define GT214_DISP_CURSOR /* if0014.h */ 0x0000857a +#define GF110_DISP_CURSOR /* if0014.h */ 0x0000907a +#define GK104_DISP_CURSOR /* if0014.h */ 0x0000917a +#define GV100_DISP_CURSOR /* if0014.h */ 0x0000c37a +#define TU102_DISP_CURSOR /* if0014.h */ 0x0000c57a +#define GA102_DISP_CURSOR /* if0014.h */ 0x0000c67a + +#define NV50_DISP_OVERLAY /* if0014.h */ 0x0000507b +#define G82_DISP_OVERLAY /* if0014.h */ 0x0000827b +#define GT214_DISP_OVERLAY /* if0014.h */ 0x0000857b +#define GF110_DISP_OVERLAY /* if0014.h */ 0x0000907b +#define GK104_DISP_OVERLAY /* if0014.h */ 0x0000917b + +#define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c37b +#define TU102_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c57b +#define GA102_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c67b + +#define NV50_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000507c +#define G82_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000827c +#define GT200_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000837c +#define GT214_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000857c +#define GF110_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000907c +#define GK104_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000917c +#define GK110_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000927c + +#define NV50_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000507d +#define G82_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000827d +#define GT200_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000837d +#define GT214_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000857d +#define GT206_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000887d +#define GF110_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000907d +#define GK104_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000917d +#define GK110_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000927d +#define GM107_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000947d +#define GM200_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000957d +#define GP100_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000977d +#define GP102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000987d +#define GV100_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c37d +#define TU102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c57d +#define GA102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c67d + +#define NV50_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000507e +#define G82_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000827e +#define GT200_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000837e +#define GT214_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000857e +#define GF110_DISP_OVERLAY_CONTROL_DMA /* if0014.h */ 0x0000907e +#define GK104_DISP_OVERLAY_CONTROL_DMA /* if0014.h */ 0x0000917e + +#define GV100_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c37e +#define TU102_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c57e +#define GA102_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c67e #define NV50_TESLA 0x00005097 #define G82_TESLA 0x00008297 diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h b/drivers/gpu/drm/nouveau/include/nvif/clc37b.h deleted file mode 100644 index 970a5ac4cb95..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLC37B_H__ -#define __NVIF_CLC37B_H__ - -struct nvc37b_window_imm_channel_dma_v0 { - __u8 version; - __u8 index; - __u8 pad02[6]; - __u64 pushbuf; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h b/drivers/gpu/drm/nouveau/include/nvif/clc37e.h deleted file mode 100644 index 7ea23695e7e1..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLC37E_H__ -#define __NVIF_CLC37E_H__ - -struct nvc37e_window_channel_dma_v0 { - __u8 version; - __u8 index; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NVC37E_WINDOW_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/conn.h b/drivers/gpu/drm/nouveau/include/nvif/conn.h new file mode 100644 index 000000000000..f72a8f138f47 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/conn.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_CONN_H__ +#define __NVIF_CONN_H__ +#include <nvif/object.h> +struct nvif_disp; + +struct nvif_conn { + struct nvif_object object; +}; + +int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *); +void nvif_conn_dtor(struct nvif_conn *); + +#define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */ +#define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1 +#define NVIF_CONN_HPD_STATUS_PRESENT 2 +int nvif_conn_hpd_status(struct nvif_conn *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h index 07ac544f282f..742632ad3bea 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/disp.h @@ -5,6 +5,8 @@ struct nvif_device; struct nvif_disp { struct nvif_object object; + unsigned long conn_mask; + unsigned long outp_mask; }; int nvif_disp_ctor(struct nvif_device *, const char *name, s32 oclass, diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0010.h b/drivers/gpu/drm/nouveau/include/nvif/if0010.h new file mode 100644 index 000000000000..fc236ef28965 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0010.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0010_H__ +#define __NVIF_IF0010_H__ + +union nvif_disp_args { + struct nvif_disp_v0 { + __u8 version; + __u8 pad01[3]; + __u32 conn_mask; + __u32 outp_mask; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h b/drivers/gpu/drm/nouveau/include/nvif/if0011.h new file mode 100644 index 000000000000..04ba6581f840 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0011_H__ +#define __NVIF_IF0011_H__ + +union nvif_conn_args { + struct nvif_conn_v0 { + __u8 version; + __u8 id; /* DCB connector table index. */ + __u8 pad02[6]; + } v0; +}; + +#define NVIF_CONN_V0_HPD_STATUS 0x00000000 + +union nvif_conn_hpd_status_args { + struct nvif_conn_hpd_status_v0 { + __u8 version; + __u8 support; + __u8 present; + __u8 pad03[5]; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h new file mode 100644 index 000000000000..243bd35d942f --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0012_H__ +#define __NVIF_IF0012_H__ + +union nvif_outp_args { + struct nvif_outp_v0 { + __u8 version; + __u8 id; /* DCB device index. */ + __u8 pad02[6]; + } v0; +}; + +#define NVIF_OUTP_V0_LOAD_DETECT 0x00 + +union nvif_outp_load_detect_args { + struct nvif_outp_load_detect_v0 { + __u8 version; + __u8 load; + __u8 pad02[2]; + __u32 data; /*TODO: move vbios loadval parsing into nvkm */ + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0014.h b/drivers/gpu/drm/nouveau/include/nvif/if0014.h new file mode 100644 index 000000000000..be0362805106 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0014.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0014_H__ +#define __NVIF_IF0014_H__ + +union nvif_disp_chan_args { + struct nvif_disp_chan_v0 { + __u8 version; + __u8 id; + __u8 pad02[6]; + __u64 pushbuf; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h index 1e4c158d20fa..f52399caee82 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/object.h +++ b/drivers/gpu/drm/nouveau/include/nvif/object.h @@ -22,6 +22,12 @@ struct nvif_object { } map; }; +static inline bool +nvif_object_constructed(struct nvif_object *object) +{ + return object->client != NULL; +} + int nvif_object_ctor(struct nvif_object *, const char *name, u32 handle, s32 oclass, void *, u32, struct nvif_object *); void nvif_object_dtor(struct nvif_object *); diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h new file mode 100644 index 000000000000..0d6aa07a9184 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_OUTP_H__ +#define __NVIF_OUTP_H__ +#include <nvif/object.h> +struct nvif_disp; + +struct nvif_outp { + struct nvif_object object; +}; + +int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_outp *); +void nvif_outp_dtor(struct nvif_outp *); +int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/printf.h b/drivers/gpu/drm/nouveau/include/nvif/printf.h index 6c299ec6be21..ec524b2faeae 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/printf.h +++ b/drivers/gpu/drm/nouveau/include/nvif/printf.h @@ -17,4 +17,13 @@ #endif #define NVIF_ERROR(o,f,a...) NVIF_PRINT(errorf, (o), f, ##a) +#define NVIF_ERRON(c,o,f,a...) do { \ + struct nvif_object *_object = (o); \ + int _cond = (c); \ + if (_cond) { \ + NVIF_ERROR(_object, f" (ret:%d)", ##a, _cond); \ + } else { \ + NVIF_DEBUG(_object, f, ##a); \ + } \ +} while(0) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index a18b6cfda07e..efede1f11e1d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -2,7 +2,6 @@ #ifndef __NVKM_DEVICE_H__ #define __NVKM_DEVICE_H__ #include <core/oclass.h> -#include <core/event.h> enum nvkm_subdev_type; enum nvkm_device_type { @@ -28,8 +27,6 @@ struct nvkm_device { void __iomem *pri; - struct nvkm_event event; - u32 debug; const struct nvkm_device_chip *chip; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index d08d3337ba0d..8b5d8a434be8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -3,23 +3,56 @@ #define __NVKM_DISP_H__ #define nvkm_disp(p) container_of((p), struct nvkm_disp, engine) #include <core/engine.h> +#include <core/object.h> #include <core/event.h> struct nvkm_disp { const struct nvkm_disp_func *func; struct nvkm_engine engine; - struct list_head head; - struct list_head ior; - struct list_head outp; - struct list_head conn; + struct list_head heads; + struct list_head iors; + struct list_head outps; + struct list_head conns; struct nvkm_event hpd; struct nvkm_event vblank; struct { + struct workqueue_struct *wq; + struct work_struct work; + u32 pending; + struct mutex mutex; + } super; + +#define NVKM_DISP_EVENT_CHAN_AWAKEN BIT(0) + struct nvkm_event uevent; + + struct { + unsigned long mask; + int nr; + } wndw, head, dac; + + struct { + unsigned long mask; + int nr; + u32 lvdsconf; + } sor; + + struct { + unsigned long mask; + int nr; + u8 type[3]; + } pior; + + struct nvkm_gpuobj *inst; + struct nvkm_ramht *ramht; + + struct nvkm_disp_chan *chan[81]; + + struct { spinlock_t lock; - struct nvkm_oproxy *object; + struct nvkm_object object; } client; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 306125d17ece..b593407b9e36 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -4,7 +4,6 @@ #define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine) #include <core/engine.h> struct nvkm_fifo_chan; -struct nvkm_gpuobj; enum nvkm_falcon_dmaidx { FALCON_DMAIDX_UCODE = 0, @@ -51,15 +50,6 @@ struct nvkm_falcon { struct nvkm_engine engine; }; -/* This constructor must be called from the owner's oneinit() hook and - * *not* its constructor. This is to ensure that DEVINIT has been - * completed, and that the device is correctly enabled before we touch - * falcon registers. - */ -int nvkm_falcon_v1_new(struct nvkm_subdev *owner, const char *name, u32 addr, - struct nvkm_falcon **); - -void nvkm_falcon_del(struct nvkm_falcon **); int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *); void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 64ee82c7c1be..15099913504d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -26,7 +26,6 @@ struct nvkm_fifo_chan { struct nvkm_gpuobj *inst; struct nvkm_gpuobj *push; struct nvkm_vmm *vmm; - void __iomem *user; u64 addr; u32 size; @@ -44,7 +43,6 @@ struct nvkm_fifo { struct mutex mutex; struct nvkm_event uevent; /* async user trigger */ - struct nvkm_event cevent; /* channel creation event */ struct nvkm_event kevent; /* channel killed */ }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h index a27a0f3fe7aa..73f9d9947e7e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h @@ -54,6 +54,7 @@ struct dcb_output { } tmdsconf; }; bool i2c_upper_default; + int id; }; u16 dcb_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index 05b99c9e9a26..d5d8877064a7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -2,7 +2,6 @@ #ifndef __NVKM_CLK_H__ #define __NVKM_CLK_H__ #include <core/subdev.h> -#include <core/notify.h> #include <subdev/pci.h> struct nvbios_pll; struct nvkm_pll_vals; @@ -94,7 +93,6 @@ struct nvkm_clk { wait_queue_head_t wait; atomic_t waiting; - struct nvkm_notify pwrsrc_ntfy; int pwrsrc; int pstate; /* current */ int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */ @@ -124,6 +122,7 @@ int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr); int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait); int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel); int nvkm_clk_tstate(struct nvkm_clk *, u8 temperature); +int nvkm_clk_pwrsrc(struct nvkm_device *); int nv04_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **); int nv40_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h index 581458ad38e0..9c78f072d62b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h @@ -1,6 +1,7 @@ #ifndef __NVKM_FAULT_H__ #define __NVKM_FAULT_H__ #include <core/subdev.h> +#include <core/event.h> #include <core/notify.h> struct nvkm_fault { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h deleted file mode 100644 index b57fe4ae93ba..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. - * - * 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#ifndef __NVKM_SECURE_BOOT_H__ -#define __NVKM_SECURE_BOOT_H__ - -#include <core/subdev.h> - -enum nvkm_secboot_falcon { - NVKM_SECBOOT_FALCON_PMU = 0, - NVKM_SECBOOT_FALCON_RESERVED = 1, - NVKM_SECBOOT_FALCON_FECS = 2, - NVKM_SECBOOT_FALCON_GPCCS = 3, - NVKM_SECBOOT_FALCON_SEC2 = 7, - NVKM_SECBOOT_FALCON_END = 8, - NVKM_SECBOOT_FALCON_INVALID = 0xffffffff, -}; - -extern const char *nvkm_secboot_falcon_name[]; - -/** - * @wpr_set: whether the WPR region is currently set -*/ -struct nvkm_secboot { - const struct nvkm_secboot_func *func; - struct nvkm_acr *acr; - struct nvkm_subdev subdev; - struct nvkm_falcon *boot_falcon; - struct nvkm_falcon *halt_falcon; - - u64 wpr_addr; - u32 wpr_size; - - bool wpr_set; -}; -#define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev) - -bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon); -int nvkm_secboot_reset(struct nvkm_secboot *, unsigned long); - -int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); -int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); -int gp102_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); -int gp108_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); -int gp10b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 4107b7006539..5bee655e7e63 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -126,9 +126,8 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, { struct nouveau_abi16_ntfy *ntfy, *temp; - /* wait for all activity to stop before releasing notify object, which - * may be still in use */ - if (chan->chan && chan->ntfy) + /* wait for all activity to stop before cleaning up */ + if (chan->chan) nouveau_channel_idle(chan->chan); /* cleanup notifier state */ @@ -147,7 +146,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, /* destroy channel object, all children will be killed too */ if (chan->chan) { - nouveau_channel_idle(chan->chan); + nvif_object_dtor(&chan->ce); nouveau_channel_del(&chan->chan); } @@ -325,6 +324,31 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) init->nr_subchan = 2; } + /* Workaround "nvc0" gallium driver using classes it doesn't allocate on + * Kepler and above. NVKM no longer always sets CE_CTX_VALID as part of + * channel init, now we know what that stuff actually is. + * + * Doesn't matter for Kepler/Pascal, CE context stored in NV_RAMIN. + * + * Userspace was fixed prior to adding Ampere support. + */ + switch (device->info.family) { + case NV_DEVICE_INFO_V0_VOLTA: + ret = nvif_object_ctor(&chan->chan->user, "abi16CeWar", 0, VOLTA_DMA_COPY_A, + NULL, 0, &chan->ce); + if (ret) + goto done; + break; + case NV_DEVICE_INFO_V0_TURING: + ret = nvif_object_ctor(&chan->chan->user, "abi16CeWar", 0, TURING_DMA_COPY_A, + NULL, 0, &chan->ce); + if (ret) + goto done; + break; + default: + break; + } + /* Named memory object area */ ret = nouveau_gem_new(cli, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART, 0, 0, &chan->ntfy); diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 70f6aa5c9dd1..27eae85f33e6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -21,6 +21,7 @@ struct nouveau_abi16_ntfy { struct nouveau_abi16_chan { struct list_head head; struct nouveau_channel *chan; + struct nvif_object ce; struct list_head notifiers; struct nouveau_bo *ntfy; struct nouveau_vma *ntfy_vma; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 41b78e9ecd4e..189903b65edc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -1801,6 +1801,8 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); else ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); + entry->id = idx; + if (!ret) return 1; /* stop parsing */ diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index ea7769135b0d..48dea5d0c580 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -385,7 +385,9 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) struct nv_dma_v0 args = {}; int ret, i; - nvif_object_map(&chan->user, NULL, 0); + ret = nvif_object_map(&chan->user, NULL, 0); + if (ret) + return ret; if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO && chan->user.oclass < AMPERE_CHANNEL_GPFIFO_B) { diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 22b83a6577eb..43a9d1e1cf71 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -404,6 +404,7 @@ nouveau_connector_destroy(struct drm_connector *connector) drm_dp_cec_unregister_connector(&nv_connector->aux); kfree(nv_connector->aux.name); } + nvif_conn_dtor(&nv_connector->conn); kfree(connector); } @@ -1361,13 +1362,11 @@ nouveau_connector_create(struct drm_device *dev, snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", dcbe->hasht, dcbe->hashm); nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL); - drm_dp_aux_init(&nv_connector->aux); - if (ret) { - NV_ERROR(drm, "Failed to init AUX adapter for sor-%04x-%04x: %d\n", - dcbe->hasht, dcbe->hashm, ret); + if (!nv_connector->aux.name) { kfree(nv_connector); - return ERR_PTR(ret); + return ERR_PTR(-ENOMEM); } + drm_dp_aux_init(&nv_connector->aux); fallthrough; default: funcs = &nouveau_connector_funcs; @@ -1388,6 +1387,15 @@ nouveau_connector_create(struct drm_device *dev, drm_connector_init(dev, connector, funcs, type); drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); + if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) { + ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index, + &nv_connector->conn); + if (ret) { + kfree(nv_connector); + return ERR_PTR(ret); + } + } + connector->funcs->reset(connector); nouveau_conn_attach_properties(connector); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index b0773af5a98f..4bf0c703eee7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -26,7 +26,7 @@ #ifndef __NOUVEAU_CONNECTOR_H__ #define __NOUVEAU_CONNECTOR_H__ - +#include <nvif/conn.h> #include <nvif/notify.h> #include <nvhw/class/cl507d.h> @@ -123,6 +123,7 @@ struct nouveau_connector { u8 index; u8 *dcb; + struct nvif_conn conn; struct nvif_notify hpd; struct drm_dp_aux aux; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2cd0932b3d68..a2f5df568ca5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -515,7 +515,7 @@ nouveau_display_hpd_work(struct work_struct *work) pm_runtime_mark_last_busy(drm->dev->dev); noop: - pm_runtime_put_sync(drm->dev->dev); + pm_runtime_put_autosuspend(dev->dev); } #ifdef CONFIG_ACPI @@ -537,7 +537,7 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, * it's own hotplug events. */ pm_runtime_put_autosuspend(drm->dev->dev); - } else if (ret == 0) { + } else if (ret == 0 || ret == -EINPROGRESS) { /* We've started resuming the GPU already, so * it will handle scheduling a full reprobe * itself diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index c36f510d5d4c..20db8ea1a0ba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -107,7 +107,7 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, struct nv50_mstm *mstm = nv_encoder->dp.mstm; enum drm_connector_status status; u8 *dpcd = nv_encoder->dp.dpcd; - int ret = NOUVEAU_DP_NONE; + int ret = NOUVEAU_DP_NONE, hpd; /* If we've already read the DPCD on an eDP device, we don't need to * reread it as it won't change @@ -133,6 +133,16 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, } } + /* Check status of HPD pin before attempting an AUX transaction that + * would result in a number of (futile) retries on a connector which + * has no display plugged. + * + * TODO: look into checking this before probing I2C to detect DVI/HDMI + */ + hpd = nvif_conn_hpd_status(&nv_connector->conn); + if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) + goto out; + status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder); if (status == connector_status_disconnected) goto out; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b2a970aa9bf4..84df5ddae4d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -102,7 +102,6 @@ struct nouveau_cli { struct list_head head; void *abi16; struct list_head objects; - struct list_head notifys; char name[32]; struct work_struct work; diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index c2f5f0cb70d5..b72e5783a00f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -26,7 +26,7 @@ #ifndef __NOUVEAU_ENCODER_H__ #define __NOUVEAU_ENCODER_H__ - +#include <nvif/outp.h> #include <subdev/bios/dcb.h> #include <drm/display/drm_dp_helper.h> @@ -46,6 +46,7 @@ struct nouveau_encoder { struct drm_encoder_slave base; struct dcb_output *dcb; + struct nvif_outp outp; int or; int link; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 4f9b3aa5deda..3c7e0c9d6baf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -39,6 +39,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_probe_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_atomic.h> @@ -466,7 +467,7 @@ nouveau_fbcon_set_suspend_work(struct work_struct *work) if (state == FBINFO_STATE_RUNNING) { nouveau_fbcon_hotplug_resume(drm->fbcon); pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_sync(drm->dev->dev); + pm_runtime_put_autosuspend(drm->dev->dev); } } @@ -605,6 +606,7 @@ nouveau_fbcon_fini(struct drm_device *dev) if (!drm->fbcon) return; + drm_kms_helper_poll_fini(dev); nouveau_fbcon_accel_fini(dev); nouveau_fbcon_destroy(dev, drm->fbcon); kfree(drm->fbcon); diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c index 52f5793b7274..df0fe58ca3ab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_nvif.c +++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c @@ -72,39 +72,10 @@ nvkm_client_suspend(void *priv) } static int -nvkm_client_ntfy(const void *header, u32 length, const void *data, u32 size) -{ - const union { - struct nvif_notify_req_v0 v0; - } *args = header; - u8 route; - - if (length == sizeof(args->v0) && args->v0.version == 0) { - route = args->v0.route; - } else { - WARN_ON(1); - return NVKM_NOTIFY_DROP; - } - - switch (route) { - case NVDRM_NOTIFY_NVIF: - return nvif_notify(header, length, data, size); - case NVDRM_NOTIFY_USIF: - return usif_notify(header, length, data, size); - default: - WARN_ON(1); - break; - } - - return NVKM_NOTIFY_DROP; -} - -static int nvkm_client_driver_init(const char *name, u64 device, const char *cfg, const char *dbg, void **ppriv) { - return nvkm_client_new(name, device, cfg, dbg, nvkm_client_ntfy, - (struct nvkm_client **)ppriv); + return nvkm_client_new(name, device, cfg, dbg, nvif_notify, (struct nvkm_client **)ppriv); } const struct nvif_driver diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c index 5da1f4d223d7..36df6840c099 100644 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/drivers/gpu/drm/nouveau/nouveau_usif.c @@ -26,232 +26,15 @@ #include "nouveau_usif.h" #include "nouveau_abi16.h" -#include <nvif/notify.h> #include <nvif/unpack.h> #include <nvif/client.h> -#include <nvif/event.h> #include <nvif/ioctl.h> #include <nvif/class.h> #include <nvif/cl0080.h> -struct usif_notify_p { - struct drm_pending_event base; - struct { - struct drm_event base; - u8 data[]; - } e; -}; - -struct usif_notify { - struct list_head head; - atomic_t enabled; - u32 handle; - u16 reply; - u8 route; - u64 token; - struct usif_notify_p *p; -}; - -static inline struct usif_notify * -usif_notify_find(struct drm_file *filp, u32 handle) -{ - struct nouveau_cli *cli = nouveau_cli(filp); - struct usif_notify *ntfy; - list_for_each_entry(ntfy, &cli->notifys, head) { - if (ntfy->handle == handle) - return ntfy; - } - return NULL; -} - -static inline void -usif_notify_dtor(struct usif_notify *ntfy) -{ - list_del(&ntfy->head); - kfree(ntfy); -} - -int -usif_notify(const void *header, u32 length, const void *data, u32 size) -{ - struct usif_notify *ntfy = NULL; - const union { - struct nvif_notify_rep_v0 v0; - } *rep = header; - struct drm_device *dev; - struct drm_file *filp; - unsigned long flags; - - if (length == sizeof(rep->v0) && rep->v0.version == 0) { - if (WARN_ON(!(ntfy = (void *)(unsigned long)rep->v0.token))) - return NVIF_NOTIFY_DROP; - BUG_ON(rep->v0.route != NVDRM_NOTIFY_USIF); - } else - if (WARN_ON(1)) - return NVIF_NOTIFY_DROP; - - if (WARN_ON(!ntfy->p || ntfy->reply != (length + size))) - return NVIF_NOTIFY_DROP; - filp = ntfy->p->base.file_priv; - dev = filp->minor->dev; - - memcpy(&ntfy->p->e.data[0], header, length); - memcpy(&ntfy->p->e.data[length], data, size); - switch (rep->v0.version) { - case 0: { - struct nvif_notify_rep_v0 *rep = (void *)ntfy->p->e.data; - rep->route = ntfy->route; - rep->token = ntfy->token; - } - break; - default: - BUG(); - break; - } - - spin_lock_irqsave(&dev->event_lock, flags); - if (!WARN_ON(filp->event_space < ntfy->p->e.base.length)) { - list_add_tail(&ntfy->p->base.link, &filp->event_list); - filp->event_space -= ntfy->p->e.base.length; - } - wake_up_interruptible(&filp->event_wait); - spin_unlock_irqrestore(&dev->event_lock, flags); - atomic_set(&ntfy->enabled, 0); - return NVIF_NOTIFY_DROP; -} - -static int -usif_notify_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) -{ - struct nouveau_cli *cli = nouveau_cli(f); - struct nvif_client *client = &cli->base; - union { - struct nvif_ioctl_ntfy_new_v0 v0; - } *args = data; - union { - struct nvif_notify_req_v0 v0; - } *req; - struct usif_notify *ntfy; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - if (usif_notify_find(f, args->v0.index)) - return -EEXIST; - } else - return ret; - req = data; - ret = -ENOSYS; - - if (!(ntfy = kmalloc(sizeof(*ntfy), GFP_KERNEL))) - return -ENOMEM; - atomic_set(&ntfy->enabled, 0); - - if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) { - ntfy->reply = sizeof(struct nvif_notify_rep_v0) + req->v0.reply; - ntfy->route = req->v0.route; - ntfy->token = req->v0.token; - req->v0.route = NVDRM_NOTIFY_USIF; - req->v0.token = (unsigned long)(void *)ntfy; - ret = nvif_client_ioctl(client, argv, argc); - req->v0.token = ntfy->token; - req->v0.route = ntfy->route; - ntfy->handle = args->v0.index; - } - - if (ret == 0) - list_add(&ntfy->head, &cli->notifys); - if (ret) - kfree(ntfy); - return ret; -} - -static int -usif_notify_del(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) -{ - struct nouveau_cli *cli = nouveau_cli(f); - struct nvif_client *client = &cli->base; - union { - struct nvif_ioctl_ntfy_del_v0 v0; - } *args = data; - struct usif_notify *ntfy; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - if (!(ntfy = usif_notify_find(f, args->v0.index))) - return -ENOENT; - } else - return ret; - - ret = nvif_client_ioctl(client, argv, argc); - if (ret == 0) - usif_notify_dtor(ntfy); - return ret; -} - -static int -usif_notify_get(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) -{ - struct nouveau_cli *cli = nouveau_cli(f); - struct nvif_client *client = &cli->base; - union { - struct nvif_ioctl_ntfy_del_v0 v0; - } *args = data; - struct usif_notify *ntfy; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - if (!(ntfy = usif_notify_find(f, args->v0.index))) - return -ENOENT; - } else - return ret; - - if (atomic_xchg(&ntfy->enabled, 1)) - return 0; - - ntfy->p = kmalloc(sizeof(*ntfy->p) + ntfy->reply, GFP_KERNEL); - if (ret = -ENOMEM, !ntfy->p) - goto done; - ntfy->p->base.event = &ntfy->p->e.base; - ntfy->p->base.file_priv = f; - ntfy->p->e.base.type = DRM_NOUVEAU_EVENT_NVIF; - ntfy->p->e.base.length = sizeof(ntfy->p->e.base) + ntfy->reply; - - ret = nvif_client_ioctl(client, argv, argc); -done: - if (ret) { - atomic_set(&ntfy->enabled, 0); - kfree(ntfy->p); - } - return ret; -} - -static int -usif_notify_put(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) -{ - struct nouveau_cli *cli = nouveau_cli(f); - struct nvif_client *client = &cli->base; - union { - struct nvif_ioctl_ntfy_put_v0 v0; - } *args = data; - struct usif_notify *ntfy; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - if (!(ntfy = usif_notify_find(f, args->v0.index))) - return -ENOENT; - } else - return ret; - - ret = nvif_client_ioctl(client, argv, argc); - if (ret == 0 && atomic_xchg(&ntfy->enabled, 0)) - kfree(ntfy->p); - return ret; -} - struct usif_object { struct list_head head; - struct list_head ntfy; u8 route; u64 token; }; @@ -369,16 +152,10 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) ret = usif_object_new(filp, data, size, argv, argc, abi16); break; case NVIF_IOCTL_V0_NTFY_NEW: - ret = usif_notify_new(filp, data, size, argv, argc); - break; case NVIF_IOCTL_V0_NTFY_DEL: - ret = usif_notify_del(filp, data, size, argv, argc); - break; case NVIF_IOCTL_V0_NTFY_GET: - ret = usif_notify_get(filp, data, size, argv, argc); - break; case NVIF_IOCTL_V0_NTFY_PUT: - ret = usif_notify_put(filp, data, size, argv, argc); + ret = -ENOSYS; break; default: ret = nvif_client_ioctl(client, argv, argc); @@ -410,11 +187,6 @@ void usif_client_fini(struct nouveau_cli *cli) { struct usif_object *object, *otemp; - struct usif_notify *notify, *ntemp; - - list_for_each_entry_safe(notify, ntemp, &cli->notifys, head) { - usif_notify_dtor(notify); - } list_for_each_entry_safe(object, otemp, &cli->objects, head) { usif_object_dtor(object); @@ -425,5 +197,4 @@ void usif_client_init(struct nouveau_cli *cli) { INIT_LIST_HEAD(&cli->objects); - INIT_LIST_HEAD(&cli->notifys); } diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index f194d354c1f5..6abc4bc42e35 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT nvif-y := nvif/object.o nvif-y += nvif/client.o +nvif-y += nvif/conn.o nvif-y += nvif/device.o nvif-y += nvif/disp.o nvif-y += nvif/driver.o @@ -8,6 +9,7 @@ nvif-y += nvif/fifo.o nvif-y += nvif/mem.o nvif-y += nvif/mmu.o nvif-y += nvif/notify.o +nvif-y += nvif/outp.o nvif-y += nvif/timer.o nvif-y += nvif/vmm.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c b/drivers/gpu/drm/nouveau/nvif/conn.c index 9af07c3cf9fc..4ce935d58c90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c +++ b/drivers/gpu/drm/nouveau/nvif/conn.c @@ -19,34 +19,44 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "rootnv50.h" -#include "channv50.h" +#include <nvif/conn.h> +#include <nvif/disp.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0011.h> -static const struct nv50_disp_root_func -ga102_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,GA102_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,GA102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,GA102_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,GA102_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -ga102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) +int +nvif_conn_hpd_status(struct nvif_conn *conn) { - return nv50_disp_root_new_(&ga102_disp_root, disp, oclass, data, size, pobject); + struct nvif_conn_hpd_status_v0 args; + int ret; + + args.version = 0; + + ret = nvif_mthd(&conn->object, NVIF_CONN_V0_HPD_STATUS, &args, sizeof(args)); + NVIF_ERRON(ret, &conn->object, "[HPD_STATUS] support:%d present:%d", + args.support, args.present); + return ret ? ret : !!args.support + !!args.present; +} + +void +nvif_conn_dtor(struct nvif_conn *conn) +{ + nvif_object_dtor(&conn->object); } -const struct nvkm_disp_oclass -ga102_disp_root_oclass = { - .base.oclass = GA102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = ga102_disp_root_new, -}; +int +nvif_conn_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_conn *conn) +{ + struct nvif_conn_v0 args; + int ret; + + args.version = 0; + args.id = id; + + ret = nvif_object_ctor(&disp->object, name ?: "nvifConn", id, NVIF_CLASS_CONN, + &args, sizeof(args), &conn->object); + NVIF_ERRON(ret, &disp->object, "[NEW conn id:%d]", id); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c b/drivers/gpu/drm/nouveau/nvif/disp.c index 529cb60d5efb..926b0c04b1e8 100644 --- a/drivers/gpu/drm/nouveau/nvif/disp.c +++ b/drivers/gpu/drm/nouveau/nvif/disp.c @@ -21,8 +21,10 @@ */ #include <nvif/disp.h> #include <nvif/device.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0010.h> void nvif_disp_dtor(struct nvif_disp *disp) @@ -31,33 +33,48 @@ nvif_disp_dtor(struct nvif_disp *disp) } int -nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, - struct nvif_disp *disp) +nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, struct nvif_disp *disp) { static const struct nvif_mclass disps[] = { - { GA102_DISP, -1 }, - { TU102_DISP, -1 }, - { GV100_DISP, -1 }, - { GP102_DISP, -1 }, - { GP100_DISP, -1 }, - { GM200_DISP, -1 }, - { GM107_DISP, -1 }, - { GK110_DISP, -1 }, - { GK104_DISP, -1 }, - { GF110_DISP, -1 }, - { GT214_DISP, -1 }, - { GT206_DISP, -1 }, - { GT200_DISP, -1 }, - { G82_DISP, -1 }, - { NV50_DISP, -1 }, - { NV04_DISP, -1 }, + { GA102_DISP, 0 }, + { TU102_DISP, 0 }, + { GV100_DISP, 0 }, + { GP102_DISP, 0 }, + { GP100_DISP, 0 }, + { GM200_DISP, 0 }, + { GM107_DISP, 0 }, + { GK110_DISP, 0 }, + { GK104_DISP, 0 }, + { GF110_DISP, 0 }, + { GT214_DISP, 0 }, + { GT206_DISP, 0 }, + { GT200_DISP, 0 }, + { G82_DISP, 0 }, + { NV50_DISP, 0 }, + { NV04_DISP, 0 }, {} }; - int cid = nvif_sclass(&device->object, disps, oclass); + struct nvif_disp_v0 args; + int cid, ret; + + cid = nvif_sclass(&device->object, disps, oclass); disp->object.client = NULL; - if (cid < 0) + if (cid < 0) { + NVIF_ERRON(cid, &device->object, "[NEW disp%04x] not supported", oclass); return cid; + } + + args.version = 0; + + ret = nvif_object_ctor(&device->object, name ?: "nvifDisp", 0, + disps[cid].oclass, &args, sizeof(args), &disp->object); + NVIF_ERRON(ret, &device->object, "[NEW disp%04x]", disps[cid].oclass); + if (ret) + return ret; - return nvif_object_ctor(&device->object, name ? name : "nvifDisp", 0, - disps[cid].oclass, NULL, 0, &disp->object); + NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x", + args.conn_mask, args.outp_mask); + disp->conn_mask = args.conn_mask; + disp->outp_mask = args.outp_mask; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c index dce1ecee2af5..4d1aaee8fe15 100644 --- a/drivers/gpu/drm/nouveau/nvif/object.c +++ b/drivers/gpu/drm/nouveau/nvif/object.c @@ -250,7 +250,7 @@ nvif_object_dtor(struct nvif_object *object) .ioctl.type = NVIF_IOCTL_V0_DEL, }; - if (!object->client) + if (!nvif_object_constructed(object)) return; nvif_object_unmap(object); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/drivers/gpu/drm/nouveau/nvif/outp.c index ef579eb00238..7bfe91a8d6f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat Inc. + * Copyright 2021 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"), @@ -18,38 +18,45 @@ * 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. - * - * Authors: Ben Skeggs */ -#include "rootnv50.h" -#include "channv50.h" +#include <nvif/outp.h> +#include <nvif/disp.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0012.h> + +int +nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval) +{ + struct nvif_outp_load_detect_v0 args; + int ret; + + args.version = 0; + args.data = loadval; + + ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LOAD_DETECT, &args, sizeof(args)); + NVIF_ERRON(ret, &outp->object, "[LOAD_DETECT data:%08x] load:%02x", args.data, args.load); + return ret < 0 ? ret : args.load; +} -static const struct nv50_disp_root_func -g94_disp_root = { - .user = { - {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, - {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, - {} - }, -}; - -static int -g94_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) +void +nvif_outp_dtor(struct nvif_outp *outp) { - return nv50_disp_root_new_(&g94_disp_root, disp, oclass, - data, size, pobject); + nvif_object_dtor(&outp->object); } -const struct nvkm_disp_oclass -g94_disp_root_oclass = { - .base.oclass = GT206_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = g94_disp_root_new, -}; +int +nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_outp *outp) +{ + struct nvif_outp_v0 args; + int ret; + + args.version = 0; + args.id = id; + + ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP, + &args, sizeof(args), &outp->object); + NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index 735cb6816f10..45f920da89af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -24,6 +24,7 @@ #include <core/ioctl.h> #include <core/client.h> #include <core/engine.h> +#include <core/event.h> #include <nvif/unpack.h> #include <nvif/ioctl.h> @@ -128,7 +129,7 @@ nvkm_ioctl_new(struct nvkm_client *client, if (ret == 0) { ret = nvkm_object_init(object); if (ret == 0) { - list_add(&object->head, &parent->tree); + list_add_tail(&object->head, &parent->tree); if (nvkm_object_insert(object)) { client->data = object; return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gv100.c index cd5e9cdca1cf..44021d1395d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gv100.c @@ -21,11 +21,35 @@ */ #include "priv.h" +#include <core/gpuobj.h> +#include <core/object.h> + #include <nvif/class.h> +static int +gv100_ce_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, int align, + struct nvkm_gpuobj **pgpuobj) +{ + struct nvkm_device *device = object->engine->subdev.device; + u32 size; + + /* Allocate fault method buffer (magics come from nvgpu). */ + size = nvkm_rd32(device, 0x104028); /* NV_PCE_PCE_MAP */ + size = 27 * 5 * (((9 + 1 + 3) * hweight32(size)) + 2); + size = roundup(size, PAGE_SIZE); + + return nvkm_gpuobj_new(device, size, align, true, parent, pgpuobj); +} + +const struct nvkm_object_func +gv100_ce_cclass = { + .bind = gv100_ce_cclass_bind, +}; + static const struct nvkm_engine_func gv100_ce = { .intr = gp100_ce_intr, + .cclass = &gv100_ce_cclass, .sclass = { { -1, -1, VOLTA_DMA_COPY_A }, {} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h index b0c8342db15f..cd53b93664d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h @@ -6,4 +6,6 @@ void gt215_ce_intr(struct nvkm_falcon *, struct nvkm_fifo_chan *); void gk104_ce_intr(struct nvkm_engine *); void gp100_ce_intr(struct nvkm_engine *); + +extern const struct nvkm_object_func gv100_ce_cclass; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c index e5ff92d9364c..9563c0175142 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c @@ -26,6 +26,7 @@ static const struct nvkm_engine_func tu102_ce = { .intr = gp100_ce_intr, + .cclass = &gv100_ce_cclass, .sclass = { { -1, -1, TURING_DMA_COPY_A }, {} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c index fdca90bc8f0e..c948a0dc9e62 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c @@ -24,17 +24,17 @@ #include "acpi.h" #include <core/device.h> +#include <subdev/clk.h> #ifdef CONFIG_ACPI static int nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) { - struct nvkm_device *device = - container_of(nb, typeof(*device), acpi.nb); + struct nvkm_device *device = container_of(nb, typeof(*device), acpi.nb); struct acpi_bus_event *info = data; if (!strcmp(info->device_class, "ac_adapter")) - nvkm_event_send(&device->event, 1, 0, NULL, 0); + nvkm_clk_pwrsrc(device); return NOTIFY_DONE; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 62efbd0f3846..568182e68dd7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -24,7 +24,6 @@ #include "priv.h" #include "acpi.h" -#include <core/notify.h> #include <core/option.h> #include <subdev/bios.h> @@ -2668,24 +2667,6 @@ nv177_chipset = { .fifo = { 0x00000001, ga102_fifo_new }, }; -static int -nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - if (!WARN_ON(size != 0)) { - notify->size = 0; - notify->types = 1; - notify->index = 0; - return 0; - } - return -EINVAL; -} - -static const struct nvkm_event_func -nvkm_device_event_func = { - .ctor = nvkm_device_event_ctor, -}; - struct nvkm_subdev * nvkm_device_subdev(struct nvkm_device *device, int type, int inst) { @@ -2838,8 +2819,6 @@ nvkm_device_del(struct nvkm_device **pdevice) list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head) nvkm_subdev_del(&subdev); - nvkm_event_fini(&device->event); - if (device->pri) iounmap(device->pri); list_del(&device->head); @@ -2914,10 +2893,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func, device->debug = nvkm_dbgopt(device->dbgopt, "device"); INIT_LIST_HEAD(&device->subdev); - ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event); - if (ret) - goto done; - mmio_base = device->func->resource_addr(device, 0); mmio_size = device->func->resource_size(device, 0); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 2ed528c065fa..ac9e122586bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -41,11 +41,9 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) ret = clk_prepare_enable(tdev->clk); if (ret) goto err_clk; - if (tdev->clk_ref) { - ret = clk_prepare_enable(tdev->clk_ref); - if (ret) - goto err_clk_ref; - } + ret = clk_prepare_enable(tdev->clk_ref); + if (ret) + goto err_clk_ref; ret = clk_prepare_enable(tdev->clk_pwr); if (ret) goto err_clk_pwr; @@ -70,8 +68,7 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) err_clamp: clk_disable_unprepare(tdev->clk_pwr); err_clk_pwr: - if (tdev->clk_ref) - clk_disable_unprepare(tdev->clk_ref); + clk_disable_unprepare(tdev->clk_ref); err_clk_ref: clk_disable_unprepare(tdev->clk); err_clk: @@ -87,8 +84,7 @@ nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev) int ret; clk_disable_unprepare(tdev->clk_pwr); - if (tdev->clk_ref) - clk_disable_unprepare(tdev->clk_ref); + clk_disable_unprepare(tdev->clk_ref); clk_disable_unprepare(tdev->clk); udelay(10); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 113ddc103ac2..45f509c11c36 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -346,6 +346,7 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index, return -EINVAL; oclass->base = sclass->base; + oclass->engine = NULL; } oclass->ctor = nvkm_udevice_child_new; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index b03f043efe26..600072a904be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -1,5 +1,14 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/disp/base.o +nvkm-y += nvkm/engine/disp/chan.o +nvkm-y += nvkm/engine/disp/conn.o +nvkm-y += nvkm/engine/disp/dp.o +nvkm-y += nvkm/engine/disp/hdmi.o +nvkm-y += nvkm/engine/disp/head.o +nvkm-y += nvkm/engine/disp/ior.o +nvkm-y += nvkm/engine/disp/outp.o +nvkm-y += nvkm/engine/disp/vga.o + nvkm-y += nvkm/engine/disp/nv04.o nvkm-y += nvkm/engine/disp/nv50.o nvkm-y += nvkm/engine/disp/g84.o @@ -18,110 +27,10 @@ nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/tu102.o nvkm-y += nvkm/engine/disp/ga102.o -nvkm-y += nvkm/engine/disp/vga.o - -nvkm-y += nvkm/engine/disp/head.o -nvkm-y += nvkm/engine/disp/headnv04.o -nvkm-y += nvkm/engine/disp/headnv50.o -nvkm-y += nvkm/engine/disp/headgf119.o -nvkm-y += nvkm/engine/disp/headgv100.o - -nvkm-y += nvkm/engine/disp/ior.o -nvkm-y += nvkm/engine/disp/dacnv50.o -nvkm-y += nvkm/engine/disp/dacgf119.o -nvkm-y += nvkm/engine/disp/piornv50.o -nvkm-y += nvkm/engine/disp/sornv50.o -nvkm-y += nvkm/engine/disp/sorg84.o -nvkm-y += nvkm/engine/disp/sorg94.o -nvkm-y += nvkm/engine/disp/sormcp77.o -nvkm-y += nvkm/engine/disp/sorgt215.o -nvkm-y += nvkm/engine/disp/sormcp89.o -nvkm-y += nvkm/engine/disp/sorgf119.o -nvkm-y += nvkm/engine/disp/sorgk104.o -nvkm-y += nvkm/engine/disp/sorgm107.o -nvkm-y += nvkm/engine/disp/sorgm200.o -nvkm-y += nvkm/engine/disp/sorgp100.o -nvkm-y += nvkm/engine/disp/sorgv100.o -nvkm-y += nvkm/engine/disp/sortu102.o -nvkm-y += nvkm/engine/disp/sorga102.o - -nvkm-y += nvkm/engine/disp/outp.o -nvkm-y += nvkm/engine/disp/dp.o - -nvkm-y += nvkm/engine/disp/hdagt215.o -nvkm-y += nvkm/engine/disp/hdagf119.o -nvkm-y += nvkm/engine/disp/hdagv100.o - -nvkm-y += nvkm/engine/disp/hdmi.o -nvkm-y += nvkm/engine/disp/hdmig84.o -nvkm-y += nvkm/engine/disp/hdmigt215.o -nvkm-y += nvkm/engine/disp/hdmigf119.o -nvkm-y += nvkm/engine/disp/hdmigk104.o -nvkm-y += nvkm/engine/disp/hdmigm200.o -nvkm-y += nvkm/engine/disp/hdmigv100.o - -nvkm-y += nvkm/engine/disp/conn.o nvkm-y += nvkm/engine/disp/rootnv04.o nvkm-y += nvkm/engine/disp/rootnv50.o -nvkm-y += nvkm/engine/disp/rootg84.o -nvkm-y += nvkm/engine/disp/rootg94.o -nvkm-y += nvkm/engine/disp/rootgt200.o -nvkm-y += nvkm/engine/disp/rootgt215.o -nvkm-y += nvkm/engine/disp/rootgf119.o -nvkm-y += nvkm/engine/disp/rootgk104.o -nvkm-y += nvkm/engine/disp/rootgk110.o -nvkm-y += nvkm/engine/disp/rootgm107.o -nvkm-y += nvkm/engine/disp/rootgm200.o -nvkm-y += nvkm/engine/disp/rootgp100.o -nvkm-y += nvkm/engine/disp/rootgp102.o -nvkm-y += nvkm/engine/disp/rootgv100.o -nvkm-y += nvkm/engine/disp/roottu102.o -nvkm-y += nvkm/engine/disp/rootga102.o - -nvkm-y += nvkm/engine/disp/capsgv100.o - -nvkm-y += nvkm/engine/disp/channv50.o -nvkm-y += nvkm/engine/disp/changf119.o -nvkm-y += nvkm/engine/disp/changv100.o - -nvkm-y += nvkm/engine/disp/dmacnv50.o -nvkm-y += nvkm/engine/disp/dmacgf119.o -nvkm-y += nvkm/engine/disp/dmacgp102.o -nvkm-y += nvkm/engine/disp/dmacgv100.o - -nvkm-y += nvkm/engine/disp/basenv50.o -nvkm-y += nvkm/engine/disp/baseg84.o -nvkm-y += nvkm/engine/disp/basegf119.o -nvkm-y += nvkm/engine/disp/basegp102.o - -nvkm-y += nvkm/engine/disp/corenv50.o -nvkm-y += nvkm/engine/disp/coreg84.o -nvkm-y += nvkm/engine/disp/coreg94.o -nvkm-y += nvkm/engine/disp/coregf119.o -nvkm-y += nvkm/engine/disp/coregk104.o -nvkm-y += nvkm/engine/disp/coregp102.o -nvkm-y += nvkm/engine/disp/coregv100.o - -nvkm-y += nvkm/engine/disp/ovlynv50.o -nvkm-y += nvkm/engine/disp/ovlyg84.o -nvkm-y += nvkm/engine/disp/ovlygt200.o -nvkm-y += nvkm/engine/disp/ovlygf119.o -nvkm-y += nvkm/engine/disp/ovlygk104.o -nvkm-y += nvkm/engine/disp/ovlygp102.o - -nvkm-y += nvkm/engine/disp/wimmgv100.o - -nvkm-y += nvkm/engine/disp/wndwgv100.o - -nvkm-y += nvkm/engine/disp/piocnv50.o -nvkm-y += nvkm/engine/disp/piocgf119.o - -nvkm-y += nvkm/engine/disp/cursnv50.o -nvkm-y += nvkm/engine/disp/cursgf119.o -nvkm-y += nvkm/engine/disp/cursgp102.o -nvkm-y += nvkm/engine/disp/cursgv100.o -nvkm-y += nvkm/engine/disp/oimmnv50.o -nvkm-y += nvkm/engine/disp/oimmgf119.o -nvkm-y += nvkm/engine/disp/oimmgp102.o +nvkm-y += nvkm/engine/disp/udisp.o +nvkm-y += nvkm/engine/disp/uconn.o +nvkm-y += nvkm/engine/disp/uoutp.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 5daa77755276..65c99d948b68 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -30,7 +30,7 @@ #include <core/client.h> #include <core/notify.h> -#include <core/oproxy.h> +#include <core/ramht.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -108,7 +108,7 @@ nvkm_disp_hpd_ctor(struct nvkm_object *object, void *data, u32 size, if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) { notify->size = sizeof(struct nvif_notify_conn_rep_v0); - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { if (ret = -ENXIO, outp->conn->index == req->v0.conn) { if (ret = -ENODEV, outp->conn->hpd.event) { notify->types = req->v0.mask; @@ -145,45 +145,12 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) return -EINVAL; } -static void -nvkm_disp_class_del(struct nvkm_oproxy *oproxy) -{ - struct nvkm_disp *disp = nvkm_disp(oproxy->base.engine); - spin_lock(&disp->client.lock); - if (disp->client.object == oproxy) - disp->client.object = NULL; - spin_unlock(&disp->client.lock); -} - -static const struct nvkm_oproxy_func -nvkm_disp_class = { - .dtor[1] = nvkm_disp_class_del, -}; - static int nvkm_disp_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { - const struct nvkm_disp_oclass *sclass = oclass->engn; - struct nvkm_disp *disp = nvkm_disp(oclass->engine); - struct nvkm_oproxy *oproxy; - int ret; - - ret = nvkm_oproxy_new_(&nvkm_disp_class, oclass, &oproxy); - if (ret) - return ret; - *pobject = &oproxy->base; - - spin_lock(&disp->client.lock); - if (disp->client.object) { - spin_unlock(&disp->client.lock); - return -EBUSY; - } - disp->client.object = oproxy; - spin_unlock(&disp->client.lock); - - return sclass->ctor(disp, oclass, data, size, &oproxy->object); + return nvkm_udisp_new(oclass, data, size, pobject); } static const struct nvkm_device_oclass @@ -197,9 +164,7 @@ nvkm_disp_class_get(struct nvkm_oclass *oclass, int index, { struct nvkm_disp *disp = nvkm_disp(oclass->engine); if (index == 0) { - const struct nvkm_disp_oclass *root = disp->func->root(disp); - oclass->base = root->base; - oclass->engn = root; + oclass->base = disp->func->root; *class = &nvkm_disp_sclass; return 0; } @@ -223,11 +188,11 @@ nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) if (disp->func->fini) disp->func->fini(disp); - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { nvkm_outp_fini(outp); } - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { nvkm_conn_fini(conn); } @@ -242,11 +207,11 @@ nvkm_disp_init(struct nvkm_engine *engine) struct nvkm_outp *outp; struct nvkm_ior *ior; - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { nvkm_conn_init(conn); } - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { nvkm_outp_init(outp); } @@ -259,7 +224,7 @@ nvkm_disp_init(struct nvkm_engine *engine) /* Set 'normal' (ie. when it's attached to a head) state for * each output resource to 'fully enabled'. */ - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { ior->func->power(ior, true, true, true, true, true); } @@ -326,12 +291,12 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) continue; } - list_add_tail(&outp->head, &disp->outp); + list_add_tail(&outp->head, &disp->outps); hpd = max(hpd, (u8)(dcbE.connector + 1)); } /* Create connector objects based on available output paths. */ - list_for_each_entry_safe(outp, outt, &disp->outp, head) { + list_for_each_entry_safe(outp, outt, &disp->outps, head) { /* VBIOS data *should* give us the most useful information. */ data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); @@ -345,7 +310,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) */ int ccb_index = outp->info.i2c_index; if (ccb_index != 0xf) { - list_for_each_entry(pair, &disp->outp, head) { + list_for_each_entry(pair, &disp->outps, head) { if (pair->info.i2c_index == ccb_index) { outp->conn = pair->conn; break; @@ -365,7 +330,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) } /* Check that we haven't already created this connector. */ - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { if (conn->index == outp->info.connector) { outp->conn = conn; break; @@ -387,7 +352,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) continue; } - list_add_tail(&outp->conn->head, &disp->conn); + list_add_tail(&outp->conn->head, &disp->conns); } ret = nvkm_event_init(&nvkm_disp_hpd_func, 3, hpd, &disp->hpd); @@ -403,7 +368,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) /* Enforce identity-mapped SOR assignment for panels, which have * certain bits (ie. backlight controls) wired to a specific SOR. */ - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { if (outp->conn->info.type == DCB_CONNECTOR_LVDS || outp->conn->info.type == DCB_CONNECTOR_eDP) { ior = nvkm_ior_find(disp, SOR, ffs(outp->info.or) - 1); @@ -414,7 +379,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) } i = 0; - list_for_each_entry(head, &disp->head, head) + list_for_each_entry(head, &disp->heads, head) i = max(i, head->id + 1); return nvkm_event_init(&nvkm_disp_vblank_func, 1, i, &disp->vblank); @@ -426,35 +391,42 @@ nvkm_disp_dtor(struct nvkm_engine *engine) struct nvkm_disp *disp = nvkm_disp(engine); struct nvkm_conn *conn; struct nvkm_outp *outp; + struct nvkm_ior *ior; + struct nvkm_head *head; void *data = disp; - if (disp->func->dtor) - data = disp->func->dtor(disp); + nvkm_ramht_del(&disp->ramht); + nvkm_gpuobj_del(&disp->inst); + + nvkm_event_fini(&disp->uevent); + + if (disp->super.wq) { + destroy_workqueue(disp->super.wq); + mutex_destroy(&disp->super.mutex); + } nvkm_event_fini(&disp->vblank); nvkm_event_fini(&disp->hpd); - while (!list_empty(&disp->conn)) { - conn = list_first_entry(&disp->conn, typeof(*conn), head); + while (!list_empty(&disp->conns)) { + conn = list_first_entry(&disp->conns, typeof(*conn), head); list_del(&conn->head); nvkm_conn_del(&conn); } - while (!list_empty(&disp->outp)) { - outp = list_first_entry(&disp->outp, typeof(*outp), head); + while (!list_empty(&disp->outps)) { + outp = list_first_entry(&disp->outps, typeof(*outp), head); list_del(&outp->head); nvkm_outp_del(&outp); } - while (!list_empty(&disp->ior)) { - struct nvkm_ior *ior = - list_first_entry(&disp->ior, typeof(*ior), head); + while (!list_empty(&disp->iors)) { + ior = list_first_entry(&disp->iors, typeof(*ior), head); nvkm_ior_del(&ior); } - while (!list_empty(&disp->head)) { - struct nvkm_head *head = - list_first_entry(&disp->head, typeof(*head), head); + while (!list_empty(&disp->heads)) { + head = list_first_entry(&disp->heads, typeof(*head), head); nvkm_head_del(&head); } @@ -472,23 +444,34 @@ nvkm_disp = { }; int -nvkm_disp_ctor(const struct nvkm_disp_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_disp *disp) -{ - disp->func = func; - INIT_LIST_HEAD(&disp->head); - INIT_LIST_HEAD(&disp->ior); - INIT_LIST_HEAD(&disp->outp); - INIT_LIST_HEAD(&disp->conn); - spin_lock_init(&disp->client.lock); - return nvkm_engine_ctor(&nvkm_disp, device, type, inst, true, &disp->engine); -} - -int nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - if (!(*pdisp = kzalloc(sizeof(**pdisp), GFP_KERNEL))) + struct nvkm_disp *disp; + int ret; + + if (!(disp = *pdisp = kzalloc(sizeof(**pdisp), GFP_KERNEL))) return -ENOMEM; - return nvkm_disp_ctor(func, device, type, inst, *pdisp); + + disp->func = func; + INIT_LIST_HEAD(&disp->heads); + INIT_LIST_HEAD(&disp->iors); + INIT_LIST_HEAD(&disp->outps); + INIT_LIST_HEAD(&disp->conns); + spin_lock_init(&disp->client.lock); + + ret = nvkm_engine_ctor(&nvkm_disp, device, type, inst, true, &disp->engine); + if (ret) + return ret; + + if (func->super) { + disp->super.wq = create_singlethread_workqueue("nvkm-disp"); + if (!disp->super.wq) + return -ENOMEM; + + INIT_WORK(&disp->super.work, func->super); + mutex_init(&disp->super.mutex); + } + + return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c deleted file mode 100644 index 01253f4a9946..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00c4, 0x610800 }, - { 0x00c8, 0x61080c }, - { 0x00cc, 0x610818 }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x00fc, 0x610824 }, - { 0x0100, 0x610894 }, - { 0x0104, 0x61082c }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -g84_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &g84_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c deleted file mode 100644 index 389e19dfc514..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x661080 }, - { 0x0084, 0x661084 }, - { 0x0088, 0x661088 }, - { 0x008c, 0x66108c }, - { 0x0090, 0x661090 }, - { 0x0094, 0x661094 }, - { 0x00a0, 0x6610a0 }, - { 0x00a4, 0x6610a4 }, - { 0x00c0, 0x6610c0 }, - { 0x00c4, 0x6610c4 }, - { 0x00c8, 0x6610c8 }, - { 0x00cc, 0x6610cc }, - { 0x00e0, 0x6610e0 }, - { 0x00e4, 0x6610e4 }, - { 0x00e8, 0x6610e8 }, - { 0x00ec, 0x6610ec }, - { 0x00fc, 0x6610fc }, - { 0x0100, 0x661100 }, - { 0x0104, 0x661104 }, - { 0x0108, 0x661108 }, - { 0x010c, 0x66110c }, - { 0x0110, 0x661110 }, - { 0x0114, 0x661114 }, - { 0x0118, 0x661118 }, - { 0x011c, 0x66111c }, - { 0x0130, 0x661130 }, - { 0x0134, 0x661134 }, - { 0x0138, 0x661138 }, - { 0x013c, 0x66113c }, - { 0x0140, 0x661140 }, - { 0x0144, 0x661144 }, - { 0x0148, 0x661148 }, - { 0x014c, 0x66114c }, - { 0x0150, 0x661150 }, - { 0x0154, 0x661154 }, - { 0x0158, 0x661158 }, - { 0x015c, 0x66115c }, - { 0x0160, 0x661160 }, - { 0x0164, 0x661164 }, - { 0x0168, 0x661168 }, - { 0x016c, 0x66116c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_image = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0400, 0x661400 }, - { 0x0404, 0x661404 }, - { 0x0408, 0x661408 }, - { 0x040c, 0x66140c }, - { 0x0410, 0x661410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gf119_disp_base_mthd = { - .name = "Base", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_base_mthd_base }, - { "Image", 2, &gf119_disp_base_mthd_image }, - {} - } -}; - -int -gf119_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gf119_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c deleted file mode 100644 index 0cb23d673aa0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gp102_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c deleted file mode 100644 index 19eb7dde01f2..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507c.h> -#include <nvif/unpack.h> - -int -nv50_disp_base_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_base_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp base channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp base channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x0100, 0x610894 }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_base_mthd_image = { - .mthd = 0x0400, - .addr = 0x000000, - .data = { - { 0x0800, 0x6108f0 }, - { 0x0804, 0x6108fc }, - { 0x0808, 0x61090c }, - { 0x080c, 0x610914 }, - { 0x0810, 0x610904 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -nv50_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &nv50_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c deleted file mode 100644 index 5026e530f4bb..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 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. - */ -#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) -#include "rootnv50.h" - -struct gv100_disp_caps { - struct nvkm_object object; - struct nv50_disp *disp; -}; - -static int -gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct gv100_disp_caps *caps = gv100_disp_caps(object); - struct nvkm_device *device = caps->disp->base.engine.subdev.device; - *type = NVKM_OBJECT_MAP_IO; - *addr = 0x640000 + device->func->resource_addr(device, 0); - *size = 0x1000; - return 0; -} - -static const struct nvkm_object_func -gv100_disp_caps = { - .map = gv100_disp_caps_map, -}; - -int -gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - struct gv100_disp_caps *caps; - - if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) - return -ENOMEM; - *pobject = &caps->object; - - nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); - caps->disp = disp; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c new file mode 100644 index 000000000000..d5e18daed79f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c @@ -0,0 +1,275 @@ +/* + * Copyright 2021 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 "chan.h" + +#include <core/oproxy.h> +#include <core/ramht.h> + +#include <nvif/if0014.h> + +static int +nvkm_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + *data = nvkm_rd32(device, base + addr); + return 0; +} + +static int +nvkm_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + nvkm_wr32(device, base + addr, data); + return 0; +} + +static int +nvkm_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + switch (type) { + case 0: + *pevent = &disp->uevent; + return 0; + default: + break; + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u64 base = device->func->resource_addr(device, 0); + + *type = NVKM_OBJECT_MAP_IO; + *addr = base + chan->func->user(chan, size); + return 0; +} + +struct nvkm_disp_chan_object { + struct nvkm_oproxy oproxy; + struct nvkm_disp *disp; + int hash; +}; + +static void +nvkm_disp_chan_child_del_(struct nvkm_oproxy *base) +{ + struct nvkm_disp_chan_object *object = container_of(base, typeof(*object), oproxy); + + nvkm_ramht_remove(object->disp->ramht, object->hash); +} + +static const struct nvkm_oproxy_func +nvkm_disp_chan_child_func_ = { + .dtor[0] = nvkm_disp_chan_child_del_, +}; + +static int +nvkm_disp_chan_child_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(oclass->parent); + struct nvkm_disp *disp = chan->disp; + struct nvkm_device *device = disp->engine.subdev.device; + const struct nvkm_device_oclass *sclass = oclass->priv; + struct nvkm_disp_chan_object *object; + int ret; + + if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(&nvkm_disp_chan_child_func_, oclass, &object->oproxy); + object->disp = disp; + *pobject = &object->oproxy.base; + + ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); + if (ret) + return ret; + + object->hash = chan->func->bind(chan, object->oproxy.object, oclass->handle); + if (object->hash < 0) + return object->hash; + + return 0; +} + +static int +nvkm_disp_chan_child_get(struct nvkm_object *object, int index, struct nvkm_oclass *sclass) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const struct nvkm_device_oclass *oclass = NULL; + + if (chan->func->bind) + sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); + else + sclass->engine = NULL; + + if (sclass->engine && sclass->engine->func->base.sclass) { + sclass->engine->func->base.sclass(sclass, index, &oclass); + if (oclass) { + sclass->ctor = nvkm_disp_chan_child_new; + sclass->priv = oclass; + return 0; + } + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->fini(chan); + chan->func->intr(chan, false); + return 0; +} + +static int +nvkm_disp_chan_init(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->intr(chan, true); + return chan->func->init(chan); +} + +static void * +nvkm_disp_chan_dtor(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + spin_lock(&disp->client.lock); + if (disp->chan[chan->chid.user] == chan) + disp->chan[chan->chid.user] = NULL; + spin_unlock(&disp->client.lock); + + nvkm_memory_unref(&chan->memory); + return chan; +} + +static const struct nvkm_object_func +nvkm_disp_chan = { + .dtor = nvkm_disp_chan_dtor, + .init = nvkm_disp_chan_init, + .fini = nvkm_disp_chan_fini, + .rd32 = nvkm_disp_chan_rd32, + .wr32 = nvkm_disp_chan_wr32, + .ntfy = nvkm_disp_chan_ntfy, + .map = nvkm_disp_chan_map, + .sclass = nvkm_disp_chan_child_get, +}; + +static int +nvkm_disp_chan_new_(struct nvkm_disp *disp, int nr, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + const struct nvkm_disp_chan_user *user = NULL; + struct nvkm_disp_chan *chan; + union nvif_disp_chan_args *args = argv; + int ret, i; + + for (i = 0; disp->func->user[i].ctor; i++) { + if (disp->func->user[i].base.oclass == oclass->base.oclass) { + user = disp->func->user[i].chan; + break; + } + } + + if (WARN_ON(!user)) + return -EINVAL; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (args->v0.id >= nr || !args->v0.pushbuf != !user->func->push) + return -EINVAL; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; + + nvkm_object_ctor(&nvkm_disp_chan, oclass, &chan->object); + chan->func = user->func; + chan->mthd = user->mthd; + chan->disp = disp; + chan->chid.ctrl = user->ctrl + args->v0.id; + chan->chid.user = user->user + args->v0.id; + chan->head = args->v0.id; + + if (chan->func->push) { + ret = chan->func->push(chan, args->v0.pushbuf); + if (ret) + return ret; + } + + spin_lock(&disp->client.lock); + if (disp->chan[chan->chid.user]) { + spin_unlock(&disp->client.lock); + return -EBUSY; + } + disp->chan[chan->chid.user] = chan; + spin_unlock(&disp->client.lock); + return 0; +} + +int +nvkm_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, disp->wndw.nr, oclass, argv, argc, pobject); +} + +int +nvkm_disp_chan_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, disp->head.nr, oclass, argv, argc, pobject); +} + +int +nvkm_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, 1, oclass, argv, argc, pobject); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h new file mode 100644 index 000000000000..398336ffb685 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_DISP_CHAN_H__ +#define __NVKM_DISP_CHAN_H__ +#define nvkm_disp_chan(p) container_of((p), struct nvkm_disp_chan, object) +#include <core/object.h> +#include "priv.h" + +struct nvkm_disp_chan { + const struct nvkm_disp_chan_func *func; + const struct nvkm_disp_chan_mthd *mthd; + struct nvkm_disp *disp; + + struct { + int ctrl; + int user; + } chid; + int head; + + struct nvkm_object object; + + struct nvkm_memory *memory; + u64 push; + + u32 suspend_put; +}; + +int nvkm_disp_core_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_disp_chan_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_disp_wndw_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); + +struct nvkm_disp_chan_func { + int (*push)(struct nvkm_disp_chan *, u64 object); + int (*init)(struct nvkm_disp_chan *); + void (*fini)(struct nvkm_disp_chan *); + void (*intr)(struct nvkm_disp_chan *, bool en); + u64 (*user)(struct nvkm_disp_chan *, u64 *size); + int (*bind)(struct nvkm_disp_chan *, struct nvkm_object *, u32 handle); +}; + +void nv50_disp_chan_intr(struct nvkm_disp_chan *, bool); +u64 nv50_disp_chan_user(struct nvkm_disp_chan *, u64 *); +extern const struct nvkm_disp_chan_func nv50_disp_pioc_func; +extern const struct nvkm_disp_chan_func nv50_disp_dmac_func; +int nv50_disp_dmac_push(struct nvkm_disp_chan *, u64); +int nv50_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func nv50_disp_core_func; + +void gf119_disp_chan_intr(struct nvkm_disp_chan *, bool); +extern const struct nvkm_disp_chan_func gf119_disp_pioc_func; +extern const struct nvkm_disp_chan_func gf119_disp_dmac_func; +void gf119_disp_dmac_fini(struct nvkm_disp_chan *); +int gf119_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func gf119_disp_core_func; +void gf119_disp_core_fini(struct nvkm_disp_chan *); + +extern const struct nvkm_disp_chan_func gp102_disp_dmac_func; + +u64 gv100_disp_chan_user(struct nvkm_disp_chan *, u64 *); +int gv100_disp_dmac_init(struct nvkm_disp_chan *); +void gv100_disp_dmac_fini(struct nvkm_disp_chan *); +int gv100_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); + +struct nvkm_disp_chan_user { + const struct nvkm_disp_chan_func *func; + int ctrl; + int user; + const struct nvkm_disp_chan_mthd *mthd; +}; + +extern const struct nvkm_disp_chan_user nv50_disp_oimm; +extern const struct nvkm_disp_chan_user nv50_disp_curs; + +extern const struct nvkm_disp_chan_user g84_disp_core; +extern const struct nvkm_disp_chan_user g84_disp_base; +extern const struct nvkm_disp_chan_user g84_disp_ovly; + +extern const struct nvkm_disp_chan_user g94_disp_core; + +extern const struct nvkm_disp_chan_user gt200_disp_ovly; + +extern const struct nvkm_disp_chan_user gf119_disp_base; +extern const struct nvkm_disp_chan_user gf119_disp_oimm; +extern const struct nvkm_disp_chan_user gf119_disp_curs; + +extern const struct nvkm_disp_chan_user gk104_disp_core; +extern const struct nvkm_disp_chan_user gk104_disp_ovly; + +extern const struct nvkm_disp_chan_user gv100_disp_core; +extern const struct nvkm_disp_chan_user gv100_disp_curs; +extern const struct nvkm_disp_chan_user gv100_disp_wndw; +extern const struct nvkm_disp_chan_user gv100_disp_wimm; + +struct nvkm_disp_mthd_list { + u32 mthd; + u32 addr; + struct { + u32 mthd; + u32 addr; + const char *name; + } data[]; +}; + +struct nvkm_disp_chan_mthd { + const char *name; + u32 addr; + s32 prev; + struct { + const char *name; + int nr; + const struct nvkm_disp_mthd_list *mthd; + } data[]; +}; + +void nv50_disp_chan_mthd(struct nvkm_disp_chan *, int debug); + +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_pior; +extern const struct nvkm_disp_mthd_list nv50_disp_base_mthd_image; + +extern const struct nvkm_disp_chan_mthd g84_disp_core_mthd; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_head; + +extern const struct nvkm_disp_chan_mthd g94_disp_core_mthd; + +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_pior; +extern const struct nvkm_disp_chan_mthd gf119_disp_base_mthd; + +extern const struct nvkm_disp_chan_mthd gk104_disp_core_mthd; +extern const struct nvkm_disp_chan_mthd gk104_disp_ovly_mthd; +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c deleted file mode 100644 index 525f95d06429..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static void -gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x61008c, 0x00000001 << index); -} - -static void -gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_wr32(device, 0x61008c, 0x00000001 << index); - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); -} - -const struct nvkm_event_func -gf119_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = gf119_disp_chan_uevent_init, - .fini = gf119_disp_chan_uevent_fini, -}; - -void -gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->chid.user; - if (!en) { - nvkm_mask(device, 0x610090, mask, 0x00000000); - nvkm_mask(device, 0x6100a0, mask, 0x00000000); - } else { - nvkm_mask(device, 0x6100a0, mask, mask); - } -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c deleted file mode 100644 index 75247c9c7e10..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "channv50.h" - -const struct nvkm_event_func -gv100_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, -}; - -u64 -gv100_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x690000 + ((chan->chid.user - 1) * 0x1000); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c deleted file mode 100644 index a7a7eb041515..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <core/client.h> -#include <core/notify.h> -#include <core/oproxy.h> -#include <core/ramht.h> -#include <engine/dma.h> - -#include <nvif/cl507d.h> -#include <nvif/event.h> -#include <nvif/unpack.h> - -static void -nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c, - const struct nv50_disp_mthd_list *list, int inst) -{ - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int i; - - for (i = 0; list->data[i].mthd; i++) { - if (list->data[i].addr) { - u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); - u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); - u32 mthd = list->data[i].mthd + (list->mthd * inst); - const char *name = list->data[i].name; - char mods[16]; - - if (prev != next) - snprintf(mods, sizeof(mods), "-> %08x", next); - else - snprintf(mods, sizeof(mods), "%13c", ' '); - - nvkm_printk_(subdev, debug, info, - "\t%04x: %08x %s%s%s\n", - mthd, prev, mods, name ? " // " : "", - name ? name : ""); - } - } -} - -void -nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - const struct nv50_disp_chan_mthd *mthd = chan->mthd; - const struct nv50_disp_mthd_list *list; - int i, j; - - if (debug > subdev->debug) - return; - if (!mthd) - return; - - for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { - u32 base = chan->head * mthd->addr; - for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { - const char *cname = mthd->name; - const char *sname = ""; - char cname_[16], sname_[16]; - - if (mthd->addr) { - snprintf(cname_, sizeof(cname_), "%s %d", - mthd->name, chan->chid.user); - cname = cname_; - } - - if (mthd->data[i].nr > 1) { - snprintf(sname_, sizeof(sname_), " - %s %d", - mthd->data[i].name, j); - sname = sname_; - } - - nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); - nv50_disp_mthd_list(disp, debug, base, mthd->prev, - list, j); - } - } -} - -static void -nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x610020, 0x00000001 << index); -} - -static void -nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_wr32(device, 0x610020, 0x00000001 << index); - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); -} - -void -nv50_disp_chan_uevent_send(struct nv50_disp *disp, int chid) -{ - struct nvif_notify_uevent_rep { - } rep; - - nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep)); -} - -int -nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - union { - struct nvif_notify_uevent_req none; - } *args = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = chan->chid.user; - return 0; - } - - return ret; -} - -const struct nvkm_event_func -nv50_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = nv50_disp_chan_uevent_init, - .fini = nv50_disp_chan_uevent_fini, -}; - -u64 -nv50_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x640000 + (chan->chid.user * 0x1000); -} - -void -nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00010001 << chan->chid.user; - const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; - nvkm_mask(device, 0x610028, mask, data); -} - -static int -nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - *data = nvkm_rd32(device, base + addr); - return 0; -} - -static int -nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - nvkm_wr32(device, base + addr, data); - return 0; -} - -static int -nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->disp; - switch (type) { - case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: - *pevent = &disp->uevent; - return 0; - default: - break; - } - return -EINVAL; -} - -static int -nv50_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u64 base = device->func->resource_addr(device, 0); - *type = NVKM_OBJECT_MAP_IO; - *addr = base + chan->func->user(chan, size); - return 0; -} - -struct nv50_disp_chan_object { - struct nvkm_oproxy oproxy; - struct nv50_disp *disp; - int hash; -}; - -static void -nv50_disp_chan_child_del_(struct nvkm_oproxy *base) -{ - struct nv50_disp_chan_object *object = - container_of(base, typeof(*object), oproxy); - nvkm_ramht_remove(object->disp->ramht, object->hash); -} - -static const struct nvkm_oproxy_func -nv50_disp_chan_child_func_ = { - .dtor[0] = nv50_disp_chan_child_del_, -}; - -static int -nv50_disp_chan_child_new(const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); - struct nv50_disp *disp = chan->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; - const struct nvkm_device_oclass *sclass = oclass->priv; - struct nv50_disp_chan_object *object; - int ret; - - if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - nvkm_oproxy_ctor(&nv50_disp_chan_child_func_, oclass, &object->oproxy); - object->disp = disp; - *pobject = &object->oproxy.base; - - ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); - if (ret) - return ret; - - object->hash = chan->func->bind(chan, object->oproxy.object, - oclass->handle); - if (object->hash < 0) - return object->hash; - - return 0; -} - -static int -nv50_disp_chan_child_get(struct nvkm_object *object, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const struct nvkm_device_oclass *oclass = NULL; - - if (chan->func->bind) - sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); - else - sclass->engine = NULL; - - if (sclass->engine && sclass->engine->func->base.sclass) { - sclass->engine->func->base.sclass(sclass, index, &oclass); - if (oclass) { - sclass->ctor = nv50_disp_chan_child_new, - sclass->priv = oclass; - return 0; - } - } - - return -EINVAL; -} - -static int -nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->fini(chan); - chan->func->intr(chan, false); - return 0; -} - -static int -nv50_disp_chan_init(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->intr(chan, true); - return chan->func->init(chan); -} - -static void * -nv50_disp_chan_dtor(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->disp; - if (chan->chid.user >= 0) - disp->chan[chan->chid.user] = NULL; - nvkm_memory_unref(&chan->memory); - return chan; -} - -static const struct nvkm_object_func -nv50_disp_chan = { - .dtor = nv50_disp_chan_dtor, - .init = nv50_disp_chan_init, - .fini = nv50_disp_chan_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, - .ntfy = nv50_disp_chan_ntfy, - .map = nv50_disp_chan_map, - .sclass = nv50_disp_chan_child_get, -}; - -int -nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int ctrl, int user, int head, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->object; - - nvkm_object_ctor(&nv50_disp_chan, oclass, &chan->object); - chan->func = func; - chan->mthd = mthd; - chan->disp = disp; - chan->chid.ctrl = ctrl; - chan->chid.user = user; - chan->head = head; - - if (disp->chan[chan->chid.user]) { - chan->chid.user = -1; - return -EBUSY; - } - disp->chan[chan->chid.user] = chan; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h deleted file mode 100644 index 9cf2cfe2010c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_CHAN_H__ -#define __NV50_DISP_CHAN_H__ -#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) -#include <core/object.h> -#include "nv50.h" -struct nv50_disp_root; - -struct nv50_disp_chan { - const struct nv50_disp_chan_func *func; - const struct nv50_disp_chan_mthd *mthd; - struct nv50_disp *disp; - - struct { - int ctrl; - int user; - } chid; - int head; - - struct nvkm_object object; - - struct nvkm_memory *memory; - u64 push; - - u32 suspend_put; -}; - -struct nv50_disp_chan_func { - int (*init)(struct nv50_disp_chan *); - void (*fini)(struct nv50_disp_chan *); - void (*intr)(struct nv50_disp_chan *, bool en); - u64 (*user)(struct nv50_disp_chan *, u64 *size); - int (*bind)(struct nv50_disp_chan *, struct nvkm_object *, u32 handle); -}; - -int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int ctrl, int user, int head, - const struct nvkm_oclass *, struct nvkm_object **); -int nv50_disp_dmac_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, int head, u64 push, - const struct nvkm_oclass *, struct nvkm_object **); - -void nv50_disp_chan_intr(struct nv50_disp_chan *, bool); -u64 nv50_disp_chan_user(struct nv50_disp_chan *, u64 *); -extern const struct nv50_disp_chan_func nv50_disp_pioc_func; -extern const struct nv50_disp_chan_func nv50_disp_dmac_func; -int nv50_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func nv50_disp_core_func; - -void gf119_disp_chan_intr(struct nv50_disp_chan *, bool); -extern const struct nv50_disp_chan_func gf119_disp_pioc_func; -extern const struct nv50_disp_chan_func gf119_disp_dmac_func; -void gf119_disp_dmac_fini(struct nv50_disp_chan *); -int gf119_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func gf119_disp_core_func; -void gf119_disp_core_fini(struct nv50_disp_chan *); - -extern const struct nv50_disp_chan_func gp102_disp_dmac_func; - -u64 gv100_disp_chan_user(struct nv50_disp_chan *, u64 *); -int gv100_disp_dmac_init(struct nv50_disp_chan *); -void gv100_disp_dmac_fini(struct nv50_disp_chan *); -int gv100_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); - -int nv50_disp_curs_new_(const struct nv50_disp_chan_func *, - struct nv50_disp *, int ctrl, int user, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_oimm_new_(const struct nv50_disp_chan_func *, - struct nv50_disp *, int ctrl, int user, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_base_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_core_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_ovly_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); - -int nv50_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int g84_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int g84_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int g84_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int g94_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gt200_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gf119_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gk104_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gk104_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gp102_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gv100_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_wimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_wndw_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -struct nv50_disp_mthd_list { - u32 mthd; - u32 addr; - struct { - u32 mthd; - u32 addr; - const char *name; - } data[]; -}; - -struct nv50_disp_chan_mthd { - const char *name; - u32 addr; - s32 prev; - struct { - const char *name; - int nr; - const struct nv50_disp_mthd_list *mthd; - } data[]; -}; - -void nv50_disp_chan_mthd(struct nv50_disp_chan *, int debug); - -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; -extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; - -extern const struct nv50_disp_chan_mthd g84_disp_core_mthd; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_head; - -extern const struct nv50_disp_chan_mthd g94_disp_core_mthd; - -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_pior; -extern const struct nv50_disp_chan_mthd gf119_disp_base_mthd; - -extern const struct nv50_disp_chan_mthd gk104_disp_core_mthd; -extern const struct nv50_disp_chan_mthd gk104_disp_ovly_mthd; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c index febc5c274488..7ed11801a3ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c @@ -86,6 +86,7 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, conn->disp = disp; conn->index = index; conn->info = *info; + conn->info.hpd = DCB_GPIO_UNUSED; CONN_DBG(conn, "type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x", info->type, info->location, info->hpd, info->dp, @@ -100,11 +101,12 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, ret = nvkm_gpio_find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); if (ret) { - CONN_ERR(conn, "func %02x lookup failed, %d", - info->hpd, ret); + CONN_ERR(conn, "func %02x lookup failed, %d", info->hpd, ret); return; } + conn->info.hpd = func.line; + ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd, true, &(struct nvkm_gpio_ntfy_req) { .mask = NVKM_GPIO_TOGGLED, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h index dcbe60a4b911..f109634ce5ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_CONN_H__ #define __NVKM_DISP_CONN_H__ -#include <engine/disp.h> +#include "priv.h" #include <core/notify.h> #include <subdev/bios.h> @@ -15,6 +15,8 @@ struct nvkm_conn { struct nvkm_notify hpd; struct list_head head; + + struct nvkm_object object; }; int nvkm_conn_new(struct nvkm_disp *, int index, struct nvbios_connE *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c deleted file mode 100644 index cfc54aad3e7c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610bc4 }, - {} - } -}; - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x085c, 0x610c5c }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0878, 0x610c50 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x089c, 0x610c68 }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - { 0x0910, 0x610c70 }, - { 0x0914, 0x610c78 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g84_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g84_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g84_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c deleted file mode 100644 index e911925f1182..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g94_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610794 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g94_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 4, &g94_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g94_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g94_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c deleted file mode 100644 index 689e3cdd959a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <subdev/timer.h> - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x660080 }, - { 0x0084, 0x660084 }, - { 0x0088, 0x660088 }, - { 0x008c, 0x000000 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_dac = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0180, 0x660180 }, - { 0x0184, 0x660184 }, - { 0x0188, 0x660188 }, - { 0x0190, 0x660190 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0200, 0x660200 }, - { 0x0204, 0x660204 }, - { 0x0208, 0x660208 }, - { 0x0210, 0x660210 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_pior = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x660300 }, - { 0x0304, 0x660304 }, - { 0x0308, 0x660308 }, - { 0x0310, 0x660310 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gf119_disp_core_mthd_head }, - {} - } -}; - -void -gf119_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610490)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -gf119_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494, chan->push); - nvkm_wr32(device, 0x610498, 0x00010000); - nvkm_wr32(device, 0x61049c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_core_func = { - .init = gf119_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gf119_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gf119_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c deleted file mode 100644 index 5c800174e079..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x047c, 0x66047c }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x0488, 0x660488 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04a0, 0x6604a0 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x0520, 0x660520 }, - { 0x0524, 0x660524 }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gk104_disp_core_mthd_head }, - {} - } -}; - -int -gk104_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c deleted file mode 100644 index 1b435beef3bf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494, chan->push); - nvkm_wr32(device, 0x611498, 0x00010000); - nvkm_wr32(device, 0x61149c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -static const struct nv50_disp_chan_func -gp102_disp_core_func = { - .init = gp102_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gp102_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gp102_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c deleted file mode 100644 index 1d333c484a49..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 "channv50.h" - -#include <subdev/timer.h> - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x680200 }, - { 0x0208, 0x680208 }, - { 0x020c, 0x68020c }, - { 0x0210, 0x680210 }, - { 0x0214, 0x680214 }, - { 0x0218, 0x680218 }, - { 0x021c, 0x68021c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x680300 }, - { 0x0304, 0x680304 }, - { 0x0308, 0x680308 }, - { 0x030c, 0x68030c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_wndw = { - .mthd = 0x0080, - .addr = 0x000080, - .data = { - { 0x1000, 0x681000 }, - { 0x1004, 0x681004 }, - { 0x1008, 0x681008 }, - { 0x100c, 0x68100c }, - { 0x1010, 0x681010 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000400, - .data = { - { 0x2000, 0x682000 }, - { 0x2004, 0x682004 }, - { 0x2008, 0x682008 }, - { 0x200c, 0x68200c }, - { 0x2014, 0x682014 }, - { 0x2018, 0x682018 }, - { 0x201c, 0x68201c }, - { 0x2020, 0x682020 }, - { 0x2028, 0x682028 }, - { 0x202c, 0x68202c }, - { 0x2030, 0x682030 }, - { 0x2038, 0x682038 }, - { 0x203c, 0x68203c }, - { 0x2048, 0x682048 }, - { 0x204c, 0x68204c }, - { 0x2050, 0x682050 }, - { 0x2054, 0x682054 }, - { 0x2058, 0x682058 }, - { 0x205c, 0x68205c }, - { 0x2060, 0x682060 }, - { 0x2064, 0x682064 }, - { 0x2068, 0x682068 }, - { 0x206c, 0x68206c }, - { 0x2070, 0x682070 }, - { 0x2074, 0x682074 }, - { 0x2078, 0x682078 }, - { 0x207c, 0x68207c }, - { 0x2080, 0x682080 }, - { 0x2088, 0x682088 }, - { 0x2090, 0x682090 }, - { 0x209c, 0x68209c }, - { 0x20a0, 0x6820a0 }, - { 0x20a4, 0x6820a4 }, - { 0x20a8, 0x6820a8 }, - { 0x20ac, 0x6820ac }, - { 0x2180, 0x682180 }, - { 0x2184, 0x682184 }, - { 0x218c, 0x68218c }, - { 0x2194, 0x682194 }, - { 0x2198, 0x682198 }, - { 0x219c, 0x68219c }, - { 0x21a0, 0x6821a0 }, - { 0x21a4, 0x6821a4 }, - { 0x2214, 0x682214 }, - { 0x2218, 0x682218 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x008000, - .data = { - { "Global", 1, &gv100_disp_core_mthd_base }, - { "SOR", 4, &gv100_disp_core_mthd_sor }, - { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, - { "HEAD", 4, &gv100_disp_core_mthd_head }, - {} - } -}; - -static int -gv100_disp_core_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610630); - if ((stat & 0x001f0000) == 0x000b0000) - return 0; - ); - return -EBUSY; -} - -static u64 -gv100_disp_core_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x10000; - return 0x680000; -} - -static void -gv100_disp_core_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); - gv100_disp_core_idle(chan); - nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x680000); -} - -static int -gv100_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28, 0x00000001); - nvkm_wr32(device, 0x610b2c, 0x00000040); - - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x680000, chan->suspend_put); - nvkm_wr32(device, 0x6104e0, 0x00000013); - return gv100_disp_core_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_core = { - .init = gv100_disp_core_init, - .fini = gv100_disp_core_fini, - .intr = gv100_disp_core_intr, - .user = gv100_disp_core_user, - .bind = gv100_disp_dmac_bind, -}; - -int -gv100_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gv100_disp_core, &gv100_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c deleted file mode 100644 index 660310b27f9c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <subdev/timer.h> - -#include <nvif/cl507d.h> -#include <nvif/unpack.h> - -int -nv50_disp_core_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_core_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - u64 push; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create disp core channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp core channel dma vers %d " - "pushbuf %016llx\n", - args->v0.version, args->v0.pushbuf); - push = args->v0.pushbuf; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid, 0, - push, oclass, pobject); -} - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x610bb8 }, - { 0x0088, 0x610b9c }, - { 0x008c, 0x000000 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610828 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610b70 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_pior = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0700, 0x610b80 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &nv50_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &nv50_disp_core_mthd_head }, - {} - } -}; - -static void -nv50_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610200)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -nv50_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* attempt to unstick channel from some unknown state */ - if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) - nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); - if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) - nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204, chan->push); - nvkm_wr32(device, 0x610208, 0x00010000); - nvkm_wr32(device, 0x61020c, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610200, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610200)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_core_func = { - .init = nv50_disp_core_init, - .fini = nv50_disp_core_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; - -int -nv50_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &nv50_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c deleted file mode 100644 index cdda3658dcb3..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c deleted file mode 100644 index 1a4601f975e6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 17, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c deleted file mode 100644 index a3e4f6900245..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 "channv50.h" - -#include <subdev/timer.h> - -static int -gv100_disp_curs_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x00070000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -static void -gv100_disp_curs_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00010000 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_curs_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 hoff = chan->chid.ctrl * 4; - nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); - gv100_disp_curs_idle(chan); - nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); -} - -static int -gv100_disp_curs_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); - return gv100_disp_curs_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_curs = { - .init = gv100_disp_curs_init, - .fini = gv100_disp_curs_fini, - .intr = gv100_disp_curs_intr, - .user = gv100_disp_chan_user, -}; - -int -gv100_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gv100_disp_curs, disp, 73, 73, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c deleted file mode 100644 index d29758504a5f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507a.h> -#include <nvif/unpack.h> - -int -nv50_disp_curs_new_(const struct nv50_disp_chan_func *func, - struct nv50_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_cursor_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp cursor size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp cursor vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&nv50_disp_pioc_func, disp, 7, 7, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c deleted file mode 100644 index 71a94777ea2e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -static void -gf119_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); -} - -static void -gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640180 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_dac = { - .state = gf119_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = gf119_dac_clock, -}; - -int -gf119_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_dac, disp, DAC, id); -} - -int -gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c deleted file mode 100644 index 558012db35f8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -static void -nv50_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); -} - -int -nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - - dac->func->power(dac, false, true, false, false, false); - - nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); - mdelay(9); - udelay(500); - loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); - - dac->func->power(dac, false, false, false, false, false); - if (!(loadval & 0x80000000)) - return -ETIMEDOUT; - - return (loadval & 0x38000000) >> 27; -} - -static void -nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) - break; - ); -} - -void -nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000040 * ! pu | - 0x00000010 * ! data | - 0x00000004 * ! vsync | - 0x00000001 * ! hsync) << shift; - const u32 field = 0xc0000000 | (0x00000055 << shift); - - nv50_dac_power_wait(device, doff); - nvkm_mask(device, 0x61a004 + doff, field, state); - nv50_dac_power_wait(device, doff); -} - -static void -nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_dac = { - .state = nv50_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = nv50_dac_clock, -}; - -int -nv50_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_dac, disp, DAC, id); -} - -int -nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c deleted file mode 100644 index 76425e8586da..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -int -gf119_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 27 | 0x00000001); -} - -void -gf119_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -gf119_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_dmac_func = { - .init = gf119_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c deleted file mode 100644 index da258df268d7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gp102_disp_dmac_func = { - .init = gp102_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c deleted file mode 100644 index fdb624ac6b87..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -static int -gv100_disp_dmac_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x000f0000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -int -gv100_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 25 | 0x00000040); -} - -void -gv100_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 coff = chan->chid.ctrl * 0x04; - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); - gv100_disp_dmac_idle(chan); - nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); -} - -int -gv100_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 poff = chan->chid.ctrl * 0x10; - const u32 coff = chan->chid.ctrl * 0x04; - - nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28 + poff, 0x00000001); - nvkm_wr32(device, 0x610b2c + poff, 0x00000040); - - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); - nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); - return gv100_disp_dmac_idle(chan); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c deleted file mode 100644 index d0a7da96d62b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <core/ramht.h> -#include <subdev/fb.h> -#include <subdev/mmu.h> -#include <subdev/timer.h> -#include <engine/dma.h> - -int -nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, int head, u64 push, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nvkm_client *client = oclass->client; - struct nv50_disp_chan *chan; - int ret; - - ret = nv50_disp_chan_new_(func, mthd, disp, chid, chid, head, oclass, - pobject); - chan = nv50_disp_chan(*pobject); - if (ret) - return ret; - - chan->memory = nvkm_umem_search(client, push); - if (IS_ERR(chan->memory)) - return PTR_ERR(chan->memory); - - if (nvkm_memory_size(chan->memory) < 0x1000) - return -EINVAL; - - switch (nvkm_memory_target(chan->memory)) { - case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; - case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; - case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; - default: - return -EINVAL; - } - - chan->push |= nvkm_memory_addr(chan->memory) >> 8; - return 0; -} - -int -nv50_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -10, handle, - chan->chid.user << 28 | - chan->chid.user); -} - -static void -nv50_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -nv50_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_dmac_func = { - .init = nv50_disp_dmac_init, - .fini = nv50_disp_dmac_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 8e09315b8fb3..c1b3206f27e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -40,7 +40,7 @@ #define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100) struct lt_state { - struct nvkm_dp *dp; + struct nvkm_outp *outp; int repeaters; int repeater; @@ -55,7 +55,7 @@ struct lt_state { static int nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) { - struct nvkm_dp *dp = lt->dp; + struct nvkm_outp *outp = lt->outp; u32 addr; int ret; @@ -66,7 +66,7 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) else addr = DPCD_LS02; - ret = nvkm_rdaux(dp->aux, addr, <->stat[0], 3); + ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[0], 3); if (ret) return ret; @@ -75,18 +75,18 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) else addr = DPCD_LS06; - ret = nvkm_rdaux(dp->aux, addr, <->stat[4], 2); + ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[4], 2); if (ret) return ret; if (pc) { - ret = nvkm_rdaux(dp->aux, DPCD_LS0C, <->pc2stat, 1); + ret = nvkm_rdaux(outp->dp.aux, DPCD_LS0C, <->pc2stat, 1); if (ret) lt->pc2stat = 0x00; - OUTP_TRACE(&dp->outp, "status %6ph pc2 %02x", - lt->stat, lt->pc2stat); + + OUTP_TRACE(outp, "status %6ph pc2 %02x", lt->stat, lt->pc2stat); } else { - OUTP_TRACE(&dp->outp, "status %6ph", lt->stat); + OUTP_TRACE(outp, "status %6ph", lt->stat); } return 0; @@ -95,8 +95,8 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) static int nvkm_dp_train_drive(struct lt_state *lt, bool pc) { - struct nvkm_dp *dp = lt->dp; - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_outp *outp = lt->outp; + struct nvkm_ior *ior = outp->ior; struct nvkm_bios *bios = ior->disp->engine.subdev.device->bios; struct nvbios_dpout info; struct nvbios_dpcfg ocfg; @@ -127,26 +127,22 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) lt->conf[i] = (lpre << 3) | lvsw; lt->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); - OUTP_TRACE(&dp->outp, "config lane %d %02x %02x", - i, lt->conf[i], lpc2); + OUTP_TRACE(outp, "config lane %d %02x %02x", i, lt->conf[i], lpc2); if (lt->repeater != lt->repeaters) continue; - data = nvbios_dpout_match(bios, dp->outp.info.hasht, - dp->outp.info.hashm, + data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, &ver, &hdr, &cnt, &len, &info); if (!data) continue; - data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3, - lpre & 3, &ver, &hdr, &cnt, &len, - &ocfg); + data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3, lpre & 3, + &ver, &hdr, &cnt, &len, &ocfg); if (!data) continue; - ior->func->dp.drive(ior, i, ocfg.pc, ocfg.dc, - ocfg.pe, ocfg.tx_pu); + ior->func->dp->drive(ior, i, ocfg.pc, ocfg.dc, ocfg.pe, ocfg.tx_pu); } if (lt->repeater) @@ -154,12 +150,12 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) else addr = DPCD_LC03(0); - ret = nvkm_wraux(dp->aux, addr, lt->conf, 4); + ret = nvkm_wraux(outp->dp.aux, addr, lt->conf, 4); if (ret) return ret; if (pc) { - ret = nvkm_wraux(dp->aux, DPCD_LC0F, lt->pc2conf, 2); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC0F, lt->pc2conf, 2); if (ret) return ret; } @@ -170,19 +166,19 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) static void nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern) { - struct nvkm_dp *dp = lt->dp; + struct nvkm_outp *outp = lt->outp; u32 addr; u8 sink_tp; - OUTP_TRACE(&dp->outp, "training pattern %d", pattern); - dp->outp.ior->func->dp.pattern(dp->outp.ior, pattern); + OUTP_TRACE(outp, "training pattern %d", pattern); + outp->ior->func->dp->pattern(outp->ior, pattern); if (lt->repeater) addr = DPCD_LTTPR_PATTERN_SET(lt->repeater); else addr = DPCD_LC02; - nvkm_rdaux(dp->aux, addr, &sink_tp, 1); + nvkm_rdaux(outp->dp.aux, addr, &sink_tp, 1); sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; sink_tp |= (pattern != 4) ? pattern : 7; @@ -190,13 +186,13 @@ nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern) sink_tp |= DPCD_LC02_SCRAMBLING_DISABLE; else sink_tp &= ~DPCD_LC02_SCRAMBLING_DISABLE; - nvkm_wraux(dp->aux, addr, &sink_tp, 1); + nvkm_wraux(outp->dp.aux, addr, &sink_tp, 1); } static int nvkm_dp_train_eq(struct lt_state *lt) { - struct nvkm_i2c_aux *aux = lt->dp->aux; + struct nvkm_i2c_aux *aux = lt->outp->dp.aux; bool eq_done = false, cr_done = true; int tries = 0, usec = 0, i; u8 data; @@ -207,17 +203,17 @@ nvkm_dp_train_eq(struct lt_state *lt) nvkm_dp_train_pattern(lt, 4); } else { - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x14 && - lt->dp->dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED) + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x14 && + lt->outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED) nvkm_dp_train_pattern(lt, 4); else - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x12 && - lt->dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED) + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x12 && + lt->outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED) nvkm_dp_train_pattern(lt, 3); else nvkm_dp_train_pattern(lt, 2); - usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; + usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; } do { @@ -227,7 +223,7 @@ nvkm_dp_train_eq(struct lt_state *lt) break; eq_done = !!(lt->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); - for (i = 0; i < lt->dp->outp.ior->dp.nr && eq_done; i++) { + for (i = 0; i < lt->outp->ior->dp.nr && eq_done; i++) { u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DPCD_LS02_LANE0_CR_DONE)) cr_done = false; @@ -249,8 +245,8 @@ nvkm_dp_train_cr(struct lt_state *lt) nvkm_dp_train_pattern(lt, 1); - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater) - usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater) + usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; do { if (nvkm_dp_train_drive(lt, false) || @@ -258,7 +254,7 @@ nvkm_dp_train_cr(struct lt_state *lt) break; cr_done = true; - for (i = 0; i < lt->dp->outp.ior->dp.nr; i++) { + for (i = 0; i < lt->outp->ior->dp.nr; i++) { u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DPCD_LS02_LANE0_CR_DONE)) { cr_done = false; @@ -278,45 +274,44 @@ nvkm_dp_train_cr(struct lt_state *lt) } static int -nvkm_dp_train_links(struct nvkm_dp *dp, int rate) +nvkm_dp_train_links(struct nvkm_outp *outp, int rate) { - struct nvkm_ior *ior = dp->outp.ior; - struct nvkm_disp *disp = dp->outp.disp; + struct nvkm_ior *ior = outp->ior; + struct nvkm_disp *disp = outp->disp; struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_bios *bios = subdev->device->bios; struct lt_state lt = { - .dp = dp, + .outp = outp, }; u32 lnkcmp; u8 sink[2], data; int ret; - OUTP_DBG(&dp->outp, "training %d x %d MB/s", - ior->dp.nr, ior->dp.bw * 27); + OUTP_DBG(outp, "training %d x %d MB/s", ior->dp.nr, ior->dp.bw * 27); /* Intersect misc. capabilities of the OR and sink. */ if (disp->engine.subdev.device->chipset < 0x110) - dp->dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; + outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; if (disp->engine.subdev.device->chipset < 0xd0) - dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; - lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED; + outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; + lt.pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED; - if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.dp->info.script[0])) { + if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.outp->dp.info.script[0])) { /* Execute BeforeLinkTraining script from DP Info table. */ while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) lnkcmp += 3; lnkcmp = nvbios_rd16(bios, lnkcmp + 1); - nvbios_init(&dp->outp.disp->engine.subdev, lnkcmp, - init.outp = &dp->outp.info; + nvbios_init(&outp->disp->engine.subdev, lnkcmp, + init.outp = &outp->info; init.or = ior->id; init.link = ior->asy.link; ); } /* Set desired link configuration on the source. */ - if ((lnkcmp = lt.dp->info.lnkcmp)) { - if (dp->version < 0x30) { + if ((lnkcmp = lt.outp->dp.info.lnkcmp)) { + if (outp->dp.version < 0x30) { while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp)) lnkcmp += 4; lnkcmp = nvbios_rd16(bios, lnkcmp + 2); @@ -327,56 +322,56 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) } nvbios_init(subdev, lnkcmp, - init.outp = &dp->outp.info; + init.outp = &outp->info; init.or = ior->id; init.link = ior->asy.link; ); } - ret = ior->func->dp.links(ior, dp->aux); + ret = ior->func->dp->links(ior, outp->dp.aux); if (ret) { if (ret < 0) { - OUTP_ERR(&dp->outp, "train failed with %d", ret); + OUTP_ERR(outp, "train failed with %d", ret); return ret; } return 0; } - ior->func->dp.power(ior, ior->dp.nr); + ior->func->dp->power(ior, ior->dp.nr); /* Select LTTPR non-transparent mode if we have a valid configuration, * use transparent mode otherwise. */ - if (dp->lttpr[0] >= 0x14) { + if (outp->dp.lttpr[0] >= 0x14) { data = DPCD_LTTPR_MODE_TRANSPARENT; - nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data)); + nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); - if (dp->lttprs) { + if (outp->dp.lttprs) { data = DPCD_LTTPR_MODE_NON_TRANSPARENT; - nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data)); - lt.repeaters = dp->lttprs; + nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); + lt.repeaters = outp->dp.lttprs; } } /* Set desired link configuration on the sink. */ - sink[0] = (dp->rate[rate].dpcd < 0) ? ior->dp.bw : 0; + sink[0] = (outp->dp.rate[rate].dpcd < 0) ? ior->dp.bw : 0; sink[1] = ior->dp.nr; if (ior->dp.ef) sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; - ret = nvkm_wraux(dp->aux, DPCD_LC00_LINK_BW_SET, sink, 2); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC00_LINK_BW_SET, sink, 2); if (ret) return ret; - if (dp->rate[rate].dpcd >= 0) { - ret = nvkm_rdaux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); + if (outp->dp.rate[rate].dpcd >= 0) { + ret = nvkm_rdaux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); if (ret) return ret; sink[0] &= ~DPCD_LC15_LINK_RATE_SET_MASK; - sink[0] |= dp->rate[rate].dpcd; + sink[0] |= outp->dp.rate[rate].dpcd; - ret = nvkm_wraux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); if (ret) return ret; } @@ -384,9 +379,9 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) /* Attempt to train the link in this configuration. */ for (lt.repeater = lt.repeaters; lt.repeater >= 0; lt.repeater--) { if (lt.repeater) - OUTP_DBG(&dp->outp, "training LTTPR%d", lt.repeater); + OUTP_DBG(outp, "training LTTPR%d", lt.repeater); else - OUTP_DBG(&dp->outp, "training sink"); + OUTP_DBG(outp, "training sink"); memset(lt.stat, 0x00, sizeof(lt.stat)); ret = nvkm_dp_train_cr(<); @@ -399,94 +394,92 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) } static void -nvkm_dp_train_fini(struct nvkm_dp *dp) +nvkm_dp_train_fini(struct nvkm_outp *outp) { /* Execute AfterLinkTraining script from DP Info table. */ - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[1], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[1], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } static void -nvkm_dp_train_init(struct nvkm_dp *dp) +nvkm_dp_train_init(struct nvkm_outp *outp) { /* Execute EnableSpread/DisableSpread script from DP Info table. */ - if (dp->dpcd[DPCD_RC03] & DPCD_RC03_MAX_DOWNSPREAD) { - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[2], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + if (outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_MAX_DOWNSPREAD) { + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[2], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } else { - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[3], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[3], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } - if (!AMPERE_IED_HACK(dp->outp.disp)) { + if (!AMPERE_IED_HACK(outp->disp)) { /* Execute BeforeLinkTraining script from DP Info table. */ - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[0], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[0], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } } static int -nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) +nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) { - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_ior *ior = outp->ior; int ret = -EINVAL, nr, rate; u8 pwr; /* Ensure sink is not in a low-power state. */ - if (!nvkm_rdaux(dp->aux, DPCD_SC00, &pwr, 1)) { + if (!nvkm_rdaux(outp->dp.aux, DPCD_SC00, &pwr, 1)) { if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { pwr &= ~DPCD_SC00_SET_POWER; pwr |= DPCD_SC00_SET_POWER_D0; - nvkm_wraux(dp->aux, DPCD_SC00, &pwr, 1); + nvkm_wraux(outp->dp.aux, DPCD_SC00, &pwr, 1); } } - ior->dp.mst = dp->lt.mst; - ior->dp.ef = dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP; + ior->dp.mst = outp->dp.lt.mst; + ior->dp.ef = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP; ior->dp.nr = 0; /* Link training. */ - OUTP_DBG(&dp->outp, "training"); - nvkm_dp_train_init(dp); - for (nr = dp->links; ret < 0 && nr; nr >>= 1) { - for (rate = 0; ret < 0 && rate < dp->rates; rate++) { - if (dp->rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { + OUTP_DBG(outp, "training"); + nvkm_dp_train_init(outp); + for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { + for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) { + if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { /* Program selected link configuration. */ - ior->dp.bw = dp->rate[rate].rate / 27000; + ior->dp.bw = outp->dp.rate[rate].rate / 27000; ior->dp.nr = nr; - ret = nvkm_dp_train_links(dp, rate); + ret = nvkm_dp_train_links(outp, rate); } } } - nvkm_dp_train_fini(dp); + nvkm_dp_train_fini(outp); if (ret < 0) - OUTP_ERR(&dp->outp, "training failed"); + OUTP_ERR(outp, "training failed"); else - OUTP_DBG(&dp->outp, "training done"); - atomic_set(&dp->lt.done, 1); + OUTP_DBG(outp, "training done"); + atomic_set(&outp->dp.lt.done, 1); return ret; } void nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior) { - struct nvkm_dp *dp = nvkm_dp(outp); - /* Execute DisableLT script from DP Info Table. */ - nvbios_init(&ior->disp->engine.subdev, dp->info.script[4], - init.outp = &dp->outp.info; + nvbios_init(&ior->disp->engine.subdev, outp->dp.info.script[4], + init.outp = &outp->info; init.or = ior->id; init.link = ior->arm.link; ); @@ -495,18 +488,15 @@ nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior) static void nvkm_dp_release(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - /* Prevent link from being retrained if sink sends an IRQ. */ - atomic_set(&dp->lt.done, 0); - dp->outp.ior->dp.nr = 0; + atomic_set(&outp->dp.lt.done, 0); + outp->ior->dp.nr = 0; } static int nvkm_dp_acquire(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_ior *ior = outp->ior; struct nvkm_head *head; bool retrain = true; u32 datakbps = 0; @@ -515,10 +505,10 @@ nvkm_dp_acquire(struct nvkm_outp *outp) u8 stat[3]; int ret, i; - mutex_lock(&dp->mutex); + mutex_lock(&outp->dp.mutex); /* Check that link configuration meets current requirements. */ - list_for_each_entry(head, &outp->disp->head, head) { + list_for_each_entry(head, &outp->disp->heads, head) { if (ior->asy.head & (1 << head->id)) { u32 khz = (head->asy.hz >> ior->asy.rgdiv) / 1000; datakbps += khz * head->asy.or.depth; @@ -527,18 +517,17 @@ nvkm_dp_acquire(struct nvkm_outp *outp) linkKBps = ior->dp.bw * 27000 * ior->dp.nr; dataKBps = DIV_ROUND_UP(datakbps, 8); - OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d", - dataKBps, linkKBps, ior->dp.mst, dp->lt.mst); - if (linkKBps < dataKBps || ior->dp.mst != dp->lt.mst) { - OUTP_DBG(&dp->outp, "link requirements changed"); + OUTP_DBG(outp, "data %d KB/s link %d KB/s mst %d->%d", + dataKBps, linkKBps, ior->dp.mst, outp->dp.lt.mst); + if (linkKBps < dataKBps || ior->dp.mst != outp->dp.lt.mst) { + OUTP_DBG(outp, "link requirements changed"); goto done; } /* Check that link is still trained. */ - ret = nvkm_rdaux(dp->aux, DPCD_LS02, stat, 3); + ret = nvkm_rdaux(outp->dp.aux, DPCD_LS02, stat, 3); if (ret) { - OUTP_DBG(&dp->outp, - "failed to read link status, assuming no sink"); + OUTP_DBG(outp, "failed to read link status, assuming no sink"); goto done; } @@ -548,125 +537,126 @@ nvkm_dp_acquire(struct nvkm_outp *outp) if (!(lane & DPCD_LS02_LANE0_CR_DONE) || !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { - OUTP_DBG(&dp->outp, - "lane %d not equalised", lane); + OUTP_DBG(outp, "lane %d not equalised", lane); goto done; } } retrain = false; } else { - OUTP_DBG(&dp->outp, "no inter-lane alignment"); + OUTP_DBG(outp, "no inter-lane alignment"); } done: - if (retrain || !atomic_read(&dp->lt.done)) - ret = nvkm_dp_train(dp, dataKBps); - mutex_unlock(&dp->mutex); + if (retrain || !atomic_read(&outp->dp.lt.done)) + ret = nvkm_dp_train(outp, dataKBps); + mutex_unlock(&outp->dp.mutex); return ret; } static bool -nvkm_dp_enable_supported_link_rates(struct nvkm_dp *dp) +nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) { u8 sink_rates[DPCD_RC10_SUPPORTED_LINK_RATES__SIZE]; int i, j, k; - if (dp->outp.conn->info.type != DCB_CONNECTOR_eDP || - dp->dpcd[DPCD_RC00_DPCD_REV] < 0x13 || - nvkm_rdaux(dp->aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), sink_rates, sizeof(sink_rates))) + if (outp->conn->info.type != DCB_CONNECTOR_eDP || + outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x13 || + nvkm_rdaux(outp->dp.aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), + sink_rates, sizeof(sink_rates))) return false; for (i = 0; i < ARRAY_SIZE(sink_rates); i += 2) { const u32 rate = ((sink_rates[i + 1] << 8) | sink_rates[i]) * 200 / 10; - if (!rate || WARN_ON(dp->rates == ARRAY_SIZE(dp->rate))) + if (!rate || WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) break; - if (rate > dp->outp.info.dpconf.link_bw * 27000) { - OUTP_DBG(&dp->outp, "rate %d !outp", rate); + if (rate > outp->info.dpconf.link_bw * 27000) { + OUTP_DBG(outp, "rate %d !outp", rate); continue; } - for (j = 0; j < dp->rates; j++) { - if (rate > dp->rate[j].rate) { - for (k = dp->rates; k > j; k--) - dp->rate[k] = dp->rate[k - 1]; + for (j = 0; j < outp->dp.rates; j++) { + if (rate > outp->dp.rate[j].rate) { + for (k = outp->dp.rates; k > j; k--) + outp->dp.rate[k] = outp->dp.rate[k - 1]; break; } } - dp->rate[j].dpcd = i / 2; - dp->rate[j].rate = rate; - dp->rates++; + outp->dp.rate[j].dpcd = i / 2; + outp->dp.rate[j].rate = rate; + outp->dp.rates++; } - for (i = 0; i < dp->rates; i++) - OUTP_DBG(&dp->outp, "link_rate[%d] = %d", dp->rate[i].dpcd, dp->rate[i].rate); + for (i = 0; i < outp->dp.rates; i++) + OUTP_DBG(outp, "link_rate[%d] = %d", outp->dp.rate[i].dpcd, outp->dp.rate[i].rate); - return dp->rates != 0; + return outp->dp.rates != 0; } static bool -nvkm_dp_enable(struct nvkm_dp *dp, bool enable) +nvkm_dp_enable(struct nvkm_outp *outp, bool enable) { - struct nvkm_i2c_aux *aux = dp->aux; + struct nvkm_i2c_aux *aux = outp->dp.aux; if (enable) { - if (!dp->present) { - OUTP_DBG(&dp->outp, "aux power -> always"); + if (!outp->dp.present) { + OUTP_DBG(outp, "aux power -> always"); nvkm_i2c_aux_monitor(aux, true); - dp->present = true; + outp->dp.present = true; } /* Detect any LTTPRs before reading DPCD receiver caps. */ - if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, dp->lttpr, sizeof(dp->lttpr)) && - dp->lttpr[0] >= 0x14 && dp->lttpr[2]) { - switch (dp->lttpr[2]) { - case 0x80: dp->lttprs = 1; break; - case 0x40: dp->lttprs = 2; break; - case 0x20: dp->lttprs = 3; break; - case 0x10: dp->lttprs = 4; break; - case 0x08: dp->lttprs = 5; break; - case 0x04: dp->lttprs = 6; break; - case 0x02: dp->lttprs = 7; break; - case 0x01: dp->lttprs = 8; break; + if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, outp->dp.lttpr, sizeof(outp->dp.lttpr)) && + outp->dp.lttpr[0] >= 0x14 && outp->dp.lttpr[2]) { + switch (outp->dp.lttpr[2]) { + case 0x80: outp->dp.lttprs = 1; break; + case 0x40: outp->dp.lttprs = 2; break; + case 0x20: outp->dp.lttprs = 3; break; + case 0x10: outp->dp.lttprs = 4; break; + case 0x08: outp->dp.lttprs = 5; break; + case 0x04: outp->dp.lttprs = 6; break; + case 0x02: outp->dp.lttprs = 7; break; + case 0x01: outp->dp.lttprs = 8; break; default: /* Unknown LTTPR count, we'll switch to transparent mode. */ WARN_ON(1); - dp->lttprs = 0; + outp->dp.lttprs = 0; break; } } else { /* No LTTPR support, or zero LTTPR count - don't touch it at all. */ - memset(dp->lttpr, 0x00, sizeof(dp->lttpr)); + memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); } - if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, dp->dpcd, sizeof(dp->dpcd))) { + if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; const u8 *rate; int rate_max; - dp->rates = 0; - dp->links = dp->dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT; - dp->links = min(dp->links, dp->outp.info.dpconf.link_nr); - if (dp->lttprs && dp->lttpr[4]) - dp->links = min_t(int, dp->links, dp->lttpr[4]); + outp->dp.rates = 0; + outp->dp.links = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT; + outp->dp.links = min(outp->dp.links, outp->info.dpconf.link_nr); + if (outp->dp.lttprs && outp->dp.lttpr[4]) + outp->dp.links = min_t(int, outp->dp.links, outp->dp.lttpr[4]); - rate_max = dp->dpcd[DPCD_RC01_MAX_LINK_RATE]; - rate_max = min(rate_max, dp->outp.info.dpconf.link_bw); - if (dp->lttprs && dp->lttpr[1]) - rate_max = min_t(int, rate_max, dp->lttpr[1]); + rate_max = outp->dp.dpcd[DPCD_RC01_MAX_LINK_RATE]; + rate_max = min(rate_max, outp->info.dpconf.link_bw); + if (outp->dp.lttprs && outp->dp.lttpr[1]) + rate_max = min_t(int, rate_max, outp->dp.lttpr[1]); - if (!nvkm_dp_enable_supported_link_rates(dp)) { + if (!nvkm_dp_enable_supported_link_rates(outp)) { for (rate = rates; *rate; rate++) { - if (*rate <= rate_max) { - if (WARN_ON(dp->rates == ARRAY_SIZE(dp->rate))) - break; - - dp->rate[dp->rates].dpcd = -1; - dp->rate[dp->rates].rate = *rate * 27000; - dp->rates++; - } + if (*rate > rate_max) + continue; + + if (WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) + break; + + outp->dp.rate[outp->dp.rates].dpcd = -1; + outp->dp.rate[outp->dp.rates].rate = *rate * 27000; + outp->dp.rates++; } } @@ -674,13 +664,13 @@ nvkm_dp_enable(struct nvkm_dp *dp, bool enable) } } - if (dp->present) { - OUTP_DBG(&dp->outp, "aux power -> demand"); + if (outp->dp.present) { + OUTP_DBG(outp, "aux power -> demand"); nvkm_i2c_aux_monitor(aux, false); - dp->present = false; + outp->dp.present = false; } - atomic_set(&dp->lt.done, 0); + atomic_set(&outp->dp.lt.done, 0); return false; } @@ -688,18 +678,18 @@ static int nvkm_dp_hpd(struct nvkm_notify *notify) { const struct nvkm_i2c_ntfy_rep *line = notify->data; - struct nvkm_dp *dp = container_of(notify, typeof(*dp), hpd); - struct nvkm_conn *conn = dp->outp.conn; - struct nvkm_disp *disp = dp->outp.disp; + struct nvkm_outp *outp = container_of(notify, typeof(*outp), dp.hpd); + struct nvkm_conn *conn = outp->conn; + struct nvkm_disp *disp = outp->disp; struct nvif_notify_conn_rep_v0 rep = {}; - OUTP_DBG(&dp->outp, "HPD: %d", line->mask); + OUTP_DBG(outp, "HPD: %d", line->mask); if (line->mask & NVKM_I2C_IRQ) { - if (atomic_read(&dp->lt.done)) - dp->outp.func->acquire(&dp->outp); + if (atomic_read(&outp->dp.lt.done)) + outp->func->acquire(outp); rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ; } else { - nvkm_dp_enable(dp, true); + nvkm_dp_enable(outp, true); } if (line->mask & NVKM_I2C_UNPLUG) @@ -714,24 +704,22 @@ nvkm_dp_hpd(struct nvkm_notify *notify) static void nvkm_dp_fini(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_put(&dp->hpd); - nvkm_dp_enable(dp, false); + nvkm_notify_put(&outp->dp.hpd); + nvkm_dp_enable(outp, false); } static void nvkm_dp_init(struct nvkm_outp *outp) { struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio; - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_put(&dp->outp.conn->hpd); + nvkm_notify_put(&outp->conn->hpd); /* eDP panels need powering on by us (if the VBIOS doesn't default it * to on) before doing any AUX channel transactions. LVDS panel power * is handled by the SOR itself, and not required for LVDS DDC. */ - if (dp->outp.conn->info.type == DCB_CONNECTOR_eDP) { + if (outp->conn->info.type == DCB_CONNECTOR_eDP) { int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); if (power == 0) nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); @@ -748,21 +736,20 @@ nvkm_dp_init(struct nvkm_outp *outp) /* If the eDP panel can't be detected, we need to restore * the panel power GPIO to avoid breaking another output. */ - if (!nvkm_dp_enable(dp, true) && power == 0) + if (!nvkm_dp_enable(outp, true) && power == 0) nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0); } else { - nvkm_dp_enable(dp, true); + nvkm_dp_enable(outp, true); } - nvkm_notify_get(&dp->hpd); + nvkm_notify_get(&outp->dp.hpd); } static void * nvkm_dp_dtor(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_fini(&dp->hpd); - return dp; + nvkm_notify_fini(&outp->dp.hpd); + return outp; } static const struct nvkm_outp_func @@ -775,75 +762,57 @@ nvkm_dp_func = { .disable = nvkm_dp_disable, }; -static int -nvkm_dp_ctor(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, - struct nvkm_i2c_aux *aux, struct nvkm_dp *dp) +int +nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c = device->i2c; + struct nvkm_outp *outp; u8 hdr, cnt, len; u32 data; int ret; - ret = nvkm_outp_ctor(&nvkm_dp_func, disp, index, dcbE, &dp->outp); + ret = nvkm_outp_new_(&nvkm_dp_func, disp, index, dcbE, poutp); + outp = *poutp; if (ret) return ret; - dp->aux = aux; - if (!dp->aux) { - OUTP_ERR(&dp->outp, "no aux"); + if (dcbE->location == 0) + outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_CCB(dcbE->i2c_index)); + else + outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); + if (!outp->dp.aux) { + OUTP_ERR(outp, "no aux"); return -EINVAL; } /* bios data is not optional */ - data = nvbios_dpout_match(bios, dp->outp.info.hasht, - dp->outp.info.hashm, &dp->version, - &hdr, &cnt, &len, &dp->info); + data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, + &outp->dp.version, &hdr, &cnt, &len, &outp->dp.info); if (!data) { - OUTP_ERR(&dp->outp, "no bios dp data"); + OUTP_ERR(outp, "no bios dp data"); return -EINVAL; } - OUTP_DBG(&dp->outp, "bios dp %02x %02x %02x %02x", - dp->version, hdr, cnt, len); + OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len); /* hotplug detect, replaces gpio-based mechanism with aux events */ ret = nvkm_notify_init(NULL, &i2c->event, nvkm_dp_hpd, true, &(struct nvkm_i2c_ntfy_req) { .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | NVKM_I2C_IRQ, - .port = dp->aux->id, + .port = outp->dp.aux->id, }, sizeof(struct nvkm_i2c_ntfy_req), sizeof(struct nvkm_i2c_ntfy_rep), - &dp->hpd); + &outp->dp.hpd); if (ret) { - OUTP_ERR(&dp->outp, "error monitoring aux hpd: %d", ret); + OUTP_ERR(outp, "error monitoring aux hpd: %d", ret); return ret; } - mutex_init(&dp->mutex); - atomic_set(&dp->lt.done, 0); + mutex_init(&outp->dp.mutex); + atomic_set(&outp->dp.lt.done, 0); return 0; } - -int -nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, - struct nvkm_outp **poutp) -{ - struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; - struct nvkm_i2c_aux *aux; - struct nvkm_dp *dp; - - if (dcbE->location == 0) - aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_CCB(dcbE->i2c_index)); - else - aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); - - if (!(dp = kzalloc(sizeof(*dp), GFP_KERNEL))) - return -ENOMEM; - *poutp = &dp->outp; - - return nvkm_dp_ctor(disp, index, dcbE, aux, dp); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h index 8e59dd469da6..1d86baa6a424 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h @@ -1,41 +1,8 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_DP_H__ #define __NVKM_DISP_DP_H__ -#define nvkm_dp(p) container_of((p), struct nvkm_dp, outp) #include "outp.h" -#include <core/notify.h> -#include <subdev/bios.h> -#include <subdev/bios/dp.h> - -struct nvkm_dp { - struct nvkm_outp outp; - - struct nvbios_dpout info; - u8 version; - - struct nvkm_i2c_aux *aux; - - struct nvkm_notify hpd; - bool present; - u8 lttpr[6]; - u8 lttprs; - u8 dpcd[16]; - - struct { - int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */ - u32 rate; - } rate[8]; - int rates; - int links; - - struct mutex mutex; - struct { - atomic_t done; - bool mst; - } lt; -}; - int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_outp **); void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 156bbe8b2de3..4966a51af3d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -21,28 +21,307 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); + nvkm_wr32(device, 0x61650c + hoff, 0x00000071); + nvkm_wr32(device, 0x616510 + hoff, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ + /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +g84_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, +}; + +int +g84_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g84_sor, disp, SOR, id, false); +} + +static const struct nvkm_disp_mthd_list +g84_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = &g84_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +g84_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00c4, 0x610800 }, + { 0x00c8, 0x61080c }, + { 0x00cc, 0x610818 }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x00fc, 0x610824 }, + { 0x0100, 0x610894 }, + { 0x0104, 0x61082c }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_base = { + .func = &nv50_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &g84_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610bc4 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x085c, 0x610c5c }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0878, 0x610c50 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x089c, 0x610c68 }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + { 0x0910, 0x610c70 }, + { 0x0914, 0x610c78 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g84_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &g84_disp_core_mthd, +}; + +static const struct nvkm_disp_func g84_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g84_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,G82_DISP }, + .user = { + {{0,0,G82_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,G82_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,G82_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,G82_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g84_disp_core }, + {{0,0,G82_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int g84_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g84_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&g84_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 3425b5d3bc72..a4853c4e5ee3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -21,28 +21,357 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +void +g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); +} + +void +g94_sor_dp_activesym(struct nvkm_ior *sor, int head, + u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); + nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | VTUf << 16 | VTUi << 8); +} + +void +g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); + nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); +} + +void +g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[3]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); +} + +void +g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x00001000; break; + case 1: data = 0x01000000; break; + case 2: data = 0x02000000; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); +} + +void +g94_sor_dp_power(struct nvkm_ior *sor, int nr) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 mask = 0, i; + + for (i = 0; i < nr; i++) + mask |= 1 << sor->func->dp->lanes[i]; + + nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); + nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) + break; + ); +} + +int +g94_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.ef) + dpctrl |= 0x00004000; + if (sor->dp.bw > 0x06) + clksor |= 0x00040000; + + nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); + return 0; +} + +const struct nvkm_ior_func_dp +g94_sor_dp = { + .lanes = { 2, 1, 0, 3}, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +static bool +g94_sor_war_needed(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (sor->asy.proto == TMDS) { + switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { + case 0x00000000: + case 0x00030000: + return true; + default: + break; + } + } + + return false; +} + +static void +g94_sor_war_update_sppll1(struct nvkm_disp *disp) +{ + struct nvkm_device *device = disp->engine.subdev.device; + struct nvkm_ior *ior; + bool used = false; + u32 clksor; + + list_for_each_entry(ior, &disp->iors, head) { + if (ior->type != SOR) + continue; + + clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); + switch (clksor & 0x03000000) { + case 0x02000000: + case 0x03000000: + used = true; + break; + default: + break; + } + } + + if (used) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); +} + +static void +g94_sor_war_3(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 sorpwr; + + if (!g94_sor_war_needed(sor)) + return; + + sorpwr = nvkm_rd32(device, 0x61c004 + soff); + if (sorpwr & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pd_pc = (seqctl & 0x00000f00) >> 8; + u32 pu_pc = seqctl & 0x0000000f; + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); + } + + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); + + if (sorpwr & 0x00000001) + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); + + g94_sor_war_update_sppll1(sor->disp); +} + +static void +g94_sor_war_2(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (!g94_sor_war_needed(sor)) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); + + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); + nvkm_usec(device, 400, NVKM_DELAY); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); + + if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pu_pc = seqctl & 0x0000000f; + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); + } +} + +void +g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610794 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; + nv50_pior_depth(sor, state, ctrl); +} + +static const struct nvkm_ior_func +g94_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .war_2 = g94_sor_war_2, + .war_3 = g94_sor_war_3, + .dp = &g94_sor_dp, +}; + +static int +g94_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g94_sor, disp, SOR, id, false); +} + +int +g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; + return 4; +} + +static const struct nvkm_disp_mthd_list +g94_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610794 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g94_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 4, &g94_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +g94_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &g94_disp_core_mthd, +}; + +static const struct nvkm_disp_func g94_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g94_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = g94_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT206_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int g94_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g94_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&g94_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c index 68aa52588d92..7489d0d7fce0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -19,29 +19,135 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +static int +ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + switch (sor->dp.bw) { + case 0x06: clksor |= 0x00000000; break; + case 0x0a: clksor |= 0x00040000; break; + case 0x14: clksor |= 0x00080000; break; + case 0x1e: clksor |= 0x000c0000; break; + case 0x08: clksor |= 0x00100000; break; + case 0x09: clksor |= 0x00140000; break; + case 0x0c: clksor |= 0x00180000; break; + case 0x10: clksor |= 0x001c0000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + + /*XXX*/ + nvkm_msec(device, 40, NVKM_DELAY); + nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); + nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); + + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +static const struct nvkm_ior_func_dp +ga102_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = ga102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +static void +ga102_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + u32 div2 = 0; + + if (sor->asy.proto == TMDS) { + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); + nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); +} + +static const struct nvkm_ior_func +ga102_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = ga102_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &ga102_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +ga102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + + return nvkm_ior_new_(&ga102_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func ga102_disp = { + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &ga102_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = ga102_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,GA102_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,GA102_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,GA102_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,GA102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,GA102_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int ga102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&ga102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&ga102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index a6bafe7fea1f..39822f1b5b95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -21,75 +21,1033 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" #include <core/ramht.h> #include <subdev/timer.h> +#include <nvif/class.h> + +static void +gf119_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); +} + +void +gf119_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); + nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); +} + +void +gf119_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + u32 data = 0x80000000; + u32 mask = 0x80000001; + + if (present) { + ior->func->hda->device_entry(ior, head); + data |= 0x00000001; + } else { + mask |= 0x00000002; + } + + nvkm_mask(device, 0x10ec10 + soff, mask, data); +} + +const struct nvkm_ior_func_hda +gf119_sor_hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, +}; + +void +gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); +} + +void +gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); +} + +void +gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616618 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) + break; + ); +} + +void +gf119_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); + nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); +} + +void +gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[4]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +static void +gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); +} + +int +gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + clksor |= sor->dp.bw << 18; + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +const struct nvkm_ior_func_dp +gf119_sor_dp = { + .lanes = { 2, 1, 0, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gf119_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +static void +gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + /* + * These appear to be the audio infoframe registers, + * but no other set of infoframe registers has yet + * been found. + */ + nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); + } + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +void +gf119_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 div1 = sor->asy.link == 3; + u32 div2 = sor->asy.link == 3; + + if (sor->asy.proto == TMDS) { + const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; + nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); +} + +void +gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640200 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gf119_sor_hdmi_ctrl, + }, + .dp = &gf119_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gf119_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_sor, disp, SOR, id, true); +} + +int +gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; + return 8; +} + +static void +gf119_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); +} + +static void +gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640180 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_dac = { + .state = gf119_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = gf119_dac_clock, +}; + +int +gf119_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_dac, disp, DAC, id, false); +} + +int +gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; + return 4; +} + +static void +gf119_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); +} + +static void +gf119_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); +} + +void +gf119_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); +} + +static void +gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; + u32 data; + + data = nvkm_rd32(device, 0x640414 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640418 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x64041c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640420 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x640450 + hoff); + + data = nvkm_rd32(device, 0x640404 + hoff); + switch ((data & 0x000003c0) >> 6) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX: "default" */ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gf119_head = { + .state = gf119_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gf119_head_vblank_get, + .vblank_put = gf119_head_vblank_put, +}; + +int +gf119_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&gf119_head, disp, id); +} + +int +gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; + return nvkm_rd32(device, 0x022448); +} + +static void +gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x61008c, 0x00000001 << index); +} + +static void +gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x61008c, 0x00000001 << index); + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); +} + +const struct nvkm_event_func +gf119_disp_chan_uevent = { + .init = gf119_disp_chan_uevent_init, + .fini = gf119_disp_chan_uevent_fini, +}; + +void +gf119_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->chid.user; + if (!en) { + nvkm_mask(device, 0x610090, mask, 0x00000000); + nvkm_mask(device, 0x6100a0, mask, 0x00000000); + } else { + nvkm_mask(device, 0x6100a0, mask, mask); + } +} + +static void +gf119_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } +} + +static int +gf119_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* activate channel */ + nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_pioc_func = { + .init = gf119_disp_pioc_init, + .fini = gf119_disp_pioc_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, +}; + +int +gf119_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 27 | 0x00000001); +} + +void +gf119_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +gf119_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = gf119_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gf119_disp_curs = { + .func = &gf119_disp_pioc_func, + .ctrl = 13, + .user = 13, +}; + +const struct nvkm_disp_chan_user +gf119_disp_oimm = { + .func = &gf119_disp_pioc_func, + .ctrl = 9, + .user = 9, +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_ovly_mthd_base }, + {} + } +}; + +static const struct nvkm_disp_chan_user +gf119_disp_ovly = { + .func = &gf119_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gf119_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x661080 }, + { 0x0084, 0x661084 }, + { 0x0088, 0x661088 }, + { 0x008c, 0x66108c }, + { 0x0090, 0x661090 }, + { 0x0094, 0x661094 }, + { 0x00a0, 0x6610a0 }, + { 0x00a4, 0x6610a4 }, + { 0x00c0, 0x6610c0 }, + { 0x00c4, 0x6610c4 }, + { 0x00c8, 0x6610c8 }, + { 0x00cc, 0x6610cc }, + { 0x00e0, 0x6610e0 }, + { 0x00e4, 0x6610e4 }, + { 0x00e8, 0x6610e8 }, + { 0x00ec, 0x6610ec }, + { 0x00fc, 0x6610fc }, + { 0x0100, 0x661100 }, + { 0x0104, 0x661104 }, + { 0x0108, 0x661108 }, + { 0x010c, 0x66110c }, + { 0x0110, 0x661110 }, + { 0x0114, 0x661114 }, + { 0x0118, 0x661118 }, + { 0x011c, 0x66111c }, + { 0x0130, 0x661130 }, + { 0x0134, 0x661134 }, + { 0x0138, 0x661138 }, + { 0x013c, 0x66113c }, + { 0x0140, 0x661140 }, + { 0x0144, 0x661144 }, + { 0x0148, 0x661148 }, + { 0x014c, 0x66114c }, + { 0x0150, 0x661150 }, + { 0x0154, 0x661154 }, + { 0x0158, 0x661158 }, + { 0x015c, 0x66115c }, + { 0x0160, 0x661160 }, + { 0x0164, 0x661164 }, + { 0x0168, 0x661168 }, + { 0x016c, 0x66116c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_image = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0400, 0x661400 }, + { 0x0404, 0x661404 }, + { 0x0408, 0x661408 }, + { 0x040c, 0x66140c }, + { 0x0410, 0x661410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gf119_disp_base_mthd = { + .name = "Base", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_base_mthd_base }, + { "Image", 2, &gf119_disp_base_mthd_image }, + {} + } +}; + +const struct nvkm_disp_chan_user +gf119_disp_base = { + .func = &gf119_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &gf119_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x660080 }, + { 0x0084, 0x660084 }, + { 0x0088, 0x660088 }, + { 0x008c, 0x000000 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_dac = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0180, 0x660180 }, + { 0x0184, 0x660184 }, + { 0x0188, 0x660188 }, + { 0x0190, 0x660190 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0200, 0x660200 }, + { 0x0204, 0x660204 }, + { 0x0208, 0x660208 }, + { 0x0210, 0x660210 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_pior = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x660300 }, + { 0x0304, 0x660304 }, + { 0x0308, 0x660308 }, + { 0x0310, 0x660310 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gf119_disp_core_mthd_head }, + {} + } +}; + +void +gf119_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610490)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +gf119_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494, chan->push); + nvkm_wr32(device, 0x610498, 0x00010000); + nvkm_wr32(device, 0x61049c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gf119_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gf119_disp_core = { + .func = &gf119_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gf119_disp_core_mthd, +}; + void gf119_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; u32 mask[4]; - nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super)); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending)); + mutex_lock(&disp->super.mutex); + + list_for_each_entry(head, &disp->heads, head) { mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800)); HEAD_DBG(head, "%08x", mask[head->id]); } - if (disp->super & 0x00000001) { + if (disp->super.pending & 0x00000001) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000002) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000002) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00010000)) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000004) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000004) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_3_0(disp, head); } } - list_for_each_entry(head, &disp->base.head, head) + list_for_each_entry(head, &disp->heads, head) nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000); + nvkm_wr32(device, 0x6101d0, 0x80000000); + mutex_unlock(&disp->super.mutex); } void -gf119_disp_intr_error(struct nv50_disp *disp, int chid) +gf119_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x6101f0 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; @@ -119,9 +1077,9 @@ gf119_disp_intr_error(struct nv50_disp *disp, int chid) } void -gf119_disp_intr(struct nv50_disp *disp) +gf119_disp_intr(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; u32 intr = nvkm_rd32(device, 0x610088); @@ -147,9 +1105,9 @@ gf119_disp_intr(struct nv50_disp *disp) if (intr & 0x00100000) { u32 stat = nvkm_rd32(device, 0x6100ac); if (stat & 0x00000007) { - disp->super = (stat & 0x00000007); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x6100ac, disp->super); + disp->super.pending = (stat & 0x00000007); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x6100ac, disp->super.pending); stat &= ~0x00000007; } @@ -161,13 +1119,13 @@ gf119_disp_intr(struct nv50_disp *disp) intr &= ~0x00100000; } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; u32 mask = 0x01000000 << head->id; if (mask & intr) { u32 stat = nvkm_rd32(device, 0x6100bc + hoff); if (stat & 0x00000001) - nvkm_disp_vblank(&disp->base, head->id); + nvkm_disp_vblank(disp, head->id); nvkm_mask(device, 0x6100bc + hoff, 0, 0); nvkm_rd32(device, 0x6100c0 + hoff); } @@ -175,17 +1133,17 @@ gf119_disp_intr(struct nv50_disp *disp) } void -gf119_disp_fini(struct nv50_disp *disp) +gf119_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; /* disable all interrupts */ nvkm_wr32(device, 0x6100b0, 0x00000000); } int -gf119_disp_init(struct nv50_disp *disp) +gf119_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; u32 tmp; int i; @@ -196,7 +1154,7 @@ gf119_disp_init(struct nv50_disp *disp) */ /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; tmp = nvkm_rd32(device, 0x616104 + hoff); nvkm_wr32(device, 0x6101b4 + hoff, tmp); @@ -243,7 +1201,7 @@ gf119_disp_init(struct nv50_disp *disp) * * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); } @@ -251,23 +1209,32 @@ gf119_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func gf119_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gf119_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gf119_sor_new }, + .root = { 0,0,GF110_DISP }, + .user = { + {{0,0,GF110_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GF110_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GF110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GF110_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gf119_disp_core }, + {{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gf119_disp_ovly }, + {} + }, }; int gf119_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gf119_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gf119_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 3b79cf233ac5..7248e9ec835e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -21,28 +21,291 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); + } + + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); + + /* ??? */ + nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +static const struct nvkm_ior_func +gk104_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = &gf119_sor_dp, + .hda = &gf119_sor_hda, +}; + +int +gk104_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gk104_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_mthd_list +gk104_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00c4, 0x6650c4 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0404, 0x665404 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gk104_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +gk104_disp_ovly = { + .func = &gf119_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gk104_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +gk104_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x047c, 0x66047c }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x0488, 0x660488 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04a0, 0x6604a0 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x0520, 0x660520 }, + { 0x0524, 0x660524 }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gk104_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +gk104_disp_core = { + .func = &gf119_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gk104_disp_core_mthd, +}; + +static const struct nvkm_disp_func gk104_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gk104_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, + .root = { 0,0,GK104_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK104_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GK104_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gk104_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gk104_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gk104_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 988eb12237a6..1704aa381ee9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -21,28 +21,39 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_disp_func gk110_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gk110_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, + .root = { 0,0,GK110_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GK110_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gk110_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gk110_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gk110_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 5d8108feeacd..9e9ef49bd8ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -21,28 +21,94 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 mask = 0x1f1f1f1f, data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + case 4: data = 0x1b1b1b1b; break; + default: + WARN_ON(1); + return; + } + + if (sor->asy.link & 1) + nvkm_mask(device, 0x61c110 + soff, mask, data); + else + nvkm_mask(device, 0x61c12c + soff, mask, data); +} + +static const struct nvkm_ior_func_dp +gm107_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +gm107_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = &gm107_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gm107_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gm107_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func gm107_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gm107_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gm107_sor_new }, + .root = { 0,0,GM107_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GM107_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gm107_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gm107_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gm107_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index f7bb66087476..4ecc8f98af6e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -21,28 +21,162 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" +#include "outp.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[4]; + + pu &= 0x0f; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x00000f00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +const struct nvkm_ior_func_dp +gm200_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +void +gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(ior); + const u32 ctrl = scdc & 0x3; + + nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); + + ior->tmds.high_speed = !!(scdc & 0x2); +} + +void +gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const u32 moff = __ffs(outp->info.or) * 0x100; + const u32 sor = ior ? ior->id + 1 : 0; + u32 link = ior ? (ior->asy.link == 2) : 0; + + if (outp->info.sorconf.link & 1) { + nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); + link++; + } + + if (outp->info.sorconf.link & 2) + nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); +} + +int +gm200_sor_route_get(struct nvkm_outp *outp, int *link) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const int sublinks = outp->info.sorconf.link; + int lnk[2], sor[2], m, s; + + for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { + if (sublinks & BIT(s)) { + u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); + lnk[s] = (data & 0x00000010) >> 4; + sor[s] = (data & 0x0000000f); + if (!sor[s]) + return -1; + *link |= lnk[s]; + } + } + + if (sublinks == 3) { + if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) + return -1; + } + + return ((sublinks & 1) ? sor[0] : sor[1]) - 1; +} + +static const struct nvkm_ior_func +gm200_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gm200_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gm200_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x101034); + + return nvkm_ior_new_(&gm200_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func gm200_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gm200_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gm200_sor_new }, + .root = { 0,0,GM200_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GM200_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gm200_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gm200_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gm200_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index af0ca812a394..7172a9dfd89b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -21,27 +21,67 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func +gp100_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gm200_sor_dp, + .hda = &gf119_sor_hda, +}; + +int +gp100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x10ebb0) >> 8; + + return nvkm_ior_new_(&gp100_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func gp100_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gp100_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .sor = { .cnt = gf119_sor_cnt, .new = gp100_sor_new }, + .root = { 0,0,GP100_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GP100_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gp100_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gp100_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gp100_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index 065fea1bdfd1..07e9aeec5e08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -21,16 +21,133 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" + +#include <subdev/timer.h> + +#include <nvif/class.h> + +static int +gp102_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gp102_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = gp102_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_curs = { + .func = &gf119_disp_pioc_func, + .ctrl = 13, + .user = 17, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_oimm = { + .func = &gf119_disp_pioc_func, + .ctrl = 9, + .user = 13, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_ovly = { + .func = &gp102_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gk104_disp_ovly_mthd, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_base = { + .func = &gp102_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &gf119_disp_base_mthd, +}; + +static int +gp102_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494, chan->push); + nvkm_wr32(device, 0x611498, 0x00010000); + nvkm_wr32(device, 0x61149c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +static const struct nvkm_disp_chan_func +gp102_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gp102_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_core = { + .func = &gp102_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gk104_disp_core_mthd, +}; static void -gp102_disp_intr_error(struct nv50_disp *disp, int chid) +gp102_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 mthd = nvkm_rd32(device, 0x6111f0 + (chid * 12)); u32 data = nvkm_rd32(device, 0x6111f4 + (chid * 12)); @@ -53,22 +170,31 @@ gp102_disp_intr_error(struct nv50_disp *disp, int chid) nvkm_wr32(device, 0x6111f0 + (chid * 12), 0x90000000); } -static const struct nv50_disp_func +static const struct nvkm_disp_func gp102_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gp102_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gp102_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .sor = { .cnt = gf119_sor_cnt, .new = gp100_sor_new }, + .root = { 0,0,GP102_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gp102_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gp102_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gp102_disp_base }, + {{0,0,GP102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gp102_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gp102_disp_ovly }, + {} + }, }; int gp102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gp102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gp102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index 22bc269df64a..6f69c4e3ade2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -21,28 +21,89 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_disp_mthd_list +gt200_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00b0, 0x610c98 }, + { 0x00b4, 0x610ca4 }, + { 0x00b8, 0x610cac }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gt200_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, >200_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +gt200_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = >200_disp_ovly_mthd, +}; + +static const struct nvkm_disp_func gt200_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >200_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT200_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT200_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g84_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int gt200_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>200_disp, device, type, inst, pdisp); + return nvkm_disp_new_(>200_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 63a912b174d7..70c49e7af9cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -21,28 +21,188 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +static void +gt215_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = ior->id * 0x800; + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8)); + nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); +} + +static void +gt215_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + u32 data = 0x80000000; + u32 mask = 0x80000001; + if (present) + data |= 0x00000001; + else + mask |= 0x00000002; + nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); +} + +const struct nvkm_ior_func_hda +gt215_sor_hda = { + .hpd = gt215_sor_hda_hpd, + .eld = gt215_sor_hda_eld, +}; + +void +gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x61c1e0 + soff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) + break; + ); +} + +static const struct nvkm_ior_func_dp +gt215_sor_dp = { + .lanes = { 2, 1, 0, 3 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +void +gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 soff = nv50_ior_base(ior); + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); + nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); + nvkm_wr32(device, 0x61c50c + soff, 0x00000071); + nvkm_wr32(device, 0x61c510 + soff, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); + nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ + /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +gt215_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = >215_sor_dp, + .hda = >215_sor_hda, +}; + +static int +gt215_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(>215_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func gt215_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >215_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = gt215_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT214_DISP }, + .user = { + {{0,0,GT214_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0,GT214_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int gt215_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>215_disp, device, type, inst, pdisp); + return nvkm_disp_new_(>215_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 53879d5271cf..6b9d49270fa7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -19,84 +19,862 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" +#include <core/client.h> #include <core/gpuobj.h> +#include <core/ramht.h> #include <subdev/timer.h> +#include <nvif/class.h> +#include <nvif/unpack.h> + +static void +gv100_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); +} + +const struct nvkm_ior_func_hda +gv100_sor_hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gv100_sor_hda_device_entry, +}; + +void +gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); +} + +void +gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); +} + +void +gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616560 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) + break; + ); +} + +static const struct nvkm_ior_func_dp +gv100_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +void +gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame (AVI). */ + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); + } + + /* Vendor-specific InfoFrame (VSI). */ + nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); + } + + + /* General Control (GCP). */ + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); + + /* Audio Clock Regeneration (ACR). */ + nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); + + /* NV_PDISP_SF_HDMI_CTRL. */ + nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); +} + +void +gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x680300 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x000000ff; +} + +static const struct nvkm_ior_func +gv100_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gv100_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +gv100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x118fb0) >> 8; + + return nvkm_ior_new_(&gv100_sor, disp, SOR, id, hda & BIT(id)); +} + +int +gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; + return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; +} + +static void +gv100_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); +} + +static void +gv100_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); +} + +static void +gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; +} + +static void +gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; + u32 data; + + data = nvkm_rd32(device, 0x682064 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682068 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x68206c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682070 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x68200c + hoff); + + data = nvkm_rd32(device, 0x682004 + hoff); + switch ((data & 0x000000f0) >> 4) { + case 5: state->or.depth = 30; break; + case 4: state->or.depth = 24; break; + case 1: state->or.depth = 18; break; + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gv100_head = { + .state = gv100_head_state, + .rgpos = gv100_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gv100_head_vblank_get, + .vblank_put = gv100_head_vblank_put, +}; + +int +gv100_head_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) + return 0; + + return nvkm_head_new_(&gv100_head, disp, id); +} + +int +gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; + return nvkm_rd32(device, 0x610074) & 0x0000000f; +} + +const struct nvkm_event_func +gv100_disp_chan_uevent = { +}; + +u64 +gv100_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x690000 + ((chan->chid.user - 1) * 0x1000); +} + +static int +gv100_disp_dmac_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x000f0000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +int +gv100_disp_dmac_bind(struct nvkm_disp_chan *chan, + struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 25 | 0x00000040); +} + +void +gv100_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 coff = chan->chid.ctrl * 0x04; + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); + gv100_disp_dmac_idle(chan); + nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); +} + +int +gv100_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 poff = chan->chid.ctrl * 0x10; + const u32 coff = chan->chid.ctrl * 0x04; + + nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28 + poff, 0x00000001); + nvkm_wr32(device, 0x610b2c + poff, 0x00000040); + + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); + nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); + return gv100_disp_dmac_idle(chan); +} + +static void +gv100_disp_wimm_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da8, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wimm_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wimm_intr, + .user = gv100_disp_chan_user, +}; + +const struct nvkm_disp_chan_user +gv100_disp_wimm = { + .func = &gv100_disp_wimm_func, + .ctrl = 33, + .user = 33, +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_wndw_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x690200 }, + { 0x020c, 0x69020c }, + { 0x0210, 0x690210 }, + { 0x0214, 0x690214 }, + { 0x0218, 0x690218 }, + { 0x021c, 0x69021c }, + { 0x0220, 0x690220 }, + { 0x0224, 0x690224 }, + { 0x0228, 0x690228 }, + { 0x022c, 0x69022c }, + { 0x0230, 0x690230 }, + { 0x0234, 0x690234 }, + { 0x0238, 0x690238 }, + { 0x0240, 0x690240 }, + { 0x0244, 0x690244 }, + { 0x0248, 0x690248 }, + { 0x024c, 0x69024c }, + { 0x0250, 0x690250 }, + { 0x0254, 0x690254 }, + { 0x0260, 0x690260 }, + { 0x0264, 0x690264 }, + { 0x0268, 0x690268 }, + { 0x026c, 0x69026c }, + { 0x0270, 0x690270 }, + { 0x0274, 0x690274 }, + { 0x0280, 0x690280 }, + { 0x0284, 0x690284 }, + { 0x0288, 0x690288 }, + { 0x028c, 0x69028c }, + { 0x0290, 0x690290 }, + { 0x0298, 0x690298 }, + { 0x029c, 0x69029c }, + { 0x02a0, 0x6902a0 }, + { 0x02a4, 0x6902a4 }, + { 0x02a8, 0x6902a8 }, + { 0x02ac, 0x6902ac }, + { 0x02b0, 0x6902b0 }, + { 0x02b4, 0x6902b4 }, + { 0x02b8, 0x6902b8 }, + { 0x02bc, 0x6902bc }, + { 0x02c0, 0x6902c0 }, + { 0x02c4, 0x6902c4 }, + { 0x02c8, 0x6902c8 }, + { 0x02cc, 0x6902cc }, + { 0x02d0, 0x6902d0 }, + { 0x02d4, 0x6902d4 }, + { 0x02d8, 0x6902d8 }, + { 0x02dc, 0x6902dc }, + { 0x02e0, 0x6902e0 }, + { 0x02e4, 0x6902e4 }, + { 0x02e8, 0x6902e8 }, + { 0x02ec, 0x6902ec }, + { 0x02f0, 0x6902f0 }, + { 0x02f4, 0x6902f4 }, + { 0x02f8, 0x6902f8 }, + { 0x02fc, 0x6902fc }, + { 0x0300, 0x690300 }, + { 0x0304, 0x690304 }, + { 0x0308, 0x690308 }, + { 0x0310, 0x690310 }, + { 0x0314, 0x690314 }, + { 0x0318, 0x690318 }, + { 0x031c, 0x69031c }, + { 0x0320, 0x690320 }, + { 0x0324, 0x690324 }, + { 0x0328, 0x690328 }, + { 0x032c, 0x69032c }, + { 0x033c, 0x69033c }, + { 0x0340, 0x690340 }, + { 0x0344, 0x690344 }, + { 0x0348, 0x690348 }, + { 0x034c, 0x69034c }, + { 0x0350, 0x690350 }, + { 0x0354, 0x690354 }, + { 0x0358, 0x690358 }, + { 0x0364, 0x690364 }, + { 0x0368, 0x690368 }, + { 0x036c, 0x69036c }, + { 0x0370, 0x690370 }, + { 0x0374, 0x690374 }, + { 0x0380, 0x690380 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_wndw_mthd = { + .name = "Window", + .addr = 0x001000, + .prev = 0x000800, + .data = { + { "Global", 1, &gv100_disp_wndw_mthd_base }, + {} + } +}; + +static void +gv100_disp_wndw_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da4, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wndw_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wndw_intr, + .user = gv100_disp_chan_user, + .bind = gv100_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gv100_disp_wndw = { + .func = &gv100_disp_wndw_func, + .ctrl = 1, + .user = 1, + .mthd = &gv100_disp_wndw_mthd, +}; + int gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask) { struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x610064); return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20; } +static int +gv100_disp_curs_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x00070000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +static void +gv100_disp_curs_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010000 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_curs_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 hoff = chan->chid.ctrl * 4; + nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); + gv100_disp_curs_idle(chan); + nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); +} + +static int +gv100_disp_curs_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); + return gv100_disp_curs_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_curs_func = { + .init = gv100_disp_curs_init, + .fini = gv100_disp_curs_fini, + .intr = gv100_disp_curs_intr, + .user = gv100_disp_chan_user, +}; + +const struct nvkm_disp_chan_user +gv100_disp_curs = { + .func = &gv100_disp_curs_func, + .ctrl = 73, + .user = 73, +}; + +const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x680200 }, + { 0x0208, 0x680208 }, + { 0x020c, 0x68020c }, + { 0x0210, 0x680210 }, + { 0x0214, 0x680214 }, + { 0x0218, 0x680218 }, + { 0x021c, 0x68021c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x680300 }, + { 0x0304, 0x680304 }, + { 0x0308, 0x680308 }, + { 0x030c, 0x68030c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_wndw = { + .mthd = 0x0080, + .addr = 0x000080, + .data = { + { 0x1000, 0x681000 }, + { 0x1004, 0x681004 }, + { 0x1008, 0x681008 }, + { 0x100c, 0x68100c }, + { 0x1010, 0x681010 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000400, + .data = { + { 0x2000, 0x682000 }, + { 0x2004, 0x682004 }, + { 0x2008, 0x682008 }, + { 0x200c, 0x68200c }, + { 0x2014, 0x682014 }, + { 0x2018, 0x682018 }, + { 0x201c, 0x68201c }, + { 0x2020, 0x682020 }, + { 0x2028, 0x682028 }, + { 0x202c, 0x68202c }, + { 0x2030, 0x682030 }, + { 0x2038, 0x682038 }, + { 0x203c, 0x68203c }, + { 0x2048, 0x682048 }, + { 0x204c, 0x68204c }, + { 0x2050, 0x682050 }, + { 0x2054, 0x682054 }, + { 0x2058, 0x682058 }, + { 0x205c, 0x68205c }, + { 0x2060, 0x682060 }, + { 0x2064, 0x682064 }, + { 0x2068, 0x682068 }, + { 0x206c, 0x68206c }, + { 0x2070, 0x682070 }, + { 0x2074, 0x682074 }, + { 0x2078, 0x682078 }, + { 0x207c, 0x68207c }, + { 0x2080, 0x682080 }, + { 0x2088, 0x682088 }, + { 0x2090, 0x682090 }, + { 0x209c, 0x68209c }, + { 0x20a0, 0x6820a0 }, + { 0x20a4, 0x6820a4 }, + { 0x20a8, 0x6820a8 }, + { 0x20ac, 0x6820ac }, + { 0x2180, 0x682180 }, + { 0x2184, 0x682184 }, + { 0x218c, 0x68218c }, + { 0x2194, 0x682194 }, + { 0x2198, 0x682198 }, + { 0x219c, 0x68219c }, + { 0x21a0, 0x6821a0 }, + { 0x21a4, 0x6821a4 }, + { 0x2214, 0x682214 }, + { 0x2218, 0x682218 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x008000, + .data = { + { "Global", 1, &gv100_disp_core_mthd_base }, + { "SOR", 4, &gv100_disp_core_mthd_sor }, + { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, + { "HEAD", 4, &gv100_disp_core_mthd_head }, + {} + } +}; + +static int +gv100_disp_core_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610630); + if ((stat & 0x001f0000) == 0x000b0000) + return 0; + ); + return -EBUSY; +} + +static u64 +gv100_disp_core_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x10000; + return 0x680000; +} + +static void +gv100_disp_core_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); + gv100_disp_core_idle(chan); + nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x680000); +} + +static int +gv100_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28, 0x00000001); + nvkm_wr32(device, 0x610b2c, 0x00000040); + + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x680000, chan->suspend_put); + nvkm_wr32(device, 0x6104e0, 0x00000013); + return gv100_disp_core_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_core_init, + .fini = gv100_disp_core_fini, + .intr = gv100_disp_core_intr, + .user = gv100_disp_core_user, + .bind = gv100_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gv100_disp_core = { + .func = &gv100_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gv100_disp_core_mthd, +}; + +#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) + +struct gv100_disp_caps { + struct nvkm_object object; + struct nvkm_disp *disp; +}; + +static int +gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct gv100_disp_caps *caps = gv100_disp_caps(object); + struct nvkm_device *device = caps->disp->engine.subdev.device; + *type = NVKM_OBJECT_MAP_IO; + *addr = 0x640000 + device->func->resource_addr(device, 0); + *size = 0x1000; + return 0; +} + +static const struct nvkm_object_func +gv100_disp_caps = { + .map = gv100_disp_caps_map, +}; + +int +gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct gv100_disp_caps *caps; + + if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) + return -ENOMEM; + *pobject = &caps->object; + + nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); + caps->disp = disp; + return 0; +} + void gv100_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; - u32 stat = nvkm_rd32(device, 0x6107a8); - u32 mask[4]; + u32 stat, mask[4]; + + mutex_lock(&disp->super.mutex); + stat = nvkm_rd32(device, 0x6107a8); - nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super), stat); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat); + list_for_each_entry(head, &disp->heads, head) { mask[head->id] = nvkm_rd32(device, 0x6107ac + (head->id * 4)); HEAD_DBG(head, "%08x", mask[head->id]); } - if (disp->super & 0x00000001) { + if (disp->super.pending & 0x00000001) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000002) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000002) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00010000)) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000004) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000004) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_3_0(disp, head); } } - list_for_each_entry(head, &disp->base.head, head) + list_for_each_entry(head, &disp->heads, head) nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000); + nvkm_wr32(device, 0x6107a8, 0x80000000); + mutex_unlock(&disp->super.mutex); } static void -gv100_disp_exception(struct nv50_disp *disp, int chid) +gv100_disp_exception(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611020 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; @@ -136,16 +914,16 @@ gv100_disp_exception(struct nv50_disp *disp, int chid) } static void -gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) +gv100_disp_intr_ctrl_disp(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611c30); if (stat & 0x00000007) { - disp->super = (stat & 0x00000007); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x611860, disp->super); + disp->super.pending = (stat & 0x00000007); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x611860, disp->super.pending); stat &= ~0x00000007; } @@ -184,9 +962,9 @@ gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_other(struct nv50_disp *disp) +gv100_disp_intr_exc_other(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611854); unsigned long mask; @@ -213,9 +991,9 @@ gv100_disp_intr_exc_other(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_winim(struct nv50_disp *disp) +gv100_disp_intr_exc_winim(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; unsigned long stat = nvkm_rd32(device, 0x611850); int wndw; @@ -233,9 +1011,9 @@ gv100_disp_intr_exc_winim(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_win(struct nv50_disp *disp) +gv100_disp_intr_exc_win(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; unsigned long stat = nvkm_rd32(device, 0x61184c); int wndw; @@ -253,9 +1031,9 @@ gv100_disp_intr_exc_win(struct nv50_disp *disp) } static void -gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) +gv100_disp_intr_head_timing(struct nvkm_disp *disp, int head) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611800 + (head * 0x04)); @@ -266,7 +1044,7 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) } if (stat & 0x00000004) { - nvkm_disp_vblank(&disp->base, head); + nvkm_disp_vblank(disp, head); nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000004); stat &= ~0x00000004; } @@ -278,9 +1056,9 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) } void -gv100_disp_intr(struct nv50_disp *disp) +gv100_disp_intr(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611ec0); unsigned long mask; @@ -318,16 +1096,16 @@ gv100_disp_intr(struct nv50_disp *disp) } void -gv100_disp_fini(struct nv50_disp *disp) +gv100_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; nvkm_wr32(device, 0x611db0, 0x00000000); } static int -gv100_disp_init(struct nv50_disp *disp) +gv100_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; int i, j; u32 tmp; @@ -354,7 +1132,7 @@ gv100_disp_init(struct nv50_disp *disp) } /* Head capabilities. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const int id = head->id; /* RG. */ @@ -414,7 +1192,7 @@ gv100_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */ /* HEAD_TIMING(n): VBLANK. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 4; nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */ nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */ @@ -426,23 +1204,32 @@ gv100_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func gv100_disp = { + .oneinit = nv50_disp_oneinit, .init = gv100_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &gv100_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = gv100_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,GV100_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,GV100_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,GV100_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,GV100_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,GV100_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int gv100_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gv100_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gv100_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c deleted file mode 100644 index 19d2d58344e4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gf119_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); -} - -void -gf119_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); - nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); -} - -void -gf119_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) { - ior->func->hda.device_entry(ior, head); - data |= 0x00000001; - } else { - mask |= 0x00000002; - } - nvkm_mask(device, 0x10ec10 + soff, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c deleted file mode 100644 index 0d1b81fe1093..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gt215_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = ior->id * 0x800; - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8)); - nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); -} - -void -gt215_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) - data |= 0x00000001; - else - mask |= 0x00000002; - nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c deleted file mode 100644 index 57d374ecfeef..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 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 "ior.h" - -void -gv100_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c deleted file mode 100644 index 661410f9b457..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -g84_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); - nvkm_wr32(device, 0x61650c + hoff, 0x00000071); - nvkm_wr32(device, 0x616510 + hoff, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ - /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c deleted file mode 100644 index 6cac0e72b4cc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gf119_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - /* - * These appear to be the audio infoframe registers, - * but no other set of infoframe registers has yet - * been found. - */ - nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); - } - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c deleted file mode 100644 index ed0a6100d76b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gk104_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); - } - - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); - - /* ??? */ - nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c deleted file mode 100644 index bb32befa6ad4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2018 Ilia Mirkin - * - * 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. - * - * Authors: Ilia Mirkin - */ -#include "hdmi.h" - -void -gm200_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(ior); - const u32 ctrl = scdc & 0x3; - - nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); - - ior->tmds.high_speed = !!(scdc & 0x2); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c deleted file mode 100644 index 0993d223bb9c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gt215_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 soff = nv50_ior_base(ior); - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); - nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); - nvkm_wr32(device, 0x61c50c + soff, 0x00000071); - nvkm_wr32(device, 0x61c510 + soff, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); - nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ - /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c deleted file mode 100644 index 3ff49344abc7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 "hdmi.h" - -void -gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame (AVI). */ - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); - } - - /* Vendor-specific InfoFrame (VSI). */ - nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); - } - - - /* General Control (GCP). */ - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); - - /* Audio Clock Regeneration (ACR). */ - nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); - - /* NV_PDISP_SF_HDMI_CTRL. */ - nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c index 5c557f3e6c2c..83152c26fe3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c @@ -32,7 +32,7 @@ struct nvkm_head * nvkm_head_find(struct nvkm_disp *disp, int id) { struct nvkm_head *head; - list_for_each_entry(head, &disp->head, head) { + list_for_each_entry(head, &disp->heads, head) { if (head->id == id) return head; } @@ -99,7 +99,7 @@ nvkm_head_new_(const struct nvkm_head_func *func, head->func = func; head->disp = disp; head->id = id; - list_add_tail(&head->head, &disp->head); + list_add_tail(&head->head, &disp->heads); HEAD_DBG(head, "ctor"); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 7dde6237441d..84a2989193cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -42,19 +42,9 @@ struct nvkm_head_func { void (*vblank_put)(struct nvkm_head *); }; -void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); - -#define HEAD_MSG(h,l,f,a...) do { \ - struct nvkm_head *_h = (h); \ - nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ -} while(0) -#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) -#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) - -int nv04_head_new(struct nvkm_disp *, int id); - int nv50_head_cnt(struct nvkm_disp *, unsigned long *); int nv50_head_new(struct nvkm_disp *, int id); +void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); int gf119_head_cnt(struct nvkm_disp *, unsigned long *); int gf119_head_new(struct nvkm_disp *, int id); @@ -62,4 +52,11 @@ void gf119_head_rgclk(struct nvkm_head *, int); int gv100_head_cnt(struct nvkm_disp *, unsigned long *); int gv100_head_new(struct nvkm_disp *, int id); + +#define HEAD_MSG(h,l,f,a...) do { \ + struct nvkm_head *_h = (h); \ + nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ +} while(0) +#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) +#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c deleted file mode 100644 index e86298b35902..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -gf119_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); -} - -static void -gf119_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); -} - -void -gf119_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); -} - -static void -gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; - u32 data; - - data = nvkm_rd32(device, 0x640414 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640418 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x64041c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640420 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x640450 + hoff); - - data = nvkm_rd32(device, 0x640404 + hoff); - switch ((data & 0x000003c0) >> 6) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX: "default" */ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gf119_head = { - .state = gf119_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gf119_head_vblank_get, - .vblank_put = gf119_head_vblank_put, -}; - -int -gf119_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&gf119_head, disp, id); -} - -int -gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; - return nvkm_rd32(device, 0x022448); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c deleted file mode 100644 index 1a061b42ae5c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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" - -static void -gv100_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); -} - -static void -gv100_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); -} - -static void -gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; -} - -static void -gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; - u32 data; - - data = nvkm_rd32(device, 0x682064 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682068 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x68206c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682070 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x68200c + hoff); - - data = nvkm_rd32(device, 0x682004 + hoff); - switch ((data & 0x000000f0) >> 4) { - case 5: state->or.depth = 30; break; - case 4: state->or.depth = 24; break; - case 1: state->or.depth = 18; break; - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gv100_head = { - .state = gv100_head_state, - .rgpos = gv100_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gv100_head_vblank_get, - .vblank_put = gv100_head_vblank_put, -}; - -int -gv100_head_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) - return 0; - return nvkm_head_new_(&gv100_head, disp, id); -} - -int -gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; - return nvkm_rd32(device, 0x610074) & 0x0000000f; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c deleted file mode 100644 index dcf459282aa1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv04_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); -} - -static void -nv04_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); -} - -static void -nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); - *hline = (data & 0xffff0000) >> 16; - *vline = (data & 0x0000ffff); -} - -static void -nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x0200; - state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; - state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; - state->vblanke = state->vtotal - 1; - state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; - state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; - state->hblanke = state->htotal - 1; -} - -static const struct nvkm_head_func -nv04_head = { - .state = nv04_head_state, - .rgpos = nv04_head_rgpos, - .vblank_get = nv04_head_vblank_get, - .vblank_put = nv04_head_vblank_put, -}; - -int -nv04_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv04_head, disp, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c deleted file mode 100644 index e7d5c397cd29..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv50_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), 0); -} - -static void -nv50_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); -} - -static void -nv50_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); -} - -void -nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; -} - -static void -nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; - u32 data; - - data = nvkm_rd32(device, 0x610ae8 + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af0 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af8 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610b00 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; -} - -static const struct nvkm_head_func -nv50_head = { - .state = nv50_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = nv50_head_rgclk, - .vblank_get = nv50_head_vblank_get, - .vblank_put = nv50_head_vblank_put, -}; - -int -nv50_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv50_head, disp, id); -} - -int -nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - *pmask = 3; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c index a475ea56795c..e420bf2e4330 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c @@ -34,7 +34,7 @@ struct nvkm_ior * nvkm_ior_find(struct nvkm_disp *disp, enum nvkm_ior_type type, int id) { struct nvkm_ior *ior; - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if (ior->type == type && (id < 0 || ior->id == id)) return ior; } @@ -55,7 +55,7 @@ nvkm_ior_del(struct nvkm_ior **pior) int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, - enum nvkm_ior_type type, int id) + enum nvkm_ior_type type, int id, bool hda) { struct nvkm_ior *ior; if (!(ior = kzalloc(sizeof(*ior), GFP_KERNEL))) @@ -64,9 +64,9 @@ nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, ior->disp = disp; ior->type = type; ior->id = id; - snprintf(ior->name, sizeof(ior->name), "%s-%d", - nvkm_ior_name[ior->type], ior->id); - list_add_tail(&ior->head, &disp->ior); + ior->hda = hda; + snprintf(ior->name, sizeof(ior->name), "%s-%d", nvkm_ior_name[ior->type], ior->id); + list_add_tail(&ior->head, &disp->iors); IOR_DBG(ior, "ctor"); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index 9f0bb7c6b010..671c4674ffcc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -13,6 +13,7 @@ struct nvkm_ior { PIOR, } type; int id; + bool hda; char name[8]; struct list_head head; @@ -69,7 +70,7 @@ struct nvkm_ior_func { void (*scdc)(struct nvkm_ior *, u8 scdc); } hdmi; - struct { + const struct nvkm_ior_func_dp { u8 lanes[4]; int (*links)(struct nvkm_ior *, struct nvkm_i2c_aux *); void (*power)(struct nvkm_ior *, int nr); @@ -83,17 +84,17 @@ struct nvkm_ior_func { void (*activesym)(struct nvkm_ior *, int head, u8 TU, u8 VTUa, u8 VTUf, u8 VTUi); void (*watermark)(struct nvkm_ior *, int head, u8 watermark); - } dp; + } *dp; - struct { + const struct nvkm_ior_func_hda { void (*hpd)(struct nvkm_ior *, int head, bool present); void (*eld)(struct nvkm_ior *, int head, u8 *data, u8 size); void (*device_entry)(struct nvkm_ior *, int head); - } hda; + } *hda; }; int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *, - enum nvkm_ior_type type, int id); + enum nvkm_ior_type type, int id, bool hda); void nvkm_ior_del(struct nvkm_ior **); struct nvkm_ior *nvkm_ior_find(struct nvkm_disp *, enum nvkm_ior_type, int id); @@ -103,10 +104,13 @@ nv50_ior_base(struct nvkm_ior *ior) return ior->id * 0x800; } +int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); +int nv50_dac_new(struct nvkm_disp *, int); void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); int nv50_dac_sense(struct nvkm_ior *, u32); -void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); +int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); +int gf119_dac_new(struct nvkm_disp *, int); static inline u32 nv50_sor_link(struct nvkm_ior *ior) @@ -114,11 +118,17 @@ nv50_sor_link(struct nvkm_ior *ior) return nv50_ior_base(ior) + ((ior->asy.link == 2) * 0x80); } +int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); void nv50_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool); void nv50_sor_clock(struct nvkm_ior *); +int g84_sor_new(struct nvkm_disp *, int); +void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); + +int g94_sor_cnt(struct nvkm_disp *, unsigned long *); void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +extern const struct nvkm_ior_func_dp g94_sor_dp; int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); void g94_sor_dp_power(struct nvkm_ior *, int); void g94_sor_dp_pattern(struct nvkm_ior *, int); @@ -127,47 +137,50 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8); void g94_sor_dp_watermark(struct nvkm_ior *, int, u8); +void gt215_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gt215_sor_dp_audio(struct nvkm_ior *, int, bool); +extern const struct nvkm_ior_func_hda gt215_sor_hda; +int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void gf119_sor_clock(struct nvkm_ior *); +extern const struct nvkm_ior_func_dp gf119_sor_dp; int gf119_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); -void gf119_sor_dp_pattern(struct nvkm_ior *, int); void gf119_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); void gf119_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); void gf119_sor_dp_audio(struct nvkm_ior *, int, bool); void gf119_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gf119_sor_dp_watermark(struct nvkm_ior *, int, u8); +extern const struct nvkm_ior_func_hda gf119_sor_hda; +void gf119_sor_hda_hpd(struct nvkm_ior *, int, bool); +void gf119_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8); + +int gk104_sor_new(struct nvkm_disp *, int); +void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gm107_sor_dp_pattern(struct nvkm_ior *, int); void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *); int gm200_sor_route_get(struct nvkm_outp *, int *); +void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8); +extern const struct nvkm_ior_func_dp gm200_sor_dp; void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); +int gp100_sor_new(struct nvkm_disp *, int); + +int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +void gv100_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gv100_sor_dp_audio(struct nvkm_ior *, int, bool); void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8); +extern const struct nvkm_ior_func_hda gv100_sor_hda; void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); -void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); - -void gm200_hdmi_scdc(struct nvkm_ior *, u8); - -void gt215_hda_hpd(struct nvkm_ior *, int, bool); -void gt215_hda_eld(struct nvkm_ior *, int, u8 *, u8); - -void gf119_hda_hpd(struct nvkm_ior *, int, bool); -void gf119_hda_eld(struct nvkm_ior *, int, u8 *, u8); -void gf119_hda_device_entry(struct nvkm_ior *, int); - -void gv100_hda_device_entry(struct nvkm_ior *, int); +int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); +int nv50_pior_new(struct nvkm_disp *, int); +void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); #define IOR_MSG(i,l,f,a...) do { \ struct nvkm_ior *_ior = (i); \ @@ -175,40 +188,4 @@ void gv100_hda_device_entry(struct nvkm_ior *, int); } while(0) #define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a) #define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a) - -int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); -int nv50_dac_new(struct nvkm_disp *, int); - -int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); -int gf119_dac_new(struct nvkm_disp *, int); - -int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); -int nv50_pior_new(struct nvkm_disp *, int); - -int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); -int nv50_sor_new(struct nvkm_disp *, int); - -int g84_sor_new(struct nvkm_disp *, int); - -int g94_sor_cnt(struct nvkm_disp *, unsigned long *); -int g94_sor_new(struct nvkm_disp *, int); - -int mcp77_sor_new(struct nvkm_disp *, int); -int gt215_sor_new(struct nvkm_disp *, int); -int mcp89_sor_new(struct nvkm_disp *, int); - -int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); -int gf119_sor_new(struct nvkm_disp *, int); - -int gk104_sor_new(struct nvkm_disp *, int); -int gm107_sor_new(struct nvkm_disp *, int); -int gm200_sor_new(struct nvkm_disp *, int); -int gp100_sor_new(struct nvkm_disp *, int); - -int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); -int gv100_sor_new(struct nvkm_disp *, int); - -int tu102_sor_new(struct nvkm_disp *, int); - -int ga102_sor_new(struct nvkm_disp *, int); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index 762a59f24bbb..916b1d477b0b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -19,28 +19,56 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func +mcp77_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, + .dp = &g94_sor_dp, +}; + +static int +mcp77_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp77_sor, disp, SOR, id, false); +} + +static const struct nvkm_disp_func mcp77_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g94_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = mcp77_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT206_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int mcp77_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp77_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&mcp77_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index e5c58aae15de..a5a0b9439374 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -19,28 +19,70 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func_dp +mcp89_sor_dp = { + .lanes = { 3, 2, 1, 0 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +mcp89_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = &mcp89_sor_dp, + .hda = >215_sor_hda, +}; + +static int +mcp89_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp89_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func mcp89_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >215_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = mcp89_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT214_DISP }, + .user = { + {{0,0,GT214_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,GT214_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int mcp89_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp89_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&mcp89_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c index a12097db2c2a..e4cf11a33969 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c @@ -24,10 +24,56 @@ #include "priv.h" #include "head.h" -static const struct nvkm_disp_oclass * -nv04_disp_root(struct nvkm_disp *disp) +#include <nvif/class.h> + +static void +nv04_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); +} + +static void +nv04_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); +} + +static void +nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); + *hline = (data & 0xffff0000) >> 16; + *vline = (data & 0x0000ffff); +} + +static void +nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x0200; + state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; + state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; + state->vblanke = state->vtotal - 1; + state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; + state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; + state->hblanke = state->htotal - 1; +} + +static const struct nvkm_head_func +nv04_head = { + .state = nv04_head_state, + .rgpos = nv04_head_rgpos, + .vblank_get = nv04_head_vblank_get, + .vblank_put = nv04_head_vblank_put, +}; + +static int +nv04_head_new(struct nvkm_disp *disp, int id) { - return &nv04_disp_root_oclass; + return nvkm_head_new_(&nv04_head, disp, id); } static void @@ -60,7 +106,8 @@ nv04_disp_intr(struct nvkm_disp *disp) static const struct nvkm_disp_func nv04_disp = { .intr = nv04_disp_intr, - .root = nv04_disp_root, + .root = { 0, 0, NV04_DISP }, + .user = { {} }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 3f20e49070ce..a46e13cc9ff1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -21,11 +21,11 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" #include <core/client.h> #include <core/ramht.h> @@ -34,150 +34,948 @@ #include <subdev/bios/init.h> #include <subdev/bios/pll.h> #include <subdev/devinit.h> +#include <subdev/i2c.h> +#include <subdev/mmu.h> #include <subdev/timer.h> -static const struct nvkm_disp_oclass * -nv50_disp_root_(struct nvkm_disp *base) +#include <nvif/class.h> +#include <nvif/unpack.h> + +static void +nv50_pior_clock(struct nvkm_ior *pior) { - return nv50_disp(base)->func->root; + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); + + nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); } +static int +nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) +{ + int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, pior->dp.ef); + if (ret) + return ret; + + return 1; +} + +static const struct nvkm_ior_func_dp +nv50_pior_dp = { + .links = nv50_pior_dp_links, +}; + static void -nv50_disp_intr_(struct nvkm_disp *base) +nv50_pior_power_wait(struct nvkm_device *device, u32 poff) { - struct nv50_disp *disp = nv50_disp(base); - disp->func->intr(disp); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) + break; + ); } static void -nv50_disp_fini_(struct nvkm_disp *base) +nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, bool data, bool vsync, bool hsync) { - struct nv50_disp *disp = nv50_disp(base); - disp->func->fini(disp); + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000101 << shift); + + nv50_pior_power_wait(device, poff); + nvkm_mask(device, 0x61e004 + poff, field, state); + nv50_pior_power_wait(device, poff); } -static int -nv50_disp_init_(struct nvkm_disp *base) +void +nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) { - struct nv50_disp *disp = nv50_disp(base); - return disp->func->init(disp); + /* GF119 moves this information to per-head methods, which is + * a lot more convenient, and where our shared code expect it. + */ + if (state->head && state == &ior->asy) { + struct nvkm_head *head = nvkm_head_find(ior->disp, __ffs(state->head)); + + if (!WARN_ON(!head)) { + struct nvkm_head_state *state = &head->asy; + switch ((ctrl & 0x000f0000) >> 16) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX*/ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } + } + } } -static void * -nv50_disp_dtor_(struct nvkm_disp *base) +static void +nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) { - struct nv50_disp *disp = nv50_disp(base); + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + state->rgdiv = 1; + switch (state->proto_evo) { + case 0: state->proto = TMDS; break; + default: + state->proto = UNKNOWN; + break; + } - nvkm_ramht_del(&disp->ramht); - nvkm_gpuobj_del(&disp->inst); + state->head = ctrl & 0x00000003; + nv50_pior_depth(pior, state, ctrl); +} - nvkm_event_fini(&disp->uevent); - if (disp->wq) - destroy_workqueue(disp->wq); +static const struct nvkm_ior_func +nv50_pior = { + .state = nv50_pior_state, + .power = nv50_pior_power, + .clock = nv50_pior_clock, + .dp = &nv50_pior_dp, +}; - return disp; +int +nv50_pior_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_pior, disp, PIOR, id, false); } -static int -nv50_disp_oneinit_(struct nvkm_disp *base) +int +nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) { - struct nv50_disp *disp = nv50_disp(base); - const struct nv50_disp_func *func = disp->func; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ret, i; + struct nvkm_device *device = disp->engine.subdev.device; - if (func->wndw.cnt) { - disp->wndw.nr = func->wndw.cnt(&disp->base, &disp->wndw.mask); - nvkm_debug(subdev, "Window(s): %d (%08lx)\n", - disp->wndw.nr, disp->wndw.mask); + *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; + return 3; +} + +void +nv50_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const int div = sor->asy.link == 3; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); +} + +static void +nv50_sor_power_wait(struct nvkm_device *device, u32 soff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) + break; + ); +} + +void +nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000001 << shift); + + nv50_sor_power_wait(device, soff); + nvkm_mask(device, 0x61c004 + soff, field, state); + nv50_sor_power_wait(device, soff); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); +} + +void +nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + default: + state->proto = UNKNOWN; + break; } - disp->head.nr = func->head.cnt(&disp->base, &disp->head.mask); - nvkm_debug(subdev, " Head(s): %d (%02lx)\n", - disp->head.nr, disp->head.mask); - for_each_set_bit(i, &disp->head.mask, disp->head.nr) { - ret = func->head.new(&disp->base, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, +}; + +static int +nv50_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_sor, disp, SOR, id, false); +} + +int +nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; + return 2; +} + +static void +nv50_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); +} + +int +nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + dac->func->power(dac, false, true, false, false, false); + + nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); + mdelay(9); + udelay(500); + loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); + + dac->func->power(dac, false, false, false, false, false); + if (!(loadval & 0x80000000)) + return -ETIMEDOUT; + + return (loadval & 0x38000000) >> 27; +} + +static void +nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); +} + +void +nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000040 * ! pu | + 0x00000010 * ! data | + 0x00000004 * ! vsync | + 0x00000001 * ! hsync) << shift; + const u32 field = 0xc0000000 | (0x00000055 << shift); + + nv50_dac_power_wait(device, doff); + nvkm_mask(device, 0x61a004 + doff, field, state); + nv50_dac_power_wait(device, doff); +} + +static void +nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; } - if (func->dac.cnt) { - disp->dac.nr = func->dac.cnt(&disp->base, &disp->dac.mask); - nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", - disp->dac.nr, disp->dac.mask); - for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { - ret = func->dac.new(&disp->base, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_dac = { + .state = nv50_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = nv50_dac_clock, +}; + +int +nv50_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_dac, disp, DAC, id, false); +} + +int +nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; + return 3; +} + +static void +nv50_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), 0); +} + +static void +nv50_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); +} + +static void +nv50_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); +} + +void +nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; +} + +static void +nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; + u32 data; + + data = nvkm_rd32(device, 0x610ae8 + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af0 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af8 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610b00 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; +} + +static const struct nvkm_head_func +nv50_head = { + .state = nv50_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = nv50_head_rgclk, + .vblank_get = nv50_head_vblank_get, + .vblank_put = nv50_head_vblank_put, +}; + +int +nv50_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&nv50_head, disp, id); +} + +int +nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + *pmask = 3; + return 2; +} + + +static void +nv50_disp_mthd_list(struct nvkm_disp *disp, int debug, u32 base, int c, + const struct nvkm_disp_mthd_list *list, int inst) +{ + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int i; + + for (i = 0; list->data[i].mthd; i++) { + if (list->data[i].addr) { + u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); + u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); + u32 mthd = list->data[i].mthd + (list->mthd * inst); + const char *name = list->data[i].name; + char mods[16]; + + if (prev != next) + snprintf(mods, sizeof(mods), "-> %08x", next); + else + snprintf(mods, sizeof(mods), "%13c", ' '); + + nvkm_printk_(subdev, debug, info, + "\t%04x: %08x %s%s%s\n", + mthd, prev, mods, name ? " // " : "", + name ? name : ""); } } +} - if (func->pior.cnt) { - disp->pior.nr = func->pior.cnt(&disp->base, &disp->pior.mask); - nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", - disp->pior.nr, disp->pior.mask); - for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { - ret = func->pior.new(&disp->base, i); - if (ret) - return ret; +void +nv50_disp_chan_mthd(struct nvkm_disp_chan *chan, int debug) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + const struct nvkm_disp_chan_mthd *mthd = chan->mthd; + const struct nvkm_disp_mthd_list *list; + int i, j; + + if (debug > subdev->debug) + return; + if (!mthd) + return; + + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; + for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { + const char *cname = mthd->name; + const char *sname = ""; + char cname_[16], sname_[16]; + + if (mthd->addr) { + snprintf(cname_, sizeof(cname_), "%s %d", + mthd->name, chan->chid.user); + cname = cname_; + } + + if (mthd->data[i].nr > 1) { + snprintf(sname_, sizeof(sname_), " - %s %d", + mthd->data[i].name, j); + sname = sname_; + } + + nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); + nv50_disp_mthd_list(disp, debug, base, mthd->prev, + list, j); } } +} - disp->sor.nr = func->sor.cnt(&disp->base, &disp->sor.mask); - nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", - disp->sor.nr, disp->sor.mask); - for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { - ret = func->sor.new(&disp->base, i); - if (ret) - return ret; +static void +nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x610020, 0x00000001 << index); +} + +static void +nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x610020, 0x00000001 << index); + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); +} + +void +nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid) +{ + nvkm_event_send(&disp->uevent, NVKM_DISP_EVENT_CHAN_AWAKEN, chid, NULL, 0); +} + +const struct nvkm_event_func +nv50_disp_chan_uevent = { + .init = nv50_disp_chan_uevent_init, + .fini = nv50_disp_chan_uevent_fini, +}; + +u64 +nv50_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x640000 + (chan->chid.user * 0x1000); +} + +void +nv50_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010001 << chan->chid.user; + const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; + nvkm_mask(device, 0x610028, mask, data); +} + +static void +nv50_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); } +} - ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, - &disp->inst); - if (ret) - return ret; +static int +nv50_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; - return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : - 0x1000, 0, disp->inst, &disp->ramht); + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout0: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout1: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; } -static const struct nvkm_disp_func -nv50_disp_ = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, - .init = nv50_disp_init_, - .fini = nv50_disp_fini_, - .intr = nv50_disp_intr_, - .root = nv50_disp_root_, +const struct nvkm_disp_chan_func +nv50_disp_pioc_func = { + .init = nv50_disp_pioc_init, + .fini = nv50_disp_pioc_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, }; int -nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) +nv50_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) { - struct nv50_disp *disp; - int ret; + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -10, handle, + chan->chid.user << 28 | chan->chid.user); +} - if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) - return -ENOMEM; - disp->func = func; - *pdisp = &disp->base; +static void +nv50_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + } - ret = nvkm_disp_ctor(&nv50_disp_, device, type, inst, &disp->base); - if (ret) - return ret; + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +nv50_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } - disp->wq = create_singlethread_workqueue("nvkm-disp"); - if (!disp->wq) - return -ENOMEM; + return 0; +} - INIT_WORK(&disp->supervisor, func->super); +int +nv50_disp_dmac_push(struct nvkm_disp_chan *chan, u64 object) +{ + chan->memory = nvkm_umem_search(chan->object.client, object); + if (IS_ERR(chan->memory)) + return PTR_ERR(chan->memory); + + if (nvkm_memory_size(chan->memory) < 0x1000) + return -EINVAL; + + switch (nvkm_memory_target(chan->memory)) { + case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; + case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; + case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; + default: + return -EINVAL; + } - return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), - &disp->uevent); + chan->push |= nvkm_memory_addr(chan->memory) >> 8; + return 0; } +const struct nvkm_disp_chan_func +nv50_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = nv50_disp_dmac_init, + .fini = nv50_disp_dmac_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +nv50_disp_curs = { + .func = &nv50_disp_pioc_func, + .ctrl = 7, + .user = 7, +}; + +const struct nvkm_disp_chan_user +nv50_disp_oimm = { + .func = &nv50_disp_pioc_func, + .ctrl = 5, + .user = 5, +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0009a0 }, + { 0x0088, 0x0009c0 }, + { 0x008c, 0x0009c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_ovly_mthd_base }, + {} + } +}; + +static const struct nvkm_disp_chan_user +nv50_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = &nv50_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x0100, 0x610894 }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_image = { + .mthd = 0x0400, + .addr = 0x000000, + .data = { + { 0x0800, 0x6108f0 }, + { 0x0804, 0x6108fc }, + { 0x0808, 0x61090c }, + { 0x080c, 0x610914 }, + { 0x0810, 0x610904 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +static const struct nvkm_disp_chan_user +nv50_disp_base = { + .func = &nv50_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &nv50_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x610bb8 }, + { 0x0088, 0x610b9c }, + { 0x008c, 0x000000 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610828 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610b70 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_pior = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0700, 0x610b80 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &nv50_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &nv50_disp_core_mthd_head }, + {} + } +}; + +static void +nv50_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610200)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +nv50_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* attempt to unstick channel from some unknown state */ + if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) + nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); + if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) + nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204, chan->push); + nvkm_wr32(device, 0x610208, 0x00010000); + nvkm_wr32(device, 0x61020c, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610200, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610200)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +nv50_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = nv50_disp_core_init, + .fini = nv50_disp_core_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +nv50_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &nv50_disp_core_mthd, +}; + static u32 nv50_disp_super_iedt(struct nvkm_head *head, struct nvkm_outp *outp, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, @@ -278,7 +1076,7 @@ static struct nvkm_ior * nv50_disp_super_ior_asy(struct nvkm_head *head) { struct nvkm_ior *ior; - list_for_each_entry(ior, &head->disp->ior, head) { + list_for_each_entry(ior, &head->disp->iors, head) { if (ior->asy.head & (1 << head->id)) { HEAD_DBG(head, "to %s", ior->name); return ior; @@ -292,7 +1090,7 @@ static struct nvkm_ior * nv50_disp_super_ior_arm(struct nvkm_head *head) { struct nvkm_ior *ior; - list_for_each_entry(ior, &head->disp->ior, head) { + list_for_each_entry(ior, &head->disp->iors, head) { if (ior->arm.head & (1 << head->id)) { HEAD_DBG(head, "on %s", ior->name); return ior; @@ -303,7 +1101,7 @@ nv50_disp_super_ior_arm(struct nvkm_head *head) } void -nv50_disp_super_3_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_3_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_ior *ior; @@ -346,7 +1144,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) do_div(v, khz); v = v - ((36 / ior->dp.nr) + 3) - 1; - ior->func->dp.audio_sym(ior, head->id, h, v); + ior->func->dp->audio_sym(ior, head->id, h, v); /* watermark / activesym */ link_data_rate = (khz * head->asy.or.depth / 8) / ior->dp.nr; @@ -355,7 +1153,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) link_ratio = link_data_rate * symbol; do_div(link_ratio, linkKBps); - for (TU = 64; ior->func->dp.activesym && TU >= 32; TU--) { + for (TU = 64; ior->func->dp->activesym && TU >= 32; TU--) { /* calculate average number of valid symbols in each TU */ u32 tu_valid = link_ratio * TU; u32 calc, diff; @@ -406,13 +1204,13 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) } } - if (ior->func->dp.activesym) { + if (ior->func->dp->activesym) { if (!bestTU) { nvkm_error(subdev, "unable to determine dp config\n"); return; } - ior->func->dp.activesym(ior, head->id, bestTU, - bestVTUa, bestVTUf, bestVTUi); + + ior->func->dp->activesym(ior, head->id, bestTU, bestVTUa, bestVTUf, bestVTUi); } else { bestTU = 64; } @@ -424,11 +1222,11 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) do_div(unk, symbol); unk += 6; - ior->func->dp.watermark(ior, head->id, unk); + ior->func->dp->watermark(ior, head->id, unk); } void -nv50_disp_super_2_2(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) { const u32 khz = head->asy.hz / 1000; struct nvkm_outp *outp; @@ -475,9 +1273,9 @@ nv50_disp_super_2_2(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_2_1(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_1(struct nvkm_disp *disp, struct nvkm_head *head) { - struct nvkm_devinit *devinit = disp->base.engine.subdev.device->devinit; + struct nvkm_devinit *devinit = disp->engine.subdev.device->devinit; const u32 khz = head->asy.hz / 1000; HEAD_DBG(head, "supervisor 2.1 - %d khz", khz); if (khz) @@ -485,7 +1283,7 @@ nv50_disp_super_2_1(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_2_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_outp *outp; struct nvkm_ior *ior; @@ -509,7 +1307,7 @@ nv50_disp_super_2_0(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_1_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_ior *ior; @@ -524,17 +1322,17 @@ nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_1(struct nv50_disp *disp) +nv50_disp_super_1(struct nvkm_disp *disp) { struct nvkm_head *head; struct nvkm_ior *ior; - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { head->func->state(head, &head->arm); head->func->state(head, &head->asy); } - list_for_each_entry(ior, &disp->base.ior, head) { + list_for_each_entry(ior, &disp->iors, head) { ior->func->state(ior, &ior->arm); ior->func->state(ior, &ior->asy); } @@ -543,19 +1341,21 @@ nv50_disp_super_1(struct nv50_disp *disp) void nv50_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; - u32 super = nvkm_rd32(device, 0x610030); + u32 super; + + mutex_lock(&disp->super.mutex); + super = nvkm_rd32(device, 0x610030); - nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super); + nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super.pending, super); - if (disp->super & 0x00000010) { + if (disp->super.pending & 0x00000010) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000020 << head->id))) continue; if (!(super & (0x00000080 << head->id))) @@ -563,26 +1363,26 @@ nv50_disp_super(struct work_struct *work) nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000020) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000020) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000200 << head->id))) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000040) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000040) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_3_0(disp, head); @@ -590,6 +1390,7 @@ nv50_disp_super(struct work_struct *work) } nvkm_wr32(device, 0x610030, 0x80000000); + mutex_unlock(&disp->super.mutex); } const struct nvkm_enum @@ -611,9 +1412,9 @@ nv50_disp_intr_error_code[] = { }; static void -nv50_disp_intr_error(struct nv50_disp *disp, int chid) +nv50_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08)); u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08)); @@ -645,9 +1446,9 @@ nv50_disp_intr_error(struct nv50_disp *disp, int chid) } void -nv50_disp_intr(struct nv50_disp *disp) +nv50_disp_intr(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; u32 intr0 = nvkm_rd32(device, 0x610020); u32 intr1 = nvkm_rd32(device, 0x610024); @@ -664,35 +1465,35 @@ nv50_disp_intr(struct nv50_disp *disp) } if (intr1 & 0x00000004) { - nvkm_disp_vblank(&disp->base, 0); + nvkm_disp_vblank(disp, 0); nvkm_wr32(device, 0x610024, 0x00000004); } if (intr1 & 0x00000008) { - nvkm_disp_vblank(&disp->base, 1); + nvkm_disp_vblank(disp, 1); nvkm_wr32(device, 0x610024, 0x00000008); } if (intr1 & 0x00000070) { - disp->super = (intr1 & 0x00000070); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x610024, disp->super); + disp->super.pending = (intr1 & 0x00000070); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x610024, disp->super.pending); } } void -nv50_disp_fini(struct nv50_disp *disp) +nv50_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; /* disable all interrupts */ nvkm_wr32(device, 0x610024, 0x00000000); nvkm_wr32(device, 0x610020, 0x00000000); } int -nv50_disp_init(struct nv50_disp *disp) +nv50_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; u32 tmp; int i; @@ -705,7 +1506,7 @@ nv50_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x610184, tmp); /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); @@ -754,23 +1555,89 @@ nv50_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +int +nv50_disp_oneinit(struct nvkm_disp *disp) +{ + const struct nvkm_disp_func *func = disp->func; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ret, i; + + if (func->wndw.cnt) { + disp->wndw.nr = func->wndw.cnt(disp, &disp->wndw.mask); + nvkm_debug(subdev, "Window(s): %d (%08lx)\n", disp->wndw.nr, disp->wndw.mask); + } + + disp->head.nr = func->head.cnt(disp, &disp->head.mask); + nvkm_debug(subdev, " Head(s): %d (%02lx)\n", disp->head.nr, disp->head.mask); + for_each_set_bit(i, &disp->head.mask, disp->head.nr) { + ret = func->head.new(disp, i); + if (ret) + return ret; + } + + if (func->dac.cnt) { + disp->dac.nr = func->dac.cnt(disp, &disp->dac.mask); + nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", disp->dac.nr, disp->dac.mask); + for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { + ret = func->dac.new(disp, i); + if (ret) + return ret; + } + } + + if (func->pior.cnt) { + disp->pior.nr = func->pior.cnt(disp, &disp->pior.mask); + nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", disp->pior.nr, disp->pior.mask); + for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { + ret = func->pior.new(disp, i); + if (ret) + return ret; + } + } + + disp->sor.nr = func->sor.cnt(disp, &disp->sor.mask); + nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", disp->sor.nr, disp->sor.mask); + for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { + ret = func->sor.new(disp, i); + if (ret) + return ret; + } + + ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, &disp->inst); + if (ret) + return ret; + + return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : + 0x1000, 0, disp->inst, &disp->ramht); +} + +static const struct nvkm_disp_func nv50_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &nv50_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = nv50_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0, 0, NV50_DISP }, + .user = { + {{0,0,NV50_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,NV50_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,NV50_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &nv50_disp_base }, + {{0,0,NV50_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &nv50_disp_core }, + {{0,0,NV50_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, &nv50_disp_ovly }, + {} + } }; int nv50_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&nv50_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&nv50_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h deleted file mode 100644 index 025cacd7c3b0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_H__ -#define __NV50_DISP_H__ -#define nv50_disp(p) container_of((p), struct nv50_disp, base) -#include "priv.h" -struct nvkm_head; - -#include <core/enum.h> - -struct nv50_disp { - const struct nv50_disp_func *func; - struct nvkm_disp base; - - struct workqueue_struct *wq; - struct work_struct supervisor; - u32 super; - - struct nvkm_event uevent; - - struct { - unsigned long mask; - int nr; - } wndw, head, dac; - - struct { - unsigned long mask; - int nr; - u32 lvdsconf; - } sor; - - struct { - unsigned long mask; - int nr; - u8 type[3]; - } pior; - - struct nvkm_gpuobj *inst; - struct nvkm_ramht *ramht; - - struct nv50_disp_chan *chan[81]; -}; - -void nv50_disp_super_1(struct nv50_disp *); -void nv50_disp_super_1_0(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_0(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_1(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_2(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_3_0(struct nv50_disp *, struct nvkm_head *); - -int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_disp **); - -struct nv50_disp_func { - int (*init)(struct nv50_disp *); - void (*fini)(struct nv50_disp *); - void (*intr)(struct nv50_disp *); - void (*intr_error)(struct nv50_disp *, int chid); - - const struct nvkm_event_func *uevent; - void (*super)(struct work_struct *); - - const struct nvkm_disp_oclass *root; - - struct { - int (*cnt)(struct nvkm_disp *, unsigned long *mask); - int (*new)(struct nvkm_disp *, int id); - } wndw, head, dac, sor, pior; - - u16 ramht_size; -}; - -int nv50_disp_init(struct nv50_disp *); -void nv50_disp_fini(struct nv50_disp *); -void nv50_disp_intr(struct nv50_disp *); -void nv50_disp_super(struct work_struct *); -extern const struct nvkm_enum nv50_disp_intr_error_type[]; - -int gf119_disp_init(struct nv50_disp *); -void gf119_disp_fini(struct nv50_disp *); -void gf119_disp_intr(struct nv50_disp *); -void gf119_disp_super(struct work_struct *); -void gf119_disp_intr_error(struct nv50_disp *, int); - -void gv100_disp_fini(struct nv50_disp *); -void gv100_disp_intr(struct nv50_disp *); -void gv100_disp_super(struct work_struct *); -int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *); - -int tu102_disp_init(struct nv50_disp *); - -void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *); -void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *); -void nv50_disp_update_sppll1(struct nv50_disp *); - -extern const struct nvkm_event_func nv50_disp_chan_uevent; -int nv50_disp_chan_uevent_ctor(struct nvkm_object *, void *, u32, - struct nvkm_notify *); -void nv50_disp_chan_uevent_send(struct nv50_disp *, int); - -extern const struct nvkm_event_func gf119_disp_chan_uevent; -extern const struct nvkm_event_func gv100_disp_chan_uevent; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c deleted file mode 100644 index 1ae0bcfc89b9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 9, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c deleted file mode 100644 index 30ffb1008505..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c deleted file mode 100644 index 0db99bfe9db9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507b.h> -#include <nvif/unpack.h> - -int -nv50_disp_oimm_new_(const struct nv50_disp_chan_func *func, - struct nv50_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp overlay size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&nv50_disp_pioc_func, disp, 5, 5, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c index 129982fef7ef..6094805fbd63 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c @@ -35,7 +35,7 @@ nvkm_outp_route(struct nvkm_disp *disp) struct nvkm_outp *outp; struct nvkm_ior *ior; - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if ((outp = ior->arm.outp) && ior->arm.outp != ior->asy.outp) { OUTP_DBG(outp, "release %s", ior->name); if (ior->func->route.set) @@ -44,7 +44,7 @@ nvkm_outp_route(struct nvkm_disp *disp) } } - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if ((outp = ior->asy.outp)) { OUTP_DBG(outp, "acquire %s", ior->name); if (ior->asy.outp != ior->arm.outp) { @@ -119,8 +119,8 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, struct nvkm_ior *ior; /* Failing that, a completely unused OR is the next best thing. */ - list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && !!ior->func->hda.hpd == hda && + list_for_each_entry(ior, &outp->disp->iors, head) { + if (!ior->identity && ior->hda == hda && !ior->asy.outp && ior->type == type && !ior->arm.outp && (ior->func->route.set || ior->id == __ffs(outp->info.or))) return nvkm_outp_acquire_ior(outp, user, ior); @@ -129,8 +129,8 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, /* Last resort is to assign an OR that's already active on HW, * but will be released during the next modeset. */ - list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && !!ior->func->hda.hpd == hda && + list_for_each_entry(ior, &outp->disp->iors, head) { + if (!ior->identity && ior->hda == hda && !ior->asy.outp && ior->type == type && (ior->func->route.set || ior->id == __ffs(outp->info.or))) return nvkm_outp_acquire_ior(outp, user, ior); @@ -168,7 +168,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) /* First preference is to reuse the OR that is currently armed * on HW, if any, in order to prevent unnecessary switching. */ - list_for_each_entry(ior, &outp->disp->ior, head) { + list_for_each_entry(ior, &outp->disp->iors, head) { if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) { /*XXX: For various complicated reasons, we can't outright switch * the boot-time OR on the first modeset without some fairly @@ -181,7 +181,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) * * This warning is to make it obvious if that proves wrong. */ - WARN_ON(hda && !ior->func->hda.hpd); + WARN_ON(hda && !ior->hda); return nvkm_outp_acquire_ior(outp, user, ior); } } @@ -294,13 +294,17 @@ nvkm_outp_del(struct nvkm_outp **poutp) } int -nvkm_outp_ctor(const struct nvkm_outp_func *func, struct nvkm_disp *disp, - int index, struct dcb_output *dcbE, struct nvkm_outp *outp) +nvkm_outp_new_(const struct nvkm_outp_func *func, struct nvkm_disp *disp, + int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; + struct nvkm_outp *outp; enum nvkm_ior_proto proto; enum nvkm_ior_type type; + if (!(outp = *poutp = kzalloc(sizeof(*outp), GFP_KERNEL))) + return -ENOMEM; + outp->func = func; outp->disp = disp; outp->index = index; @@ -330,7 +334,5 @@ int nvkm_outp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { - if (!(*poutp = kzalloc(sizeof(**poutp), GFP_KERNEL))) - return -ENOMEM; - return nvkm_outp_ctor(&nvkm_outp, disp, index, dcbE, *poutp); + return nvkm_outp_new_(&nvkm_outp, disp, index, dcbE, poutp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index ee028d30cfe7..3f3924c41957 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -1,10 +1,12 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_OUTP_H__ #define __NVKM_DISP_OUTP_H__ -#include <engine/disp.h> +#include "priv.h" +#include <core/notify.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> +#include <subdev/bios/dp.h> struct nvkm_outp { const struct nvkm_outp_func *func; @@ -23,12 +25,41 @@ struct nvkm_outp { #define NVKM_OUTP_USER 2 u8 acquired:2; struct nvkm_ior *ior; + + union { + struct { + struct nvbios_dpout info; + u8 version; + + struct nvkm_i2c_aux *aux; + + struct nvkm_notify hpd; + bool present; + u8 lttpr[6]; + u8 lttprs; + u8 dpcd[16]; + + struct { + int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */ + u32 rate; + } rate[8]; + int rates; + int links; + + struct mutex mutex; + struct { + atomic_t done; + bool mst; + } lt; + } dp; + }; + + struct nvkm_object object; }; -int nvkm_outp_ctor(const struct nvkm_outp_func *, struct nvkm_disp *, - int index, struct dcb_output *, struct nvkm_outp *); -int nvkm_outp_new(struct nvkm_disp *, int index, struct dcb_output *, - struct nvkm_outp **); +int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index, + struct dcb_output *, struct nvkm_outp **); +int nvkm_outp_new(struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_outp **); void nvkm_outp_del(struct nvkm_outp **); void nvkm_outp_init(struct nvkm_outp *); void nvkm_outp_fini(struct nvkm_outp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c deleted file mode 100644 index 31b915d48699..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_ovly_mthd_base }, - {} - } -}; - -int -g84_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &g84_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c deleted file mode 100644 index 83fd534c44da..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_ovly_mthd_base }, - {} - } -}; - -int -gf119_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gf119_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c deleted file mode 100644 index a7acacbc92c1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00c4, 0x6650c4 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0404, 0x665404 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gk104_disp_ovly_mthd_base }, - {} - } -}; - -int -gk104_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c deleted file mode 100644 index e0eca6ea914c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gp102_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gp102_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c deleted file mode 100644 index dc60cd00dc16..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gt200_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00b0, 0x610c98 }, - { 0x00b4, 0x610ca4 }, - { 0x00b8, 0x610cac }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gt200_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, >200_disp_ovly_mthd_base }, - {} - } -}; - -int -gt200_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, >200_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c deleted file mode 100644 index 6974c12c4518..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507e.h> -#include <nvif/unpack.h> - -int -nv50_disp_ovly_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp overlay channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0009a0 }, - { 0x0088, 0x0009c0 }, - { 0x008c, 0x0009c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_ovly_mthd_base }, - {} - } -}; - -int -nv50_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &nv50_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c deleted file mode 100644 index 5296e7bee813..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <subdev/timer.h> - -static void -gf119_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } -} - -static int -gf119_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* activate channel */ - nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_pioc_func = { - .init = gf119_disp_pioc_init, - .fini = gf119_disp_pioc_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c deleted file mode 100644 index 4faed6fce682..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <subdev/timer.h> - -static void -nv50_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } -} - -static int -nv50_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout0: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout1: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_pioc_func = { - .init = nv50_disp_pioc_init, - .fini = nv50_disp_pioc_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c deleted file mode 100644 index e997a207f546..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" -#include "head.h" - -#include <subdev/i2c.h> -#include <subdev/timer.h> - -static void -nv50_pior_clock(struct nvkm_ior *pior) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); -} - -static int -nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) -{ - int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, - pior->dp.ef); - if (ret) - return ret; - return 1; -} - -static void -nv50_pior_power_wait(struct nvkm_device *device, u32 poff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) - break; - ); -} - -static void -nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000101 << shift); - - nv50_pior_power_wait(device, poff); - nvkm_mask(device, 0x61e004 + poff, field, state); - nv50_pior_power_wait(device, poff); -} - -void -nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) -{ - /* GF119 moves this information to per-head methods, which is - * a lot more convenient, and where our shared code expect it. - */ - if (state->head && state == &ior->asy) { - struct nvkm_head *head = - nvkm_head_find(ior->disp, __ffs(state->head)); - if (!WARN_ON(!head)) { - struct nvkm_head_state *state = &head->asy; - switch ((ctrl & 0x000f0000) >> 16) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX*/ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } - } - } -} - -static void -nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - state->rgdiv = 1; - switch (state->proto_evo) { - case 0: state->proto = TMDS; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(pior, state, ctrl); -} - -static const struct nvkm_ior_func -nv50_pior = { - .state = nv50_pior_state, - .power = nv50_pior_power, - .clock = nv50_pior_clock, - .dp = { - .links = nv50_pior_dp_links, - }, -}; - -int -nv50_pior_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_pior, disp, PIOR, id); -} - -int -nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index ec57d8b6bce9..cb25dfe849f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -1,8 +1,12 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_PRIV_H__ #define __NVKM_DISP_PRIV_H__ +#define nvkm_udisp(p) container_of((p), struct nvkm_disp, client.object) #include <engine/disp.h> -#include "outp.h" +#include <core/enum.h> +struct nvkm_head; +struct nvkm_outp; +struct dcb_output; int nvkm_disp_ctor(const struct nvkm_disp_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_disp *); @@ -11,22 +15,75 @@ int nvkm_disp_new_(const struct nvkm_disp_func *, struct nvkm_device *, enum nvk void nvkm_disp_vblank(struct nvkm_disp *, int head); struct nvkm_disp_func { - void *(*dtor)(struct nvkm_disp *); int (*oneinit)(struct nvkm_disp *); int (*init)(struct nvkm_disp *); void (*fini)(struct nvkm_disp *); void (*intr)(struct nvkm_disp *); + void (*intr_error)(struct nvkm_disp *, int chid); - const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *); + void (*super)(struct work_struct *); + + const struct nvkm_event_func *uevent; + + struct { + int (*cnt)(struct nvkm_disp *, unsigned long *mask); + int (*new)(struct nvkm_disp *, int id); + } wndw, head, dac, sor, pior; + + u16 ramht_size; + + const struct nvkm_sclass root; + + struct nvkm_disp_user { + struct nvkm_sclass base; + int (*ctor)(const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); + const struct nvkm_disp_chan_user *chan; + } user[]; }; int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); +int nv04_disp_mthd(struct nvkm_object *, u32, void *, u32); +int nv50_disp_root_mthd_(struct nvkm_object *, u32, void *, u32); -extern const struct nvkm_disp_oclass nv04_disp_root_oclass; +int nv50_disp_oneinit(struct nvkm_disp *); +int nv50_disp_init(struct nvkm_disp *); +void nv50_disp_fini(struct nvkm_disp *); +void nv50_disp_intr(struct nvkm_disp *); +extern const struct nvkm_enum nv50_disp_intr_error_type[]; +void nv50_disp_super(struct work_struct *); +void nv50_disp_super_1(struct nvkm_disp *); +void nv50_disp_super_1_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_1(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_2(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_3_0(struct nvkm_disp *, struct nvkm_head *); -struct nvkm_disp_oclass { - int (*ctor)(struct nvkm_disp *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); - struct nvkm_sclass base; -}; +int gf119_disp_init(struct nvkm_disp *); +void gf119_disp_fini(struct nvkm_disp *); +void gf119_disp_intr(struct nvkm_disp *); +void gf119_disp_super(struct work_struct *); +void gf119_disp_intr_error(struct nvkm_disp *, int); + +void gv100_disp_fini(struct nvkm_disp *); +void gv100_disp_intr(struct nvkm_disp *); +void gv100_disp_super(struct work_struct *); +int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *); +int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); + +int tu102_disp_init(struct nvkm_disp *); + +void nv50_disp_dptmds_war_2(struct nvkm_disp *, struct dcb_output *); +void nv50_disp_dptmds_war_3(struct nvkm_disp *, struct dcb_output *); +void nv50_disp_update_sppll1(struct nvkm_disp *); + +extern const struct nvkm_event_func nv50_disp_chan_uevent; +void nv50_disp_chan_uevent_send(struct nvkm_disp *, int); + +extern const struct nvkm_event_func gf119_disp_chan_uevent; +extern const struct nvkm_event_func gv100_disp_chan_uevent; + +int nvkm_udisp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_uconn_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_uoutp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c deleted file mode 100644 index 1ed371fd7ddf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -g84_disp_root = { - .user = { - {{0,0,G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,G82_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,G82_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, - {{0,0,G82_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, - {} - }, -}; - -static int -g84_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&g84_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -g84_disp_root_oclass = { - .base.oclass = G82_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = g84_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c deleted file mode 100644 index fe011165dc02..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gf119_disp_root = { - .user = { - {{0,0,GF110_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GF110_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GF110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GF110_DISP_CORE_CHANNEL_DMA }, gf119_disp_core_new }, - {{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, gf119_disp_ovly_new }, - {} - }, -}; - -static int -gf119_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gf119_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gf119_disp_root_oclass = { - .base.oclass = GF110_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gf119_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c deleted file mode 100644 index 9e8ffd348b50..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gk104_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK104_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GK104_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gk104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gk104_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gk104_disp_root_oclass = { - .base.oclass = GK104_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gk104_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c deleted file mode 100644 index dc85cc1c9490..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gk110_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GK110_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gk110_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gk110_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gk110_disp_root_oclass = { - .base.oclass = GK110_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gk110_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c deleted file mode 100644 index e0181ca08840..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gm107_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GM107_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gm107_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gm107_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gm107_disp_root_oclass = { - .base.oclass = GM107_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gm107_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c deleted file mode 100644 index e5e590e19f62..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gm200_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GM200_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gm200_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gm200_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gm200_disp_root_oclass = { - .base.oclass = GM200_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gm200_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c deleted file mode 100644 index 762a1a922e05..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gp100_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GP100_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gp100_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gp100_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gp100_disp_root_oclass = { - .base.oclass = GP100_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gp100_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c deleted file mode 100644 index c7f00946c9af..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gp102_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gp102_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gp102_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gp102_disp_base_new }, - {{0,0,GP102_DISP_CORE_CHANNEL_DMA }, gp102_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gp102_disp_ovly_new }, - {} - }, -}; - -static int -gp102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gp102_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gp102_disp_root_oclass = { - .base.oclass = GP102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gp102_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c deleted file mode 100644 index a6963654087c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gt200_disp_root = { - .user = { - {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT200_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, - {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, - {} - }, -}; - -static int -gt200_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(>200_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gt200_disp_root_oclass = { - .base.oclass = GT200_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gt200_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c deleted file mode 100644 index 4fe0a3ae8891..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gt215_disp_root = { - .user = { - {{0,0,GT214_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,GT214_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, - {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, - {} - }, -}; - -static int -gt215_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(>215_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gt215_disp_root_oclass = { - .base.oclass = GT214_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gt215_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c deleted file mode 100644 index 47efb48d769a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gv100_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,GV100_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,GV100_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,GV100_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,GV100_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -gv100_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gv100_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gv100_disp_root_oclass = { - .base.oclass = GV100_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gv100_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c index 7f3e2554a83d..9acaec5c271e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c @@ -21,25 +21,18 @@ * * Authors: Ben Skeggs */ -#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object) #include "priv.h" #include "head.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl0046.h> #include <nvif/unpack.h> -struct nv04_disp_root { - struct nvkm_object object; - struct nvkm_disp *disp; -}; - -static int +int nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { - struct nv04_disp_root *root = nv04_disp_root(object); + struct nvkm_disp *disp = nvkm_disp(object->engine); union { struct nv04_disp_mthd_v0 v0; } *args = data; @@ -55,7 +48,7 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!(head = nvkm_head_find(root->disp, id))) + if (!(head = nvkm_head_find(disp, id))) return -ENXIO; switch (mthd) { @@ -67,32 +60,3 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } - -static const struct nvkm_object_func -nv04_disp_root = { - .mthd = nv04_disp_mthd, - .ntfy = nvkm_disp_ntfy, -}; - -static int -nv04_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nv04_disp_root *root; - - if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) - return -ENOMEM; - root->disp = disp; - *pobject = &root->object; - - nvkm_object_ctor(&nv04_disp_root, oclass, &root->object); - return 0; -} - -const struct nvkm_disp_oclass -nv04_disp_root_oclass = { - .base.oclass = NV04_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = nv04_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index ecde98dd2454..0af45ccd140c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -21,11 +21,10 @@ * * Authors: Ben Skeggs */ -#include "rootnv50.h" -#include "channv50.h" -#include "dp.h" +#include "chan.h" #include "head.h" #include "ior.h" +#include "outp.h" #include <core/client.h> @@ -33,15 +32,14 @@ #include <nvif/cl5070.h> #include <nvif/unpack.h> -static int +int nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) { union { struct nv50_disp_mthd_v0 v0; struct nv50_disp_mthd_v1 v1; } *args = data; - struct nv50_disp_root *root = nv50_disp_root(object); - struct nv50_disp *disp = root->disp; + struct nvkm_disp *disp = nvkm_udisp(object); struct nvkm_outp *temp, *outp = NULL; struct nvkm_head *head; u16 type, mask = 0; @@ -69,11 +67,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!(head = nvkm_head_find(&disp->base, hidx))) + if (!(head = nvkm_head_find(disp, hidx))) return -ENXIO; if (mask) { - list_for_each_entry(temp, &disp->base.outp, head) { + list_for_each_entry(temp, &disp->outps, head) { if ((temp->info.hasht == type) && (temp->info.hashm & mask) == mask) { outp = temp; @@ -111,27 +109,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) case NV50_DISP_MTHD_V1_RELEASE: nvkm_outp_release(outp, NVKM_OUTP_USER); return 0; - case NV50_DISP_MTHD_V1_DAC_LOAD: { - union { - struct nv50_disp_dac_load_v0 v0; - } *args = data; - int ret = -ENOSYS; - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - if (args->v0.data & 0xfff00000) - return -EINVAL; - ret = nvkm_outp_acquire(outp, NVKM_OUTP_PRIV, false); - if (ret) - return ret; - ret = outp->ior->func->sense(outp->ior, args->v0.data); - nvkm_outp_release(outp, NVKM_OUTP_PRIV); - if (ret < 0) - return ret; - args->v0.load = ret; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_HDA_ELD: { union { struct nv50_disp_sor_hda_eld_v0 v0; @@ -148,18 +125,18 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!ior->func->hda.hpd) + if (!ior->hda) return -ENODEV; if (size && args->v0.data[0]) { if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp.audio(ior, hidx, true); - ior->func->hda.hpd(ior, hidx, true); - ior->func->hda.eld(ior, hidx, data, size); + ior->func->dp->audio(ior, hidx, true); + ior->func->hda->hpd(ior, hidx, true); + ior->func->hda->eld(ior, hidx, data, size); } else { if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp.audio(ior, hidx, false); - ior->func->hda.hpd(ior, hidx, false); + ior->func->dp->audio(ior, hidx, false); + ior->func->hda->hpd(ior, hidx, false); } return 0; @@ -227,7 +204,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } break; case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { - struct nvkm_dp *dp = nvkm_dp(outp); union { struct nv50_disp_sor_dp_mst_link_v0 v0; } *args = data; @@ -236,7 +212,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n", args->v0.version, args->v0.state); - dp->lt.mst = !!args->v0.state; + outp->dp.lt.mst = !!args->v0.state; return 0; } else return ret; @@ -254,9 +230,9 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) args->v0.version, args->v0.start_slot, args->v0.num_slots, args->v0.pbn, args->v0.aligned_pbn); - if (!outp->ior->func->dp.vcpi) + if (!outp->ior->func->dp->vcpi) return -ENODEV; - outp->ior->func->dp.vcpi(outp->ior, hidx, + outp->ior->func->dp->vcpi(outp->ior, hidx, args->v0.start_slot, args->v0.num_slots, args->v0.pbn, @@ -272,89 +248,3 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } - -static int -nv50_disp_root_child_new_(const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nv50_disp *disp = nv50_disp_root(oclass->parent)->disp; - const struct nv50_disp_user *user = oclass->priv; - return user->ctor(oclass, argv, argc, disp, pobject); -} - -static int -nv50_disp_root_child_get_(struct nvkm_object *object, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - - if (root->func->user[index].ctor) { - sclass->base = root->func->user[index].base; - sclass->priv = root->func->user + index; - sclass->ctor = nv50_disp_root_child_new_; - return 0; - } - - return -EINVAL; -} - -static void * -nv50_disp_root_dtor_(struct nvkm_object *object) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - return root; -} - -static const struct nvkm_object_func -nv50_disp_root_ = { - .dtor = nv50_disp_root_dtor_, - .mthd = nv50_disp_root_mthd_, - .ntfy = nvkm_disp_ntfy, - .sclass = nv50_disp_root_child_get_, -}; - -int -nv50_disp_root_new_(const struct nv50_disp_root_func *func, - struct nvkm_disp *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nv50_disp *disp = nv50_disp(base); - struct nv50_disp_root *root; - - if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) - return -ENOMEM; - *pobject = &root->object; - - nvkm_object_ctor(&nv50_disp_root_, oclass, &root->object); - root->func = func; - root->disp = disp; - return 0; -} - -static const struct nv50_disp_root_func -nv50_disp_root = { - .user = { - {{0,0,NV50_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,NV50_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,NV50_DISP_BASE_CHANNEL_DMA }, nv50_disp_base_new }, - {{0,0,NV50_DISP_CORE_CHANNEL_DMA }, nv50_disp_core_new }, - {{0,0,NV50_DISP_OVERLAY_CHANNEL_DMA}, nv50_disp_ovly_new }, - {} - }, -}; - -static int -nv50_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&nv50_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -nv50_disp_root_oclass = { - .base.oclass = NV50_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = nv50_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h deleted file mode 100644 index 27bb170d0293..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_ROOT_H__ -#define __NV50_DISP_ROOT_H__ -#define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object) -#include <core/object.h> -#include "nv50.h" - -struct nv50_disp_root { - const struct nv50_disp_root_func *func; - struct nv50_disp *disp; - struct nvkm_object object; -}; - -struct nv50_disp_root_func { - int blah; - struct nv50_disp_user { - struct nvkm_sclass base; - int (*ctor)(const struct nvkm_oclass *, void *argv, u32 argc, - struct nv50_disp *, struct nvkm_object **); - } user[]; -}; - -int nv50_disp_root_new_(const struct nv50_disp_root_func *, struct nvkm_disp *, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); - -int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -extern const struct nvkm_disp_oclass nv50_disp_root_oclass; -extern const struct nvkm_disp_oclass g84_disp_root_oclass; -extern const struct nvkm_disp_oclass g94_disp_root_oclass; -extern const struct nvkm_disp_oclass gt200_disp_root_oclass; -extern const struct nvkm_disp_oclass gt215_disp_root_oclass; -extern const struct nvkm_disp_oclass gf119_disp_root_oclass; -extern const struct nvkm_disp_oclass gk104_disp_root_oclass; -extern const struct nvkm_disp_oclass gk110_disp_root_oclass; -extern const struct nvkm_disp_oclass gm107_disp_root_oclass; -extern const struct nvkm_disp_oclass gm200_disp_root_oclass; -extern const struct nvkm_disp_oclass gp100_disp_root_oclass; -extern const struct nvkm_disp_oclass gp102_disp_root_oclass; -extern const struct nvkm_disp_oclass gv100_disp_root_oclass; -extern const struct nvkm_disp_oclass tu102_disp_root_oclass; -extern const struct nvkm_disp_oclass ga102_disp_root_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c deleted file mode 100644 index d8719d38b98a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -tu102_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,TU102_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,TU102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,TU102_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,TU102_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -tu102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&tu102_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -tu102_disp_root_oclass = { - .base.oclass = TU102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = tu102_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c deleted file mode 100644 index ec3a7db08118..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -static const struct nvkm_ior_func -g84_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, -}; - -int -g84_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g84_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c deleted file mode 100644 index 56b8f4411988..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); -} - -void -g94_sor_dp_activesym(struct nvkm_ior *sor, int head, - u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); - nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | - VTUf << 16 | - VTUi << 8); -} - -void -g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); - nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); -} - -void -g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[3]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); -} - -void -g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x00001000; break; - case 1: data = 0x01000000; break; - case 2: data = 0x02000000; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); -} - -void -g94_sor_dp_power(struct nvkm_ior *sor, int nr) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 mask = 0, i; - - for (i = 0; i < nr; i++) - mask |= 1 << sor->func->dp.lanes[i]; - - nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); - nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) - break; - ); -} - -int -g94_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.ef) - dpctrl |= 0x00004000; - if (sor->dp.bw > 0x06) - clksor |= 0x00040000; - - nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); - nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); - return 0; -} - -static bool -g94_sor_war_needed(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - if (sor->asy.proto == TMDS) { - switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { - case 0x00000000: - case 0x00030000: - return true; - default: - break; - } - } - return false; -} - -static void -g94_sor_war_update_sppll1(struct nvkm_disp *disp) -{ - struct nvkm_device *device = disp->engine.subdev.device; - struct nvkm_ior *ior; - bool used = false; - u32 clksor; - - list_for_each_entry(ior, &disp->ior, head) { - if (ior->type != SOR) - continue; - - clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); - switch (clksor & 0x03000000) { - case 0x02000000: - case 0x03000000: - used = true; - break; - default: - break; - } - } - - if (used) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); -} - -static void -g94_sor_war_3(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 sorpwr; - - if (!g94_sor_war_needed(sor)) - return; - - sorpwr = nvkm_rd32(device, 0x61c004 + soff); - if (sorpwr & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pd_pc = (seqctl & 0x00000f00) >> 8; - u32 pu_pc = seqctl & 0x0000000f; - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); - } - - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); - - if (sorpwr & 0x00000001) { - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); - } - - g94_sor_war_update_sppll1(sor->disp); -} - -static void -g94_sor_war_2(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - - if (!g94_sor_war_needed(sor)) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); - - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); - nvkm_usec(device, 400, NVKM_DELAY); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); - - if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pu_pc = seqctl & 0x0000000f; - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); - } -} - -void -g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610794 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(sor, state, ctrl); -} - -static const struct nvkm_ior_func -g94_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .war_2 = g94_sor_war_2, - .war_3 = g94_sor_war_3, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -g94_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g94_sor, disp, SOR, id); -} - -int -g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c deleted file mode 100644 index d2c05f5c4aa0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2021 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 "ior.h" - -#include <subdev/timer.h> - -static int -ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - switch (sor->dp.bw) { - case 0x06: clksor |= 0x00000000; break; - case 0x0a: clksor |= 0x00040000; break; - case 0x14: clksor |= 0x00080000; break; - case 0x1e: clksor |= 0x000c0000; break; - case 0x08: clksor |= 0x00100000; break; - case 0x09: clksor |= 0x00140000; break; - case 0x0c: clksor |= 0x00180000; break; - case 0x10: clksor |= 0x001c0000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - - /*XXX*/ - nvkm_msec(device, 40, NVKM_DELAY); - nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); - nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); - - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -static void -ga102_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - u32 div2 = 0; - if (sor->asy.proto == TMDS) { - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); - nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); -} - -static const struct nvkm_ior_func -ga102_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -ga102_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -ga102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&ga102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&ga102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c deleted file mode 100644 index c431e0b9fc11..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); -} - -void -gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); -} - -void -gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616618 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) - break; - ); -} - -void -gf119_sor_dp_vcpi(struct nvkm_ior *sor, int head, - u8 slot, u8 slot_nr, u16 pbn, u16 aligned) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - - nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); - nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); -} - -void -gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); -} - -int -gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - clksor |= sor->dp.bw << 18; - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -void -gf119_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 div1 = sor->asy.link == 3; - u32 div2 = sor->asy.link == 3; - if (sor->asy.proto == TMDS) { - const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; - nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); -} - -void -gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640200 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gf119_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gf119_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_sor, disp, SOR, id); -} - -int -gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; - return 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c deleted file mode 100644 index 0c0925680790..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -static const struct nvkm_ior_func -gk104_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gk104_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gk104_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c deleted file mode 100644 index 3696bfd3bfd7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "ior.h" - -void -gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 mask = 0x1f1f1f1f, data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - case 4: data = 0x1b1b1b1b; break; - default: - WARN_ON(1); - return; - } - - if (sor->asy.link & 1) - nvkm_mask(device, 0x61c110 + soff, mask, data); - else - nvkm_mask(device, 0x61c12c + soff, mask, data); -} - -static const struct nvkm_ior_func -gm107_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gm107_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gm107_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c deleted file mode 100644 index 4dd7f382968e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - pu &= 0x0f; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x00000f00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const u32 moff = __ffs(outp->info.or) * 0x100; - const u32 sor = ior ? ior->id + 1 : 0; - u32 link = ior ? (ior->asy.link == 2) : 0; - - if (outp->info.sorconf.link & 1) { - nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); - link++; - } - - if (outp->info.sorconf.link & 2) - nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); -} - -int -gm200_sor_route_get(struct nvkm_outp *outp, int *link) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const int sublinks = outp->info.sorconf.link; - int lnk[2], sor[2], m, s; - - for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { - if (sublinks & BIT(s)) { - u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); - lnk[s] = (data & 0x00000010) >> 4; - sor[s] = (data & 0x0000000f); - if (!sor[s]) - return -1; - *link |= lnk[s]; - } - } - - if (sublinks == 3) { - if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) - return -1; - } - - return ((sublinks & 1) ? sor[0] : sor[1]) - 1; -} - -static const struct nvkm_ior_func -gm200_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gm200_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gm200_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x101034); - - if (hda & BIT(id)) - return nvkm_ior_new_(&gm200_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gm200_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c deleted file mode 100644 index c54f88317a07..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 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 "ior.h" - -static const struct nvkm_ior_func -gp100_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gp100_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gp100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x10ebb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gp100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gp100_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c deleted file mode 100644 index 54d134d4ca1d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -#include <subdev/timer.h> - -void -gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x61c1e0 + soff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) - break; - ); -} - -static const struct nvkm_ior_func -gt215_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -gt215_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(>215_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c deleted file mode 100644 index 4441187e8ec9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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 "ior.h" - -#include <subdev/timer.h> - -void -gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); -} - -void -gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); -} - -void -gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616560 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) - break; - ); -} - -void -gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x680300 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x000000ff; -} - -static const struct nvkm_ior_func -gv100_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gv100_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -gv100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x118fb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gv100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gv100_sor, disp, SOR, id); -} - -int -gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; - return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c deleted file mode 100644 index 8a70dd25b13a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -static const struct nvkm_ior_func -mcp77_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -mcp77_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp77_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c deleted file mode 100644 index eac9c5be9166..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 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 "ior.h" - -static const struct nvkm_ior_func -mcp89_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 3, 2, 1, 0 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -mcp89_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp89_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c deleted file mode 100644 index b4729f8798af..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -nv50_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const int div = sor->asy.link == 3; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); -} - -static void -nv50_sor_power_wait(struct nvkm_device *device, u32 soff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) - break; - ); -} - -void -nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000001 << shift); - - nv50_sor_power_wait(device, soff); - nvkm_mask(device, 0x61c004 + soff, field, state); - nv50_sor_power_wait(device, soff); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); -} - -void -nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, -}; - -int -nv50_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_sor, disp, SOR, id); -} - -int -nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c deleted file mode 100644 index 0cf9e8752d25..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 "ior.h" - -#include <subdev/timer.h> - -void -tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, - u8 slot, u8 slot_nr, u16 pbn, u16 aligned) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - - nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn); - nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot); -} - -static int -tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - clksor |= sor->dp.bw << 18; - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - - /*XXX*/ - nvkm_msec(device, 40, NVKM_DELAY); - nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); - nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); - - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -static const struct nvkm_ior_func -tu102_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -tu102_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -tu102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&tu102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&tu102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c index f5f8dc8e8f35..e4ad1a6f6c88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -19,19 +19,96 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "chan.h" +#include "priv.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" #include <core/gpuobj.h> #include <subdev/timer.h> +#include <nvif/class.h> + +void +tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn); + nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot); +} + +static int +tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + clksor |= sor->dp.bw << 18; + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + + /*XXX*/ + nvkm_msec(device, 40, NVKM_DELAY); + nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); + nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); + + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +static const struct nvkm_ior_func_dp +tu102_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = tu102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +tu102_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &tu102_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +tu102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + + return nvkm_ior_new_(&tu102_sor, disp, SOR, id, hda & BIT(id)); +} + int -tu102_disp_init(struct nv50_disp *disp) +tu102_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; int i, j; u32 tmp; @@ -58,7 +135,7 @@ tu102_disp_init(struct nv50_disp *disp) } /* Head capabilities. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const int id = head->id; /* RG. */ @@ -119,7 +196,7 @@ tu102_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */ /* HEAD_TIMING(n): VBLANK. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 4; nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */ nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */ @@ -131,23 +208,32 @@ tu102_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func tu102_disp = { + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &tu102_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = tu102_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,TU102_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,TU102_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,TU102_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,TU102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,TU102_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int tu102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&tu102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&tu102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c new file mode 100644 index 000000000000..fd9f18144c26 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -0,0 +1,117 @@ +/* + * Copyright 2021 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. + */ +#define nvkm_uconn(p) container_of((p), struct nvkm_conn, object) +#include "conn.h" + +#include <subdev/gpio.h> + +#include <nvif/if0011.h> + +static int +nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc) +{ + struct nvkm_gpio *gpio = conn->disp->engine.subdev.device->gpio; + union nvif_conn_hpd_status_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + args->v0.support = gpio && conn->info.hpd != DCB_GPIO_UNUSED; + args->v0.present = 0; + + if (args->v0.support) { + int ret = nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->info.hpd); + + if (WARN_ON(ret < 0)) { + args->v0.support = false; + return 0; + } + + args->v0.present = ret; + } + + return 0; +} + +static int +nvkm_uconn_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + + switch (mthd) { + case NVIF_CONN_V0_HPD_STATUS: return nvkm_uconn_mthd_hpd_status(conn, argv, argc); + default: + break; + } + + return -EINVAL; +} + +static void * +nvkm_uconn_dtor(struct nvkm_object *object) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + struct nvkm_disp *disp = conn->disp; + + spin_lock(&disp->client.lock); + conn->object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_uconn = { + .dtor = nvkm_uconn_dtor, + .mthd = nvkm_uconn_mthd, +}; + +int +nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct nvkm_conn *cont, *conn = NULL; + union nvif_conn_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + list_for_each_entry(cont, &disp->conns, head) { + if (cont->index == args->v0.id) { + conn = cont; + break; + } + } + + if (!conn) + return -EINVAL; + + ret = -EBUSY; + spin_lock(&disp->client.lock); + if (!conn->object.func) { + nvkm_object_ctor(&nvkm_uconn, oclass, &conn->object); + *pobject = &conn->object; + ret = 0; + } + spin_unlock(&disp->client.lock); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c new file mode 100644 index 000000000000..0841e7ce0343 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c @@ -0,0 +1,115 @@ +/* + * Copyright 2021 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 "priv.h" +#include "conn.h" +#include "outp.h" + +#include <nvif/class.h> +#include <nvif/if0010.h> + +static int +nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *sclass) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + if (index-- == 0) { + sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_CONN }; + sclass->ctor = nvkm_uconn_new; + return 0; + } + + if (index-- == 0) { + sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_OUTP }; + sclass->ctor = nvkm_uoutp_new; + return 0; + } + + if (disp->func->user[index].ctor) { + sclass->base = disp->func->user[index].base; + sclass->ctor = disp->func->user[index].ctor; + return 0; + } + + return -EINVAL; +} + +static int +nvkm_udisp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + if (disp->engine.subdev.device->card_type >= NV_50) + return nv50_disp_root_mthd_(object, mthd, argv, argc); + + return nv04_disp_mthd(object, mthd, argv, argc); +} + +static void * +nvkm_udisp_dtor(struct nvkm_object *object) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + spin_lock(&disp->client.lock); + if (object == &disp->client.object) + disp->client.object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_udisp = { + .dtor = nvkm_udisp_dtor, + .mthd = nvkm_udisp_mthd, + .ntfy = nvkm_disp_ntfy, + .sclass = nvkm_udisp_sclass, +}; + +int +nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + struct nvkm_conn *conn; + struct nvkm_outp *outp; + union nvif_disp_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + spin_lock(&disp->client.lock); + if (disp->client.object.func) { + spin_unlock(&disp->client.lock); + return -EBUSY; + } + nvkm_object_ctor(&nvkm_udisp, oclass, &disp->client.object); + *pobject = &disp->client.object; + spin_unlock(&disp->client.lock); + + args->v0.conn_mask = 0; + list_for_each_entry(conn, &disp->conns, head) + args->v0.conn_mask |= BIT(conn->index); + + args->v0.outp_mask = 0; + list_for_each_entry(outp, &disp->outps, head) + args->v0.outp_mask |= BIT(outp->index); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c new file mode 100644 index 000000000000..abedb3e86361 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -0,0 +1,129 @@ +/* + * Copyright 2021 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. + */ +#define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object) +#include "outp.h" +#include "ior.h" + +#include <nvif/if0012.h> + +static int +nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_load_detect_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + ret = nvkm_outp_acquire(outp, NVKM_OUTP_PRIV, false); + if (ret == 0) { + if (outp->ior->func->sense) { + ret = outp->ior->func->sense(outp->ior, args->v0.data); + args->v0.load = ret < 0 ? 0 : ret; + } else { + ret = -EINVAL; + } + nvkm_outp_release(outp, NVKM_OUTP_PRIV); + } + + return ret; +} + +static int +nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) +{ + switch (mthd) { + case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc); + default: + break; + } + + return 1; +} + +static int +nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_outp *outp = nvkm_uoutp(object); + struct nvkm_disp *disp = outp->disp; + int ret; + + mutex_lock(&disp->super.mutex); + + ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc); + if (ret <= 0) + goto done; + +done: + mutex_unlock(&disp->super.mutex); + return ret; +} + +static void * +nvkm_uoutp_dtor(struct nvkm_object *object) +{ + struct nvkm_outp *outp = nvkm_uoutp(object); + struct nvkm_disp *disp = outp->disp; + + spin_lock(&disp->client.lock); + outp->object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_uoutp = { + .dtor = nvkm_uoutp_dtor, + .mthd = nvkm_uoutp_mthd, +}; + +int +nvkm_uoutp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct nvkm_outp *outt, *outp = NULL; + union nvif_outp_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + list_for_each_entry(outt, &disp->outps, head) { + if (outt->index == args->v0.id) { + outp = outt; + break; + } + } + + if (!outp) + return -EINVAL; + + ret = -EBUSY; + spin_lock(&disp->client.lock); + if (!outp->object.func) { + nvkm_object_ctor(&nvkm_uoutp, oclass, &outp->object); + *pobject = &outp->object; + ret = 0; + } + spin_unlock(&disp->client.lock); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c deleted file mode 100644 index bb4db6351ddf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37b.h> -#include <nvif/unpack.h> - -static void -gv100_disp_wimm_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da8, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wimm = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wimm_intr, - .user = gv100_disp_chan_user, -}; - -static int -gv100_disp_wimm_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37b_window_imm_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window imm channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window imm channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wimm_new_(&gv100_disp_wimm, NULL, disp, 33, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c deleted file mode 100644 index e635247d794f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37e.h> -#include <nvif/unpack.h> - -static const struct nv50_disp_mthd_list -gv100_disp_wndw_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x690200 }, - { 0x020c, 0x69020c }, - { 0x0210, 0x690210 }, - { 0x0214, 0x690214 }, - { 0x0218, 0x690218 }, - { 0x021c, 0x69021c }, - { 0x0220, 0x690220 }, - { 0x0224, 0x690224 }, - { 0x0228, 0x690228 }, - { 0x022c, 0x69022c }, - { 0x0230, 0x690230 }, - { 0x0234, 0x690234 }, - { 0x0238, 0x690238 }, - { 0x0240, 0x690240 }, - { 0x0244, 0x690244 }, - { 0x0248, 0x690248 }, - { 0x024c, 0x69024c }, - { 0x0250, 0x690250 }, - { 0x0254, 0x690254 }, - { 0x0260, 0x690260 }, - { 0x0264, 0x690264 }, - { 0x0268, 0x690268 }, - { 0x026c, 0x69026c }, - { 0x0270, 0x690270 }, - { 0x0274, 0x690274 }, - { 0x0280, 0x690280 }, - { 0x0284, 0x690284 }, - { 0x0288, 0x690288 }, - { 0x028c, 0x69028c }, - { 0x0290, 0x690290 }, - { 0x0298, 0x690298 }, - { 0x029c, 0x69029c }, - { 0x02a0, 0x6902a0 }, - { 0x02a4, 0x6902a4 }, - { 0x02a8, 0x6902a8 }, - { 0x02ac, 0x6902ac }, - { 0x02b0, 0x6902b0 }, - { 0x02b4, 0x6902b4 }, - { 0x02b8, 0x6902b8 }, - { 0x02bc, 0x6902bc }, - { 0x02c0, 0x6902c0 }, - { 0x02c4, 0x6902c4 }, - { 0x02c8, 0x6902c8 }, - { 0x02cc, 0x6902cc }, - { 0x02d0, 0x6902d0 }, - { 0x02d4, 0x6902d4 }, - { 0x02d8, 0x6902d8 }, - { 0x02dc, 0x6902dc }, - { 0x02e0, 0x6902e0 }, - { 0x02e4, 0x6902e4 }, - { 0x02e8, 0x6902e8 }, - { 0x02ec, 0x6902ec }, - { 0x02f0, 0x6902f0 }, - { 0x02f4, 0x6902f4 }, - { 0x02f8, 0x6902f8 }, - { 0x02fc, 0x6902fc }, - { 0x0300, 0x690300 }, - { 0x0304, 0x690304 }, - { 0x0308, 0x690308 }, - { 0x0310, 0x690310 }, - { 0x0314, 0x690314 }, - { 0x0318, 0x690318 }, - { 0x031c, 0x69031c }, - { 0x0320, 0x690320 }, - { 0x0324, 0x690324 }, - { 0x0328, 0x690328 }, - { 0x032c, 0x69032c }, - { 0x033c, 0x69033c }, - { 0x0340, 0x690340 }, - { 0x0344, 0x690344 }, - { 0x0348, 0x690348 }, - { 0x034c, 0x69034c }, - { 0x0350, 0x690350 }, - { 0x0354, 0x690354 }, - { 0x0358, 0x690358 }, - { 0x0364, 0x690364 }, - { 0x0368, 0x690368 }, - { 0x036c, 0x69036c }, - { 0x0370, 0x690370 }, - { 0x0374, 0x690374 }, - { 0x0380, 0x690380 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_wndw_mthd = { - .name = "Window", - .addr = 0x001000, - .prev = 0x000800, - .data = { - { "Global", 1, &gv100_disp_wndw_mthd_base }, - {} - } -}; - -static void -gv100_disp_wndw_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da4, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wndw = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wndw_intr, - .user = gv100_disp_chan_user, - .bind = gv100_disp_dmac_bind, -}; - -static int -gv100_disp_wndw_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37e_window_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wndw_new_(&gv100_disp_wndw, &gv100_disp_wndw_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 2ed4ff05d207..58b8df75fc40 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -144,30 +144,6 @@ nvkm_fifo_kevent_func = { .ctor = nvkm_fifo_kevent_ctor, }; -static int -nvkm_fifo_cevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - if (size == 0) { - notify->size = 0; - notify->types = 1; - notify->index = 0; - return 0; - } - return -ENOSYS; -} - -static const struct nvkm_event_func -nvkm_fifo_cevent_func = { - .ctor = nvkm_fifo_cevent_ctor, -}; - -void -nvkm_fifo_cevent(struct nvkm_fifo *fifo) -{ - nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0); -} - static void nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index) { @@ -332,7 +308,6 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) if (fifo->func->dtor) data = fifo->func->dtor(fifo); nvkm_event_fini(&fifo->kevent); - nvkm_event_fini(&fifo->cevent); nvkm_event_fini(&fifo->uevent); mutex_destroy(&fifo->mutex); return data; @@ -378,9 +353,5 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, return ret; } - ret = nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent); - if (ret) - return ret; - return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 8d957643940a..2e7f32cebf2a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -272,36 +272,6 @@ nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, } static int -nvkm_fifo_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (unlikely(!chan->user)) { - chan->user = ioremap(chan->addr, chan->size); - if (!chan->user) - return -ENOMEM; - } - if (unlikely(addr + 4 > chan->size)) - return -EINVAL; - *data = ioread32_native(chan->user + addr); - return 0; -} - -static int -nvkm_fifo_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (unlikely(!chan->user)) { - chan->user = ioremap(chan->addr, chan->size); - if (!chan->user) - return -ENOMEM; - } - if (unlikely(addr + 4 > chan->size)) - return -EINVAL; - iowrite32_native(data, chan->user + addr); - return 0; -} - -static int nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); @@ -332,9 +302,6 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) } spin_unlock_irqrestore(&fifo->lock, flags); - if (chan->user) - iounmap(chan->user); - if (chan->vmm) { nvkm_vmm_part(chan->vmm, chan->inst->memory); nvkm_vmm_unref(&chan->vmm); @@ -352,8 +319,6 @@ nvkm_fifo_chan_func = { .fini = nvkm_fifo_chan_fini, .ntfy = nvkm_fifo_chan_ntfy, .map = nvkm_fifo_chan_map, - .rd32 = nvkm_fifo_chan_rd32, - .wr32 = nvkm_fifo_chan_wr32, .sclass = nvkm_fifo_chan_child_get, }; @@ -424,7 +389,5 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, chan->addr = device->func->resource_addr(device, bar) + base + user * chan->chid; chan->size = user; - - nvkm_fifo_cevent(fifo); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index cfbe096e604f..9713daee6c76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -14,8 +14,6 @@ struct gk104_fifo_chan { struct list_head head; bool killed; - struct nvkm_memory *mthd; - #define GK104_FIFO_ENGN_SW 15 struct gk104_fifo_engn { struct nvkm_gpuobj *inst; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index ae6c4d846eb5..80456ec70e8a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -175,13 +175,19 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); int ret; - if (!gk104_fifo_gpfifo_engine_addr(engine)) - return 0; + if (!gk104_fifo_gpfifo_engine_addr(engine)) { + if (engine->subdev.type != NVKM_ENGINE_CE || + engine->subdev.device->card_type < GV100) + return 0; + } ret = nvkm_object_bind(object, NULL, 0, &engn->inst); if (ret) return ret; + if (!gk104_fifo_gpfifo_engine_addr(engine)) + return 0; + ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma); if (ret) return ret; @@ -231,7 +237,6 @@ void * gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - nvkm_memory_unref(&chan->mthd); kfree(chan->cgrp); return chan; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 743791c514fe..428f9b41165c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -70,8 +70,17 @@ gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, struct nvkm_gpuobj *inst = chan->base.inst; int ret; - if (engine->subdev.type == NVKM_ENGINE_CE) - return gk104_fifo_gpfifo_kick(chan); + if (engine->subdev.type == NVKM_ENGINE_CE) { + ret = gv100_fifo_gpfifo_engine_valid(chan, true, false); + if (ret && suspend) + return ret; + + nvkm_kmap(inst); + nvkm_wo32(chan->base.inst, 0x220, 0x00000000); + nvkm_wo32(chan->base.inst, 0x224, 0x00000000); + nvkm_done(inst); + return ret; + } ret = gv100_fifo_gpfifo_engine_valid(chan, false, false); if (ret && suspend) @@ -92,8 +101,16 @@ gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); struct nvkm_gpuobj *inst = chan->base.inst; - if (engine->subdev.type == NVKM_ENGINE_CE) - return 0; + if (engine->subdev.type == NVKM_ENGINE_CE) { + const u64 bar2 = nvkm_memory_bar2(engn->inst->memory); + + nvkm_kmap(inst); + nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(bar2)); + nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(bar2)); + nvkm_done(inst); + + return gv100_fifo_gpfifo_engine_valid(chan, true, true); + } nvkm_kmap(inst); nvkm_wo32(inst, 0x210, lower_32_bits(engn->vma->addr) | 0x00000004); @@ -123,11 +140,9 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, u32 *token, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nvkm_device *device = fifo->base.engine.subdev.device; struct gk104_fifo_chan *chan; int runlist = ffs(*runlists) -1, ret, i; - u64 usermem, mthd; - u32 size; + u64 usermem; if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) return -EINVAL; @@ -173,20 +188,6 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, nvkm_done(fifo->user.mem); usermem = nvkm_memory_addr(fifo->user.mem) + usermem; - /* Allocate fault method buffer (magics come from nvgpu). */ - size = nvkm_rd32(device, 0x104028); /* NV_PCE_PCE_MAP */ - size = 27 * 5 * (((9 + 1 + 3) * hweight32(size)) + 2); - size = roundup(size, PAGE_SIZE); - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, true, - &chan->mthd); - if (ret) - return ret; - - mthd = nvkm_memory_bar2(chan->mthd); - if (mthd == ~0ULL) - return -EFAULT; - /* RAMFC */ nvkm_kmap(chan->base.inst); nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); @@ -203,10 +204,8 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000); nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); - nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(mthd)); - nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(mthd)); nvkm_done(chan->base.inst); - return gv100_fifo_gpfifo_engine_valid(chan, true, true); + return 0; } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 70e16a91ac12..faf0fe9f704c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -52,7 +52,7 @@ gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, nvkm_wo32(memory, offset + 0xc, 0x00000000); } -const struct gk104_fifo_runlist_func +static const struct gk104_fifo_runlist_func gv100_fifo_runlist = { .size = 16, .cgrp = gv100_fifo_runlist_cgrp, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 899272801a8b..79cec57647f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -7,7 +7,6 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, int nr, struct nvkm_fifo *); void nvkm_fifo_uevent(struct nvkm_fifo *); -void nvkm_fifo_cevent(struct nvkm_fifo *); void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 397ff4fe9df8..f16eabf4f642 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1922,8 +1922,8 @@ gf100_gr_oneinit_tiles(struct gf100_gr *gr) for (i = 0; i < gr->gpc_nr; i++) { init_frac[i] = gr->tpc_nr[gpc_map[i]] * gr->gpc_nr * mul_factor; - init_err[i] = i * gr->tpc_max * mul_factor - comm_denom/2; - run_err[i] = init_frac[i] + init_err[i]; + init_err[i] = i * gr->tpc_max * mul_factor - comm_denom/2; + run_err[i] = init_frac[i] + init_err[i]; } for (i = 0; i < gr->tpc_total;) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 5c38ff0fe7f9..385cfd91b266 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -26,7 +26,6 @@ #include <core/firmware.h> #include <subdev/acr.h> -#include <subdev/secboot.h> #include <nvfw/flcn.h> diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index c91130a6be2a..f3f90c1063dd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -221,13 +221,3 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func, mutex_init(&falcon->dmem_mutex); return 0; } - -void -nvkm_falcon_del(struct nvkm_falcon **pfalcon) -{ - if (*pfalcon) { - nvkm_falcon_dtor(*pfalcon); - kfree(*pfalcon); - *pfalcon = NULL; - } -} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 1ff9b9c2e651..b0ee4c31414c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -309,28 +309,3 @@ nvkm_falcon_v1_disable(struct nvkm_falcon *falcon) nvkm_falcon_wr32(falcon, 0x014, 0xff); falcon_v1_wait_idle(falcon); } - -static const struct nvkm_falcon_func -nvkm_falcon_v1 = { - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .start = nvkm_falcon_v1_start, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, - .set_start_addr = nvkm_falcon_v1_set_start_addr, -}; - -int -nvkm_falcon_v1_new(struct nvkm_subdev *owner, const char *name, u32 addr, - struct nvkm_falcon **pfalcon) -{ - struct nvkm_falcon *falcon; - if (!(falcon = *pfalcon = kzalloc(sizeof(*falcon), GFP_KERNEL))) - return -ENOMEM; - nvkm_falcon_ctor(&nvkm_falcon_v1, owner, name, addr, falcon); - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c index 64e423dddd9e..6c318e41bde0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c @@ -33,7 +33,7 @@ nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) { u32 p = *addr; - if (*addr > bios->image0_size && bios->imaged_addr) { + if (*addr >= bios->image0_size && bios->imaged_addr) { *addr -= bios->image0_size; *addr += bios->imaged_addr; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h index fac1bff1311b..cfa8a0c356dd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h @@ -19,7 +19,7 @@ struct nvbios_source { int nvbios_extend(struct nvkm_bios *, u32 length); int nvbios_shadow(struct nvkm_bios *); -extern const struct nvbios_source nvbios_rom; +extern const struct nvbios_source nvbios_prom; extern const struct nvbios_source nvbios_ramin; extern const struct nvbios_source nvbios_acpi_fast; extern const struct nvbios_source nvbios_acpi_slow; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c index 4b571cc6bc70..19188683c8fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c @@ -171,7 +171,7 @@ nvbios_shadow(struct nvkm_bios *bios) struct shadow mthds[] = { { 0, &nvbios_of }, { 0, &nvbios_ramin }, - { 0, &nvbios_rom }, + { 0, &nvbios_prom }, { 0, &nvbios_acpi_fast }, { 4, &nvbios_acpi_slow }, { 1, &nvbios_pcirom }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c index ffa4b395220a..39144ceb117b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c @@ -25,7 +25,7 @@ #include <subdev/pci.h> static u32 -prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) +nvbios_prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { struct nvkm_device *device = data; u32 i; @@ -38,14 +38,14 @@ prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) } static void -prom_fini(void *data) +nvbios_prom_fini(void *data) { struct nvkm_device *device = data; nvkm_pci_rom_shadow(device->pci, true); } static void * -prom_init(struct nvkm_bios *bios, const char *name) +nvbios_prom_init(struct nvkm_bios *bios, const char *name) { struct nvkm_device *device = bios->subdev.device; if (device->card_type == NV_40 && device->chipset >= 0x4c) @@ -55,10 +55,10 @@ prom_init(struct nvkm_bios *bios, const char *name) } const struct nvbios_source -nvbios_rom = { +nvbios_prom = { .name = "PROM", - .init = prom_init, - .fini = prom_fini, - .read = prom_read, + .init = nvbios_prom_init, + .fini = nvbios_prom_fini, + .read = nvbios_prom_read, .rw = false, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index c2b5cc5f97ed..da07a2fbef06 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -330,7 +330,6 @@ nvkm_pstate_work(struct work_struct *work) } wake_up_all(&clk->wait); - nvkm_notify_get(&clk->pwrsrc_ntfy); } static int @@ -559,13 +558,12 @@ nvkm_clk_dstate(struct nvkm_clk *clk, int req, int rel) return nvkm_pstate_calc(clk, true); } -static int -nvkm_clk_pwrsrc(struct nvkm_notify *notify) +int +nvkm_clk_pwrsrc(struct nvkm_device *device) { - struct nvkm_clk *clk = - container_of(notify, typeof(*clk), pwrsrc_ntfy); - nvkm_pstate_calc(clk, false); - return NVKM_NOTIFY_DROP; + if (device->clk) + return nvkm_pstate_calc(device->clk, false); + return 0; } /****************************************************************************** @@ -582,7 +580,6 @@ static int nvkm_clk_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_clk *clk = nvkm_clk(subdev); - nvkm_notify_put(&clk->pwrsrc_ntfy); flush_work(&clk->work); if (clk->func->fini) clk->func->fini(clk); @@ -629,8 +626,6 @@ nvkm_clk_dtor(struct nvkm_subdev *subdev) struct nvkm_clk *clk = nvkm_clk(subdev); struct nvkm_pstate *pstate, *temp; - nvkm_notify_fini(&clk->pwrsrc_ntfy); - /* Early return if the pstates have been provided statically */ if (clk->func->pstates) return clk; @@ -692,11 +687,6 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, clk->state_nr = func->nr_pstates; } - ret = nvkm_notify_init(NULL, &device->event, nvkm_clk_pwrsrc, true, - NULL, 0, 0, &clk->pwrsrc_ntfy); - if (ret) - return ret; - mode = nvkm_stropt(device->cfgopt, "NvClkMode", &arglen); if (mode) { clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index 8bf00b396ec1..ae793f400ba1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -280,7 +280,7 @@ nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1])) nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes); - /* PT no longer neeed? Destroy it. */ + /* PT no longer needed? Destroy it. */ if (!pgt->refs[type]) { it->lvl++; TRA(it, "%s empty", nvkm_vmm_desc_type(desc)); @@ -1048,7 +1048,7 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key); /* Locate the smallest page size supported by the backend, it will - * have the the deepest nesting of page tables. + * have the deepest nesting of page tables. */ while (page[1].shift) page++; |