aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h2
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/Makefile30
-rw-r--r--drivers/gpu/drm/drm_file.c3
-rw-r--r--drivers/gpu/drm/drm_gem_ttm_helper.c9
-rw-r--r--drivers/gpu/drm/drm_panel_orientation_quirks.c15
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_create.c20
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c15
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c47
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h3
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_types.h18
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_region.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.c55
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.h3
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c99
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h1
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_wait.c34
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_pages.c7
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c141
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c87
-rw-r--r--drivers/gpu/drm/i915/gt/intel_breadcrumbs.c3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_types.h11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c34
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h22
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c15
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.c25
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.h24
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_regs.h7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_region_lmem.c109
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c37
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c6
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_lrc.c8
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_slpc.c323
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h3
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.h5
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c16
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h45
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_log.c2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c352
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c65
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h7
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c6
-rw-r--r--drivers/gpu/drm/i915/i915_active.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c42
-rw-r--r--drivers/gpu/drm/i915/i915_params.c2
-rw-r--r--drivers/gpu/drm/i915/i915_params.h1
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c28
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c158
-rw-r--r--drivers/gpu/drm/i915/i915_query.c16
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.c27
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.h6
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.c31
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.h3
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c37
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c17
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h5
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.c18
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.h4
-rw-r--r--drivers/gpu/drm/i915/intel_region_ttm.c10
-rw-r--r--drivers/gpu/drm/i915/intel_region_ttm.h3
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_gtt.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_memory_region.c21
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_region.c3
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-dev.c3
-rw-r--r--drivers/gpu/drm/lima/lima_devfreq.c12
-rw-r--r--drivers/gpu/drm/meson/meson_viu.c22
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base507c.c17
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core507d.c4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs507a.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c43
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/oimm507b.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly507e.c17
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c7
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c9
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.h3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c7
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl5070.h8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl507a.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl507b.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl507c.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl507d.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl507e.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h141
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/clc37b.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/clc37e.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/conn.h18
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/disp.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0010.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0011.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0012.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0014.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/outp.h14
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/printf.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h43
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c12
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/conn.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c)60
-rw-r--r--drivers/gpu/drm/nouveau/nvif/disp.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvif/outp.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c)65
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild115
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c139
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c74
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c108
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c119
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c60
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c275
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h135
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c62
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c34
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c364
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h193
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c111
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c231
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c126
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c207
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c234
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c81
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c121
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c96
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c79
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c137
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c457
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h33
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c291
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c341
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c120
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c1041
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c275
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c146
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c52
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c144
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c73
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c172
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c883
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c62
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c91
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c91
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c84
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c104
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c105
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c74
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h95
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c54
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c1159
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h102
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c95
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c97
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c74
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c107
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c87
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c139
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h75
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c53
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c42
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c140
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c53
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c302
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c144
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c208
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c54
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c80
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c160
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c93
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c69
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c155
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c48
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c53
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c106
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c129
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c108
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c117
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c115
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c129
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c184
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c3
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c19
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_mmu.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_cmm.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_cmm.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c7
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c19
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c14
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_regs.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.c19
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_writeback.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_writeback.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds_regs.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c17
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c2
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c2
259 files changed, 8176 insertions, 9429 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 7a5e8a7b4a1b..28ec5f8ac1c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -395,11 +395,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
unsigned long pages_per_block;
int r;
- lpfn = place->lpfn << PAGE_SHIFT;
+ lpfn = (u64)place->lpfn << PAGE_SHIFT;
if (!lpfn)
lpfn = man->size;
- fpfn = place->fpfn << PAGE_SHIFT;
+ fpfn = (u64)place->fpfn << PAGE_SHIFT;
max_bytes = adev->gmc.mc_vram_size;
if (tbo->type != ttm_bo_type_kernel)
@@ -439,12 +439,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
/* Allocate blocks in desired range */
vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
- remaining_size = vres->base.num_pages << PAGE_SHIFT;
+ remaining_size = (u64)vres->base.num_pages << PAGE_SHIFT;
mutex_lock(&mgr->lock);
while (remaining_size) {
if (tbo->page_alignment)
- min_block_size = tbo->page_alignment << PAGE_SHIFT;
+ min_block_size = (u64)tbo->page_alignment << PAGE_SHIFT;
else
min_block_size = mgr->default_page_size;
@@ -453,12 +453,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
/* Limit maximum size to 2GiB due to SG table limitations */
size = min(remaining_size, 2ULL << 30);
- if (size >= pages_per_block << PAGE_SHIFT)
- min_block_size = pages_per_block << PAGE_SHIFT;
+ if (size >= (u64)pages_per_block << PAGE_SHIFT)
+ min_block_size = (u64)pages_per_block << PAGE_SHIFT;
cur_size = size;
- if (fpfn + size != place->lpfn << PAGE_SHIFT) {
+ if (fpfn + size != (u64)place->lpfn << PAGE_SHIFT) {
/*
* Except for actual range allocation, modify the size and
* min_block_size conforming to continuous flag enablement
@@ -498,7 +498,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
LIST_HEAD(temp);
trim_list = &vres->blocks;
- original_size = vres->base.num_pages << PAGE_SHIFT;
+ original_size = (u64)vres->base.num_pages << PAGE_SHIFT;
/*
* If size value is rounded up to min_block_size, trim the last
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
index 4b267bf1c5db..0e04e42cf809 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -50,7 +50,7 @@ static inline u64 amdgpu_vram_mgr_block_start(struct drm_buddy_block *block)
static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block)
{
- return PAGE_SIZE << drm_buddy_block_order(block);
+ return (u64)PAGE_SIZE << drm_buddy_block_order(block);
}
static inline struct amdgpu_vram_mgr_resource *
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index 96cbc87f7b6b..413d8c6d592f 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -6,7 +6,7 @@ config DRM_AMD_DC
bool "AMD DC - Enable new display engine"
default y
select SND_HDA_COMPONENT if SND_HDA_CORE
- select DRM_AMD_DC_DCN if (X86 || PPC64)
+ select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128)
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index b7c2ae9ddfda..c20331eb62e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -30,6 +30,36 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \
dcn30_dio_link_encoder.o dcn30_resource.o
+
+ifdef CONFIG_X86
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -msse
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse
+endif
+
+ifdef CONFIG_PPC64
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec
+endif
+
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
+
+ifdef CONFIG_X86
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4
+else
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2
+endif
+endif
+
AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30))
AMD_DISPLAY_FILES += $(AMD_DAL_DCN30)
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index ed25168619fc..dc7d2e5b16c8 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal);
* Since events are used by the KMS API for vblank and page flip completion this
* means all modern display drivers must use it.
*
- * @offset is ignored, DRM events are read like a pipe. Therefore drivers also
- * must set the &file_operation.llseek to no_llseek(). Polling support is
+ * @offset is ignored, DRM events are read like a pipe. Polling support is
* provided by drm_poll().
*
* This function will only ever read a full event. Therefore userspace must
diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c
index d5962a34c01d..e5fc875990c4 100644
--- a/drivers/gpu/drm/drm_gem_ttm_helper.c
+++ b/drivers/gpu/drm/drm_gem_ttm_helper.c
@@ -64,8 +64,13 @@ int drm_gem_ttm_vmap(struct drm_gem_object *gem,
struct iosys_map *map)
{
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
+ int ret;
+
+ dma_resv_lock(gem->resv, NULL);
+ ret = ttm_bo_vmap(bo, map);
+ dma_resv_unlock(gem->resv);
- return ttm_bo_vmap(bo, map);
+ return ret;
}
EXPORT_SYMBOL(drm_gem_ttm_vmap);
@@ -82,7 +87,9 @@ void drm_gem_ttm_vunmap(struct drm_gem_object *gem,
{
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
+ dma_resv_lock(gem->resv, NULL);
ttm_bo_vunmap(bo, map);
+ dma_resv_unlock(gem->resv);
}
EXPORT_SYMBOL(drm_gem_ttm_vunmap);
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 7a9eeed239f3..fc1728d46ac2 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -286,6 +286,21 @@ static const struct dmi_system_id orientation_data[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
},
.driver_data = (void *)&lcd1200x1920_rightside_up,
+ }, { /* Lenovo Yoga Tablet 2 830F / 830L */
+ .matches = {
+ /*
+ * Note this also matches the Lenovo Yoga Tablet 2 1050F/L
+ * since that uses the same mainboard. The resolution match
+ * will limit this to only matching on the 830F/L. Neither has
+ * any external video outputs so those are not a concern.
+ */
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
+ /* Partial match on beginning of BIOS version */
+ DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
+ },
+ .driver_data = (void *)&lcd1200x1920_rightside_up,
}, { /* OneGX1 Pro */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"),
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c
index 5802692ea604..33673fe7ee0a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_create.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c
@@ -241,6 +241,7 @@ struct create_ext {
struct drm_i915_private *i915;
struct intel_memory_region *placements[INTEL_REGION_UNKNOWN];
unsigned int n_placements;
+ unsigned int placement_mask;
unsigned long flags;
};
@@ -337,6 +338,7 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args,
for (i = 0; i < args->num_regions; i++)
ext_data->placements[i] = placements[i];
+ ext_data->placement_mask = mask;
return 0;
out_dump:
@@ -411,7 +413,7 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_object *obj;
int ret;
- if (args->flags)
+ if (args->flags & ~I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS)
return -EINVAL;
ret = i915_user_extensions(u64_to_user_ptr(args->extensions),
@@ -427,6 +429,22 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
ext_data.n_placements = 1;
}
+ if (args->flags & I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS) {
+ if (ext_data.n_placements == 1)
+ return -EINVAL;
+
+ /*
+ * We always need to be able to spill to system memory, if we
+ * can't place in the mappable part of LMEM.
+ */
+ if (!(ext_data.placement_mask & BIT(INTEL_REGION_SMEM)))
+ return -EINVAL;
+ } else {
+ if (ext_data.n_placements > 1 ||
+ ext_data.placements[0]->type != INTEL_MEMORY_SYSTEM)
+ ext_data.flags |= I915_BO_ALLOC_GPU_ONLY;
+ }
+
obj = __i915_gem_object_create_user_ext(i915, args->size,
ext_data.placements,
ext_data.n_placements,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 30fe847c6664..b7b2c14fd9e1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -1951,7 +1951,7 @@ eb_find_first_request_added(struct i915_execbuffer *eb)
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
/* Stage with GFP_KERNEL allocations before we enter the signaling critical path */
-static void eb_capture_stage(struct i915_execbuffer *eb)
+static int eb_capture_stage(struct i915_execbuffer *eb)
{
const unsigned int count = eb->buffer_count;
unsigned int i = count, j;
@@ -1964,6 +1964,10 @@ static void eb_capture_stage(struct i915_execbuffer *eb)
if (!(flags & EXEC_OBJECT_CAPTURE))
continue;
+ if (i915_gem_context_is_recoverable(eb->gem_context) &&
+ (IS_DGFX(eb->i915) || GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 0)))
+ return -EINVAL;
+
for_each_batch_create_order(eb, j) {
struct i915_capture_list *capture;
@@ -1976,6 +1980,8 @@ static void eb_capture_stage(struct i915_execbuffer *eb)
eb->capture_lists[j] = capture;
}
}
+
+ return 0;
}
/* Commit once we're in the critical path */
@@ -2017,8 +2023,9 @@ static void eb_capture_list_clear(struct i915_execbuffer *eb)
#else
-static void eb_capture_stage(struct i915_execbuffer *eb)
+static int eb_capture_stage(struct i915_execbuffer *eb)
{
+ return 0;
}
static void eb_capture_commit(struct i915_execbuffer *eb)
@@ -3410,7 +3417,9 @@ i915_gem_do_execbuffer(struct drm_device *dev,
}
ww_acquire_done(&eb.ww.ctx);
- eb_capture_stage(&eb);
+ err = eb_capture_stage(&eb);
+ if (err)
+ goto err_vma;
out_fence = eb_requests_create(&eb, in_fence, out_fence_fd);
if (IS_ERR(out_fence)) {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 06b1b188ce5a..ccec4055fde3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -717,6 +717,32 @@ bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj,
return false;
}
+/**
+ * i915_gem_object_needs_ccs_pages - Check whether the object requires extra
+ * pages when placed in system-memory, in order to save and later restore the
+ * flat-CCS aux state when the object is moved between local-memory and
+ * system-memory
+ * @obj: Pointer to the object
+ *
+ * Return: True if the object needs extra ccs pages. False otherwise.
+ */
+bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
+{
+ bool lmem_placement = false;
+ int i;
+
+ for (i = 0; i < obj->mm.n_placements; i++) {
+ /* Compression is not allowed for the objects with smem placement */
+ if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM)
+ return false;
+ if (!lmem_placement &&
+ obj->mm.placements[i]->type == INTEL_MEMORY_LOCAL)
+ lmem_placement = true;
+ }
+
+ return lmem_placement;
+}
+
void i915_gem_init__objects(struct drm_i915_private *i915)
{
INIT_DELAYED_WORK(&i915->mm.free_work, __i915_gem_free_work);
@@ -783,10 +809,31 @@ int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj,
intr, MAX_SCHEDULE_TIMEOUT);
if (!ret)
ret = -ETIME;
+ else if (ret > 0 && i915_gem_object_has_unknown_state(obj))
+ ret = -EIO;
return ret < 0 ? ret : 0;
}
+/**
+ * i915_gem_object_has_unknown_state - Return true if the object backing pages are
+ * in an unknown_state. This means that userspace must NEVER be allowed to touch
+ * the pages, with either the GPU or CPU.
+ *
+ * ONLY valid to be called after ensuring that all kernel fences have signalled
+ * (in particular the fence for moving/clearing the object).
+ */
+bool i915_gem_object_has_unknown_state(struct drm_i915_gem_object *obj)
+{
+ /*
+ * The below barrier pairs with the dma_fence_signal() in
+ * __memcpy_work(). We should only sample the unknown_state after all
+ * the kernel fences have signalled.
+ */
+ smp_rmb();
+ return obj->mm.unknown_state;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/huge_gem_object.c"
#include "selftests/huge_pages.c"
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index e11d82a9f7c3..6f0a3ce35567 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -524,6 +524,7 @@ int i915_gem_object_get_moving_fence(struct drm_i915_gem_object *obj,
struct dma_fence **fence);
int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj,
bool intr);
+bool i915_gem_object_has_unknown_state(struct drm_i915_gem_object *obj);
void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
unsigned int cache_level);
@@ -617,6 +618,8 @@ int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj,
enum intel_memory_type type);
+bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj);
+
int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
size_t size, struct intel_memory_region *mr,
struct address_space *mapping,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 2c88bdb8ff7c..5cf36a130061 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -548,6 +548,24 @@ struct drm_i915_gem_object {
bool ttm_shrinkable;
/**
+ * @unknown_state: Indicate that the object is effectively
+ * borked. This is write-once and set if we somehow encounter a
+ * fatal error when moving/clearing the pages, and we are not
+ * able to fallback to memcpy/memset, like on small-BAR systems.
+ * The GPU should also be wedged (or in the process) at this
+ * point.
+ *
+ * Only valid to read this after acquiring the dma-resv lock and
+ * waiting for all DMA_RESV_USAGE_KERNEL fences to be signalled,
+ * or if we otherwise know that the moving fence has signalled,
+ * and we are certain the pages underneath are valid for
+ * immediate access (under normal operation), like just prior to
+ * binding the object or when setting up the CPU fault handler.
+ * See i915_gem_object_has_unknown_state();
+ */
+ bool unknown_state;
+
+ /**
* Priority list of potential placements for this object.
*/
struct intel_memory_region **placements;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c
index f46ee16a323a..a4fb577eceb4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
@@ -60,6 +60,8 @@ __i915_gem_object_create_region(struct intel_memory_region *mem,
if (page_size)
default_page_size = page_size;
+ /* We should be able to fit a page within an sg entry */
+ GEM_BUG_ON(overflows_type(default_page_size, u32));
GEM_BUG_ON(!is_power_of_2_u64(default_page_size));
GEM_BUG_ON(default_page_size < PAGE_SIZE);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 4c25d9b2f138..f131dc065f47 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -266,24 +266,6 @@ static const struct i915_refct_sgt_ops tt_rsgt_ops = {
.release = i915_ttm_tt_release
};
-static inline bool
-i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
-{
- bool lmem_placement = false;
- int i;
-
- for (i = 0; i < obj->mm.n_placements; i++) {
- /* Compression is not allowed for the objects with smem placement */
- if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM)
- return false;
- if (!lmem_placement &&
- obj->mm.placements[i]->type == INTEL_MEMORY_LOCAL)
- lmem_placement = true;
- }
-
- return lmem_placement;
-}
-
static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
@@ -620,10 +602,15 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj,
struct ttm_resource *res)
{
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+ u32 page_alignment;
if (!i915_ttm_gtt_binds_lmem(res))
return i915_ttm_tt_get_st(bo->ttm);
+ page_alignment = bo->page_alignment << PAGE_SHIFT;
+ if (!page_alignment)
+ page_alignment = obj->mm.region->min_page_size;
+
/*
* If CPU mapping differs, we need to add the ttm_tt pages to
* the resulting st. Might make sense for GGTT.
@@ -634,7 +621,8 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj,
struct i915_refct_sgt *rsgt;
rsgt = intel_region_ttm_resource_to_rsgt(obj->mm.region,
- res);
+ res,
+ page_alignment);
if (IS_ERR(rsgt))
return rsgt;
@@ -643,7 +631,8 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj,
return i915_refct_sgt_get(obj->ttm.cached_io_rsgt);
}
- return intel_region_ttm_resource_to_rsgt(obj->mm.region, res);
+ return intel_region_ttm_resource_to_rsgt(obj->mm.region, res,
+ page_alignment);
}
static int i915_ttm_truncate(struct drm_i915_gem_object *obj)
@@ -675,7 +664,15 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object *bo)
i915_ttm_purge(obj);
}
-static bool i915_ttm_resource_mappable(struct ttm_resource *res)
+/**
+ * i915_ttm_resource_mappable - Return true if the ttm resource is CPU
+ * accessible.
+ * @res: The TTM resource to check.
+ *
+ * This is interesting on small-BAR systems where we may encounter lmem objects
+ * that can't be accessed via the CPU.
+ */
+bool i915_ttm_resource_mappable(struct ttm_resource *res)
{
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
@@ -687,6 +684,22 @@ static bool i915_ttm_resource_mappable(struct ttm_resource *res)
static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(mem->bo);
+ bool unknown_state;
+
+ if (!obj)
+ return -EINVAL;
+
+ if (!kref_get_unless_zero(&obj->base.refcount))
+ return -EINVAL;
+
+ assert_object_held(obj);
+
+ unknown_state = i915_gem_object_has_unknown_state(obj);
+ i915_gem_object_put(obj);
+ if (unknown_state)
+ return -EINVAL;
+
if (!i915_ttm_cpu_maps_iomem(mem))
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index 73e371aa3850..e4842b4296fc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -92,4 +92,7 @@ static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem)
/* Once / if we support GGTT, this is also false for cached ttm_tts */
return mem->mem_type != I915_PL_SYSTEM;
}
+
+bool i915_ttm_resource_mappable(struct ttm_resource *res);
+
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index a10716f4e717..9a7e50534b84 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -33,6 +33,7 @@
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
static bool fail_gpu_migration;
static bool fail_work_allocation;
+static bool ban_memcpy;
void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
bool work_allocation)
@@ -40,6 +41,11 @@ void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
fail_gpu_migration = gpu_migration;
fail_work_allocation = work_allocation;
}
+
+void i915_ttm_migrate_set_ban_memcpy(bool ban)
+{
+ ban_memcpy = ban;
+}
#endif
static enum i915_cache_level
@@ -258,15 +264,23 @@ struct i915_ttm_memcpy_arg {
* from the callback for lockdep reasons.
* @cb: Callback for the accelerated migration fence.
* @arg: The argument for the memcpy functionality.
+ * @i915: The i915 pointer.
+ * @obj: The GEM object.
+ * @memcpy_allowed: Instead of processing the @arg, and falling back to memcpy
+ * or memset, we wedge the device and set the @obj unknown_state, to prevent
+ * further access to the object with the CPU or GPU. On some devices we might
+ * only be permitted to use the blitter engine for such operations.
*/
struct i915_ttm_memcpy_work {
struct dma_fence fence;
struct work_struct work;
- /* The fence lock */
spinlock_t lock;
struct irq_work irq_work;
struct dma_fence_cb cb;
struct i915_ttm_memcpy_arg arg;
+ struct drm_i915_private *i915;
+ struct drm_i915_gem_object *obj;
+ bool memcpy_allowed;
};
static void i915_ttm_move_memcpy(struct i915_ttm_memcpy_arg *arg)
@@ -317,14 +331,42 @@ static void __memcpy_work(struct work_struct *work)
struct i915_ttm_memcpy_work *copy_work =
container_of(work, typeof(*copy_work), work);
struct i915_ttm_memcpy_arg *arg = &copy_work->arg;
- bool cookie = dma_fence_begin_signalling();
+ bool cookie;
+
+ /*
+ * FIXME: We need to take a closer look here. We should be able to plonk
+ * this into the fence critical section.
+ */
+ if (!copy_work->memcpy_allowed) {
+ struct intel_gt *gt;
+ unsigned int id;
+
+ for_each_gt(gt, copy_work->i915, id)
+ intel_gt_set_wedged(gt);
+ }
+
+ cookie = dma_fence_begin_signalling();
+
+ if (copy_work->memcpy_allowed) {
+ i915_ttm_move_memcpy(arg);
+ } else {
+ /*
+ * Prevent further use of the object. Any future GTT binding or
+ * CPU access is not allowed once we signal the fence. Outside
+ * of the fence critical section, we then also then wedge the gpu
+ * to indicate the device is not functional.
+ *
+ * The below dma_fence_signal() is our write-memory-barrier.
+ */
+ copy_work->obj->mm.unknown_state = true;
+ }
- i915_ttm_move_memcpy(arg);
dma_fence_end_signalling(cookie);
dma_fence_signal(&copy_work->fence);
i915_ttm_memcpy_release(arg);
+ i915_gem_object_put(copy_work->obj);
dma_fence_put(&copy_work->fence);
}
@@ -336,6 +378,7 @@ static void __memcpy_irq_work(struct irq_work *irq_work)
dma_fence_signal(&copy_work->fence);
i915_ttm_memcpy_release(arg);
+ i915_gem_object_put(copy_work->obj);
dma_fence_put(&copy_work->fence);
}
@@ -389,6 +432,19 @@ i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work *work,
return &work->fence;
}
+static bool i915_ttm_memcpy_allowed(struct ttm_buffer_object *bo,
+ struct ttm_resource *dst_mem)
+{
+ if (i915_gem_object_needs_ccs_pages(i915_ttm_to_gem(bo)))
+ return false;
+
+ if (!(i915_ttm_resource_mappable(bo->resource) &&
+ i915_ttm_resource_mappable(dst_mem)))
+ return false;
+
+ return I915_SELFTEST_ONLY(ban_memcpy) ? false : true;
+}
+
static struct dma_fence *
__i915_ttm_move(struct ttm_buffer_object *bo,
const struct ttm_operation_ctx *ctx, bool clear,
@@ -396,6 +452,9 @@ __i915_ttm_move(struct ttm_buffer_object *bo,
struct i915_refct_sgt *dst_rsgt, bool allow_accel,
const struct i915_deps *move_deps)
{
+ const bool memcpy_allowed = i915_ttm_memcpy_allowed(bo, dst_mem);
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ struct drm_i915_private *i915 = to_i915(bo->base.dev);
struct i915_ttm_memcpy_work *copy_work = NULL;
struct i915_ttm_memcpy_arg _arg, *arg = &_arg;
struct dma_fence *fence = ERR_PTR(-EINVAL);
@@ -423,9 +482,14 @@ __i915_ttm_move(struct ttm_buffer_object *bo,
copy_work = kzalloc(sizeof(*copy_work), GFP_KERNEL);
if (copy_work) {
+ copy_work->i915 = i915;
+ copy_work->memcpy_allowed = memcpy_allowed;
+ copy_work->obj = i915_gem_object_get(obj);
arg = &copy_work->arg;
- i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm,
- dst_rsgt);
+ if (memcpy_allowed)
+ i915_ttm_memcpy_init(arg, bo, clear, dst_mem,
+ dst_ttm, dst_rsgt);
+
fence = i915_ttm_memcpy_work_arm(copy_work, dep);
} else {
dma_fence_wait(dep, false);
@@ -450,17 +514,23 @@ __i915_ttm_move(struct ttm_buffer_object *bo,
}
/* Error intercept failed or no accelerated migration to start with */
- if (!copy_work)
- i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm,
- dst_rsgt);
- i915_ttm_move_memcpy(arg);
- i915_ttm_memcpy_release(arg);
+
+ if (memcpy_allowed) {
+ if (!copy_work)
+ i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm,
+ dst_rsgt);
+ i915_ttm_move_memcpy(arg);
+ i915_ttm_memcpy_release(arg);
+ }
+ if (copy_work)
+ i915_gem_object_put(copy_work->obj);
kfree(copy_work);
- return NULL;
+ return memcpy_allowed ? NULL : ERR_PTR(-EIO);
out:
if (!fence && copy_work) {
i915_ttm_memcpy_release(arg);
+ i915_gem_object_put(copy_work->obj);
kfree(copy_work);
}
@@ -539,8 +609,11 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
}
if (migration_fence) {
- ret = ttm_bo_move_accel_cleanup(bo, migration_fence, evict,
- true, dst_mem);
+ if (I915_SELFTEST_ONLY(evict && fail_gpu_migration))
+ ret = -EIO; /* never feed non-migrate fences into ttm */
+ else
+ ret = ttm_bo_move_accel_cleanup(bo, migration_fence, evict,
+ true, dst_mem);
if (ret) {
dma_fence_wait(migration_fence, false);
ttm_bo_move_sync_cleanup(bo, dst_mem);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h
index d2e7f149e05c..8a5d5ab0cc34 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h
@@ -22,6 +22,7 @@ int i915_ttm_move_notify(struct ttm_buffer_object *bo);
I915_SELFTEST_DECLARE(void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
bool work_allocation));
+I915_SELFTEST_DECLARE(void i915_ttm_migrate_set_ban_memcpy(bool ban));
int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
struct drm_i915_gem_object *src,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index 319936f91ac5..e6e01c2a74a6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -9,6 +9,7 @@
#include <linux/jiffies.h>
#include "gt/intel_engine.h"
+#include "gt/intel_rps.h"
#include "i915_gem_ioctls.h"
#include "i915_gem_object.h"
@@ -31,6 +32,37 @@ i915_gem_object_wait_fence(struct dma_fence *fence,
timeout);
}
+static void
+i915_gem_object_boost(struct dma_resv *resv, unsigned int flags)
+{
+ struct dma_resv_iter cursor;
+ struct dma_fence *fence;
+
+ /*
+ * Prescan all fences for potential boosting before we begin waiting.
+ *
+ * When we wait, we wait on outstanding fences serially. If the
+ * dma-resv contains a sequence such as 1:1, 1:2 instead of a reduced
+ * form 1:2, then as we look at each wait in turn we see that each
+ * request is currently executing and not worthy of boosting. But if
+ * we only happen to look at the final fence in the sequence (because
+ * of request coalescing or splitting between read/write arrays by
+ * the iterator), then we would boost. As such our decision to boost
+ * or not is delicately balanced on the order we wait on fences.
+ *
+ * So instead of looking for boosts sequentially, look for all boosts
+ * upfront and then wait on the outstanding fences.
+ */
+
+ dma_resv_iter_begin(&cursor, resv,
+ dma_resv_usage_rw(flags & I915_WAIT_ALL));
+ dma_resv_for_each_fence_unlocked(&cursor, fence)
+ if (dma_fence_is_i915(fence) &&
+ !i915_request_started(to_request(fence)))
+ intel_rps_boost(to_request(fence));
+ dma_resv_iter_end(&cursor);
+}
+
static long
i915_gem_object_wait_reservation(struct dma_resv *resv,
unsigned int flags,
@@ -40,6 +72,8 @@ i915_gem_object_wait_reservation(struct dma_resv *resv,
struct dma_fence *fence;
long ret = timeout ?: 1;
+ i915_gem_object_boost(resv, flags);
+
dma_resv_iter_begin(&cursor, resv,
dma_resv_usage_rw(flags & I915_WAIT_ALL));
dma_resv_for_each_fence_unlocked(&cursor, fence) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index ef15967be51a..72ce2c9f42fd 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -1623,6 +1623,7 @@ static int igt_shrink_thp(void *arg)
struct file *file;
unsigned int flags = PIN_USER;
unsigned int n;
+ intel_wakeref_t wf;
bool should_swap;
int err;
@@ -1659,9 +1660,11 @@ static int igt_shrink_thp(void *arg)
goto out_put;
}
+ wf = intel_runtime_pm_get(&i915->runtime_pm); /* active shrink */
+
err = i915_vma_pin(vma, 0, 0, flags);
if (err)
- goto out_put;
+ goto out_wf;
if (obj->mm.page_sizes.phys < I915_GTT_PAGE_SIZE_2M) {
pr_info("failed to allocate THP, finishing test early\n");
@@ -1732,6 +1735,8 @@ static int igt_shrink_thp(void *arg)
out_unpin:
i915_vma_unpin(vma);
+out_wf:
+ intel_runtime_pm_put(&i915->runtime_pm, wf);
out_put:
i915_gem_object_put(obj);
out_vm:
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
index 801af51aff62..fe6c37fd7859 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
@@ -9,6 +9,7 @@
#include "i915_deps.h"
+#include "selftests/igt_reset.h"
#include "selftests/igt_spinner.h"
static int igt_fill_check_buffer(struct drm_i915_gem_object *obj,
@@ -109,7 +110,8 @@ static int igt_same_create_migrate(void *arg)
static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
struct drm_i915_gem_object *obj,
- struct i915_vma *vma)
+ struct i915_vma *vma,
+ bool silent_migrate)
{
int err;
@@ -138,7 +140,8 @@ static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
if (i915_gem_object_is_lmem(obj)) {
err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
if (err) {
- pr_err("Object failed migration to smem\n");
+ if (!silent_migrate)
+ pr_err("Object failed migration to smem\n");
if (err)
return err;
}
@@ -156,7 +159,8 @@ static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
} else {
err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM_0);
if (err) {
- pr_err("Object failed migration to lmem\n");
+ if (!silent_migrate)
+ pr_err("Object failed migration to lmem\n");
if (err)
return err;
}
@@ -179,7 +183,8 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt,
struct i915_address_space *vm,
struct i915_deps *deps,
struct igt_spinner *spin,
- struct dma_fence *spin_fence)
+ struct dma_fence *spin_fence,
+ bool borked_migrate)
{
struct drm_i915_private *i915 = gt->i915;
struct drm_i915_gem_object *obj;
@@ -242,7 +247,8 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt,
*/
for (i = 1; i <= 5; ++i) {
for_i915_gem_ww(&ww, err, true)
- err = lmem_pages_migrate_one(&ww, obj, vma);
+ err = lmem_pages_migrate_one(&ww, obj, vma,
+ borked_migrate);
if (err)
goto out_put;
}
@@ -283,23 +289,70 @@ out_put:
static int igt_lmem_pages_failsafe_migrate(void *arg)
{
- int fail_gpu, fail_alloc, ret;
+ int fail_gpu, fail_alloc, ban_memcpy, ret;
struct intel_gt *gt = arg;
for (fail_gpu = 0; fail_gpu < 2; ++fail_gpu) {
for (fail_alloc = 0; fail_alloc < 2; ++fail_alloc) {
- pr_info("Simulated failure modes: gpu: %d, alloc: %d\n",
- fail_gpu, fail_alloc);
- i915_ttm_migrate_set_failure_modes(fail_gpu,
- fail_alloc);
- ret = __igt_lmem_pages_migrate(gt, NULL, NULL, NULL, NULL);
- if (ret)
- goto out_err;
+ for (ban_memcpy = 0; ban_memcpy < 2; ++ban_memcpy) {
+ pr_info("Simulated failure modes: gpu: %d, alloc:%d, ban_memcpy: %d\n",
+ fail_gpu, fail_alloc, ban_memcpy);
+ i915_ttm_migrate_set_ban_memcpy(ban_memcpy);
+ i915_ttm_migrate_set_failure_modes(fail_gpu,
+ fail_alloc);
+ ret = __igt_lmem_pages_migrate(gt, NULL, NULL,
+ NULL, NULL,
+ ban_memcpy &&
+ fail_gpu);
+
+ if (ban_memcpy && fail_gpu) {
+ struct intel_gt *__gt;
+ unsigned int id;
+
+ if (ret != -EIO) {
+ pr_err("expected -EIO, got (%d)\n", ret);
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ }
+
+ for_each_gt(__gt, gt->i915, id) {
+ intel_wakeref_t wakeref;
+ bool wedged;
+
+ mutex_lock(&__gt->reset.mutex);
+ wedged = test_bit(I915_WEDGED, &__gt->reset.flags);
+ mutex_unlock(&__gt->reset.mutex);
+
+ if (fail_gpu && !fail_alloc) {
+ if (!wedged) {
+ pr_err("gt(%u) not wedged\n", id);
+ ret = -EINVAL;
+ continue;
+ }
+ } else if (wedged) {
+ pr_err("gt(%u) incorrectly wedged\n", id);
+ ret = -EINVAL;
+ } else {
+ continue;
+ }
+
+ wakeref = intel_runtime_pm_get(__gt->uncore->rpm);
+ igt_global_reset_lock(__gt);
+ intel_gt_reset(__gt, ALL_ENGINES, NULL);
+ igt_global_reset_unlock(__gt);
+ intel_runtime_pm_put(__gt->uncore->rpm, wakeref);
+ }
+ if (ret)
+ goto out_err;
+ }
+ }
}
}
out_err:
i915_ttm_migrate_set_failure_modes(false, false);
+ i915_ttm_migrate_set_ban_memcpy(false);
return ret;
}
@@ -370,7 +423,7 @@ static int igt_async_migrate(struct intel_gt *gt)
goto out_ce;
err = __igt_lmem_pages_migrate(gt, &ppgtt->vm, &deps, &spin,
- spin_fence);
+ spin_fence, false);
i915_deps_fini(&deps);
dma_fence_put(spin_fence);
if (err)
@@ -394,23 +447,67 @@ out_spin:
#define ASYNC_FAIL_ALLOC 1
static int igt_lmem_async_migrate(void *arg)
{
- int fail_gpu, fail_alloc, ret;
+ int fail_gpu, fail_alloc, ban_memcpy, ret;
struct intel_gt *gt = arg;
for (fail_gpu = 0; fail_gpu < 2; ++fail_gpu) {
for (fail_alloc = 0; fail_alloc < ASYNC_FAIL_ALLOC; ++fail_alloc) {
- pr_info("Simulated failure modes: gpu: %d, alloc: %d\n",
- fail_gpu, fail_alloc);
- i915_ttm_migrate_set_failure_modes(fail_gpu,
- fail_alloc);
- ret = igt_async_migrate(gt);
- if (ret)
- goto out_err;
+ for (ban_memcpy = 0; ban_memcpy < 2; ++ban_memcpy) {
+ pr_info("Simulated failure modes: gpu: %d, alloc: %d, ban_memcpy: %d\n",
+ fail_gpu, fail_alloc, ban_memcpy);
+ i915_ttm_migrate_set_ban_memcpy(ban_memcpy);
+ i915_ttm_migrate_set_failure_modes(fail_gpu,
+ fail_alloc);
+ ret = igt_async_migrate(gt);
+
+ if (fail_gpu && ban_memcpy) {
+ struct intel_gt *__gt;
+ unsigned int id;
+
+ if (ret != -EIO) {
+ pr_err("expected -EIO, got (%d)\n", ret);
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ }
+
+ for_each_gt(__gt, gt->i915, id) {
+ intel_wakeref_t wakeref;
+ bool wedged;
+
+ mutex_lock(&__gt->reset.mutex);
+ wedged = test_bit(I915_WEDGED, &__gt->reset.flags);
+ mutex_unlock(&__gt->reset.mutex);
+
+ if (fail_gpu && !fail_alloc) {
+ if (!wedged) {
+ pr_err("gt(%u) not wedged\n", id);
+ ret = -EINVAL;
+ continue;
+ }
+ } else if (wedged) {
+ pr_err("gt(%u) incorrectly wedged\n", id);
+ ret = -EINVAL;
+ } else {
+ continue;
+ }
+
+ wakeref = intel_runtime_pm_get(__gt->uncore->rpm);
+ igt_global_reset_lock(__gt);
+ intel_gt_reset(__gt, ALL_ENGINES, NULL);
+ igt_global_reset_unlock(__gt);
+ intel_runtime_pm_put(__gt->uncore->rpm, wakeref);
+ }
+ }
+ if (ret)
+ goto out_err;
+ }
}
}
out_err:
i915_ttm_migrate_set_failure_modes(false, false);
+ i915_ttm_migrate_set_ban_memcpy(false);
return ret;
}
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 5bc93a1ce3e3..3ced9948a331 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -10,6 +10,7 @@
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_ttm.h"
+#include "gem/i915_gem_ttm_move.h"
#include "gt/intel_engine_pm.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_gt.h"
@@ -21,6 +22,7 @@
#include "i915_selftest.h"
#include "selftests/i915_random.h"
#include "selftests/igt_flush_test.h"
+#include "selftests/igt_reset.h"
#include "selftests/igt_mmap.h"
struct tile {
@@ -979,6 +981,9 @@ static int igt_mmap(void *arg)
};
int i;
+ if (mr->private)
+ continue;
+
for (i = 0; i < ARRAY_SIZE(sizes); i++) {
struct drm_i915_gem_object *obj;
int err;
@@ -1160,6 +1165,7 @@ out_unmap:
#define IGT_MMAP_MIGRATE_FILL (1 << 1)
#define IGT_MMAP_MIGRATE_EVICTABLE (1 << 2)
#define IGT_MMAP_MIGRATE_UNFAULTABLE (1 << 3)
+#define IGT_MMAP_MIGRATE_FAIL_GPU (1 << 4)
static int __igt_mmap_migrate(struct intel_memory_region **placements,
int n_placements,
struct intel_memory_region *expected_mr,
@@ -1221,8 +1227,10 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements,
expand32(POISON_INUSE), &rq);
i915_gem_object_unpin_pages(obj);
if (rq) {
- dma_resv_add_fence(obj->base.resv, &rq->fence,
- DMA_RESV_USAGE_KERNEL);
+ err = dma_resv_reserve_fences(obj->base.resv, 1);
+ if (!err)
+ dma_resv_add_fence(obj->base.resv, &rq->fence,
+ DMA_RESV_USAGE_KERNEL);
i915_request_put(rq);
}
i915_gem_object_unlock(obj);
@@ -1232,13 +1240,62 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements,
if (flags & IGT_MMAP_MIGRATE_EVICTABLE)
igt_make_evictable(&objects);
+ if (flags & IGT_MMAP_MIGRATE_FAIL_GPU) {
+ err = i915_gem_object_lock(obj, NULL);
+ if (err)
+ goto out_put;
+
+ /*
+ * Ensure we only simulate the gpu failuire when faulting the
+ * pages.
+ */
+ err = i915_gem_object_wait_moving_fence(obj, true);
+ i915_gem_object_unlock(obj);
+ if (err)
+ goto out_put;
+ i915_ttm_migrate_set_failure_modes(true, false);
+ }
+
err = ___igt_mmap_migrate(i915, obj, addr,
flags & IGT_MMAP_MIGRATE_UNFAULTABLE);
+
if (!err && obj->mm.region != expected_mr) {
pr_err("%s region mismatch %s\n", __func__, expected_mr->name);
err = -EINVAL;
}
+ if (flags & IGT_MMAP_MIGRATE_FAIL_GPU) {
+ struct intel_gt *gt;
+ unsigned int id;
+
+ i915_ttm_migrate_set_failure_modes(false, false);
+
+ for_each_gt(gt, i915, id) {
+ intel_wakeref_t wakeref;
+ bool wedged;
+
+ mutex_lock(&gt->reset.mutex);
+ wedged = test_bit(I915_WEDGED, &gt->reset.flags);
+ mutex_unlock(&gt->reset.mutex);
+ if (!wedged) {
+ pr_err("gt(%u) not wedged\n", id);
+ err = -EINVAL;
+ continue;
+ }
+
+ wakeref = intel_runtime_pm_get(gt->uncore->rpm);
+ igt_global_reset_lock(gt);
+ intel_gt_reset(gt, ALL_ENGINES, NULL);
+ igt_global_reset_unlock(gt);
+ intel_runtime_pm_put(gt->uncore->rpm, wakeref);
+ }
+
+ if (!i915_gem_object_has_unknown_state(obj)) {
+ pr_err("object missing unknown_state\n");
+ err = -EINVAL;
+ }
+ }
+
out_put:
i915_gem_object_put(obj);
igt_close_objects(i915, &objects);
@@ -1319,6 +1376,23 @@ static int igt_mmap_migrate(void *arg)
IGT_MMAP_MIGRATE_TOPDOWN |
IGT_MMAP_MIGRATE_FILL |
IGT_MMAP_MIGRATE_UNFAULTABLE);
+ if (err)
+ goto out_io_size;
+
+ /*
+ * Allocate in the non-mappable portion, but force migrating to
+ * the mappable portion on fault (LMEM -> LMEM). We then also
+ * simulate a gpu error when moving the pages when faulting the
+ * pages, which should result in wedging the gpu and returning
+ * SIGBUS in the fault handler, since we can't fallback to
+ * memcpy.
+ */
+ err = __igt_mmap_migrate(single, ARRAY_SIZE(single), mr,
+ IGT_MMAP_MIGRATE_TOPDOWN |
+ IGT_MMAP_MIGRATE_FILL |
+ IGT_MMAP_MIGRATE_EVICTABLE |
+ IGT_MMAP_MIGRATE_FAIL_GPU |
+ IGT_MMAP_MIGRATE_UNFAULTABLE);
out_io_size:
mr->io_size = saved_io_size;
i915_ttm_buddy_man_force_visible_size(man,
@@ -1435,6 +1509,9 @@ static int igt_mmap_access(void *arg)
struct drm_i915_gem_object *obj;
int err;
+ if (mr->private)
+ continue;
+
obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
@@ -1580,6 +1657,9 @@ static int igt_mmap_gpu(void *arg)
struct drm_i915_gem_object *obj;
int err;
+ if (mr->private)
+ continue;
+
obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
@@ -1727,6 +1807,9 @@ static int igt_mmap_revoke(void *arg)
struct drm_i915_gem_object *obj;
int err;
+ if (mr->private)
+ continue;
+
obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 9dc9dccf7b09..ecc990ec1b95 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -399,7 +399,8 @@ static void insert_breadcrumb(struct i915_request *rq)
* the request as it may have completed and raised the interrupt as
* we were attaching it into the lists.
*/
- irq_work_queue(&b->irq_work);
+ if (!b->irq_armed || __i915_request_is_complete(rq))
+ irq_work_queue(&b->irq_work);
}
bool i915_request_enable_breadcrumb(struct i915_request *rq)
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h
index d2d75d9c0c8d..04eacae1aca5 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -275,10 +275,17 @@ struct intel_context {
u8 child_index;
/** @guc: GuC specific members for parallel submission */
struct {
- /** @wqi_head: head pointer in work queue */
+ /** @wqi_head: cached head pointer in work queue */
u16 wqi_head;
- /** @wqi_tail: tail pointer in work queue */
+ /** @wqi_tail: cached tail pointer in work queue */
u16 wqi_tail;
+ /** @wq_head: pointer to the actual head in work queue */
+ u32 *wq_head;
+ /** @wq_tail: pointer to the actual head in work queue */
+ u32 *wq_tail;
+ /** @wq_status: pointer to the status in work queue */
+ u32 *wq_status;
+
/**
* @parent_page: page in context state (ce->state) used
* by parent for work queue, process descriptor
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 283870c65991..37fa813af766 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1517,7 +1517,6 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine,
struct intel_instdone *instdone)
{
struct drm_i915_private *i915 = engine->i915;
- const struct sseu_dev_info *sseu = &engine->gt->info.sseu;
struct intel_uncore *uncore = engine->uncore;
u32 mmio_base = engine->mmio_base;
int slice;
@@ -1542,32 +1541,19 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine,
intel_uncore_read(uncore, GEN12_SC_INSTDONE_EXTRA2);
}
- if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
- for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) {
- instdone->sampler[slice][subslice] =
- intel_gt_mcr_read(engine->gt,
- GEN7_SAMPLER_INSTDONE,
- slice, subslice);
- instdone->row[slice][subslice] =
- intel_gt_mcr_read(engine->gt,
- GEN7_ROW_INSTDONE,
- slice, subslice);
- }
- } else {
- for_each_instdone_slice_subslice(i915, sseu, slice, subslice) {
- instdone->sampler[slice][subslice] =
- intel_gt_mcr_read(engine->gt,
- GEN7_SAMPLER_INSTDONE,
- slice, subslice);
- instdone->row[slice][subslice] =
- intel_gt_mcr_read(engine->gt,
- GEN7_ROW_INSTDONE,
- slice, subslice);
- }
+ for_each_ss_steering(iter, engine->gt, slice, subslice) {
+ instdone->sampler[slice][subslice] =
+ intel_gt_mcr_read(engine->gt,
+ GEN7_SAMPLER_INSTDONE,
+ slice, subslice);
+ instdone->row[slice][subslice] =
+ intel_gt_mcr_read(engine->gt,
+ GEN7_ROW_INSTDONE,
+ slice, subslice);
}
if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) {
- for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice)
+ for_each_ss_steering(iter, engine->gt, slice, subslice)
instdone->geom_svg[slice][subslice] =
intel_gt_mcr_read(engine->gt,
XEHPG_INSTDONE_GEOM_SVG,
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 2286f96f5f87..633a7e5dba3b 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -647,26 +647,4 @@ intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine)
return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT;
}
-#define instdone_has_slice(dev_priv___, sseu___, slice___) \
- ((GRAPHICS_VER(dev_priv___) == 7 ? 1 : ((sseu___)->slice_mask)) & BIT(slice___))
-
-#define instdone_has_subslice(dev_priv__, sseu__, slice__, subslice__) \
- (GRAPHICS_VER(dev_priv__) == 7 ? (1 & BIT(subslice__)) : \
- intel_sseu_has_subslice(sseu__, 0, subslice__))
-
-#define for_each_instdone_slice_subslice(dev_priv_, sseu_, slice_, subslice_) \
- for ((slice_) = 0, (subslice_) = 0; (slice_) < I915_MAX_SLICES; \
- (subslice_) = ((subslice_) + 1) % I915_MAX_SUBSLICES, \
- (slice_) += ((subslice_) == 0)) \
- for_each_if((instdone_has_slice(dev_priv_, sseu_, slice_)) && \
- (instdone_has_subslice(dev_priv_, sseu_, slice_, \
- subslice_)))
-
-#define for_each_instdone_gslice_dss_xehp(dev_priv_, sseu_, iter_, gslice_, dss_) \
- for ((iter_) = 0, (gslice_) = 0, (dss_) = 0; \
- (iter_) < GEN_SS_MASK_SIZE; \
- (iter_)++, (gslice_) = (iter_) / GEN_DSS_PER_GSLICE, \
- (dss_) = (iter_) % GEN_DSS_PER_GSLICE) \
- for_each_if(intel_sseu_has_subslice((sseu_), 0, (iter_)))
-
#endif /* __INTEL_ENGINE_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 8da3314bb6bf..68c2b0d8f187 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -952,6 +952,20 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
mutex_lock(&gt->tlb_invalidate_lock);
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
+ spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */
+
+ for_each_engine(engine, gt, id) {
+ struct reg_and_bit rb;
+
+ rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
+ if (!i915_mmio_reg_offset(rb.reg))
+ continue;
+
+ intel_uncore_write_fw(uncore, rb.reg, rb.bit);
+ }
+
+ spin_unlock_irq(&uncore->lock);
+
for_each_engine(engine, gt, id) {
/*
* HW architecture suggest typical invalidation time at 40us,
@@ -966,7 +980,6 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
if (!i915_mmio_reg_offset(rb.reg))
continue;
- intel_uncore_write_fw(uncore, rb.reg, rb.bit);
if (__intel_wait_for_register_fw(uncore,
rb.reg, rb.bit, 0,
timeout_us, timeout_ms,
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
index 777025d5bd66..e79405a45312 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
@@ -495,3 +495,28 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
}
}
+/**
+ * intel_gt_mcr_get_ss_steering - returns the group/instance steering for a SS
+ * @gt: GT structure
+ * @dss: DSS ID to obtain steering for
+ * @group: pointer to storage for steering group ID
+ * @instance: pointer to storage for steering instance ID
+ *
+ * Returns the steering IDs (via the @group and @instance parameters) that
+ * correspond to a specific subslice/DSS ID.
+ */
+void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
+ unsigned int *group, unsigned int *instance)
+{
+ if (IS_PONTEVECCHIO(gt->i915)) {
+ *group = dss / GEN_DSS_PER_CSLICE;
+ *instance = dss % GEN_DSS_PER_CSLICE;
+ } else if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50)) {
+ *group = dss / GEN_DSS_PER_GSLICE;
+ *instance = dss % GEN_DSS_PER_GSLICE;
+ } else {
+ *group = dss / GEN_MAX_SS_PER_HSW_SLICE;
+ *instance = dss % GEN_MAX_SS_PER_HSW_SLICE;
+ return;
+ }
+}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
index 506b0cbc8db3..77a8b11c287d 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
@@ -31,4 +31,28 @@ void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt,
void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
bool dump_table);
+void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
+ unsigned int *group, unsigned int *instance);
+
+/*
+ * Helper for for_each_ss_steering loop. On pre-Xe_HP platforms, subslice
+ * presence is determined by using the group/instance as direct lookups in the
+ * slice/subslice topology. On Xe_HP and beyond, the steering is unrelated to
+ * the topology, so we lookup the DSS ID directly in "slice 0."
+ */
+#define _HAS_SS(ss_, gt_, group_, instance_) ( \
+ GRAPHICS_VER_FULL(gt_->i915) >= IP_VER(12, 50) ? \
+ intel_sseu_has_subslice(&(gt_)->info.sseu, 0, ss_) : \
+ intel_sseu_has_subslice(&(gt_)->info.sseu, group_, instance_))
+
+/*
+ * Loop over each subslice/DSS and determine the group and instance IDs that
+ * should be used to steer MCR accesses toward this DSS.
+ */
+#define for_each_ss_steering(ss_, gt_, group_, instance_) \
+ for (ss_ = 0, intel_gt_mcr_get_ss_steering(gt_, 0, &group_, &instance_); \
+ ss_ < I915_MAX_SS_FUSE_BITS; \
+ ss_++, intel_gt_mcr_get_ss_steering(gt_, ss_, &group_, &instance_)) \
+ for_each_if(_HAS_SS(ss_, gt_, group_, instance_))
+
#endif /* __INTEL_GT_MCR__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index 37c1095d8603..60d6eb5f245b 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -371,6 +371,9 @@
#define GEN9_WM_CHICKEN3 _MMIO(0x5588)
#define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9)
+#define CHICKEN_RASTER_1 _MMIO(0x6204)
+#define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8)
+
#define VFLSKPD _MMIO(0x62a8)
#define DIS_OVER_FETCH_CACHE REG_BIT(1)
#define DIS_MULT_MISS_RD_SQUASH REG_BIT(0)
@@ -918,6 +921,10 @@
#define GEN7_L3CNTLREG1 _MMIO(0xb01c)
#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C
#define GEN7_L3AGDIS (1 << 19)
+
+#define XEHPC_LNCFMISCCFGREG0 _MMIO(0xb01c)
+#define XEHPC_OVRLSCCC REG_BIT(0)
+
#define GEN7_L3CNTLREG2 _MMIO(0xb020)
/* MOCS (Memory Object Control State) registers */
diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
index d09b996a9759..6e90032e12e9 100644
--- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c
+++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
@@ -15,6 +15,103 @@
#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_regs.h"
+static void _release_bars(struct pci_dev *pdev)
+{
+ int resno;
+
+ for (resno = PCI_STD_RESOURCES; resno < PCI_STD_RESOURCE_END; resno++) {
+ if (pci_resource_len(pdev, resno))
+ pci_release_resource(pdev, resno);
+ }
+}
+
+static void
+_resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ int bar_size = pci_rebar_bytes_to_size(size);
+ int ret;
+
+ _release_bars(pdev);
+
+ ret = pci_resize_resource(pdev, resno, bar_size);
+ if (ret) {
+ drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n",
+ resno, 1 << bar_size, ERR_PTR(ret));
+ return;
+ }
+
+ drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size);
+}
+
+#define LMEM_BAR_NUM 2
+static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ struct pci_bus *root = pdev->bus;
+ struct resource *root_res;
+ resource_size_t rebar_size;
+ resource_size_t current_size;
+ u32 pci_cmd;
+ int i;
+
+ current_size = roundup_pow_of_two(pci_resource_len(pdev, LMEM_BAR_NUM));
+
+ if (i915->params.lmem_bar_size) {
+ u32 bar_sizes;
+
+ rebar_size = i915->params.lmem_bar_size *
+ (resource_size_t)SZ_1M;
+ bar_sizes = pci_rebar_get_possible_sizes(pdev,
+ LMEM_BAR_NUM);
+
+ if (rebar_size == current_size)
+ return;
+
+ if (!(bar_sizes & BIT(pci_rebar_bytes_to_size(rebar_size))) ||
+ rebar_size >= roundup_pow_of_two(lmem_size)) {
+ rebar_size = lmem_size;
+
+ drm_info(&i915->drm,
+ "Given bar size is not within supported size, setting it to default: %llu\n",
+ (u64)lmem_size >> 20);
+ }
+ } else {
+ rebar_size = current_size;
+
+ if (rebar_size != roundup_pow_of_two(lmem_size))
+ rebar_size = lmem_size;
+ else
+ return;
+ }
+
+ /* Find out if root bus contains 64bit memory addressing */
+ while (root->parent)
+ root = root->parent;
+
+ pci_bus_for_each_resource(root, root_res, i) {
+ if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) &&
+ root_res->start > 0x100000000ull)
+ break;
+ }
+
+ /* pci_resize_resource will fail anyways */
+ if (!root_res) {
+ drm_info(&i915->drm, "Can't resize LMEM BAR - platform support is missing\n");
+ return;
+ }
+
+ /* First disable PCI memory decoding references */
+ pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd);
+ pci_write_config_dword(pdev, PCI_COMMAND,
+ pci_cmd & ~PCI_COMMAND_MEMORY);
+
+ _resize_bar(i915, LMEM_BAR_NUM, rebar_size);
+
+ pci_assign_unassigned_bus_resources(pdev->bus);
+ pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd);
+}
+
static int
region_lmem_release(struct intel_memory_region *mem)
{
@@ -112,12 +209,6 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt)
flat_ccs_base = intel_gt_mcr_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR);
flat_ccs_base = (flat_ccs_base >> XEHP_CCS_BASE_SHIFT) * SZ_64K;
- /* FIXME: Remove this when we have small-bar enabled */
- if (pci_resource_len(pdev, 2) < lmem_size) {
- drm_err(&i915->drm, "System requires small-BAR support, which is currently unsupported on this kernel\n");
- return ERR_PTR(-EINVAL);
- }
-
if (GEM_WARN_ON(lmem_size < flat_ccs_base))
return ERR_PTR(-EIO);
@@ -134,6 +225,8 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt)
lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE);
}
+ i915_resize_lmem_bar(i915, lmem_size);
+
if (i915->params.lmem_size > 0) {
lmem_size = min_t(resource_size_t, lmem_size,
mul_u32_u32(i915->params.lmem_size, SZ_1M));
@@ -170,6 +263,10 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt)
drm_info(&i915->drm, "Local memory available: %pa\n",
&lmem_size);
+ if (io_size < lmem_size)
+ drm_info(&i915->drm, "Using a reduced BAR size of %lluMiB. Consider enabling 'Resizable BAR' or similar, if available in the BIOS.\n",
+ (u64)io_size >> 20);
+
return mem;
err_region_put:
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index a5338c3fde7a..c68d36fb5bbd 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -300,9 +300,9 @@ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)
return err;
}
-static int gen6_reset_engines(struct intel_gt *gt,
- intel_engine_mask_t engine_mask,
- unsigned int retry)
+static int __gen6_reset_engines(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask,
+ unsigned int retry)
{
struct intel_engine_cs *engine;
u32 hw_mask;
@@ -321,6 +321,20 @@ static int gen6_reset_engines(struct intel_gt *gt,
return gen6_hw_domain_reset(gt, hw_mask);
}
+static int gen6_reset_engines(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask,
+ unsigned int retry)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&gt->uncore->lock, flags);
+ ret = __gen6_reset_engines(gt, engine_mask, retry);
+ spin_unlock_irqrestore(&gt->uncore->lock, flags);
+
+ return ret;
+}
+
static struct intel_engine_cs *find_sfc_paired_vecs_engine(struct intel_engine_cs *engine)
{
int vecs_id;
@@ -487,9 +501,9 @@ static void gen11_unlock_sfc(struct intel_engine_cs *engine)
rmw_clear_fw(uncore, sfc_lock.lock_reg, sfc_lock.lock_bit);
}
-static int gen11_reset_engines(struct intel_gt *gt,
- intel_engine_mask_t engine_mask,
- unsigned int retry)
+static int __gen11_reset_engines(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask,
+ unsigned int retry)
{
struct intel_engine_cs *engine;
intel_engine_mask_t tmp;
@@ -583,8 +597,11 @@ static int gen8_reset_engines(struct intel_gt *gt,
struct intel_engine_cs *engine;
const bool reset_non_ready = retry >= 1;
intel_engine_mask_t tmp;
+ unsigned long flags;
int ret;
+ spin_lock_irqsave(&gt->uncore->lock, flags);
+
for_each_engine_masked(engine, gt, engine_mask, tmp) {
ret = gen8_engine_reset_prepare(engine);
if (ret && !reset_non_ready)
@@ -612,17 +629,19 @@ static int gen8_reset_engines(struct intel_gt *gt,
* This is best effort, so ignore any error from the initial reset.
*/
if (IS_DG2(gt->i915) && engine_mask == ALL_ENGINES)
- gen11_reset_engines(gt, gt->info.engine_mask, 0);
+ __gen11_reset_engines(gt, gt->info.engine_mask, 0);
if (GRAPHICS_VER(gt->i915) >= 11)
- ret = gen11_reset_engines(gt, engine_mask, retry);
+ ret = __gen11_reset_engines(gt, engine_mask, retry);
else
- ret = gen6_reset_engines(gt, engine_mask, retry);
+ ret = __gen6_reset_engines(gt, engine_mask, retry);
skip_reset:
for_each_engine_masked(engine, gt, engine_mask, tmp)
gen8_engine_reset_cancel(engine);
+ spin_unlock_irqrestore(&gt->uncore->lock, flags);
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 3213c593a55f..e8111fce56d0 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -689,6 +689,9 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine,
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_B0, STEP_FOREVER) ||
IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915))
wa_masked_field_set(wal, VF_PREEMPTION, PREEMPTION_VERTEX_COUNT, 0x4000);
+
+ /* Wa_15010599737:dg2 */
+ wa_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN);
}
static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine,
@@ -2687,6 +2690,9 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
* performance guide section.
*/
wa_write(wal, XEHPC_L3SCRUB, SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK);
+
+ /* Wa_16016694945 */
+ wa_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC);
}
if (IS_XEHPSDV(i915)) {
diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index 8b2c11dbe354..1109088fe8f6 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -176,8 +176,8 @@ static int live_lrc_layout(void *arg)
continue;
hw = shmem_pin_map(engine->default_state);
- if (IS_ERR(hw)) {
- err = PTR_ERR(hw);
+ if (!hw) {
+ err = -ENOMEM;
break;
}
hw += LRC_STATE_OFFSET / sizeof(*hw);
@@ -365,8 +365,8 @@ static int live_lrc_fixed(void *arg)
continue;
hw = shmem_pin_map(engine->default_state);
- if (IS_ERR(hw)) {
- err = PTR_ERR(hw);
+ if (!hw) {
+ err = -ENOMEM;
break;
}
hw += LRC_STATE_OFFSET / sizeof(*hw);
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
index b768cea5943d..ac29691e0b1a 100644
--- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -8,6 +8,11 @@
#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
#define FREQUENCY_REQ_UNIT DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \
GEN9_FREQ_SCALER)
+enum test_type {
+ VARY_MIN,
+ VARY_MAX,
+ MAX_GRANTED
+};
static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
{
@@ -36,147 +41,114 @@ static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
return ret;
}
-static int live_slpc_clamp_min(void *arg)
+static int vary_max_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
+ u32 *max_act_freq)
{
- struct drm_i915_private *i915 = arg;
- struct intel_gt *gt = to_gt(i915);
- struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
- struct intel_rps *rps = &gt->rps;
- struct intel_engine_cs *engine;
- enum intel_engine_id id;
- struct igt_spinner spin;
- u32 slpc_min_freq, slpc_max_freq;
+ u32 step, max_freq, req_freq;
+ u32 act_freq;
int err = 0;
- if (!intel_uc_uses_guc_slpc(&gt->uc))
- return 0;
+ /* Go from max to min in 5 steps */
+ step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
+ *max_act_freq = slpc->min_freq;
+ for (max_freq = slpc->rp0_freq; max_freq > slpc->min_freq;
+ max_freq -= step) {
+ err = slpc_set_max_freq(slpc, max_freq);
+ if (err)
+ break;
- if (igt_spinner_init(&spin, gt))
- return -ENOMEM;
+ req_freq = intel_rps_read_punit_req_frequency(rps);
- if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
- pr_err("Could not get SLPC max freq\n");
- return -EIO;
- }
+ /* GuC requests freq in multiples of 50/3 MHz */
+ if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
+ pr_err("SWReq is %d, should be at most %d\n", req_freq,
+ max_freq + FREQUENCY_REQ_UNIT);
+ err = -EINVAL;
+ }
- if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
- pr_err("Could not get SLPC min freq\n");
- return -EIO;
- }
+ act_freq = intel_rps_read_actual_frequency(rps);
+ if (act_freq > *max_act_freq)
+ *max_act_freq = act_freq;
- if (slpc_min_freq == slpc_max_freq) {
- pr_err("Min/Max are fused to the same value\n");
- return -EINVAL;
+ if (err)
+ break;
}
- intel_gt_pm_wait_for_idle(gt);
- intel_gt_pm_get(gt);
- for_each_engine(engine, gt, id) {
- struct i915_request *rq;
- u32 step, min_freq, req_freq;
- u32 act_freq, max_act_freq;
+ return err;
+}
- if (!intel_engine_can_store_dword(engine))
- continue;
+static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
+ u32 *max_act_freq)
+{
+ u32 step, min_freq, req_freq;
+ u32 act_freq;
+ int err = 0;
- /* Go from min to max in 5 steps */
- step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
- max_act_freq = slpc_min_freq;
- for (min_freq = slpc_min_freq; min_freq < slpc_max_freq;
- min_freq += step) {
- err = slpc_set_min_freq(slpc, min_freq);
- if (err)
- break;
-
- st_engine_heartbeat_disable(engine);
-
- rq = igt_spinner_create_request(&spin,
- engine->kernel_context,
- MI_NOOP);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- st_engine_heartbeat_enable(engine);
- break;
- }
+ /* Go from min to max in 5 steps */
+ step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
+ *max_act_freq = slpc->min_freq;
+ for (min_freq = slpc->min_freq; min_freq < slpc->rp0_freq;
+ min_freq += step) {
+ err = slpc_set_min_freq(slpc, min_freq);
+ if (err)
+ break;
- i915_request_add(rq);
+ req_freq = intel_rps_read_punit_req_frequency(rps);
- if (!igt_wait_for_spinner(&spin, rq)) {
- pr_err("%s: Spinner did not start\n",
- engine->name);
- igt_spinner_end(&spin);
- st_engine_heartbeat_enable(engine);
- intel_gt_set_wedged(engine->gt);
- err = -EIO;
- break;
- }
+ /* GuC requests freq in multiples of 50/3 MHz */
+ if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
+ pr_err("SWReq is %d, should be at least %d\n", req_freq,
+ min_freq - FREQUENCY_REQ_UNIT);
+ err = -EINVAL;
+ }
- /* Wait for GuC to detect business and raise
- * requested frequency if necessary.
- */
- delay_for_h2g();
+ act_freq = intel_rps_read_actual_frequency(rps);
+ if (act_freq > *max_act_freq)
+ *max_act_freq = act_freq;
- req_freq = intel_rps_read_punit_req_frequency(rps);
+ if (err)
+ break;
+ }
- /* GuC requests freq in multiples of 50/3 MHz */
- if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
- pr_err("SWReq is %d, should be at least %d\n", req_freq,
- min_freq - FREQUENCY_REQ_UNIT);
- igt_spinner_end(&spin);
- st_engine_heartbeat_enable(engine);
- err = -EINVAL;
- break;
- }
+ return err;
+}
- act_freq = intel_rps_read_actual_frequency(rps);
- if (act_freq > max_act_freq)
- max_act_freq = act_freq;
+static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, u32 *max_act_freq)
+{
+ struct intel_gt *gt = rps_to_gt(rps);
+ u32 perf_limit_reasons;
+ int err = 0;
- igt_spinner_end(&spin);
- st_engine_heartbeat_enable(engine);
- }
+ err = slpc_set_min_freq(slpc, slpc->rp0_freq);
+ if (err)
+ return err;
- pr_info("Max actual frequency for %s was %d\n",
- engine->name, max_act_freq);
+ *max_act_freq = intel_rps_read_actual_frequency(rps);
+ if (*max_act_freq != slpc->rp0_freq) {
+ /* Check if there was some throttling by pcode */
+ perf_limit_reasons = intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS);
- /* Actual frequency should rise above min */
- if (max_act_freq == slpc_min_freq) {
- pr_err("Actual freq did not rise above min\n");
+ /* If not, this is an error */
+ if (!(perf_limit_reasons & GT0_PERF_LIMIT_REASONS_MASK)) {
+ pr_err("Pcode did not grant max freq\n");
err = -EINVAL;
+ } else {
+ pr_info("Pcode throttled frequency 0x%x\n", perf_limit_reasons);
}
-
- if (err)
- break;
}
- /* Restore min/max frequencies */
- slpc_set_max_freq(slpc, slpc_max_freq);
- slpc_set_min_freq(slpc, slpc_min_freq);
-
- if (igt_flush_test(gt->i915))
- err = -EIO;
-
- intel_gt_pm_put(gt);
- igt_spinner_fini(&spin);
- intel_gt_pm_wait_for_idle(gt);
-
return err;
}
-static int live_slpc_clamp_max(void *arg)
+static int run_test(struct intel_gt *gt, int test_type)
{
- struct drm_i915_private *i915 = arg;
- struct intel_gt *gt = to_gt(i915);
- struct intel_guc_slpc *slpc;
- struct intel_rps *rps;
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+ struct intel_rps *rps = &gt->rps;
struct intel_engine_cs *engine;
enum intel_engine_id id;
struct igt_spinner spin;
- int err = 0;
u32 slpc_min_freq, slpc_max_freq;
-
- slpc = &gt->uc.guc.slpc;
- rps = &gt->rps;
+ int err = 0;
if (!intel_uc_uses_guc_slpc(&gt->uc))
return 0;
@@ -194,7 +166,7 @@ static int live_slpc_clamp_max(void *arg)
return -EIO;
}
- if (slpc_min_freq == slpc_max_freq) {
+ if (slpc->min_freq == slpc->rp0_freq) {
pr_err("Min/Max are fused to the same value\n");
return -EINVAL;
}
@@ -203,93 +175,82 @@ static int live_slpc_clamp_max(void *arg)
intel_gt_pm_get(gt);
for_each_engine(engine, gt, id) {
struct i915_request *rq;
- u32 max_freq, req_freq;
- u32 act_freq, max_act_freq;
- u32 step;
+ u32 max_act_freq;
if (!intel_engine_can_store_dword(engine))
continue;
- /* Go from max to min in 5 steps */
- step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
- max_act_freq = slpc_min_freq;
- for (max_freq = slpc_max_freq; max_freq > slpc_min_freq;
- max_freq -= step) {
- err = slpc_set_max_freq(slpc, max_freq);
- if (err)
- break;
-
- st_engine_heartbeat_disable(engine);
-
- rq = igt_spinner_create_request(&spin,
- engine->kernel_context,
- MI_NOOP);
- if (IS_ERR(rq)) {
- st_engine_heartbeat_enable(engine);
- err = PTR_ERR(rq);
- break;
- }
+ st_engine_heartbeat_disable(engine);
- i915_request_add(rq);
+ rq = igt_spinner_create_request(&spin,
+ engine->kernel_context,
+ MI_NOOP);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ st_engine_heartbeat_enable(engine);
+ break;
+ }
- if (!igt_wait_for_spinner(&spin, rq)) {
- pr_err("%s: SLPC spinner did not start\n",
- engine->name);
- igt_spinner_end(&spin);
- st_engine_heartbeat_enable(engine);
- intel_gt_set_wedged(engine->gt);
- err = -EIO;
- break;
- }
+ i915_request_add(rq);
- delay_for_h2g();
+ if (!igt_wait_for_spinner(&spin, rq)) {
+ pr_err("%s: Spinner did not start\n",
+ engine->name);
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ intel_gt_set_wedged(engine->gt);
+ err = -EIO;
+ break;
+ }
- /* Verify that SWREQ indeed was set to specific value */
- req_freq = intel_rps_read_punit_req_frequency(rps);
+ switch (test_type) {
+ case VARY_MIN:
+ err = vary_min_freq(slpc, rps, &max_act_freq);
+ break;
- /* GuC requests freq in multiples of 50/3 MHz */
- if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
- pr_err("SWReq is %d, should be at most %d\n", req_freq,
- max_freq + FREQUENCY_REQ_UNIT);
+ case VARY_MAX:
+ err = vary_max_freq(slpc, rps, &max_act_freq);
+ break;
+
+ case MAX_GRANTED:
+ /* Media engines have a different RP0 */
+ if (engine->class == VIDEO_DECODE_CLASS ||
+ engine->class == VIDEO_ENHANCEMENT_CLASS) {
igt_spinner_end(&spin);
st_engine_heartbeat_enable(engine);
- err = -EINVAL;
- break;
+ err = 0;
+ continue;
}
- act_freq = intel_rps_read_actual_frequency(rps);
- if (act_freq > max_act_freq)
- max_act_freq = act_freq;
-
- st_engine_heartbeat_enable(engine);
- igt_spinner_end(&spin);
-
- if (err)
- break;
+ err = max_granted_freq(slpc, rps, &max_act_freq);
+ break;
}
pr_info("Max actual frequency for %s was %d\n",
engine->name, max_act_freq);
/* Actual frequency should rise above min */
- if (max_act_freq == slpc_min_freq) {
+ if (max_act_freq <= slpc_min_freq) {
pr_err("Actual freq did not rise above min\n");
+ pr_err("Perf Limit Reasons: 0x%x\n",
+ intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS));
err = -EINVAL;
}
- if (igt_flush_test(gt->i915)) {
- err = -EIO;
- break;
- }
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
if (err)
break;
}
- /* Restore min/max freq */
+ /* Restore min/max frequencies */
slpc_set_max_freq(slpc, slpc_max_freq);
slpc_set_min_freq(slpc, slpc_min_freq);
+ if (igt_flush_test(gt->i915))
+ err = -EIO;
+
intel_gt_pm_put(gt);
igt_spinner_fini(&spin);
intel_gt_pm_wait_for_idle(gt);
@@ -297,11 +258,37 @@ static int live_slpc_clamp_max(void *arg)
return err;
}
+static int live_slpc_vary_min(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt = to_gt(i915);
+
+ return run_test(gt, VARY_MIN);
+}
+
+static int live_slpc_vary_max(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt = to_gt(i915);
+
+ return run_test(gt, VARY_MAX);
+}
+
+/* check if pcode can grant RP0 */
+static int live_slpc_max_granted(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt = to_gt(i915);
+
+ return run_test(gt, MAX_GRANTED);
+}
+
int intel_slpc_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
- SUBTEST(live_slpc_clamp_max),
- SUBTEST(live_slpc_clamp_min),
+ SUBTEST(live_slpc_vary_max),
+ SUBTEST(live_slpc_vary_min),
+ SUBTEST(live_slpc_max_granted),
};
if (intel_gt_is_wedged(to_gt(i915)))
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 4ef9990ed7f8..29ef8afc8c2e 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -122,6 +122,9 @@ enum intel_guc_action {
INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
INTEL_GUC_ACTION_SCHED_ENGINE_MODE_SET = 0x1003,
INTEL_GUC_ACTION_SCHED_ENGINE_MODE_DONE = 0x1004,
+ INTEL_GUC_ACTION_V69_SET_CONTEXT_PRIORITY = 0x1005,
+ INTEL_GUC_ACTION_V69_SET_CONTEXT_EXECUTION_QUANTUM = 0x1006,
+ INTEL_GUC_ACTION_V69_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007,
INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
INTEL_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES = 0x100B,
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index d0d99f178f2d..a7acffbf15d1 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -170,6 +170,11 @@ struct intel_guc {
/** @ads_engine_usage_size: size of engine usage in the ADS */
u32 ads_engine_usage_size;
+ /** @lrc_desc_pool_v69: object allocated to hold the GuC LRC descriptor pool */
+ struct i915_vma *lrc_desc_pool_v69;
+ /** @lrc_desc_pool_vaddr_v69: contents of the GuC LRC descriptor pool */
+ void *lrc_desc_pool_vaddr_v69;
+
/**
* @context_lookup: used to resolve intel_context from guc_id, if a
* context is present in this structure it is registered with the GuC
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
index 97a32e610c30..75257bd20ff0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
@@ -9,6 +9,7 @@
#include "gt/intel_engine_regs.h"
#include "gt/intel_gt.h"
+#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_regs.h"
#include "gt/intel_lrc.h"
#include "guc_capture_fwif.h"
@@ -281,8 +282,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc,
const struct __guc_mmio_reg_descr_group *lists)
{
struct intel_gt *gt = guc_to_gt(guc);
- struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
- int slice, subslice, i, num_steer_regs, num_tot_regs = 0;
+ int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0;
const struct __guc_mmio_reg_descr_group *list;
struct __guc_mmio_reg_descr_group *extlists;
struct __guc_mmio_reg_descr *extarray;
@@ -298,7 +298,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc,
num_steer_regs = ARRAY_SIZE(xe_extregs);
sseu = &gt->info.sseu;
- for_each_instdone_slice_subslice(i915, sseu, slice, subslice)
+ for_each_ss_steering(iter, gt, slice, subslice)
num_tot_regs += num_steer_regs;
if (!num_tot_regs)
@@ -315,7 +315,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc,
}
extarray = extlists[0].extlist;
- for_each_instdone_slice_subslice(i915, sseu, slice, subslice) {
+ for_each_ss_steering(iter, gt, slice, subslice) {
for (i = 0; i < num_steer_regs; ++i) {
__fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
++extarray;
@@ -359,9 +359,8 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc,
num_steer_regs += ARRAY_SIZE(xehpg_extregs);
sseu = &gt->info.sseu;
- for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) {
+ for_each_ss_steering(iter, gt, slice, subslice)
num_tot_regs += num_steer_regs;
- }
if (!num_tot_regs)
return;
@@ -377,7 +376,7 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc,
}
extarray = extlists[0].extlist;
- for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) {
+ for_each_ss_steering(iter, gt, slice, subslice) {
for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) {
__fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
++extarray;
@@ -1261,7 +1260,8 @@ static int __guc_capture_flushlog_complete(struct intel_guc *guc)
GUC_CAPTURE_LOG_BUFFER
};
- return intel_guc_send(guc, action, ARRAY_SIZE(action));
+ return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0);
+
}
static void __guc_capture_process_output(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index b3c9a9327f76..323b055e5db9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -204,6 +204,20 @@ struct guc_wq_item {
u32 fence_id;
} __packed;
+struct guc_process_desc_v69 {
+ u32 stage_id;
+ u64 db_base_addr;
+ u32 head;
+ u32 tail;
+ u32 error_offset;
+ u64 wq_base_addr;
+ u32 wq_size_bytes;
+ u32 wq_status;
+ u32 engine_presence;
+ u32 priority;
+ u32 reserved[36];
+} __packed;
+
struct guc_sched_wq_desc {
u32 head;
u32 tail;
@@ -228,6 +242,37 @@ struct guc_ctxt_registration_info {
};
#define CONTEXT_REGISTRATION_FLAG_KMD BIT(0)
+/* Preempt to idle on quantum expiry */
+#define CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69 BIT(0)
+
+/*
+ * GuC Context registration descriptor.
+ * FIXME: This is only required to exist during context registration.
+ * The current 1:1 between guc_lrc_desc and LRCs for the lifetime of the LRC
+ * is not required.
+ */
+struct guc_lrc_desc_v69 {
+ u32 hw_context_desc;
+ u32 slpm_perf_mode_hint; /* SPLC v1 only */
+ u32 slpm_freq_hint;
+ u32 engine_submit_mask; /* In logical space */
+ u8 engine_class;
+ u8 reserved0[3];
+ u32 priority;
+ u32 process_desc;
+ u32 wq_addr;
+ u32 wq_size;
+ u32 context_flags; /* CONTEXT_REGISTRATION_* */
+ /* Time for one workload to execute. (in micro seconds) */
+ u32 execution_quantum;
+ /* Time to wait for a preemption request to complete before issuing a
+ * reset. (in micro seconds).
+ */
+ u32 preemption_timeout;
+ u32 policy_flags; /* CONTEXT_POLICY_* */
+ u32 reserved1[19];
+} __packed;
+
/* 32-bit KLV structure as used by policy updates and others */
struct guc_klv_generic_dw_t {
u32 kl;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
index 02311ad90264..25b2d7ce6640 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
@@ -31,7 +31,7 @@ static int guc_action_flush_log_complete(struct intel_guc *guc)
GUC_DEBUG_LOG_BUFFER
};
- return intel_guc_send(guc, action, ARRAY_SIZE(action));
+ return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0);
}
static int guc_action_flush_log(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 40f726c61e95..76916aed897a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -414,12 +414,15 @@ struct sync_semaphore {
};
struct parent_scratch {
- struct guc_sched_wq_desc wq_desc;
+ union guc_descs {
+ struct guc_sched_wq_desc wq_desc;
+ struct guc_process_desc_v69 pdesc;
+ } descs;
struct sync_semaphore go;
struct sync_semaphore join[MAX_ENGINE_INSTANCE + 1];
- u8 unused[WQ_OFFSET - sizeof(struct guc_sched_wq_desc) -
+ u8 unused[WQ_OFFSET - sizeof(union guc_descs) -
sizeof(struct sync_semaphore) * (MAX_ENGINE_INSTANCE + 2)];
u32 wq[WQ_SIZE / sizeof(u32)];
@@ -456,17 +459,23 @@ __get_parent_scratch(struct intel_context *ce)
LRC_STATE_OFFSET) / sizeof(u32)));
}
+static struct guc_process_desc_v69 *
+__get_process_desc_v69(struct intel_context *ce)
+{
+ struct parent_scratch *ps = __get_parent_scratch(ce);
+
+ return &ps->descs.pdesc;
+}
+
static struct guc_sched_wq_desc *
-__get_wq_desc(struct intel_context *ce)
+__get_wq_desc_v70(struct intel_context *ce)
{
struct parent_scratch *ps = __get_parent_scratch(ce);
- return &ps->wq_desc;
+ return &ps->descs.wq_desc;
}
-static u32 *get_wq_pointer(struct guc_sched_wq_desc *wq_desc,
- struct intel_context *ce,
- u32 wqi_size)
+static u32 *get_wq_pointer(struct intel_context *ce, u32 wqi_size)
{
/*
* Check for space in work queue. Caching a value of head pointer in
@@ -476,7 +485,7 @@ static u32 *get_wq_pointer(struct guc_sched_wq_desc *wq_desc,
#define AVAILABLE_SPACE \
CIRC_SPACE(ce->parallel.guc.wqi_tail, ce->parallel.guc.wqi_head, WQ_SIZE)
if (wqi_size > AVAILABLE_SPACE) {
- ce->parallel.guc.wqi_head = READ_ONCE(wq_desc->head);
+ ce->parallel.guc.wqi_head = READ_ONCE(*ce->parallel.guc.wq_head);
if (wqi_size > AVAILABLE_SPACE)
return NULL;
@@ -495,11 +504,55 @@ static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id)
return ce;
}
+static struct guc_lrc_desc_v69 *__get_lrc_desc_v69(struct intel_guc *guc, u32 index)
+{
+ struct guc_lrc_desc_v69 *base = guc->lrc_desc_pool_vaddr_v69;
+
+ if (!base)
+ return NULL;
+
+ GEM_BUG_ON(index >= GUC_MAX_CONTEXT_ID);
+
+ return &base[index];
+}
+
+static int guc_lrc_desc_pool_create_v69(struct intel_guc *guc)
+{
+ u32 size;
+ int ret;
+
+ size = PAGE_ALIGN(sizeof(struct guc_lrc_desc_v69) *
+ GUC_MAX_CONTEXT_ID);
+ ret = intel_guc_allocate_and_map_vma(guc, size, &guc->lrc_desc_pool_v69,
+ (void **)&guc->lrc_desc_pool_vaddr_v69);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void guc_lrc_desc_pool_destroy_v69(struct intel_guc *guc)
+{
+ if (!guc->lrc_desc_pool_vaddr_v69)
+ return;
+
+ guc->lrc_desc_pool_vaddr_v69 = NULL;
+ i915_vma_unpin_and_release(&guc->lrc_desc_pool_v69, I915_VMA_RELEASE_MAP);
+}
+
static inline bool guc_submission_initialized(struct intel_guc *guc)
{
return guc->submission_initialized;
}
+static inline void _reset_lrc_desc_v69(struct intel_guc *guc, u32 id)
+{
+ struct guc_lrc_desc_v69 *desc = __get_lrc_desc_v69(guc, id);
+
+ if (desc)
+ memset(desc, 0, sizeof(*desc));
+}
+
static inline bool ctx_id_mapped(struct intel_guc *guc, u32 id)
{
return __get_context(guc, id);
@@ -526,6 +579,8 @@ static inline void clr_ctx_id_mapping(struct intel_guc *guc, u32 id)
if (unlikely(!guc_submission_initialized(guc)))
return;
+ _reset_lrc_desc_v69(guc, id);
+
/*
* xarray API doesn't have xa_erase_irqsave wrapper, so calling
* the lower level functions directly.
@@ -611,7 +666,7 @@ int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout)
true, timeout);
}
-static int guc_context_policy_init(struct intel_context *ce, bool loop);
+static int guc_context_policy_init_v70(struct intel_context *ce, bool loop);
static int try_context_registration(struct intel_context *ce, bool loop);
static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq)
@@ -639,7 +694,7 @@ static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq)
GEM_BUG_ON(context_guc_id_invalid(ce));
if (context_policy_required(ce)) {
- err = guc_context_policy_init(ce, false);
+ err = guc_context_policy_init_v70(ce, false);
if (err)
return err;
}
@@ -737,9 +792,7 @@ static u32 wq_space_until_wrap(struct intel_context *ce)
return (WQ_SIZE - ce->parallel.guc.wqi_tail);
}
-static void write_wqi(struct guc_sched_wq_desc *wq_desc,
- struct intel_context *ce,
- u32 wqi_size)
+static void write_wqi(struct intel_context *ce, u32 wqi_size)
{
BUILD_BUG_ON(!is_power_of_2(WQ_SIZE));
@@ -750,13 +803,12 @@ static void write_wqi(struct guc_sched_wq_desc *wq_desc,
ce->parallel.guc.wqi_tail = (ce->parallel.guc.wqi_tail + wqi_size) &
(WQ_SIZE - 1);
- WRITE_ONCE(wq_desc->tail, ce->parallel.guc.wqi_tail);
+ WRITE_ONCE(*ce->parallel.guc.wq_tail, ce->parallel.guc.wqi_tail);
}
static int guc_wq_noop_append(struct intel_context *ce)
{
- struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
- u32 *wqi = get_wq_pointer(wq_desc, ce, wq_space_until_wrap(ce));
+ u32 *wqi = get_wq_pointer(ce, wq_space_until_wrap(ce));
u32 len_dw = wq_space_until_wrap(ce) / sizeof(u32) - 1;
if (!wqi)
@@ -775,7 +827,6 @@ static int __guc_wq_item_append(struct i915_request *rq)
{
struct intel_context *ce = request_to_scheduling_context(rq);
struct intel_context *child;
- struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
unsigned int wqi_size = (ce->parallel.number_children + 4) *
sizeof(u32);
u32 *wqi;
@@ -795,7 +846,7 @@ static int __guc_wq_item_append(struct i915_request *rq)
return ret;
}
- wqi = get_wq_pointer(wq_desc, ce, wqi_size);
+ wqi = get_wq_pointer(ce, wqi_size);
if (!wqi)
return -EBUSY;
@@ -810,7 +861,7 @@ static int __guc_wq_item_append(struct i915_request *rq)
for_each_child(ce, child)
*wqi++ = child->ring->tail / sizeof(u64);
- write_wqi(wq_desc, ce, wqi_size);
+ write_wqi(ce, wqi_size);
return 0;
}
@@ -1812,20 +1863,34 @@ static void reset_fail_worker_func(struct work_struct *w);
int intel_guc_submission_init(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
+ int ret;
if (guc->submission_initialized)
return 0;
+ if (guc->fw.major_ver_found < 70) {
+ ret = guc_lrc_desc_pool_create_v69(guc);
+ if (ret)
+ return ret;
+ }
+
guc->submission_state.guc_ids_bitmap =
bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL);
- if (!guc->submission_state.guc_ids_bitmap)
- return -ENOMEM;
+ if (!guc->submission_state.guc_ids_bitmap) {
+ ret = -ENOMEM;
+ goto destroy_pool;
+ }
guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ;
guc->timestamp.shift = gpm_timestamp_shift(gt);
guc->submission_initialized = true;
return 0;
+
+destroy_pool:
+ guc_lrc_desc_pool_destroy_v69(guc);
+
+ return ret;
}
void intel_guc_submission_fini(struct intel_guc *guc)
@@ -1834,6 +1899,7 @@ void intel_guc_submission_fini(struct intel_guc *guc)
return;
guc_flush_destroyed_contexts(guc);
+ guc_lrc_desc_pool_destroy_v69(guc);
i915_sched_engine_put(guc->sched_engine);
bitmap_free(guc->submission_state.guc_ids_bitmap);
guc->submission_initialized = false;
@@ -2091,10 +2157,34 @@ static void unpin_guc_id(struct intel_guc *guc, struct intel_context *ce)
spin_unlock_irqrestore(&guc->submission_state.lock, flags);
}
-static int __guc_action_register_multi_lrc(struct intel_guc *guc,
- struct intel_context *ce,
- struct guc_ctxt_registration_info *info,
- bool loop)
+static int __guc_action_register_multi_lrc_v69(struct intel_guc *guc,
+ struct intel_context *ce,
+ u32 guc_id,
+ u32 offset,
+ bool loop)
+{
+ struct intel_context *child;
+ u32 action[4 + MAX_ENGINE_INSTANCE];
+ int len = 0;
+
+ GEM_BUG_ON(ce->parallel.number_children > MAX_ENGINE_INSTANCE);
+
+ action[len++] = INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC;
+ action[len++] = guc_id;
+ action[len++] = ce->parallel.number_children + 1;
+ action[len++] = offset;
+ for_each_child(ce, child) {
+ offset += sizeof(struct guc_lrc_desc_v69);
+ action[len++] = offset;
+ }
+
+ return guc_submission_send_busy_loop(guc, action, len, 0, loop);
+}
+
+static int __guc_action_register_multi_lrc_v70(struct intel_guc *guc,
+ struct intel_context *ce,
+ struct guc_ctxt_registration_info *info,
+ bool loop)
{
struct intel_context *child;
u32 action[13 + (MAX_ENGINE_INSTANCE * 2)];
@@ -2134,9 +2224,24 @@ static int __guc_action_register_multi_lrc(struct intel_guc *guc,
return guc_submission_send_busy_loop(guc, action, len, 0, loop);
}
-static int __guc_action_register_context(struct intel_guc *guc,
- struct guc_ctxt_registration_info *info,
- bool loop)
+static int __guc_action_register_context_v69(struct intel_guc *guc,
+ u32 guc_id,
+ u32 offset,
+ bool loop)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_REGISTER_CONTEXT,
+ guc_id,
+ offset,
+ };
+
+ return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
+ 0, loop);
+}
+
+static int __guc_action_register_context_v70(struct intel_guc *guc,
+ struct guc_ctxt_registration_info *info,
+ bool loop)
{
u32 action[] = {
INTEL_GUC_ACTION_REGISTER_CONTEXT,
@@ -2157,24 +2262,52 @@ static int __guc_action_register_context(struct intel_guc *guc,
0, loop);
}
-static void prepare_context_registration_info(struct intel_context *ce,
- struct guc_ctxt_registration_info *info);
+static void prepare_context_registration_info_v69(struct intel_context *ce);
+static void prepare_context_registration_info_v70(struct intel_context *ce,
+ struct guc_ctxt_registration_info *info);
-static int register_context(struct intel_context *ce, bool loop)
+static int
+register_context_v69(struct intel_guc *guc, struct intel_context *ce, bool loop)
+{
+ u32 offset = intel_guc_ggtt_offset(guc, guc->lrc_desc_pool_v69) +
+ ce->guc_id.id * sizeof(struct guc_lrc_desc_v69);
+
+ prepare_context_registration_info_v69(ce);
+
+ if (intel_context_is_parent(ce))
+ return __guc_action_register_multi_lrc_v69(guc, ce, ce->guc_id.id,
+ offset, loop);
+ else
+ return __guc_action_register_context_v69(guc, ce->guc_id.id,
+ offset, loop);
+}
+
+static int
+register_context_v70(struct intel_guc *guc, struct intel_context *ce, bool loop)
{
struct guc_ctxt_registration_info info;
+
+ prepare_context_registration_info_v70(ce, &info);
+
+ if (intel_context_is_parent(ce))
+ return __guc_action_register_multi_lrc_v70(guc, ce, &info, loop);
+ else
+ return __guc_action_register_context_v70(guc, &info, loop);
+}
+
+static int register_context(struct intel_context *ce, bool loop)
+{
struct intel_guc *guc = ce_to_guc(ce);
int ret;
GEM_BUG_ON(intel_context_is_child(ce));
trace_intel_context_register(ce);
- prepare_context_registration_info(ce, &info);
-
- if (intel_context_is_parent(ce))
- ret = __guc_action_register_multi_lrc(guc, ce, &info, loop);
+ if (guc->fw.major_ver_found >= 70)
+ ret = register_context_v70(guc, ce, loop);
else
- ret = __guc_action_register_context(guc, &info, loop);
+ ret = register_context_v69(guc, ce, loop);
+
if (likely(!ret)) {
unsigned long flags;
@@ -2182,7 +2315,8 @@ static int register_context(struct intel_context *ce, bool loop)
set_context_registered(ce);
spin_unlock_irqrestore(&ce->guc_state.lock, flags);
- guc_context_policy_init(ce, loop);
+ if (guc->fw.major_ver_found >= 70)
+ guc_context_policy_init_v70(ce, loop);
}
return ret;
@@ -2279,7 +2413,7 @@ static int __guc_context_set_context_policies(struct intel_guc *guc,
0, loop);
}
-static int guc_context_policy_init(struct intel_context *ce, bool loop)
+static int guc_context_policy_init_v70(struct intel_context *ce, bool loop)
{
struct intel_engine_cs *engine = ce->engine;
struct intel_guc *guc = &engine->gt->uc.guc;
@@ -2338,6 +2472,19 @@ static int guc_context_policy_init(struct intel_context *ce, bool loop)
return ret;
}
+static void guc_context_policy_init_v69(struct intel_engine_cs *engine,
+ struct guc_lrc_desc_v69 *desc)
+{
+ desc->policy_flags = 0;
+
+ if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
+ desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69;
+
+ /* NB: For both of these, zero means disabled. */
+ desc->execution_quantum = engine->props.timeslice_duration_ms * 1000;
+ desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000;
+}
+
static u32 map_guc_prio_to_lrc_desc_prio(u8 prio)
{
/*
@@ -2358,8 +2505,75 @@ static u32 map_guc_prio_to_lrc_desc_prio(u8 prio)
}
}
-static void prepare_context_registration_info(struct intel_context *ce,
- struct guc_ctxt_registration_info *info)
+static void prepare_context_registration_info_v69(struct intel_context *ce)
+{
+ struct intel_engine_cs *engine = ce->engine;
+ struct intel_guc *guc = &engine->gt->uc.guc;
+ u32 ctx_id = ce->guc_id.id;
+ struct guc_lrc_desc_v69 *desc;
+ struct intel_context *child;
+
+ GEM_BUG_ON(!engine->mask);
+
+ /*
+ * Ensure LRC + CT vmas are is same region as write barrier is done
+ * based on CT vma region.
+ */
+ GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) !=
+ i915_gem_object_is_lmem(ce->ring->vma->obj));
+
+ desc = __get_lrc_desc_v69(guc, ctx_id);
+ desc->engine_class = engine_class_to_guc_class(engine->class);
+ desc->engine_submit_mask = engine->logical_mask;
+ desc->hw_context_desc = ce->lrc.lrca;
+ desc->priority = ce->guc_state.prio;
+ desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
+ guc_context_policy_init_v69(engine, desc);
+
+ /*
+ * If context is a parent, we need to register a process descriptor
+ * describing a work queue and register all child contexts.
+ */
+ if (intel_context_is_parent(ce)) {
+ struct guc_process_desc_v69 *pdesc;
+
+ ce->parallel.guc.wqi_tail = 0;
+ ce->parallel.guc.wqi_head = 0;
+
+ desc->process_desc = i915_ggtt_offset(ce->state) +
+ __get_parent_scratch_offset(ce);
+ desc->wq_addr = i915_ggtt_offset(ce->state) +
+ __get_wq_offset(ce);
+ desc->wq_size = WQ_SIZE;
+
+ pdesc = __get_process_desc_v69(ce);
+ memset(pdesc, 0, sizeof(*(pdesc)));
+ pdesc->stage_id = ce->guc_id.id;
+ pdesc->wq_base_addr = desc->wq_addr;
+ pdesc->wq_size_bytes = desc->wq_size;
+ pdesc->wq_status = WQ_STATUS_ACTIVE;
+
+ ce->parallel.guc.wq_head = &pdesc->head;
+ ce->parallel.guc.wq_tail = &pdesc->tail;
+ ce->parallel.guc.wq_status = &pdesc->wq_status;
+
+ for_each_child(ce, child) {
+ desc = __get_lrc_desc_v69(guc, child->guc_id.id);
+
+ desc->engine_class =
+ engine_class_to_guc_class(engine->class);
+ desc->hw_context_desc = child->lrc.lrca;
+ desc->priority = ce->guc_state.prio;
+ desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
+ guc_context_policy_init_v69(engine, desc);
+ }
+
+ clear_children_join_go_memory(ce);
+ }
+}
+
+static void prepare_context_registration_info_v70(struct intel_context *ce,
+ struct guc_ctxt_registration_info *info)
{
struct intel_engine_cs *engine = ce->engine;
struct intel_guc *guc = &engine->gt->uc.guc;
@@ -2409,10 +2623,14 @@ static void prepare_context_registration_info(struct intel_context *ce,
info->wq_base_hi = upper_32_bits(wq_base_offset);
info->wq_size = WQ_SIZE;
- wq_desc = __get_wq_desc(ce);
+ wq_desc = __get_wq_desc_v70(ce);
memset(wq_desc, 0, sizeof(*wq_desc));
wq_desc->wq_status = WQ_STATUS_ACTIVE;
+ ce->parallel.guc.wq_head = &wq_desc->head;
+ ce->parallel.guc.wq_tail = &wq_desc->tail;
+ ce->parallel.guc.wq_status = &wq_desc->wq_status;
+
clear_children_join_go_memory(ce);
}
}
@@ -2727,11 +2945,21 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc,
u16 guc_id,
u32 preemption_timeout)
{
- struct context_policy policy;
+ if (guc->fw.major_ver_found >= 70) {
+ struct context_policy policy;
- __guc_context_policy_start_klv(&policy, guc_id);
- __guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
- __guc_context_set_context_policies(guc, &policy, true);
+ __guc_context_policy_start_klv(&policy, guc_id);
+ __guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
+ __guc_context_set_context_policies(guc, &policy, true);
+ } else {
+ u32 action[] = {
+ INTEL_GUC_ACTION_V69_SET_CONTEXT_PREEMPTION_TIMEOUT,
+ guc_id,
+ preemption_timeout
+ };
+
+ intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
+ }
}
static void
@@ -2982,11 +3210,21 @@ static int guc_context_alloc(struct intel_context *ce)
static void __guc_context_set_prio(struct intel_guc *guc,
struct intel_context *ce)
{
- struct context_policy policy;
+ if (guc->fw.major_ver_found >= 70) {
+ struct context_policy policy;
- __guc_context_policy_start_klv(&policy, ce->guc_id.id);
- __guc_context_policy_add_priority(&policy, ce->guc_state.prio);
- __guc_context_set_context_policies(guc, &policy, true);
+ __guc_context_policy_start_klv(&policy, ce->guc_id.id);
+ __guc_context_policy_add_priority(&policy, ce->guc_state.prio);
+ __guc_context_set_context_policies(guc, &policy, true);
+ } else {
+ u32 action[] = {
+ INTEL_GUC_ACTION_V69_SET_CONTEXT_PRIORITY,
+ ce->guc_id.id,
+ ce->guc_state.prio,
+ };
+
+ guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
+ }
}
static void guc_context_set_prio(struct intel_guc *guc,
@@ -4496,17 +4734,19 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc,
guc_log_context_priority(p, ce);
if (intel_context_is_parent(ce)) {
- struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
struct intel_context *child;
drm_printf(p, "\t\tNumber children: %u\n",
ce->parallel.number_children);
- drm_printf(p, "\t\tWQI Head: %u\n",
- READ_ONCE(wq_desc->head));
- drm_printf(p, "\t\tWQI Tail: %u\n",
- READ_ONCE(wq_desc->tail));
- drm_printf(p, "\t\tWQI Status: %u\n\n",
- READ_ONCE(wq_desc->wq_status));
+
+ if (ce->parallel.guc.wq_status) {
+ drm_printf(p, "\t\tWQI Head: %u\n",
+ READ_ONCE(*ce->parallel.guc.wq_head));
+ drm_printf(p, "\t\tWQI Tail: %u\n",
+ READ_ONCE(*ce->parallel.guc.wq_tail));
+ drm_printf(p, "\t\tWQI Status: %u\n\n",
+ READ_ONCE(*ce->parallel.guc.wq_status));
+ }
if (ce->engine->emit_bb_start ==
emit_bb_start_parent_no_preempt_mid_batch) {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index c06e83872c34..56a0d80f88ba 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -70,6 +70,10 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
fw_def(BROXTON, 0, guc_def(bxt, 70, 1, 1)) \
fw_def(SKYLAKE, 0, guc_def(skl, 70, 1, 1))
+#define INTEL_GUC_FIRMWARE_DEFS_FALLBACK(fw_def, guc_def) \
+ fw_def(ALDERLAKE_P, 0, guc_def(adlp, 69, 0, 3)) \
+ fw_def(ALDERLAKE_S, 0, guc_def(tgl, 69, 0, 3))
+
#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_def) \
fw_def(ALDERLAKE_P, 0, huc_def(tgl, 7, 9, 3)) \
fw_def(ALDERLAKE_S, 0, huc_def(tgl, 7, 9, 3)) \
@@ -105,6 +109,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
MODULE_FIRMWARE(uc_);
INTEL_GUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH)
+INTEL_GUC_FIRMWARE_DEFS_FALLBACK(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH)
INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH)
/* The below structs and macros are used to iterate across the list of blobs */
@@ -149,6 +154,9 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
static const struct uc_fw_platform_requirement blobs_guc[] = {
INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB)
};
+ static const struct uc_fw_platform_requirement blobs_guc_fallback[] = {
+ INTEL_GUC_FIRMWARE_DEFS_FALLBACK(MAKE_FW_LIST, GUC_FW_BLOB)
+ };
static const struct uc_fw_platform_requirement blobs_huc[] = {
INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB)
};
@@ -162,6 +170,15 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
u8 rev = INTEL_REVID(i915);
int i;
+ /*
+ * The only difference between the ADL GuC FWs is the HWConfig support.
+ * ADL-N does not support HWConfig, so we should use the same binary as
+ * ADL-S, otherwise the GuC might attempt to fetch a config table that
+ * does not exist.
+ */
+ if (IS_ADLP_N(i915))
+ p = INTEL_ALDERLAKE_S;
+
GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all));
fw_blobs = blobs_all[uc_fw->type].blobs;
fw_count = blobs_all[uc_fw->type].count;
@@ -170,12 +187,29 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
if (p == fw_blobs[i].p && rev >= fw_blobs[i].rev) {
const struct uc_fw_blob *blob = &fw_blobs[i].blob;
uc_fw->path = blob->path;
+ uc_fw->wanted_path = blob->path;
uc_fw->major_ver_wanted = blob->major;
uc_fw->minor_ver_wanted = blob->minor;
break;
}
}
+ if (uc_fw->type == INTEL_UC_FW_TYPE_GUC) {
+ const struct uc_fw_platform_requirement *blobs = blobs_guc_fallback;
+ u32 count = ARRAY_SIZE(blobs_guc_fallback);
+
+ for (i = 0; i < count && p <= blobs[i].p; i++) {
+ if (p == blobs[i].p && rev >= blobs[i].rev) {
+ const struct uc_fw_blob *blob = &blobs[i].blob;
+
+ uc_fw->fallback.path = blob->path;
+ uc_fw->fallback.major_ver = blob->major;
+ uc_fw->fallback.minor_ver = blob->minor;
+ break;
+ }
+ }
+ }
+
/* make sure the list is ordered as expected */
if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)) {
for (i = 1; i < fw_count; i++) {
@@ -403,7 +437,24 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
__force_fw_fetch_failures(uc_fw, -EINVAL);
__force_fw_fetch_failures(uc_fw, -ESTALE);
- err = request_firmware(&fw, uc_fw->path, dev);
+ err = firmware_request_nowarn(&fw, uc_fw->path, dev);
+ if (err && !intel_uc_fw_is_overridden(uc_fw) && uc_fw->fallback.path) {
+ err = firmware_request_nowarn(&fw, uc_fw->fallback.path, dev);
+ if (!err) {
+ drm_notice(&i915->drm,
+ "%s firmware %s is recommended, but only %s was found\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ uc_fw->wanted_path,
+ uc_fw->fallback.path);
+ drm_info(&i915->drm,
+ "Consider updating your linux-firmware pkg or downloading from %s\n",
+ INTEL_UC_FIRMWARE_URL);
+
+ uc_fw->path = uc_fw->fallback.path;
+ uc_fw->major_ver_wanted = uc_fw->fallback.major_ver;
+ uc_fw->minor_ver_wanted = uc_fw->fallback.minor_ver;
+ }
+ }
if (err)
goto fail;
@@ -451,8 +502,8 @@ fail:
INTEL_UC_FIRMWARE_MISSING :
INTEL_UC_FIRMWARE_ERROR);
- drm_notice(&i915->drm, "%s firmware %s: fetch failed with error %d\n",
- intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
+ i915_probe_error(i915, "%s firmware %s: fetch failed with error %d\n",
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
drm_info(&i915->drm, "%s firmware(s) can be downloaded from %s\n",
intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL);
@@ -813,7 +864,13 @@ size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
{
drm_printf(p, "%s firmware: %s\n",
- intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->wanted_path);
+ if (uc_fw->fallback.path) {
+ drm_printf(p, "%s firmware fallback: %s\n",
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->fallback.path);
+ drm_printf(p, "fallback selected: %s\n",
+ str_yes_no(uc_fw->path == uc_fw->fallback.path));
+ }
drm_printf(p, "\tstatus: %s\n",
intel_uc_fw_status_repr(uc_fw->status));
drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
index 4f169035f504..7aa2644400b9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
@@ -74,6 +74,7 @@ struct intel_uc_fw {
const enum intel_uc_fw_status status;
enum intel_uc_fw_status __status; /* no accidental overwrites */
};
+ const char *wanted_path;
const char *path;
bool user_overridden;
size_t size;
@@ -98,6 +99,12 @@ struct intel_uc_fw {
u16 major_ver_found;
u16 minor_ver_found;
+ struct {
+ const char *path;
+ u16 major_ver;
+ u16 minor_ver;
+ } fallback;
+
u32 rsa_size;
u32 ucode_size;
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index 0ba2a3455d99..de13f102d4fd 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -3117,9 +3117,9 @@ void intel_gvt_update_reg_whitelist(struct intel_vgpu *vgpu)
continue;
vaddr = shmem_pin_map(engine->default_state);
- if (IS_ERR(vaddr)) {
- gvt_err("failed to map %s->default state, err:%zd\n",
- engine->name, PTR_ERR(vaddr));
+ if (!vaddr) {
+ gvt_err("failed to map %s->default state\n",
+ engine->name);
return;
}
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index ee2b3a375362..7412abf166a8 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -974,7 +974,7 @@ void i915_active_acquire_barrier(struct i915_active *ref)
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
llist_add(barrier_to_ll(node), &engine->barrier_tasks);
- intel_engine_pm_put_delay(engine, 1);
+ intel_engine_pm_put_delay(engine, 2);
}
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c22f29c3faa0..d25647be25d1 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1005,7 +1005,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_XEHPSDV(dev_priv) IS_PLATFORM(dev_priv, INTEL_XEHPSDV)
#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG2)
#define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, INTEL_PONTEVECCHIO)
+#define IS_METEORLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_METEORLAKE)
+#define IS_METEORLAKE_M(dev_priv) \
+ IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_M)
+#define IS_METEORLAKE_P(dev_priv) \
+ IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_P)
#define IS_DG2_G10(dev_priv) \
IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G10)
#define IS_DG2_G11(dev_priv) \
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index f9b1969ed7ed..32e92651ef7c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -46,6 +46,7 @@
#include "gem/i915_gem_lmem.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gt.h"
+#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_pm.h"
#include "gt/intel_gt_regs.h"
#include "gt/uc/intel_guc_capture.h"
@@ -436,7 +437,6 @@ static void err_compression_marker(struct drm_i915_error_state_buf *m)
static void error_print_instdone(struct drm_i915_error_state_buf *m,
const struct intel_engine_coredump *ee)
{
- const struct sseu_dev_info *sseu = &ee->engine->gt->info.sseu;
int slice;
int subslice;
int iter;
@@ -453,33 +453,21 @@ static void error_print_instdone(struct drm_i915_error_state_buf *m,
if (GRAPHICS_VER(m->i915) <= 6)
return;
- if (GRAPHICS_VER_FULL(m->i915) >= IP_VER(12, 50)) {
- for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice)
- err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
- slice, subslice,
- ee->instdone.sampler[slice][subslice]);
-
- for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice)
- err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n",
- slice, subslice,
- ee->instdone.row[slice][subslice]);
- } else {
- for_each_instdone_slice_subslice(m->i915, sseu, slice, subslice)
- err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
- slice, subslice,
- ee->instdone.sampler[slice][subslice]);
+ for_each_ss_steering(iter, ee->engine->gt, slice, subslice)
+ err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice,
+ ee->instdone.sampler[slice][subslice]);
- for_each_instdone_slice_subslice(m->i915, sseu, slice, subslice)
- err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n",
- slice, subslice,
- ee->instdone.row[slice][subslice]);
- }
+ for_each_ss_steering(iter, ee->engine->gt, slice, subslice)
+ err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice,
+ ee->instdone.row[slice][subslice]);
if (GRAPHICS_VER(m->i915) < 12)
return;
if (GRAPHICS_VER_FULL(m->i915) >= IP_VER(12, 55)) {
- for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice)
+ for_each_ss_steering(iter, ee->engine->gt, slice, subslice)
err_printf(m, " GEOM_SVGUNIT_INSTDONE[%d][%d]: 0x%08x\n",
slice, subslice,
ee->instdone.geom_svg[slice][subslice]);
@@ -1129,11 +1117,15 @@ i915_vma_coredump_create(const struct intel_gt *gt,
dma_addr_t dma;
for_each_sgt_daddr(dma, iter, vma_res->bi.pages) {
+ dma_addr_t offset = dma - mem->region.start;
void __iomem *s;
- s = io_mapping_map_wc(&mem->iomap,
- dma - mem->region.start,
- PAGE_SIZE);
+ if (offset + PAGE_SIZE > mem->io_size) {
+ ret = -EINVAL;
+ break;
+ }
+
+ s = io_mapping_map_wc(&mem->iomap, offset, PAGE_SIZE);
ret = compress_page(compress,
(void __force *)s, dst,
true);
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 701fbc98afa0..6fc475a5db61 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -204,6 +204,8 @@ i915_param_named_unsafe(request_timeout_ms, uint, 0600,
i915_param_named_unsafe(lmem_size, uint, 0400,
"Set the lmem size(in MiB) for each region. (default: 0, all memory)");
+i915_param_named_unsafe(lmem_bar_size, uint, 0400,
+ "Set the lmem bar size(in MiB).");
static __always_inline void _print_param(struct drm_printer *p,
const char *name,
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index b5e7ea45d191..2733cb6cfe09 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -74,6 +74,7 @@ struct drm_printer;
param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE, 0400) \
param(unsigned int, request_timeout_ms, CONFIG_DRM_I915_REQUEST_TIMEOUT, CONFIG_DRM_I915_REQUEST_TIMEOUT ? 0600 : 0) \
param(unsigned int, lmem_size, 0, 0400) \
+ param(unsigned int, lmem_bar_size, 0, 0400) \
/* leave bools at the end to not create holes */ \
param(bool, enable_hangcheck, true, 0600) \
param(bool, load_detect_test, false, 0600) \
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 5edc8fbf1dff..aacc10f2e73f 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -1075,7 +1075,6 @@ static const struct intel_device_info dg2_info = {
.require_force_probe = 1,
};
-__maybe_unused
static const struct intel_device_info ats_m_info = {
DG2_FEATURES,
.display = { 0 },
@@ -1108,6 +1107,31 @@ static const struct intel_device_info pvc_info = {
.require_force_probe = 1,
};
+#define XE_LPDP_FEATURES \
+ XE_LPD_FEATURES, \
+ .display.ver = 14, \
+ .display.has_cdclk_crawl = 1
+
+__maybe_unused
+static const struct intel_device_info mtl_info = {
+ XE_HP_FEATURES,
+ XE_LPDP_FEATURES,
+ /*
+ * Real graphics IP version will be obtained from hardware GMD_ID
+ * register. Value provided here is just for sanity checking.
+ */
+ .graphics.ver = 12,
+ .graphics.rel = 70,
+ .media.ver = 13,
+ PLATFORM(INTEL_METEORLAKE),
+ .display.has_modular_fia = 1,
+ .has_flat_ccs = 0,
+ .has_snoop = 1,
+ .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
+ .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0),
+ .require_force_probe = 1,
+};
+
#undef PLATFORM
/*
@@ -1189,6 +1213,8 @@ static const struct pci_device_id pciidlist[] = {
INTEL_RPLS_IDS(&adl_s_info),
INTEL_RPLP_IDS(&adl_p_info),
INTEL_DG2_IDS(&dg2_info),
+ INTEL_ATS_M_IDS(&ats_m_info),
+ INTEL_MTL_IDS(&mtl_info),
{0, 0, 0}
};
MODULE_DEVICE_TABLE(pci, pciidlist);
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 1577ab6754db..f3c23fe9ad9c 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -885,8 +885,9 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
if (ret)
return ret;
- DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
- stream->period_exponent);
+ drm_dbg(&stream->perf->i915->drm,
+ "OA buffer overflow (exponent = %d): force restart\n",
+ stream->period_exponent);
stream->perf->ops.oa_disable(stream);
stream->perf->ops.oa_enable(stream);
@@ -1108,8 +1109,9 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
if (ret)
return ret;
- DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
- stream->period_exponent);
+ drm_dbg(&stream->perf->i915->drm,
+ "OA buffer overflow (exponent = %d): force restart\n",
+ stream->period_exponent);
stream->perf->ops.oa_disable(stream);
stream->perf->ops.oa_enable(stream);
@@ -2863,7 +2865,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
int ret;
if (!props->engine) {
- DRM_DEBUG("OA engine not specified\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "OA engine not specified\n");
return -EINVAL;
}
@@ -2873,18 +2876,21 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
* IDs
*/
if (!perf->metrics_kobj) {
- DRM_DEBUG("OA metrics weren't advertised via sysfs\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "OA metrics weren't advertised via sysfs\n");
return -EINVAL;
}
if (!(props->sample_flags & SAMPLE_OA_REPORT) &&
(GRAPHICS_VER(perf->i915) < 12 || !stream->ctx)) {
- DRM_DEBUG("Only OA report sampling supported\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "Only OA report sampling supported\n");
return -EINVAL;
}
if (!perf->ops.enable_metric_set) {
- DRM_DEBUG("OA unit not supported\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "OA unit not supported\n");
return -ENODEV;
}
@@ -2894,12 +2900,14 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
* we currently only allow exclusive access
*/
if (perf->exclusive_stream) {
- DRM_DEBUG("OA unit already in use\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "OA unit already in use\n");
return -EBUSY;
}
if (!props->oa_format) {
- DRM_DEBUG("OA report format not specified\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "OA report format not specified\n");
return -EINVAL;
}
@@ -2929,20 +2937,23 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
if (stream->ctx) {
ret = oa_get_render_ctx_id(stream);
if (ret) {
- DRM_DEBUG("Invalid context id to filter with\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "Invalid context id to filter with\n");
return ret;
}
}
ret = alloc_noa_wait(stream);
if (ret) {
- DRM_DEBUG("Unable to allocate NOA wait batch buffer\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "Unable to allocate NOA wait batch buffer\n");
goto err_noa_wait_alloc;
}
stream->oa_config = i915_perf_get_oa_config(perf, props->metrics_set);
if (!stream->oa_config) {
- DRM_DEBUG("Invalid OA config id=%i\n", props->metrics_set);
+ drm_dbg(&stream->perf->i915->drm,
+ "Invalid OA config id=%i\n", props->metrics_set);
ret = -EINVAL;
goto err_config;
}
@@ -2973,11 +2984,13 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
ret = i915_perf_stream_enable_sync(stream);
if (ret) {
- DRM_DEBUG("Unable to enable metric set\n");
+ drm_dbg(&stream->perf->i915->drm,
+ "Unable to enable metric set\n");
goto err_enable;
}
- DRM_DEBUG("opening stream oa config uuid=%s\n",
+ drm_dbg(&stream->perf->i915->drm,
+ "opening stream oa config uuid=%s\n",
stream->oa_config->uuid);
hrtimer_init(&stream->poll_check_timer,
@@ -3429,7 +3442,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf,
specific_ctx = i915_gem_context_lookup(file_priv, ctx_handle);
if (IS_ERR(specific_ctx)) {
- DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n",
+ drm_dbg(&perf->i915->drm,
+ "Failed to look up context with ID %u for opening perf stream\n",
ctx_handle);
ret = PTR_ERR(specific_ctx);
goto err;
@@ -3463,7 +3477,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf,
if (props->hold_preemption) {
if (!props->single_context) {
- DRM_DEBUG("preemption disable with no context\n");
+ drm_dbg(&perf->i915->drm,
+ "preemption disable with no context\n");
ret = -EINVAL;
goto err;
}
@@ -3485,7 +3500,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf,
*/
if (privileged_op &&
i915_perf_stream_paranoid && !perfmon_capable()) {
- DRM_DEBUG("Insufficient privileges to open i915 perf stream\n");
+ drm_dbg(&perf->i915->drm,
+ "Insufficient privileges to open i915 perf stream\n");
ret = -EACCES;
goto err_ctx;
}
@@ -3592,7 +3608,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
props->poll_oa_period = DEFAULT_POLL_PERIOD_NS;
if (!n_props) {
- DRM_DEBUG("No i915 perf properties given\n");
+ drm_dbg(&perf->i915->drm,
+ "No i915 perf properties given\n");
return -EINVAL;
}
@@ -3601,7 +3618,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
I915_ENGINE_CLASS_RENDER,
0);
if (!props->engine) {
- DRM_DEBUG("No RENDER-capable engines\n");
+ drm_dbg(&perf->i915->drm,
+ "No RENDER-capable engines\n");
return -EINVAL;
}
@@ -3612,7 +3630,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
* from userspace.
*/
if (n_props >= DRM_I915_PERF_PROP_MAX) {
- DRM_DEBUG("More i915 perf properties specified than exist\n");
+ drm_dbg(&perf->i915->drm,
+ "More i915 perf properties specified than exist\n");
return -EINVAL;
}
@@ -3629,7 +3648,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
return ret;
if (id == 0 || id >= DRM_I915_PERF_PROP_MAX) {
- DRM_DEBUG("Unknown i915 perf property ID\n");
+ drm_dbg(&perf->i915->drm,
+ "Unknown i915 perf property ID\n");
return -EINVAL;
}
@@ -3644,19 +3664,22 @@ static int read_properties_unlocked(struct i915_perf *perf,
break;
case DRM_I915_PERF_PROP_OA_METRICS_SET:
if (value == 0) {
- DRM_DEBUG("Unknown OA metric set ID\n");
+ drm_dbg(&perf->i915->drm,
+ "Unknown OA metric set ID\n");
return -EINVAL;
}
props->metrics_set = value;
break;
case DRM_I915_PERF_PROP_OA_FORMAT:
if (value == 0 || value >= I915_OA_FORMAT_MAX) {
- DRM_DEBUG("Out-of-range OA report format %llu\n",
+ drm_dbg(&perf->i915->drm,
+ "Out-of-range OA report format %llu\n",
value);
return -EINVAL;
}
if (!oa_format_valid(perf, value)) {
- DRM_DEBUG("Unsupported OA report format %llu\n",
+ drm_dbg(&perf->i915->drm,
+ "Unsupported OA report format %llu\n",
value);
return -EINVAL;
}
@@ -3664,7 +3687,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
break;
case DRM_I915_PERF_PROP_OA_EXPONENT:
if (value > OA_EXPONENT_MAX) {
- DRM_DEBUG("OA timer exponent too high (> %u)\n",
+ drm_dbg(&perf->i915->drm,
+ "OA timer exponent too high (> %u)\n",
OA_EXPONENT_MAX);
return -EINVAL;
}
@@ -3692,7 +3716,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
oa_freq_hz = 0;
if (oa_freq_hz > i915_oa_max_sample_rate && !perfmon_capable()) {
- DRM_DEBUG("OA exponent would exceed the max sampling frequency (sysctl dev.i915.oa_max_sample_rate) %uHz without CAP_PERFMON or CAP_SYS_ADMIN privileges\n",
+ drm_dbg(&perf->i915->drm,
+ "OA exponent would exceed the max sampling frequency (sysctl dev.i915.oa_max_sample_rate) %uHz without CAP_PERFMON or CAP_SYS_ADMIN privileges\n",
i915_oa_max_sample_rate);
return -EACCES;
}
@@ -3706,16 +3731,25 @@ static int read_properties_unlocked(struct i915_perf *perf,
case DRM_I915_PERF_PROP_GLOBAL_SSEU: {
struct drm_i915_gem_context_param_sseu user_sseu;
+ if (GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 50)) {
+ drm_dbg(&perf->i915->drm,
+ "SSEU config not supported on gfx %x\n",
+ GRAPHICS_VER_FULL(perf->i915));
+ return -ENODEV;
+ }
+
if (copy_from_user(&user_sseu,
u64_to_user_ptr(value),
sizeof(user_sseu))) {
- DRM_DEBUG("Unable to copy global sseu parameter\n");
+ drm_dbg(&perf->i915->drm,
+ "Unable to copy global sseu parameter\n");
return -EFAULT;
}
ret = get_sseu_config(&props->sseu, props->engine, &user_sseu);
if (ret) {
- DRM_DEBUG("Invalid SSEU configuration\n");
+ drm_dbg(&perf->i915->drm,
+ "Invalid SSEU configuration\n");
return ret;
}
props->has_sseu = true;
@@ -3723,7 +3757,8 @@ static int read_properties_unlocked(struct i915_perf *perf,
}
case DRM_I915_PERF_PROP_POLL_OA_PERIOD:
if (value < 100000 /* 100us */) {
- DRM_DEBUG("OA availability timer too small (%lluns < 100us)\n",
+ drm_dbg(&perf->i915->drm,
+ "OA availability timer too small (%lluns < 100us)\n",
value);
return -EINVAL;
}
@@ -3774,7 +3809,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
int ret;
if (!perf->i915) {
- DRM_DEBUG("i915 perf interface not available for this system\n");
+ drm_dbg(&perf->i915->drm,
+ "i915 perf interface not available for this system\n");
return -ENOTSUPP;
}
@@ -3782,7 +3818,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
I915_PERF_FLAG_FD_NONBLOCK |
I915_PERF_FLAG_DISABLED;
if (param->flags & ~known_open_flags) {
- DRM_DEBUG("Unknown drm_i915_perf_open_param flag\n");
+ drm_dbg(&perf->i915->drm,
+ "Unknown drm_i915_perf_open_param flag\n");
return -EINVAL;
}
@@ -4028,7 +4065,8 @@ static struct i915_oa_reg *alloc_oa_regs(struct i915_perf *perf,
goto addr_err;
if (!is_valid(perf, addr)) {
- DRM_DEBUG("Invalid oa_reg address: %X\n", addr);
+ drm_dbg(&perf->i915->drm,
+ "Invalid oa_reg address: %X\n", addr);
err = -EINVAL;
goto addr_err;
}
@@ -4102,30 +4140,35 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
int err, id;
if (!perf->i915) {
- DRM_DEBUG("i915 perf interface not available for this system\n");
+ drm_dbg(&perf->i915->drm,
+ "i915 perf interface not available for this system\n");
return -ENOTSUPP;
}
if (!perf->metrics_kobj) {
- DRM_DEBUG("OA metrics weren't advertised via sysfs\n");
+ drm_dbg(&perf->i915->drm,
+ "OA metrics weren't advertised via sysfs\n");
return -EINVAL;
}
if (i915_perf_stream_paranoid && !perfmon_capable()) {
- DRM_DEBUG("Insufficient privileges to add i915 OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Insufficient privileges to add i915 OA config\n");
return -EACCES;
}
if ((!args->mux_regs_ptr || !args->n_mux_regs) &&
(!args->boolean_regs_ptr || !args->n_boolean_regs) &&
(!args->flex_regs_ptr || !args->n_flex_regs)) {
- DRM_DEBUG("No OA registers given\n");
+ drm_dbg(&perf->i915->drm,
+ "No OA registers given\n");
return -EINVAL;
}
oa_config = kzalloc(sizeof(*oa_config), GFP_KERNEL);
if (!oa_config) {
- DRM_DEBUG("Failed to allocate memory for the OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to allocate memory for the OA config\n");
return -ENOMEM;
}
@@ -4133,7 +4176,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
kref_init(&oa_config->ref);
if (!uuid_is_valid(args->uuid)) {
- DRM_DEBUG("Invalid uuid format for OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Invalid uuid format for OA config\n");
err = -EINVAL;
goto reg_err;
}
@@ -4150,7 +4194,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
args->n_mux_regs);
if (IS_ERR(regs)) {
- DRM_DEBUG("Failed to create OA config for mux_regs\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to create OA config for mux_regs\n");
err = PTR_ERR(regs);
goto reg_err;
}
@@ -4163,7 +4208,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
args->n_boolean_regs);
if (IS_ERR(regs)) {
- DRM_DEBUG("Failed to create OA config for b_counter_regs\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to create OA config for b_counter_regs\n");
err = PTR_ERR(regs);
goto reg_err;
}
@@ -4182,7 +4228,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
args->n_flex_regs);
if (IS_ERR(regs)) {
- DRM_DEBUG("Failed to create OA config for flex_regs\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to create OA config for flex_regs\n");
err = PTR_ERR(regs);
goto reg_err;
}
@@ -4198,7 +4245,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
*/
idr_for_each_entry(&perf->metrics_idr, tmp, id) {
if (!strcmp(tmp->uuid, oa_config->uuid)) {
- DRM_DEBUG("OA config already exists with this uuid\n");
+ drm_dbg(&perf->i915->drm,
+ "OA config already exists with this uuid\n");
err = -EADDRINUSE;
goto sysfs_err;
}
@@ -4206,7 +4254,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
err = create_dynamic_oa_sysfs_entry(perf, oa_config);
if (err) {
- DRM_DEBUG("Failed to create sysfs entry for OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to create sysfs entry for OA config\n");
goto sysfs_err;
}
@@ -4215,14 +4264,16 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
oa_config, 2,
0, GFP_KERNEL);
if (oa_config->id < 0) {
- DRM_DEBUG("Failed to create sysfs entry for OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to create sysfs entry for OA config\n");
err = oa_config->id;
goto sysfs_err;
}
mutex_unlock(&perf->metrics_lock);
- DRM_DEBUG("Added config %s id=%i\n", oa_config->uuid, oa_config->id);
+ drm_dbg(&perf->i915->drm,
+ "Added config %s id=%i\n", oa_config->uuid, oa_config->id);
return oa_config->id;
@@ -4230,7 +4281,8 @@ sysfs_err:
mutex_unlock(&perf->metrics_lock);
reg_err:
i915_oa_config_put(oa_config);
- DRM_DEBUG("Failed to add new OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to add new OA config\n");
return err;
}
@@ -4254,12 +4306,14 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
int ret;
if (!perf->i915) {
- DRM_DEBUG("i915 perf interface not available for this system\n");
+ drm_dbg(&perf->i915->drm,
+ "i915 perf interface not available for this system\n");
return -ENOTSUPP;
}
if (i915_perf_stream_paranoid && !perfmon_capable()) {
- DRM_DEBUG("Insufficient privileges to remove i915 OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Insufficient privileges to remove i915 OA config\n");
return -EACCES;
}
@@ -4269,7 +4323,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
oa_config = idr_find(&perf->metrics_idr, *arg);
if (!oa_config) {
- DRM_DEBUG("Failed to remove unknown OA config\n");
+ drm_dbg(&perf->i915->drm,
+ "Failed to remove unknown OA config\n");
ret = -ENOENT;
goto err_unlock;
}
@@ -4282,7 +4337,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&perf->metrics_lock);
- DRM_DEBUG("Removed config %s id=%i\n", oa_config->uuid, oa_config->id);
+ drm_dbg(&perf->i915->drm,
+ "Removed config %s id=%i\n", oa_config->uuid, oa_config->id);
i915_oa_config_put(oa_config);
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 0094f67c63f2..6ec9c9fb7b0d 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -498,7 +498,21 @@ static int query_memregion_info(struct drm_i915_private *i915,
info.region.memory_class = mr->type;
info.region.memory_instance = mr->instance;
info.probed_size = mr->total;
- info.unallocated_size = mr->avail;
+
+ if (mr->type == INTEL_MEMORY_LOCAL)
+ info.probed_cpu_visible_size = mr->io_size;
+ else
+ info.probed_cpu_visible_size = mr->total;
+
+ if (perfmon_capable()) {
+ intel_memory_region_avail(mr,
+ &info.unallocated_size,
+ &info.unallocated_cpu_visible_size);
+ } else {
+ info.unallocated_size = info.probed_size;
+ info.unallocated_cpu_visible_size =
+ info.probed_cpu_visible_size;
+ }
if (__copy_to_user(info_ptr, &info, sizeof(info)))
return -EFAULT;
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c
index 159571b9bd24..dcc081874ec8 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -68,6 +68,7 @@ void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size)
* drm_mm_node
* @node: The drm_mm_node.
* @region_start: An offset to add to the dma addresses of the sg list.
+ * @page_alignment: Required page alignment for each sg entry. Power of two.
*
* Create a struct sg_table, initializing it from a struct drm_mm_node,
* taking a maximum segment length into account, splitting into segments
@@ -77,22 +78,25 @@ void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size)
* error code cast to an error pointer on failure.
*/
struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
- u64 region_start)
+ u64 region_start,
+ u32 page_alignment)
{
- const u64 max_segment = SZ_1G; /* Do we have a limit on this? */
- u64 segment_pages = max_segment >> PAGE_SHIFT;
+ const u32 max_segment = round_down(UINT_MAX, page_alignment);
+ const u32 segment_pages = max_segment >> PAGE_SHIFT;
u64 block_size, offset, prev_end;
struct i915_refct_sgt *rsgt;
struct sg_table *st;
struct scatterlist *sg;
+ GEM_BUG_ON(!max_segment);
+
rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL);
if (!rsgt)
return ERR_PTR(-ENOMEM);
i915_refct_sgt_init(rsgt, node->size << PAGE_SHIFT);
st = &rsgt->table;
- if (sg_alloc_table(st, DIV_ROUND_UP(node->size, segment_pages),
+ if (sg_alloc_table(st, DIV_ROUND_UP_ULL(node->size, segment_pages),
GFP_KERNEL)) {
i915_refct_sgt_put(rsgt);
return ERR_PTR(-ENOMEM);
@@ -112,12 +116,14 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
sg = __sg_next(sg);
sg_dma_address(sg) = region_start + offset;
+ GEM_BUG_ON(!IS_ALIGNED(sg_dma_address(sg),
+ page_alignment));
sg_dma_len(sg) = 0;
sg->length = 0;
st->nents++;
}
- len = min(block_size, max_segment - sg->length);
+ len = min_t(u64, block_size, max_segment - sg->length);
sg->length += len;
sg_dma_len(sg) += len;
@@ -138,6 +144,7 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
* i915_buddy_block list
* @res: The struct i915_ttm_buddy_resource.
* @region_start: An offset to add to the dma addresses of the sg list.
+ * @page_alignment: Required page alignment for each sg entry. Power of two.
*
* Create a struct sg_table, initializing it from struct i915_buddy_block list,
* taking a maximum segment length into account, splitting into segments
@@ -147,11 +154,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
* error code cast to an error pointer on failure.
*/
struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
- u64 region_start)
+ u64 region_start,
+ u32 page_alignment)
{
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
const u64 size = res->num_pages << PAGE_SHIFT;
- const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE);
+ const u32 max_segment = round_down(UINT_MAX, page_alignment);
struct drm_buddy *mm = bman_res->mm;
struct list_head *blocks = &bman_res->blocks;
struct drm_buddy_block *block;
@@ -161,6 +169,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
resource_size_t prev_end;
GEM_BUG_ON(list_empty(blocks));
+ GEM_BUG_ON(!max_segment);
rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL);
if (!rsgt)
@@ -191,12 +200,14 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
sg = __sg_next(sg);
sg_dma_address(sg) = region_start + offset;
+ GEM_BUG_ON(!IS_ALIGNED(sg_dma_address(sg),
+ page_alignment));
sg_dma_len(sg) = 0;
sg->length = 0;
st->nents++;
}
- len = min(block_size, max_segment - sg->length);
+ len = min_t(u64, block_size, max_segment - sg->length);
sg->length += len;
sg_dma_len(sg) += len;
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
index 12c6a1684081..9ddb3e743a3e 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.h
+++ b/drivers/gpu/drm/i915/i915_scatterlist.h
@@ -213,9 +213,11 @@ static inline void __i915_refct_sgt_init(struct i915_refct_sgt *rsgt,
void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size);
struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
- u64 region_start);
+ u64 region_start,
+ u32 page_alignment);
struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
- u64 region_start);
+ u64 region_start,
+ u32 page_alignment);
#endif
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
index a5109548abc0..427de1aaab36 100644
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -104,18 +104,15 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
min_page_size,
&bman_res->blocks,
bman_res->flags);
- mutex_unlock(&bman->lock);
if (unlikely(err))
goto err_free_blocks;
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
u64 original_size = (u64)bman_res->base.num_pages << PAGE_SHIFT;
- mutex_lock(&bman->lock);
drm_buddy_block_trim(mm,
original_size,
&bman_res->blocks);
- mutex_unlock(&bman->lock);
}
if (lpfn <= bman->visible_size) {
@@ -137,11 +134,10 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
}
}
- if (bman_res->used_visible_size) {
- mutex_lock(&bman->lock);
+ if (bman_res->used_visible_size)
bman->visible_avail -= bman_res->used_visible_size;
- mutex_unlock(&bman->lock);
- }
+
+ mutex_unlock(&bman->lock);
if (place->lpfn - place->fpfn == n_pages)
bman_res->base.start = place->fpfn;
@@ -154,7 +150,6 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
return 0;
err_free_blocks:
- mutex_lock(&bman->lock);
drm_buddy_free_list(mm, &bman_res->blocks);
mutex_unlock(&bman->lock);
err_free_res:
@@ -365,6 +360,26 @@ u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man)
return bman->visible_size;
}
+/**
+ * i915_ttm_buddy_man_avail - Query the avail tracking for the manager.
+ *
+ * @man: The buddy allocator ttm manager
+ * @avail: The total available memory in pages for the entire manager.
+ * @visible_avail: The total available memory in pages for the CPU visible
+ * portion. Note that this will always give the same value as @avail on
+ * configurations that don't have a small BAR.
+ */
+void i915_ttm_buddy_man_avail(struct ttm_resource_manager *man,
+ u64 *avail, u64 *visible_avail)
+{
+ struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+
+ mutex_lock(&bman->lock);
+ *avail = bman->mm.avail >> PAGE_SHIFT;
+ *visible_avail = bman->visible_avail;
+ mutex_unlock(&bman->lock);
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
void i915_ttm_buddy_man_force_visible_size(struct ttm_resource_manager *man,
u64 size)
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
index 52d9586d242c..d64620712830 100644
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
@@ -61,6 +61,9 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man);
+void i915_ttm_buddy_man_avail(struct ttm_resource_manager *man,
+ u64 *avail, u64 *avail_visible);
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
void i915_ttm_buddy_man_force_visible_size(struct ttm_resource_manager *man,
u64 size);
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 5d5828b9a242..ef3b04c7e153 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -310,7 +310,7 @@ struct i915_vma_work {
struct i915_address_space *vm;
struct i915_vm_pt_stash stash;
struct i915_vma_resource *vma_res;
- struct drm_i915_gem_object *pinned;
+ struct drm_i915_gem_object *obj;
struct i915_sw_dma_fence_cb cb;
enum i915_cache_level cache_level;
unsigned int flags;
@@ -321,17 +321,25 @@ static void __vma_bind(struct dma_fence_work *work)
struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
struct i915_vma_resource *vma_res = vw->vma_res;
+ /*
+ * We are about the bind the object, which must mean we have already
+ * signaled the work to potentially clear/move the pages underneath. If
+ * something went wrong at that stage then the object should have
+ * unknown_state set, in which case we need to skip the bind.
+ */
+ if (i915_gem_object_has_unknown_state(vw->obj))
+ return;
+
vma_res->ops->bind_vma(vma_res->vm, &vw->stash,
vma_res, vw->cache_level, vw->flags);
-
}
static void __vma_release(struct dma_fence_work *work)
{
struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
- if (vw->pinned)
- i915_gem_object_put(vw->pinned);
+ if (vw->obj)
+ i915_gem_object_put(vw->obj);
i915_vm_free_pt_stash(vw->vm, &vw->stash);
if (vw->vma_res)
@@ -517,14 +525,7 @@ int i915_vma_bind(struct i915_vma *vma,
}
work->base.dma.error = 0; /* enable the queue_work() */
-
- /*
- * If we don't have the refcounted pages list, keep a reference
- * on the object to avoid waiting for the async bind to
- * complete in the object destruction path.
- */
- if (!work->vma_res->bi.pages_rsgt)
- work->pinned = i915_gem_object_get(vma->obj);
+ work->obj = i915_gem_object_get(vma->obj);
} else {
ret = i915_gem_object_wait_moving_fence(vma->obj, true);
if (ret) {
@@ -1645,10 +1646,10 @@ static void force_unbind(struct i915_vma *vma)
GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
}
-static void release_references(struct i915_vma *vma, bool vm_ddestroy)
+static void release_references(struct i915_vma *vma, struct intel_gt *gt,
+ bool vm_ddestroy)
{
struct drm_i915_gem_object *obj = vma->obj;
- struct intel_gt *gt = vma->vm->gt;
GEM_BUG_ON(i915_vma_is_active(vma));
@@ -1703,11 +1704,12 @@ void i915_vma_destroy_locked(struct i915_vma *vma)
force_unbind(vma);
list_del_init(&vma->vm_link);
- release_references(vma, false);
+ release_references(vma, vma->vm->gt, false);
}
void i915_vma_destroy(struct i915_vma *vma)
{
+ struct intel_gt *gt;
bool vm_ddestroy;
mutex_lock(&vma->vm->mutex);
@@ -1715,8 +1717,11 @@ void i915_vma_destroy(struct i915_vma *vma)
list_del_init(&vma->vm_link);
vm_ddestroy = vma->vm_ddestroy;
vma->vm_ddestroy = false;
+
+ /* vma->vm may be freed when releasing vma->vm->mutex. */
+ gt = vma->vm->gt;
mutex_unlock(&vma->vm->mutex);
- release_references(vma, vm_ddestroy);
+ release_references(vma, gt, vm_ddestroy);
}
void i915_vma_parked(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index 7eb893666595..d98fbbd589aa 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -73,6 +73,7 @@ static const char * const platform_names[] = {
PLATFORM_NAME(XEHPSDV),
PLATFORM_NAME(DG2),
PLATFORM_NAME(PONTEVECCHIO),
+ PLATFORM_NAME(METEORLAKE),
};
#undef PLATFORM_NAME
@@ -189,16 +190,26 @@ static const u16 subplatform_rpl_ids[] = {
static const u16 subplatform_g10_ids[] = {
INTEL_DG2_G10_IDS(0),
+ INTEL_ATS_M150_IDS(0),
};
static const u16 subplatform_g11_ids[] = {
INTEL_DG2_G11_IDS(0),
+ INTEL_ATS_M75_IDS(0),
};
static const u16 subplatform_g12_ids[] = {
INTEL_DG2_G12_IDS(0),
};
+static const u16 subplatform_m_ids[] = {
+ INTEL_MTL_M_IDS(0),
+};
+
+static const u16 subplatform_p_ids[] = {
+ INTEL_MTL_P_IDS(0),
+};
+
static bool find_devid(u16 id, const u16 *p, unsigned int num)
{
for (; num; num--, p++) {
@@ -253,6 +264,12 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915)
} else if (find_devid(devid, subplatform_g12_ids,
ARRAY_SIZE(subplatform_g12_ids))) {
mask = BIT(INTEL_SUBPLATFORM_G12);
+ } else if (find_devid(devid, subplatform_m_ids,
+ ARRAY_SIZE(subplatform_m_ids))) {
+ mask = BIT(INTEL_SUBPLATFORM_M);
+ } else if (find_devid(devid, subplatform_p_ids,
+ ARRAY_SIZE(subplatform_p_ids))) {
+ mask = BIT(INTEL_SUBPLATFORM_P);
}
GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_MASK);
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index 1c150cd7dceb..23bf230aa104 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -89,6 +89,7 @@ enum intel_platform {
INTEL_XEHPSDV,
INTEL_DG2,
INTEL_PONTEVECCHIO,
+ INTEL_METEORLAKE,
INTEL_MAX_PLATFORMS
};
@@ -126,6 +127,10 @@ enum intel_platform {
*/
#define INTEL_SUBPLATFORM_N 1
+/* MTL */
+#define INTEL_SUBPLATFORM_M 0
+#define INTEL_SUBPLATFORM_P 1
+
enum intel_ppgtt_type {
INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE,
INTEL_PPGTT_ALIASING = I915_GEM_PPGTT_ALIASING,
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index e38d2db1c3e3..9a4a7fb55582 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -198,8 +198,7 @@ void intel_memory_region_debug(struct intel_memory_region *mr,
if (mr->region_private)
ttm_resource_manager_debug(mr->region_private, printer);
else
- drm_printf(printer, "total:%pa, available:%pa bytes\n",
- &mr->total, &mr->avail);
+ drm_printf(printer, "total:%pa bytes\n", &mr->total);
}
static int intel_memory_region_memtest(struct intel_memory_region *mem,
@@ -242,7 +241,6 @@ intel_memory_region_create(struct drm_i915_private *i915,
mem->min_page_size = min_page_size;
mem->ops = ops;
mem->total = size;
- mem->avail = mem->total;
mem->type = type;
mem->instance = instance;
@@ -279,6 +277,20 @@ void intel_memory_region_set_name(struct intel_memory_region *mem,
va_end(ap);
}
+void intel_memory_region_avail(struct intel_memory_region *mr,
+ u64 *avail, u64 *visible_avail)
+{
+ if (mr->type == INTEL_MEMORY_LOCAL) {
+ i915_ttm_buddy_man_avail(mr->region_private,
+ avail, visible_avail);
+ *avail <<= PAGE_SHIFT;
+ *visible_avail <<= PAGE_SHIFT;
+ } else {
+ *avail = mr->total;
+ *visible_avail = mr->total;
+ }
+}
+
void intel_memory_region_destroy(struct intel_memory_region *mem)
{
int ret = 0;
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index 3d8378c1b447..2953ed5c3248 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -75,7 +75,6 @@ struct intel_memory_region {
resource_size_t io_size;
resource_size_t min_page_size;
resource_size_t total;
- resource_size_t avail;
u16 type;
u16 instance;
@@ -127,6 +126,9 @@ int intel_memory_region_reserve(struct intel_memory_region *mem,
void intel_memory_region_debug(struct intel_memory_region *mr,
struct drm_printer *printer);
+void intel_memory_region_avail(struct intel_memory_region *mr,
+ u64 *avail, u64 *visible_avail);
+
struct intel_memory_region *
i915_gem_ttm_system_setup(struct drm_i915_private *i915,
u16 type, u16 instance);
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 62ff77445b01..575d67bc6ffe 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -152,6 +152,7 @@ int intel_region_ttm_fini(struct intel_memory_region *mem)
* Convert an opaque TTM resource manager resource to a refcounted sg_table.
* @mem: The memory region.
* @res: The resource manager resource obtained from the TTM resource manager.
+ * @page_alignment: Required page alignment for each sg entry. Power of two.
*
* The gem backends typically use sg-tables for operations on the underlying
* io_memory. So provide a way for the backends to translate the
@@ -161,16 +162,19 @@ int intel_region_ttm_fini(struct intel_memory_region *mem)
*/
struct i915_refct_sgt *
intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
- struct ttm_resource *res)
+ struct ttm_resource *res,
+ u32 page_alignment)
{
if (mem->is_range_manager) {
struct ttm_range_mgr_node *range_node =
to_ttm_range_mgr_node(res);
return i915_rsgt_from_mm_node(&range_node->mm_nodes[0],
- mem->region.start);
+ mem->region.start,
+ page_alignment);
} else {
- return i915_rsgt_from_buddy_resource(res, mem->region.start);
+ return i915_rsgt_from_buddy_resource(res, mem->region.start,
+ page_alignment);
}
}
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h
index cf9d86dcf409..5bb8d8b582ae 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.h
+++ b/drivers/gpu/drm/i915/intel_region_ttm.h
@@ -24,7 +24,8 @@ int intel_region_ttm_fini(struct intel_memory_region *mem);
struct i915_refct_sgt *
intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
- struct ttm_resource *res);
+ struct ttm_resource *res,
+ u32 page_alignment);
void intel_region_ttm_resource_free(struct intel_memory_region *mem,
struct ttm_resource *res);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index 8633bec18fa7..ab9f17fc85bc 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -742,7 +742,7 @@ static int pot_hole(struct i915_address_space *vm,
u64 addr;
for (addr = round_up(hole_start + min_alignment, step) - min_alignment;
- addr <= round_down(hole_end - (2 * min_alignment), step) - min_alignment;
+ hole_end > addr && hole_end - addr >= 2 * min_alignment;
addr += step) {
err = i915_vma_pin(vma, 0, 0, addr | flags);
if (err) {
diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
index 73eb53edb8de..3b18e5905c86 100644
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -451,7 +451,6 @@ out_put:
static int igt_mock_max_segment(void *arg)
{
- const unsigned int max_segment = rounddown(UINT_MAX, PAGE_SIZE);
struct intel_memory_region *mem = arg;
struct drm_i915_private *i915 = mem->i915;
struct i915_ttm_buddy_resource *res;
@@ -460,7 +459,10 @@ static int igt_mock_max_segment(void *arg)
struct drm_buddy *mm;
struct list_head *blocks;
struct scatterlist *sg;
+ I915_RND_STATE(prng);
LIST_HEAD(objects);
+ unsigned int max_segment;
+ unsigned int ps;
u64 size;
int err = 0;
@@ -472,7 +474,13 @@ static int igt_mock_max_segment(void *arg)
*/
size = SZ_8G;
- mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0, 0);
+ ps = PAGE_SIZE;
+ if (i915_prandom_u64_state(&prng) & 1)
+ ps = SZ_64K; /* For something like DG2 */
+
+ max_segment = round_down(UINT_MAX, ps);
+
+ mem = mock_region_create(i915, 0, size, ps, 0, 0);
if (IS_ERR(mem))
return PTR_ERR(mem);
@@ -498,12 +506,21 @@ static int igt_mock_max_segment(void *arg)
}
for (sg = obj->mm.pages->sgl; sg; sg = sg_next(sg)) {
+ dma_addr_t daddr = sg_dma_address(sg);
+
if (sg->length > max_segment) {
pr_err("%s: Created an oversized scatterlist entry, %u > %u\n",
__func__, sg->length, max_segment);
err = -EINVAL;
goto out_close;
}
+
+ if (!IS_ALIGNED(daddr, ps)) {
+ pr_err("%s: Created an unaligned scatterlist entry, addr=%pa, ps=%u\n",
+ __func__, &daddr, ps);
+ err = -EINVAL;
+ goto out_close;
+ }
}
out_close:
diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c
index 670557ce1024..bac21fe84ca5 100644
--- a/drivers/gpu/drm/i915/selftests/mock_region.c
+++ b/drivers/gpu/drm/i915/selftests/mock_region.c
@@ -33,7 +33,8 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj)
return PTR_ERR(obj->mm.res);
obj->mm.rsgt = intel_region_ttm_resource_to_rsgt(obj->mm.region,
- obj->mm.res);
+ obj->mm.res,
+ obj->mm.region->min_page_size);
if (IS_ERR(obj->mm.rsgt)) {
err = PTR_ERR(obj->mm.rsgt);
goto err_free_resource;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c
index c849533ca83e..3f5750cc2673 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-dev.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c
@@ -207,6 +207,7 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output)
ret = dcss_submodules_init(dcss);
if (ret) {
+ of_node_put(dcss->of_port);
dev_err(dev, "submodules initialization failed\n");
goto clks_err;
}
@@ -237,6 +238,8 @@ void dcss_dev_destroy(struct dcss_dev *dcss)
dcss_clocks_disable(dcss);
}
+ of_node_put(dcss->of_port);
+
pm_runtime_disable(dcss->dev);
dcss_submodules_stop(dcss);
diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
index 8989e215dfc9..011be7ff51e1 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.c
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
@@ -111,6 +111,12 @@ int lima_devfreq_init(struct lima_device *ldev)
struct dev_pm_opp *opp;
unsigned long cur_freq;
int ret;
+ const char *regulator_names[] = { "mali", NULL };
+ const char *clk_names[] = { "core", NULL };
+ struct dev_pm_opp_config config = {
+ .regulator_names = regulator_names,
+ .clk_names = clk_names,
+ };
if (!device_property_present(dev, "operating-points-v2"))
/* Optional, continue without devfreq */
@@ -118,11 +124,7 @@ int lima_devfreq_init(struct lima_device *ldev)
spin_lock_init(&ldevfreq->lock);
- ret = devm_pm_opp_set_clkname(dev, "core");
- if (ret)
- return ret;
-
- ret = devm_pm_opp_set_regulators(dev, (const char *[]){ "mali" }, 1);
+ ret = devm_pm_opp_set_config(dev, &config);
if (ret) {
/* Continue if the optional regulator is missing */
if (ret != -ENODEV)
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
index 259f3e6bec90..bb7e109534de 100644
--- a/drivers/gpu/drm/meson/meson_viu.c
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -469,17 +469,17 @@ void meson_viu_init(struct meson_drm *priv)
priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
- writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) |
- VIU_OSD_BLEND_REORDER(1, 0) |
- VIU_OSD_BLEND_REORDER(2, 0) |
- VIU_OSD_BLEND_REORDER(3, 0) |
- VIU_OSD_BLEND_DIN_EN(1) |
- VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
- VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
- VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
- VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
- VIU_OSD_BLEND_HOLD_LINES(4),
- priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
+ u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
+ (u32)VIU_OSD_BLEND_REORDER(1, 0) |
+ (u32)VIU_OSD_BLEND_REORDER(2, 0) |
+ (u32)VIU_OSD_BLEND_REORDER(3, 0) |
+ (u32)VIU_OSD_BLEND_DIN_EN(1) |
+ (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
+ (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
+ (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
+ (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
+ (u32)VIU_OSD_BLEND_HOLD_LINES(4);
+ writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
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 ade2988e85f3..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);
}
/******************************************************************************
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 b21f49f0eae5..7a2cceaee6e9 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -644,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);
@@ -688,12 +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;
-}
-
static const u64 nv50_cursor_format_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID,
@@ -747,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 96542ce666fc..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;
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/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/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/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/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/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_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_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 5226323e55d3..3c7e0c9d6baf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -467,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);
}
}
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/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/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, &lt->stat[0], 3);
+ ret = nvkm_rdaux(outp->dp.aux, addr, &lt->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, &lt->stat[4], 2);
+ ret = nvkm_rdaux(outp->dp.aux, addr, &lt->stat[4], 2);
if (ret)
return ret;
if (pc) {
- ret = nvkm_rdaux(dp->aux, DPCD_LS0C, &lt->pc2stat, 1);
+ ret = nvkm_rdaux(outp->dp.aux, DPCD_LS0C, &lt->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(&lt);
@@ -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, &gt200_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, &gt200_disp_ovly_mthd_base },
+ {}
+ }
+};
+
+const struct nvkm_disp_chan_user
+gt200_disp_ovly = {
+ .func = &nv50_disp_dmac_func,
+ .ctrl = 3,
+ .user = 3,
+ .mthd = &gt200_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 = &gt200_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, &gt200_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_(&gt200_disp, device, type, inst, pdisp);
+ return nvkm_disp_new_(&gt200_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 = &gt215_sor_dp,
+ .hda = &gt215_sor_hda,
+};
+
+static int
+gt215_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&gt215_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 = &gt215_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_(&gt215_disp, device, type, inst, pdisp);
+ return nvkm_disp_new_(&gt215_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, &gt200_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 = &gt215_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 = &gt215_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, &gt200_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, &gt200_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_(&gt200_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_(&gt215_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_(&gt215_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/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 3626469c4cc2..cdb154c8b866 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -738,7 +738,7 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel)
of_property_read_u32(dev->of_node, "hpd-reliable-delay-ms", &reliable_ms);
desc->delay.hpd_reliable = reliable_ms;
of_property_read_u32(dev->of_node, "hpd-absent-delay-ms", &absent_ms);
- desc->delay.hpd_reliable = absent_ms;
+ desc->delay.hpd_absent = absent_ms;
/* Power the panel on so we can read the EDID */
ret = pm_runtime_get_sync(dev);
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 194af7f607a6..5110cd9b2425 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -101,8 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
return 0;
}
- ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names,
- pfdev->comp->num_supplies);
+ ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names);
if (ret) {
/* Continue if the optional regulator is missing */
if (ret != -ENODEV) {
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index c58075bc096e..2fa5afe21288 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -433,8 +433,8 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
if (args->retained) {
if (args->madv == PANFROST_MADV_DONTNEED)
- list_add_tail(&bo->base.madv_list,
- &pfdev->shrinker_list);
+ list_move_tail(&bo->base.madv_list,
+ &pfdev->shrinker_list);
else if (args->madv == PANFROST_MADV_WILLNEED)
list_del_init(&bo->base.madv_list);
}
@@ -626,24 +626,29 @@ static int panfrost_remove(struct platform_device *pdev)
return 0;
}
-static const char * const default_supplies[] = { "mali" };
+/*
+ * The OPP core wants the supply names to be NULL terminated, but we need the
+ * correct num_supplies value for regulator core. Hence, we NULL terminate here
+ * and then initialize num_supplies with ARRAY_SIZE - 1.
+ */
+static const char * const default_supplies[] = { "mali", NULL };
static const struct panfrost_compatible default_data = {
- .num_supplies = ARRAY_SIZE(default_supplies),
+ .num_supplies = ARRAY_SIZE(default_supplies) - 1,
.supply_names = default_supplies,
.num_pm_domains = 1, /* optional */
.pm_domain_names = NULL,
};
static const struct panfrost_compatible amlogic_data = {
- .num_supplies = ARRAY_SIZE(default_supplies),
+ .num_supplies = ARRAY_SIZE(default_supplies) - 1,
.supply_names = default_supplies,
.vendor_quirk = panfrost_gpu_amlogic_quirk,
};
-static const char * const mediatek_mt8183_supplies[] = { "mali", "sram" };
+static const char * const mediatek_mt8183_supplies[] = { "mali", "sram", NULL };
static const char * const mediatek_mt8183_pm_domains[] = { "core0", "core1", "core2" };
static const struct panfrost_compatible mediatek_mt8183_data = {
- .num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies),
+ .num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies) - 1,
.supply_names = mediatek_mt8183_supplies,
.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
.pm_domain_names = mediatek_mt8183_pm_domains,
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index d3f82b26a631..b285a8001b1d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -518,7 +518,7 @@ err_map:
err_pages:
drm_gem_shmem_put_pages(&bo->base);
err_bo:
- drm_gem_object_put(&bo->base.base);
+ panfrost_gem_mapping_put(bomapping);
return ret;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
index 382d53f8a22e..e2a67dda4658 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.c
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_cmm.c -- R-Car Display Unit Color Management Module
+ * R-Car Display Unit Color Management Module
*
* Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
index b5f7ec6db04a..628072acc98b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.h
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_cmm.h -- R-Car Display Unit Color Management Module
+ * R-Car Display Unit Color Management Module
*
* Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index f361a604337f..621bbccb95d4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_crtc.c -- R-Car Display Unit CRTCs
+ * R-Car Display Unit CRTCs
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
@@ -300,6 +300,11 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
| DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, dsmr);
+ /*
+ * When the CMM is enabled, an additional offset of 25 pixels must be
+ * subtracted from the HDS (horizontal display start) and HDE
+ * (horizontal display end) registers.
+ */
hdse_offset = 19;
if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2))
hdse_offset += 25;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 66e8839db708..d0f38a8b3561 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_crtc.h -- R-Car Display Unit CRTCs
+ * R-Car Display Unit CRTCs
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 957ea97541d5..70d85610d720 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_drv.c -- R-Car Display Unit DRM driver
+ * R-Car Display Unit DRM driver
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
@@ -55,6 +55,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
@@ -77,6 +78,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
.port = 1,
},
},
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
@@ -104,6 +106,7 @@ static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
.port = 2,
},
},
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
@@ -133,6 +136,7 @@ static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(1),
};
@@ -163,6 +167,7 @@ static const struct rcar_du_device_info rcar_du_r8a774b1_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(1),
};
@@ -190,6 +195,7 @@ static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
},
},
.num_lvds = 2,
+ .num_rpf = 4,
.lvds_clk_mask = BIT(1) | BIT(0),
};
@@ -220,6 +226,7 @@ static const struct rcar_du_device_info rcar_du_r8a774e1_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(1),
};
@@ -272,6 +279,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
},
},
.num_lvds = 2,
+ .num_rpf = 4,
};
/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
@@ -297,6 +305,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rcar_du_r8a7792_info = {
@@ -317,6 +326,7 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
.port = 1,
},
},
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rcar_du_r8a7794_info = {
@@ -340,6 +350,7 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.port = 1,
},
},
+ .num_rpf = 4,
};
static const struct rcar_du_device_info rcar_du_r8a7795_info = {
@@ -373,6 +384,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(2) | BIT(1),
};
@@ -403,6 +415,7 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(1),
};
@@ -433,6 +446,7 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
.dpll_mask = BIT(1),
};
@@ -459,6 +473,7 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
},
},
.num_lvds = 1,
+ .num_rpf = 5,
};
static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
@@ -486,6 +501,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
},
},
.num_lvds = 2,
+ .num_rpf = 5,
.lvds_clk_mask = BIT(1) | BIT(0),
};
@@ -505,6 +521,7 @@ static const struct rcar_du_device_info rcar_du_r8a779a0_info = {
.port = 1,
},
},
+ .num_rpf = 5,
.dsi_clk_mask = BIT(1) | BIT(0),
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 101f42df86ea..bfad7775d9a1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_drv.h -- R-Car Display Unit DRM driver
+ * R-Car Display Unit DRM driver
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
@@ -69,6 +69,7 @@ struct rcar_du_output_routing {
* @channels_mask: bit mask of available DU channels
* @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
* @num_lvds: number of internal LVDS encoders
+ * @num_rpf: number of RPFs in VSP
* @dpll_mask: bit mask of DU channels equipped with a DPLL
* @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot clock
* @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
@@ -80,6 +81,7 @@ struct rcar_du_device_info {
unsigned int channels_mask;
struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
unsigned int num_lvds;
+ unsigned int num_rpf;
unsigned int dpll_mask;
unsigned int dsi_clk_mask;
unsigned int lvds_clk_mask;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index abf8022eb884..60d6be78323b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_encoder.c -- R-Car Display Unit Encoder
+ * R-Car Display Unit Encoder
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 73560563fb31..e5ec8fbb3979 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_encoder.h -- R-Car Display Unit Encoder
+ * R-Car Display Unit Encoder
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 8665a1dd2186..1fe8581577ed 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_group.c -- R-Car Display Unit Channels Pair
+ * R-Car Display Unit Channels Pair
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index e9906609c635..55649ad86a10 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_group.c -- R-Car Display Unit Planes and CRTCs Group
+ * R-Car Display Unit Planes and CRTCs Group
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 0f09e1ee0390..761451ee5263 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_kms.c -- R-Car Display Unit Mode Setting
+ * R-Car Display Unit Mode Setting
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.h b/drivers/gpu/drm/rcar-du/rcar_du_kms.h
index 789154e19535..f31afeeee05a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_kms.h -- R-Car Display Unit Mode Setting
+ * R-Car Display Unit Mode Setting
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index e98b76db703a..501d79367e3e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_plane.c -- R-Car Display Unit Planes
+ * R-Car Display Unit Planes
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
@@ -512,6 +512,18 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
rcar_du_plane_write(rgrp, index, PnDDCR4,
state->format->edf | PnDDCR4_CODE);
+
+ /*
+ * On Gen3, some DU channels have two planes, each being wired to a
+ * separate VSPD instance. The DU can then blend two planes. While
+ * this feature isn't used by the driver, issues related to alpha
+ * blending (such as incorrect colors or planes being invisible) may
+ * still occur if the PnALPHAR register has a stale value. Set the
+ * register to 0 to avoid this.
+ */
+
+ /* TODO: Check if alpha-blending should be disabled in PnMR. */
+ rcar_du_plane_write(rgrp, index, PnALPHAR, 0);
}
static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 81bbf207ad0e..f9893d7d6dfc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_plane.h -- R-Car Display Unit Planes
+ * R-Car Display Unit Planes
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 1cdaa51eb9ac..c1bcb0e8b5b4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * rcar_du_regs.h -- R-Car Display Unit Registers Definitions
+ * R-Car Display Unit Registers Definitions
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index e778fd52f890..dbc68cdabcff 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor
+ * R-Car Display Unit VSP-Based Compositor
*
* Copyright (C) 2015 Renesas Electronics Corporation
*
@@ -407,11 +407,7 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
if (ret < 0)
return ret;
- /*
- * The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
- * 4 RPFs.
- */
- num_planes = rcdu->info->gen >= 3 ? 5 : 4;
+ num_planes = rcdu->info->num_rpf;
vsp->planes = kcalloc(num_planes, sizeof(*vsp->planes), GFP_KERNEL);
if (!vsp->planes)
@@ -437,14 +433,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
drm_plane_helper_add(&plane->plane,
&rcar_du_vsp_plane_helper_funcs);
- if (type == DRM_PLANE_TYPE_PRIMARY) {
- drm_plane_create_zpos_immutable_property(&plane->plane,
- 0);
- } else {
- drm_plane_create_alpha_property(&plane->plane);
- drm_plane_create_zpos_property(&plane->plane, 1, 1,
- num_planes - 1);
- }
+ drm_plane_create_alpha_property(&plane->plane);
+ drm_plane_create_zpos_property(&plane->plane, i, 0,
+ num_planes - 1);
vsp->num_planes++;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
index 9b4724159378..67630f0b6599 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor
+ * R-Car Display Unit VSP-Based Compositor
*
* Copyright (C) 2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c
index 4fd6067f6fb4..25f50a297c11 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * rcar_du_writeback.c -- R-Car Display Unit Writeback Support
+ * R-Car Display Unit Writeback Support
*
* Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h b/drivers/gpu/drm/rcar-du/rcar_du_writeback.h
index fa87ebf8d21f..a71c9c08cafa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * rcar_du_writeback.h -- R-Car Display Unit Writeback Support
+ * R-Car Display Unit Writeback Support
*
* Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 830aac0a2cb4..d85aa4bc7f84 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * rcar_lvds.c -- R-Car LVDS Encoder
+ * R-Car LVDS Encoder
*
* Copyright (C) 2013-2018 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h
index eb7c6ef03b00..3097bf749bec 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * rcar_lvds.h -- R-Car LVDS Encoder
+ * R-Car LVDS Encoder
*
* Copyright (C) 2013-2018 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 87149f2f8056..ab0406a27d33 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * rcar_lvds_regs.h -- R-Car LVDS Interface Registers Definitions
+ * R-Car LVDS Interface Registers Definitions
*
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
index 31ed285073e0..62f7eb84ab01 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
+++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * rcar_mipi_dsi.c -- R-Car MIPI DSI Encoder
+ * R-Car MIPI DSI Encoder
*
* Copyright (C) 2020 Renesas Electronics Corporation
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
index 0e7a9274749f..2eaca54636f3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * rcar_mipi_dsi_regs.h -- R-Car MIPI DSI Interface Registers Definitions
+ * R-Car MIPI DSI Interface Registers Definitions
*
* Copyright (C) 2020 Renesas Electronics Corporation
*/
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 67d38f53d3e5..13ed33e74457 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -23,6 +23,14 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
+#if defined(CONFIG_ARM_DMA_USE_IOMMU)
+#include <asm/dma-iommu.h>
+#else
+#define arm_iommu_detach_device(...) ({ })
+#define arm_iommu_release_mapping(...) ({ })
+#define to_dma_iommu_mapping(dev) NULL
+#endif
+
#include "rockchip_drm_drv.h"
#include "rockchip_drm_fb.h"
#include "rockchip_drm_gem.h"
@@ -49,6 +57,15 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
if (!private->domain)
return 0;
+ if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+
+ if (mapping) {
+ arm_iommu_detach_device(dev);
+ arm_iommu_release_mapping(mapping);
+ }
+ }
+
ret = iommu_attach_device(private->domain, dev);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to attach iommu device\n");
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 77f80b0d3a5e..5a3e3b78cd9e 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -352,7 +352,7 @@ static int ssd130x_init(struct ssd130x_device *ssd130x)
/* Set precharge period in number of ticks from the internal clock */
precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) |
- SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep2));
+ SSD130X_SET_PRECHARGE_PERIOD2_SET(ssd130x->prechargep2));
ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 768242a78e2b..5422363690e7 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -627,7 +627,7 @@ static const struct drm_connector_funcs simpledrm_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static int
+static enum drm_mode_status
simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
const struct drm_display_mode *mode)
{