aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/drm.tmpl50
-rw-r--r--Documentation/devicetree/bindings/drm/bridge/ptn3460.txt27
-rw-r--r--Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt42
-rw-r--r--Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/lg,lp129qe.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/samsung,ld9040.txt66
-rw-r--r--Documentation/devicetree/bindings/panel/samsung,s6e8aa0.txt56
-rw-r--r--Documentation/devicetree/bindings/video/exynos_dp.txt17
-rw-r--r--Documentation/devicetree/bindings/video/exynos_dsim.txt80
-rw-r--r--Documentation/devicetree/bindings/video/exynos_hdmi.txt5
-rw-r--r--Documentation/devicetree/bindings/video/samsung-fimd.txt17
-rw-r--r--MAINTAINERS16
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi14
-rw-r--r--arch/arm/boot/dts/exynos4210-trats.dts61
-rw-r--r--arch/arm/boot/dts/exynos4210-universal_c210.dts64
-rw-r--r--arch/arm/boot/dts/exynos4412-trats2.dts70
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile4
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c23
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c12
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c4
-rw-r--r--drivers/gpu/drm/bridge/Kconfig5
-rw-r--r--drivers/gpu/drm/bridge/Makefile3
-rw-r--r--drivers/gpu/drm/bridge/ptn3460.c350
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c10
-rw-r--r--drivers/gpu/drm/drm_crtc.c203
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c62
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c12
-rw-r--r--drivers/gpu/drm/drm_drv.c132
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c22
-rw-r--r--drivers/gpu/drm/drm_fops.c26
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c19
-rw-r--r--drivers/gpu/drm/drm_ioctl.c7
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c6
-rw-r--r--drivers/gpu/drm/drm_mm.c78
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c333
-rw-r--r--drivers/gpu/drm/drm_stub.c77
-rw-r--r--drivers/gpu/drm/exynos/Kconfig24
-rw-r--r--drivers/gpu/drm/exynos/Makefile9
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c (renamed from drivers/video/exynos/exynos_dp_core.c)304
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.h (renamed from drivers/video/exynos/exynos_dp_core.h)9
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_reg.c (renamed from drivers/video/exynos/exynos_dp_reg.c)0
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_reg.h (renamed from drivers/video/exynos/exynos_dp_reg.h)0
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c92
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c193
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c159
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c339
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c197
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h163
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c1524
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c359
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.h18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c23
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c700
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c439
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.h67
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c19
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c441
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c472
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c573
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.h20
-rw-r--r--drivers/gpu/drm/gma500/Makefile2
-rw-r--r--drivers/gpu/drm/gma500/blitter.c51
-rw-r--r--drivers/gpu/drm/gma500/blitter.h22
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.c40
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_crt.c9
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_display.c73
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c2
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_hdmi.c11
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c5
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c2
-rw-r--r--drivers/gpu/drm/gma500/gem.c56
-rw-r--r--drivers/gpu/drm/gma500/gem.h21
-rw-r--r--drivers/gpu/drm/gma500/gma_device.c56
-rw-r--r--drivers/gpu/drm/gma500/gma_device.h21
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c23
-rw-r--r--drivers/gpu/drm/gma500/gma_display.h3
-rw-r--r--drivers/gpu/drm/gma500/gtt.c45
-rw-r--r--drivers/gpu/drm/gma500/gtt.h3
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.c2
-rw-r--r--drivers/gpu/drm/gma500/mdfld_intel_display.c16
-rw-r--r--drivers/gpu/drm/gma500/mmu.c297
-rw-r--r--drivers/gpu/drm/gma500/mmu.h93
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_crtc.c12
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi.c9
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds.c5
-rw-r--r--drivers/gpu/drm/gma500/opregion.c25
-rw-r--r--drivers/gpu/drm/gma500/psb_device.c42
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c404
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h203
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_display.c32
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_drv.h2
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c5
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_sdvo.c22
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c81
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7xxx.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_ivch.c30
-rw-r--r--drivers/gpu/drm/i915/dvo_ns2501.c10
-rw-r--r--drivers/gpu/drm/i915/dvo_sil164.c10
-rw-r--r--drivers/gpu/drm/i915/dvo_tfp410.c24
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c3
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c152
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c4
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c6
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c4
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c38
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c26
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c105
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c65
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h16
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c50
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h25
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_audio.c273
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c26
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c33
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c27
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.c3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c139
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c15
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c85
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h16
-rw-r--r--drivers/gpu/drm/nouveau/Makefile16
-rw-r--r--drivers/gpu/drm/nouveau/core/core/namedb.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/core/parent.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/base.c85
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/gm100.c106
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv10.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv20.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv30.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv40.c32
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv50.c28
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c44
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/gm107.c101
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c370
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h54
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c191
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c67
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c361
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c187
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/priv.h10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/falcon.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c509
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c507
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c989
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c1041
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c308
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h170
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c270
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c (renamed from drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c)78
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c144
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c216
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c278
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c285
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c782
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc7
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc542
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h473
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h354
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h336
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h396
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h396
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h396
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc540
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h916
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gm107.c465
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv108.c133
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv20.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv50.c45
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c312
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h214
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c115
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c (renamed from drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c)86
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c104
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c175
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c154
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve4.c192
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c136
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/xtensa.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h12
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/device.h31
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/namedb.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/device.h18
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/disp.h19
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/graph.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h23
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h7
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/devinit.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/fb.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/mc.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/timer.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/os.h12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c109
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/base.c55
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c29
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/init.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/therm.c11
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/base.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c38
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c34
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c (renamed from drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c)109
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h21
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c142
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/base.c55
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mxm/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c40
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c57
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c83
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h27
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c22
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c22
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_agp.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c22
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c88
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hwmon.c17
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sysfs.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c31
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c5
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c17
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c13
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c5
-rw-r--r--drivers/gpu/drm/panel/Kconfig14
-rw-r--r--drivers/gpu/drm/panel/Makefile2
-rw-r--r--drivers/gpu/drm/panel/panel-ld9040.c376
-rw-r--r--drivers/gpu/drm/panel/panel-s6e8aa0.c1069
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c157
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c10
-rw-r--r--drivers/gpu/drm/qxl/qxl_release.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_ttm.c1
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c20
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c268
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c82
-rw-r--r--drivers/gpu/drm/radeon/cik.c33
-rw-r--r--drivers/gpu/drm/radeon/r100.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c19
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c248
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c10
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c5
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c16
-rw-r--r--drivers/gpu/drm/tegra/Makefile2
-rw-r--r--drivers/gpu/drm/tegra/dc.c16
-rw-r--r--drivers/gpu/drm/tegra/dc.h1
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c544
-rw-r--r--drivers/gpu/drm/tegra/dpaux.h73
-rw-r--r--drivers/gpu/drm/tegra/drm.c19
-rw-r--r--drivers/gpu/drm/tegra/drm.h20
-rw-r--r--drivers/gpu/drm/tegra/dsi.c20
-rw-r--r--drivers/gpu/drm/tegra/dsi.h20
-rw-r--r--drivers/gpu/drm/tegra/gem.c25
-rw-r--r--drivers/gpu/drm/tegra/gem.h14
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c14
-rw-r--r--drivers/gpu/drm/tegra/mipi-phy.c20
-rw-r--r--drivers/gpu/drm/tegra/mipi-phy.h20
-rw-r--r--drivers/gpu/drm/tegra/output.c8
-rw-r--r--drivers/gpu/drm/tegra/sor.c1092
-rw-r--r--drivers/gpu/drm/tegra/sor.h278
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c26
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_manager.c11
-rw-r--r--drivers/gpu/drm/ttm/ttm_execbuf_util.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_object.c46
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c15
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c143
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c14
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c29
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c143
-rw-r--r--drivers/gpu/host1x/syncpt.c1
-rw-r--r--drivers/staging/imx-drm/ipuv3-crtc.c6
-rw-r--r--drivers/staging/imx-drm/ipuv3-plane.c2
-rw-r--r--drivers/video/exynos/Kconfig7
-rw-r--r--drivers/video/exynos/Makefile1
-rw-r--r--include/drm/bridge/ptn3460.h37
-rw-r--r--include/drm/drmP.h173
-rw-r--r--include/drm/drm_crtc.h50
-rw-r--r--include/drm/drm_gem_cma_helper.h2
-rw-r--r--include/drm/drm_mipi_dsi.h6
-rw-r--r--include/drm/drm_mm.h32
-rw-r--r--include/drm/drm_plane_helper.h49
-rw-r--r--include/drm/gma_drm.h70
-rw-r--r--include/drm/ttm/ttm_bo_driver.h47
-rw-r--r--include/drm/ttm/ttm_object.h4
-rw-r--r--include/drm/ttm/ttm_placement.h3
-rw-r--r--include/linux/host1x.h1
-rw-r--r--include/uapi/drm/drm.h17
-rw-r--r--include/uapi/drm/msm_drm.h12
-rw-r--r--include/uapi/drm/tegra_drm.h24
-rw-r--r--include/uapi/drm/vmwgfx_drm.h12
374 files changed, 22151 insertions, 9114 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 9f5457ac0373..702c4474919c 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -1194,7 +1194,7 @@ int max_width, max_height;</synopsis>
1194 pointer to CRTC functions. 1194 pointer to CRTC functions.
1195 </para> 1195 </para>
1196 </sect3> 1196 </sect3>
1197 <sect3> 1197 <sect3 id="drm-kms-crtcops">
1198 <title>CRTC Operations</title> 1198 <title>CRTC Operations</title>
1199 <sect4> 1199 <sect4>
1200 <title>Set Configuration</title> 1200 <title>Set Configuration</title>
@@ -1335,15 +1335,47 @@ int max_width, max_height;</synopsis>
1335 optionally scale it to a destination size. The result is then blended 1335 optionally scale it to a destination size. The result is then blended
1336 with or overlayed on top of a CRTC. 1336 with or overlayed on top of a CRTC.
1337 </para> 1337 </para>
1338 <para>
1339 The DRM core recognizes three types of planes:
1340 <itemizedlist>
1341 <listitem>
1342 DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC. Primary
1343 planes are the planes operated upon by by CRTC modesetting and flipping
1344 operations described in <xref linkend="drm-kms-crtcops"/>.
1345 </listitem>
1346 <listitem>
1347 DRM_PLANE_TYPE_CURSOR represents a "cursor" plane for a CRTC. Cursor
1348 planes are the planes operated upon by the DRM_IOCTL_MODE_CURSOR and
1349 DRM_IOCTL_MODE_CURSOR2 ioctls.
1350 </listitem>
1351 <listitem>
1352 DRM_PLANE_TYPE_OVERLAY represents all non-primary, non-cursor planes.
1353 Some drivers refer to these types of planes as "sprites" internally.
1354 </listitem>
1355 </itemizedlist>
1356 For compatibility with legacy userspace, only overlay planes are made
1357 available to userspace by default. Userspace clients may set the
1358 DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate that
1359 they wish to receive a universal plane list containing all plane types.
1360 </para>
1338 <sect3> 1361 <sect3>
1339 <title>Plane Initialization</title> 1362 <title>Plane Initialization</title>
1340 <para> 1363 <para>
1341 Planes are optional. To create a plane, a KMS drivers allocates and 1364 To create a plane, a KMS drivers allocates and
1342 zeroes an instances of struct <structname>drm_plane</structname> 1365 zeroes an instances of struct <structname>drm_plane</structname>
1343 (possibly as part of a larger structure) and registers it with a call 1366 (possibly as part of a larger structure) and registers it with a call
1344 to <function>drm_plane_init</function>. The function takes a bitmask 1367 to <function>drm_universal_plane_init</function>. The function takes a bitmask
1345 of the CRTCs that can be associated with the plane, a pointer to the 1368 of the CRTCs that can be associated with the plane, a pointer to the
1346 plane functions and a list of format supported formats. 1369 plane functions, a list of format supported formats, and the type of
1370 plane (primary, cursor, or overlay) being initialized.
1371 </para>
1372 <para>
1373 Cursor and overlay planes are optional. All drivers should provide
1374 one primary plane per CRTC (although this requirement may change in
1375 the future); drivers that do not wish to provide special handling for
1376 primary planes may make use of the helper functions described in
1377 <xref linkend="drm-kms-planehelpers"/> to create and register a
1378 primary plane with standard capabilities.
1347 </para> 1379 </para>
1348 </sect3> 1380 </sect3>
1349 <sect3> 1381 <sect3>
@@ -1774,7 +1806,7 @@ void intel_crt_init(struct drm_device *dev)
1774 <sect1> 1806 <sect1>
1775 <title>Mode Setting Helper Functions</title> 1807 <title>Mode Setting Helper Functions</title>
1776 <para> 1808 <para>
1777 The CRTC, encoder and connector functions provided by the drivers 1809 The plane, CRTC, encoder and connector functions provided by the drivers
1778 implement the DRM API. They're called by the DRM core and ioctl handlers 1810 implement the DRM API. They're called by the DRM core and ioctl handlers
1779 to handle device state changes and configuration request. As implementing 1811 to handle device state changes and configuration request. As implementing
1780 those functions often requires logic not specific to drivers, mid-layer 1812 those functions often requires logic not specific to drivers, mid-layer
@@ -1782,8 +1814,8 @@ void intel_crt_init(struct drm_device *dev)
1782 </para> 1814 </para>
1783 <para> 1815 <para>
1784 The DRM core contains one mid-layer implementation. The mid-layer provides 1816 The DRM core contains one mid-layer implementation. The mid-layer provides
1785 implementations of several CRTC, encoder and connector functions (called 1817 implementations of several plane, CRTC, encoder and connector functions
1786 from the top of the mid-layer) that pre-process requests and call 1818 (called from the top of the mid-layer) that pre-process requests and call
1787 lower-level functions provided by the driver (at the bottom of the 1819 lower-level functions provided by the driver (at the bottom of the
1788 mid-layer). For instance, the 1820 mid-layer). For instance, the
1789 <function>drm_crtc_helper_set_config</function> function can be used to 1821 <function>drm_crtc_helper_set_config</function> function can be used to
@@ -2293,6 +2325,10 @@ void intel_crt_init(struct drm_device *dev)
2293!Iinclude/linux/hdmi.h 2325!Iinclude/linux/hdmi.h
2294!Edrivers/video/hdmi.c 2326!Edrivers/video/hdmi.c
2295 </sect2> 2327 </sect2>
2328 <sect2>
2329 <title id="drm-kms-planehelpers">Plane Helper Reference</title>
2330!Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers
2331 </sect2>
2296 </sect1> 2332 </sect1>
2297 2333
2298 <!-- Internals: kms properties --> 2334 <!-- Internals: kms properties -->
diff --git a/Documentation/devicetree/bindings/drm/bridge/ptn3460.txt b/Documentation/devicetree/bindings/drm/bridge/ptn3460.txt
new file mode 100644
index 000000000000..52b93b2c6748
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/bridge/ptn3460.txt
@@ -0,0 +1,27 @@
1ptn3460 bridge bindings
2
3Required properties:
4 - compatible: "nxp,ptn3460"
5 - reg: i2c address of the bridge
6 - powerdown-gpio: OF device-tree gpio specification
7 - reset-gpio: OF device-tree gpio specification
8 - edid-emulation: The EDID emulation entry to use
9 +-------+------------+------------------+
10 | Value | Resolution | Description |
11 | 0 | 1024x768 | NXP Generic |
12 | 1 | 1920x1080 | NXP Generic |
13 | 2 | 1920x1080 | NXP Generic |
14 | 3 | 1600x900 | Samsung LTM200KT |
15 | 4 | 1920x1080 | Samsung LTM230HT |
16 | 5 | 1366x768 | NXP Generic |
17 | 6 | 1600x900 | ChiMei M215HGE |
18 +-------+------------+------------------+
19
20Example:
21 lvds-bridge@20 {
22 compatible = "nxp,ptn3460";
23 reg = <0x20>;
24 powerdown-gpio = <&gpy2 5 1 0 0>;
25 reset-gpio = <&gpx1 5 1 0 0>;
26 edid-emulation = <5>;
27 };
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
index efaeec8961b6..efa8b8451f93 100644
--- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -190,6 +190,48 @@ of the following host1x client modules:
190 - nvidia,edid: supplies a binary EDID blob 190 - nvidia,edid: supplies a binary EDID blob
191 - nvidia,panel: phandle of a display panel 191 - nvidia,panel: phandle of a display panel
192 192
193- sor: serial output resource
194
195 Required properties:
196 - compatible: "nvidia,tegra124-sor"
197 - reg: Physical base address and length of the controller's registers.
198 - interrupts: The interrupt outputs from the controller.
199 - clocks: Must contain an entry for each entry in clock-names.
200 See ../clocks/clock-bindings.txt for details.
201 - clock-names: Must include the following entries:
202 - sor: clock input for the SOR hardware
203 - parent: input for the pixel clock
204 - dp: reference clock for the SOR clock
205 - safe: safe reference for the SOR clock during power up
206 - resets: Must contain an entry for each entry in reset-names.
207 See ../reset/reset.txt for details.
208 - reset-names: Must include the following entries:
209 - sor
210
211 Optional properties:
212 - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
213 - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
214 - nvidia,edid: supplies a binary EDID blob
215 - nvidia,panel: phandle of a display panel
216
217 Optional properties when driving an eDP output:
218 - nvidia,dpaux: phandle to a DispayPort AUX interface
219
220- dpaux: DisplayPort AUX interface
221 - compatible: "nvidia,tegra124-dpaux"
222 - reg: Physical base address and length of the controller's registers.
223 - interrupts: The interrupt outputs from the controller.
224 - clocks: Must contain an entry for each entry in clock-names.
225 See ../clocks/clock-bindings.txt for details.
226 - clock-names: Must include the following entries:
227 - dpaux: clock input for the DPAUX hardware
228 - parent: reference clock
229 - resets: Must contain an entry for each entry in reset-names.
230 See ../reset/reset.txt for details.
231 - reset-names: Must include the following entries:
232 - dpaux
233 - vdd-supply: phandle of a supply that powers the DisplayPort link
234
193Example: 235Example:
194 236
195/ { 237/ {
diff --git a/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt b/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt
new file mode 100644
index 000000000000..5e649cb9aa1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt
@@ -0,0 +1,7 @@
1LG Corporation 7" WXGA TFT LCD panel
2
3Required properties:
4- compatible: should be "lg,ld070wx3-sl01"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt b/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt
new file mode 100644
index 000000000000..a04fd2b2e73d
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt
@@ -0,0 +1,7 @@
1LG Corporation 5" HD TFT LCD panel
2
3Required properties:
4- compatible: should be "lg,lh500wx1-sd03"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/lg,lp129qe.txt b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt
new file mode 100644
index 000000000000..9f262e0c5a2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt
@@ -0,0 +1,7 @@
1LG 12.9" (2560x1700 pixels) TFT LCD panel
2
3Required properties:
4- compatible: should be "lg,lp129qe"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/samsung,ld9040.txt b/Documentation/devicetree/bindings/panel/samsung,ld9040.txt
new file mode 100644
index 000000000000..07c36c3f7b52
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,ld9040.txt
@@ -0,0 +1,66 @@
1Samsung LD9040 AMOLED LCD parallel RGB panel with SPI control bus
2
3Required properties:
4 - compatible: "samsung,ld9040"
5 - reg: address of the panel on SPI bus
6 - vdd3-supply: core voltage supply
7 - vci-supply: voltage supply for analog circuits
8 - reset-gpios: a GPIO spec for the reset pin
9 - display-timings: timings for the connected panel according to [1]
10
11The panel must obey rules for SPI slave device specified in document [2].
12
13Optional properties:
14 - power-on-delay: delay after turning regulators on [ms]
15 - reset-delay: delay after reset sequence [ms]
16 - panel-width-mm: physical panel width [mm]
17 - panel-height-mm: physical panel height [mm]
18
19The device node can contain one 'port' child node with one child
20'endpoint' node, according to the bindings defined in [3]. This
21node should describe panel's video bus.
22
23[1]: Documentation/devicetree/bindings/video/display-timing.txt
24[2]: Documentation/devicetree/bindings/spi/spi-bus.txt
25[3]: Documentation/devicetree/bindings/media/video-interfaces.txt
26
27Example:
28
29 lcd@0 {
30 compatible = "samsung,ld9040";
31 reg = <0>;
32 vdd3-supply = <&ldo7_reg>;
33 vci-supply = <&ldo17_reg>;
34 reset-gpios = <&gpy4 5 0>;
35 spi-max-frequency = <1200000>;
36 spi-cpol;
37 spi-cpha;
38 power-on-delay = <10>;
39 reset-delay = <10>;
40 panel-width-mm = <90>;
41 panel-height-mm = <154>;
42
43 display-timings {
44 timing {
45 clock-frequency = <23492370>;
46 hactive = <480>;
47 vactive = <800>;
48 hback-porch = <16>;
49 hfront-porch = <16>;
50 vback-porch = <2>;
51 vfront-porch = <28>;
52 hsync-len = <2>;
53 vsync-len = <1>;
54 hsync-active = <0>;
55 vsync-active = <0>;
56 de-active = <0>;
57 pixelclk-active = <0>;
58 };
59 };
60
61 port {
62 lcd_ep: endpoint {
63 remote-endpoint = <&fimd_dpi_ep>;
64 };
65 };
66 };
diff --git a/Documentation/devicetree/bindings/panel/samsung,s6e8aa0.txt b/Documentation/devicetree/bindings/panel/samsung,s6e8aa0.txt
new file mode 100644
index 000000000000..e7ee988e3156
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,s6e8aa0.txt
@@ -0,0 +1,56 @@
1Samsung S6E8AA0 AMOLED LCD 5.3 inch panel
2
3Required properties:
4 - compatible: "samsung,s6e8aa0"
5 - reg: the virtual channel number of a DSI peripheral
6 - vdd3-supply: core voltage supply
7 - vci-supply: voltage supply for analog circuits
8 - reset-gpios: a GPIO spec for the reset pin
9 - display-timings: timings for the connected panel as described by [1]
10
11Optional properties:
12 - power-on-delay: delay after turning regulators on [ms]
13 - reset-delay: delay after reset sequence [ms]
14 - init-delay: delay after initialization sequence [ms]
15 - panel-width-mm: physical panel width [mm]
16 - panel-height-mm: physical panel height [mm]
17 - flip-horizontal: boolean to flip image horizontally
18 - flip-vertical: boolean to flip image vertically
19
20The device node can contain one 'port' child node with one child
21'endpoint' node, according to the bindings defined in [2]. This
22node should describe panel's video bus.
23
24[1]: Documentation/devicetree/bindings/video/display-timing.txt
25[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
26
27Example:
28
29 panel {
30 compatible = "samsung,s6e8aa0";
31 reg = <0>;
32 vdd3-supply = <&vcclcd_reg>;
33 vci-supply = <&vlcd_reg>;
34 reset-gpios = <&gpy4 5 0>;
35 power-on-delay= <50>;
36 reset-delay = <100>;
37 init-delay = <100>;
38 panel-width-mm = <58>;
39 panel-height-mm = <103>;
40 flip-horizontal;
41 flip-vertical;
42
43 display-timings {
44 timing0: timing-0 {
45 clock-frequency = <57153600>;
46 hactive = <720>;
47 vactive = <1280>;
48 hfront-porch = <5>;
49 hback-porch = <5>;
50 hsync-len = <5>;
51 vfront-porch = <13>;
52 vback-porch = <1>;
53 vsync-len = <2>;
54 };
55 };
56 };
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index 3289d76a21d0..57ccdde02c3a 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -49,6 +49,8 @@ Required properties for dp-controller:
49 -samsung,lane-count: 49 -samsung,lane-count:
50 number of lanes supported by the panel. 50 number of lanes supported by the panel.
51 LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 51 LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
52 - display-timings: timings for the connected panel as described by
53 Documentation/devicetree/bindings/video/display-timing.txt
52 54
53Optional properties for dp-controller: 55Optional properties for dp-controller:
54 -interlaced: 56 -interlaced:
@@ -84,4 +86,19 @@ Board Specific portion:
84 samsung,color-depth = <1>; 86 samsung,color-depth = <1>;
85 samsung,link-rate = <0x0a>; 87 samsung,link-rate = <0x0a>;
86 samsung,lane-count = <4>; 88 samsung,lane-count = <4>;
89
90 display-timings {
91 native-mode = <&lcd_timing>;
92 lcd_timing: 1366x768 {
93 clock-frequency = <70589280>;
94 hactive = <1366>;
95 vactive = <768>;
96 hfront-porch = <40>;
97 hback-porch = <40>;
98 hsync-len = <32>;
99 vback-porch = <10>;
100 vfront-porch = <12>;
101 vsync-len = <6>;
102 };
103 };
87 }; 104 };
diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt b/Documentation/devicetree/bindings/video/exynos_dsim.txt
new file mode 100644
index 000000000000..33b5730d07ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -0,0 +1,80 @@
1Exynos MIPI DSI Master
2
3Required properties:
4 - compatible: "samsung,exynos4210-mipi-dsi"
5 - reg: physical base address and length of the registers set for the device
6 - interrupts: should contain DSI interrupt
7 - clocks: list of clock specifiers, must contain an entry for each required
8 entry in clock-names
9 - clock-names: should include "bus_clk"and "pll_clk" entries
10 - phys: list of phy specifiers, must contain an entry for each required
11 entry in phy-names
12 - phy-names: should include "dsim" entry
13 - vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V)
14 - vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
15 - samsung,pll-clock-frequency: specifies frequency of the "pll_clk" clock
16 - #address-cells, #size-cells: should be set respectively to <1> and <0>
17 according to DSI host bindings (see MIPI DSI bindings [1])
18
19Optional properties:
20 - samsung,power-domain: a phandle to DSIM power domain node
21
22Child nodes:
23 Should contain DSI peripheral nodes (see MIPI DSI bindings [1]).
24
25Video interfaces:
26 Device node can contain video interface port nodes according to [2].
27 The following are properties specific to those nodes:
28
29 port node:
30 - reg: (required) can be 0 for input RGB/I80 port or 1 for DSI port;
31
32 endpoint node of DSI port (reg = 1):
33 - samsung,burst-clock-frequency: specifies DSI frequency in high-speed burst
34 mode
35 - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
36
37[1]: Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt
38[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
39
40Example:
41
42 dsi@11C80000 {
43 compatible = "samsung,exynos4210-mipi-dsi";
44 reg = <0x11C80000 0x10000>;
45 interrupts = <0 79 0>;
46 clocks = <&clock 286>, <&clock 143>;
47 clock-names = "bus_clk", "pll_clk";
48 phys = <&mipi_phy 1>;
49 phy-names = "dsim";
50 vddcore-supply = <&vusb_reg>;
51 vddio-supply = <&vmipi_reg>;
52 samsung,power-domain = <&pd_lcd0>;
53 #address-cells = <1>;
54 #size-cells = <0>;
55 samsung,pll-clock-frequency = <24000000>;
56
57 panel@1 {
58 reg = <0>;
59 ...
60 port {
61 panel_ep: endpoint {
62 remote-endpoint = <&dsi_ep>;
63 };
64 };
65 };
66
67 ports {
68 #address-cells = <1>;
69 #size-cells = <0>;
70
71 port@1 {
72 dsi_ep: endpoint {
73 reg = <0>;
74 samsung,burst-clock-frequency = <500000000>;
75 samsung,esc-clock-frequency = <20000000>;
76 remote-endpoint = <&panel_ep>;
77 };
78 };
79 };
80 };
diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
index 50decf8e1b90..f9187a259259 100644
--- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
@@ -25,6 +25,9 @@ Required properties:
25 sclk_pixel. 25 sclk_pixel.
26- clock-names: aliases as per driver requirements for above clock IDs: 26- clock-names: aliases as per driver requirements for above clock IDs:
27 "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi". 27 "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi".
28- ddc: phandle to the hdmi ddc node
29- phy: phandle to the hdmi phy node
30
28Example: 31Example:
29 32
30 hdmi { 33 hdmi {
@@ -32,4 +35,6 @@ Example:
32 reg = <0x14530000 0x100000>; 35 reg = <0x14530000 0x100000>;
33 interrupts = <0 95 0>; 36 interrupts = <0 95 0>;
34 hpd-gpio = <&gpx3 7 1>; 37 hpd-gpio = <&gpx3 7 1>;
38 ddc = <&hdmi_ddc_node>;
39 phy = <&hdmi_phy_node>;
35 }; 40 };
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index 778838a0336a..2dad41b689af 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -39,6 +39,23 @@ Required properties:
39 39
40Optional Properties: 40Optional Properties:
41- samsung,power-domain: a phandle to FIMD power domain node. 41- samsung,power-domain: a phandle to FIMD power domain node.
42- samsung,invert-vden: video enable signal is inverted
43- samsung,invert-vclk: video clock signal is inverted
44- display-timings: timing settings for FIMD, as described in document [1].
45 Can be used in case timings cannot be provided otherwise
46 or to override timings provided by the panel.
47
48The device node can contain 'port' child nodes according to the bindings defined
49in [2]. The following are properties specific to those nodes:
50- reg: (required) port index, can be:
51 0 - for CAMIF0 input,
52 1 - for CAMIF1 input,
53 2 - for CAMIF2 input,
54 3 - for parallel output,
55 4 - for write-back interface
56
57[1]: Documentation/devicetree/bindings/video/display-timing.txt
58[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
42 59
43Example: 60Example:
44 61
diff --git a/MAINTAINERS b/MAINTAINERS
index 900d98eec2fc..719e6279b80a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2866,6 +2866,16 @@ F: drivers/gpu/drm/radeon/
2866F: include/drm/radeon* 2866F: include/drm/radeon*
2867F: include/uapi/drm/radeon* 2867F: include/uapi/drm/radeon*
2868 2868
2869DRM PANEL DRIVERS
2870M: Thierry Reding <thierry.reding@gmail.com>
2871L: dri-devel@lists.freedesktop.org
2872T: git git://anongit.freedesktop.org/tegra/linux.git
2873S: Maintained
2874F: drivers/gpu/drm/drm_panel.c
2875F: drivers/gpu/drm/panel/
2876F: include/drm/drm_panel.h
2877F: Documentation/devicetree/bindings/panel/
2878
2869INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets) 2879INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
2870M: Daniel Vetter <daniel.vetter@ffwll.ch> 2880M: Daniel Vetter <daniel.vetter@ffwll.ch>
2871M: Jani Nikula <jani.nikula@linux.intel.com> 2881M: Jani Nikula <jani.nikula@linux.intel.com>
@@ -3393,12 +3403,6 @@ S: Maintained
3393F: drivers/extcon/ 3403F: drivers/extcon/
3394F: Documentation/extcon/ 3404F: Documentation/extcon/
3395 3405
3396EXYNOS DP DRIVER
3397M: Jingoo Han <jg1.han@samsung.com>
3398L: linux-fbdev@vger.kernel.org
3399S: Maintained
3400F: drivers/video/exynos/exynos_dp*
3401
3402EXYNOS MIPI DISPLAY DRIVERS 3406EXYNOS MIPI DISPLAY DRIVERS
3403M: Inki Dae <inki.dae@samsung.com> 3407M: Inki Dae <inki.dae@samsung.com>
3404M: Donghwa Lee <dh09.lee@samsung.com> 3408M: Donghwa Lee <dh09.lee@samsung.com>
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 08452e183b57..3d14cdb0776a 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -104,6 +104,20 @@
104 reg = <0x10010000 0x400>; 104 reg = <0x10010000 0x400>;
105 }; 105 };
106 106
107 dsi_0: dsi@11C80000 {
108 compatible = "samsung,exynos4210-mipi-dsi";
109 reg = <0x11C80000 0x10000>;
110 interrupts = <0 79 0>;
111 samsung,power-domain = <&pd_lcd0>;
112 phys = <&mipi_phy 1>;
113 phy-names = "dsim";
114 clocks = <&clock 286>, <&clock 143>;
115 clock-names = "bus_clk", "pll_clk";
116 status = "disabled";
117 #address-cells = <1>;
118 #size-cells = <0>;
119 };
120
107 camera { 121 camera {
108 compatible = "samsung,fimc", "simple-bus"; 122 compatible = "samsung,fimc", "simple-bus";
109 status = "disabled"; 123 status = "disabled";
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 63cc571ca307..02c6768f52b4 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -353,6 +353,67 @@
353 }; 353 };
354 }; 354 };
355 355
356 dsi_0: dsi@11C80000 {
357 vddcore-supply = <&vusb_reg>;
358 vddio-supply = <&vmipi_reg>;
359 samsung,pll-clock-frequency = <24000000>;
360 status = "okay";
361
362 ports {
363 #address-cells = <1>;
364 #size-cells = <0>;
365
366 port@1 {
367 reg = <1>;
368
369 dsi_out: endpoint {
370 remote-endpoint = <&dsi_in>;
371 samsung,burst-clock-frequency = <500000000>;
372 samsung,esc-clock-frequency = <20000000>;
373 };
374 };
375 };
376
377 panel@0 {
378 reg = <0>;
379 compatible = "samsung,s6e8aa0";
380 vdd3-supply = <&vcclcd_reg>;
381 vci-supply = <&vlcd_reg>;
382 reset-gpios = <&gpy4 5 0>;
383 power-on-delay= <50>;
384 reset-delay = <100>;
385 init-delay = <100>;
386 flip-horizontal;
387 flip-vertical;
388 panel-width-mm = <58>;
389 panel-height-mm = <103>;
390
391 display-timings {
392 timing-0 {
393 clock-frequency = <57153600>;
394 hactive = <720>;
395 vactive = <1280>;
396 hfront-porch = <5>;
397 hback-porch = <5>;
398 hsync-len = <5>;
399 vfront-porch = <13>;
400 vback-porch = <1>;
401 vsync-len = <2>;
402 };
403 };
404
405 port {
406 dsi_in: endpoint {
407 remote-endpoint = <&dsi_out>;
408 };
409 };
410 };
411 };
412
413 fimd@11c00000 {
414 status = "okay";
415 };
416
356 camera { 417 camera {
357 pinctrl-names = "default"; 418 pinctrl-names = "default";
358 pinctrl-0 = <>; 419 pinctrl-0 = <>;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index d2e3f5f5916d..0a80a72368d3 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -345,6 +345,70 @@
345 }; 345 };
346 }; 346 };
347 347
348 spi-lcd {
349 compatible = "spi-gpio";
350 #address-cells = <1>;
351 #size-cells = <0>;
352
353 gpio-sck = <&gpy3 1 0>;
354 gpio-mosi = <&gpy3 3 0>;
355 num-chipselects = <1>;
356 cs-gpios = <&gpy4 3 0>;
357
358 lcd@0 {
359 compatible = "samsung,ld9040";
360 reg = <0>;
361 vdd3-supply = <&ldo7_reg>;
362 vci-supply = <&ldo17_reg>;
363 reset-gpios = <&gpy4 5 0>;
364 spi-max-frequency = <1200000>;
365 spi-cpol;
366 spi-cpha;
367 power-on-delay = <10>;
368 reset-delay = <10>;
369 panel-width-mm = <90>;
370 panel-height-mm = <154>;
371 display-timings {
372 timing {
373 clock-frequency = <23492370>;
374 hactive = <480>;
375 vactive = <800>;
376 hback-porch = <16>;
377 hfront-porch = <16>;
378 vback-porch = <2>;
379 vfront-porch = <28>;
380 hsync-len = <2>;
381 vsync-len = <1>;
382 hsync-active = <0>;
383 vsync-active = <0>;
384 de-active = <0>;
385 pixelclk-active = <0>;
386 };
387 };
388 port {
389 lcd_ep: endpoint {
390 remote-endpoint = <&fimd_dpi_ep>;
391 };
392 };
393 };
394 };
395
396 fimd: fimd@11c00000 {
397 pinctrl-0 = <&lcd_clk>, <&lcd_data24>;
398 pinctrl-names = "default";
399 status = "okay";
400 samsung,invert-vden;
401 samsung,invert-vclk;
402 #address-cells = <1>;
403 #size-cells = <0>;
404 port@3 {
405 reg = <3>;
406 fimd_dpi_ep: endpoint {
407 remote-endpoint = <&lcd_ep>;
408 };
409 };
410 };
411
348 pwm@139D0000 { 412 pwm@139D0000 {
349 compatible = "samsung,s5p6440-pwm"; 413 compatible = "samsung,s5p6440-pwm";
350 status = "okay"; 414 status = "okay";
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 4f851ccf40eb..53c717b6eb69 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -71,6 +71,15 @@
71 enable-active-high; 71 enable-active-high;
72 }; 72 };
73 73
74 lcd_vdd3_reg: voltage-regulator-2 {
75 compatible = "regulator-fixed";
76 regulator-name = "LCD_VDD_2.2V";
77 regulator-min-microvolt = <2200000>;
78 regulator-max-microvolt = <2200000>;
79 gpio = <&gpc0 1 0>;
80 enable-active-high;
81 };
82
74 /* More to come */ 83 /* More to come */
75 }; 84 };
76 85
@@ -511,6 +520,67 @@
511 }; 520 };
512 }; 521 };
513 522
523 dsi_0: dsi@11C80000 {
524 vddcore-supply = <&ldo8_reg>;
525 vddio-supply = <&ldo10_reg>;
526 samsung,pll-clock-frequency = <24000000>;
527 status = "okay";
528
529 ports {
530 #address-cells = <1>;
531 #size-cells = <0>;
532
533 port@1 {
534 reg = <1>;
535
536 dsi_out: endpoint {
537 remote-endpoint = <&dsi_in>;
538 samsung,burst-clock-frequency = <500000000>;
539 samsung,esc-clock-frequency = <20000000>;
540 };
541 };
542 };
543
544 panel@0 {
545 compatible = "samsung,s6e8aa0";
546 reg = <0>;
547 vdd3-supply = <&lcd_vdd3_reg>;
548 vci-supply = <&ldo25_reg>;
549 reset-gpios = <&gpy4 5 0>;
550 power-on-delay= <50>;
551 reset-delay = <100>;
552 init-delay = <100>;
553 flip-horizontal;
554 flip-vertical;
555 panel-width-mm = <58>;
556 panel-height-mm = <103>;
557
558 display-timings {
559 timing-0 {
560 clock-frequency = <0>;
561 hactive = <720>;
562 vactive = <1280>;
563 hfront-porch = <5>;
564 hback-porch = <5>;
565 hsync-len = <5>;
566 vfront-porch = <13>;
567 vback-porch = <1>;
568 vsync-len = <2>;
569 };
570 };
571
572 port {
573 dsi_in: endpoint {
574 remote-endpoint = <&dsi_out>;
575 };
576 };
577 };
578 };
579
580 fimd@11c00000 {
581 status = "okay";
582 };
583
514 camera { 584 camera {
515 pinctrl-0 = <&cam_port_b_clk_active>; 585 pinctrl-0 = <&cam_port_b_clk_active>;
516 pinctrl-names = "default"; 586 pinctrl-names = "default";
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 8e7fa4dbaed8..d1cc2f613a78 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -199,3 +199,5 @@ source "drivers/gpu/drm/msm/Kconfig"
199source "drivers/gpu/drm/tegra/Kconfig" 199source "drivers/gpu/drm/tegra/Kconfig"
200 200
201source "drivers/gpu/drm/panel/Kconfig" 201source "drivers/gpu/drm/panel/Kconfig"
202
203source "drivers/gpu/drm/bridge/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 292a79d64146..9d25dbbe6771 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
13 drm_crtc.o drm_modes.o drm_edid.o \ 13 drm_crtc.o drm_modes.o drm_edid.o \
14 drm_info.o drm_debugfs.o drm_encoder_slave.o \ 14 drm_info.o drm_debugfs.o drm_encoder_slave.o \
15 drm_trace_points.o drm_global.o drm_prime.o \ 15 drm_trace_points.o drm_global.o drm_prime.o \
16 drm_rect.o drm_vma_manager.o drm_flip_work.o 16 drm_rect.o drm_vma_manager.o drm_flip_work.o \
17 drm_plane_helper.o
17 18
18drm-$(CONFIG_COMPAT) += drm_ioc32.o 19drm-$(CONFIG_COMPAT) += drm_ioc32.o
19drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -63,3 +64,4 @@ obj-$(CONFIG_DRM_MSM) += msm/
63obj-$(CONFIG_DRM_TEGRA) += tegra/ 64obj-$(CONFIG_DRM_TEGRA) += tegra/
64obj-y += i2c/ 65obj-y += i2c/
65obj-y += panel/ 66obj-y += panel/
67obj-y += bridge/
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index d8e398275ca8..5831e4109e75 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -478,11 +478,12 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
478 unsigned i; 478 unsigned i;
479 bool interlaced; 479 bool interlaced;
480 480
481 drm_framebuffer_reference(crtc->fb); 481 drm_framebuffer_reference(crtc->primary->fb);
482 482
483 interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE); 483 interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
484 484
485 i = armada_drm_crtc_calc_fb(dcrtc->crtc.fb, x, y, regs, interlaced); 485 i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb,
486 x, y, regs, interlaced);
486 487
487 rm = adj->crtc_hsync_start - adj->crtc_hdisplay; 488 rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
488 lm = adj->crtc_htotal - adj->crtc_hsync_end; 489 lm = adj->crtc_htotal - adj->crtc_hsync_end;
@@ -567,10 +568,10 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
567 } 568 }
568 569
569 val = CFG_GRA_ENA | CFG_GRA_HSMOOTH; 570 val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
570 val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt); 571 val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
571 val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.fb)->mod); 572 val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
572 573
573 if (drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt > CFG_420) 574 if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
574 val |= CFG_PALETTE_ENA; 575 val |= CFG_PALETTE_ENA;
575 576
576 if (interlaced) 577 if (interlaced)
@@ -608,7 +609,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
608 struct armada_regs regs[4]; 609 struct armada_regs regs[4];
609 unsigned i; 610 unsigned i;
610 611
611 i = armada_drm_crtc_calc_fb(crtc->fb, crtc->x, crtc->y, regs, 612 i = armada_drm_crtc_calc_fb(crtc->primary->fb, crtc->x, crtc->y, regs,
612 dcrtc->interlaced); 613 dcrtc->interlaced);
613 armada_reg_queue_end(regs, i); 614 armada_reg_queue_end(regs, i);
614 615
@@ -616,7 +617,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
616 wait_event(dcrtc->frame_wait, !dcrtc->frame_work); 617 wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
617 618
618 /* Take a reference to the new fb as we're using it */ 619 /* Take a reference to the new fb as we're using it */
619 drm_framebuffer_reference(crtc->fb); 620 drm_framebuffer_reference(crtc->primary->fb);
620 621
621 /* Update the base in the CRTC */ 622 /* Update the base in the CRTC */
622 armada_drm_crtc_update_regs(dcrtc, regs); 623 armada_drm_crtc_update_regs(dcrtc, regs);
@@ -637,7 +638,7 @@ static void armada_drm_crtc_disable(struct drm_crtc *crtc)
637 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 638 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
638 639
639 armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 640 armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
640 armada_drm_crtc_finish_fb(dcrtc, crtc->fb, true); 641 armada_drm_crtc_finish_fb(dcrtc, crtc->primary->fb, true);
641 642
642 /* Power down most RAMs and FIFOs */ 643 /* Power down most RAMs and FIFOs */
643 writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 | 644 writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
@@ -904,7 +905,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
904 int ret; 905 int ret;
905 906
906 /* We don't support changing the pixel format */ 907 /* We don't support changing the pixel format */
907 if (fb->pixel_format != crtc->fb->pixel_format) 908 if (fb->pixel_format != crtc->primary->fb->pixel_format)
908 return -EINVAL; 909 return -EINVAL;
909 910
910 work = kmalloc(sizeof(*work), GFP_KERNEL); 911 work = kmalloc(sizeof(*work), GFP_KERNEL);
@@ -912,7 +913,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
912 return -ENOMEM; 913 return -ENOMEM;
913 914
914 work->event = event; 915 work->event = event;
915 work->old_fb = dcrtc->crtc.fb; 916 work->old_fb = dcrtc->crtc.primary->fb;
916 917
917 i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs, 918 i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs,
918 dcrtc->interlaced); 919 dcrtc->interlaced);
@@ -941,7 +942,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
941 * will _not_ drop that reference on successful return from this 942 * will _not_ drop that reference on successful return from this
942 * function. Simply mark this new framebuffer as the current one. 943 * function. Simply mark this new framebuffer as the current one.
943 */ 944 */
944 dcrtc->crtc.fb = fb; 945 dcrtc->crtc.primary->fb = fb;
945 946
946 /* 947 /*
947 * Finally, if the display is blanked, we won't receive an 948 * Finally, if the display is blanked, we won't receive an
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index cca063b11083..a4afdc8bb578 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
81 u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; 81 u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
82 u32 hborder, vborder; 82 u32 hborder, vborder;
83 83
84 switch (crtc->fb->bits_per_pixel) { 84 switch (crtc->primary->fb->bits_per_pixel) {
85 case 8: 85 case 8:
86 vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; 86 vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
87 color_index = VGAModeIndex - 1; 87 color_index = VGAModeIndex - 1;
@@ -176,7 +176,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
176 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); 176 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
177 177
178 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); 178 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
179 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel); 179 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
180 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); 180 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
181 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); 181 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
182 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); 182 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
@@ -340,7 +340,7 @@ static void ast_set_offset_reg(struct drm_crtc *crtc)
340 340
341 u16 offset; 341 u16 offset;
342 342
343 offset = crtc->fb->pitches[0] >> 3; 343 offset = crtc->primary->fb->pitches[0] >> 3;
344 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff)); 344 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
345 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); 345 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
346} 346}
@@ -365,7 +365,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
365 struct ast_private *ast = crtc->dev->dev_private; 365 struct ast_private *ast = crtc->dev->dev_private;
366 u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; 366 u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
367 367
368 switch (crtc->fb->bits_per_pixel) { 368 switch (crtc->primary->fb->bits_per_pixel) {
369 case 8: 369 case 8:
370 jregA0 = 0x70; 370 jregA0 = 0x70;
371 jregA3 = 0x01; 371 jregA3 = 0x01;
@@ -418,7 +418,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
418static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, 418static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
419 struct ast_vbios_mode_info *vbios_mode) 419 struct ast_vbios_mode_info *vbios_mode)
420{ 420{
421 switch (crtc->fb->bits_per_pixel) { 421 switch (crtc->primary->fb->bits_per_pixel) {
422 case 8: 422 case 8:
423 break; 423 break;
424 default: 424 default:
@@ -490,7 +490,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
490 ast_bo_unreserve(bo); 490 ast_bo_unreserve(bo);
491 } 491 }
492 492
493 ast_fb = to_ast_framebuffer(crtc->fb); 493 ast_fb = to_ast_framebuffer(crtc->primary->fb);
494 obj = ast_fb->obj; 494 obj = ast_fb->obj;
495 bo = gem_to_ast_bo(obj); 495 bo = gem_to_ast_bo(obj);
496 496
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 62ec7d4b3816..dcf2e55f4ae9 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -62,10 +62,10 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
62 } 62 }
63 } 63 }
64 64
65 if (WARN_ON(crtc->fb == NULL)) 65 if (WARN_ON(crtc->primary->fb == NULL))
66 return -EINVAL; 66 return -EINVAL;
67 67
68 bochs_fb = to_bochs_framebuffer(crtc->fb); 68 bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
69 bo = gem_to_bochs_bo(bochs_fb->obj); 69 bo = gem_to_bochs_bo(bochs_fb->obj);
70 ret = ttm_bo_reserve(&bo->bo, true, false, false, 0); 70 ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
71 if (ret) 71 if (ret)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
new file mode 100644
index 000000000000..884923f982d9
--- /dev/null
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -0,0 +1,5 @@
1config DRM_PTN3460
2 tristate "PTN3460 DP/LVDS bridge"
3 depends on DRM
4 select DRM_KMS_HELPER
5 ---help---
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
new file mode 100644
index 000000000000..b4733e1fbd2e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -0,0 +1,3 @@
1ccflags-y := -Iinclude/drm
2
3obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c
new file mode 100644
index 000000000000..b171901a3553
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ptn3460.c
@@ -0,0 +1,350 @@
1/*
2 * NXP PTN3460 DP/LVDS bridge driver
3 *
4 * Copyright (C) 2013 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/of_gpio.h>
19#include <linux/i2c.h>
20#include <linux/gpio.h>
21#include <linux/delay.h>
22
23#include "drmP.h"
24#include "drm_edid.h"
25#include "drm_crtc.h"
26#include "drm_crtc_helper.h"
27
28#include "bridge/ptn3460.h"
29
30#define PTN3460_EDID_ADDR 0x0
31#define PTN3460_EDID_EMULATION_ADDR 0x84
32#define PTN3460_EDID_ENABLE_EMULATION 0
33#define PTN3460_EDID_EMULATION_SELECTION 1
34#define PTN3460_EDID_SRAM_LOAD_ADDR 0x85
35
36struct ptn3460_bridge {
37 struct drm_connector connector;
38 struct i2c_client *client;
39 struct drm_encoder *encoder;
40 struct drm_bridge *bridge;
41 struct edid *edid;
42 int gpio_pd_n;
43 int gpio_rst_n;
44 u32 edid_emulation;
45 bool enabled;
46};
47
48static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr,
49 u8 *buf, int len)
50{
51 int ret;
52
53 ret = i2c_master_send(ptn_bridge->client, &addr, 1);
54 if (ret <= 0) {
55 DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
56 return ret;
57 }
58
59 ret = i2c_master_recv(ptn_bridge->client, buf, len);
60 if (ret <= 0) {
61 DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret);
62 return ret;
63 }
64
65 return 0;
66}
67
68static int ptn3460_write_byte(struct ptn3460_bridge *ptn_bridge, char addr,
69 char val)
70{
71 int ret;
72 char buf[2];
73
74 buf[0] = addr;
75 buf[1] = val;
76
77 ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf));
78 if (ret <= 0) {
79 DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
80 return ret;
81 }
82
83 return 0;
84}
85
86static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
87{
88 int ret;
89 char val;
90
91 /* Load the selected edid into SRAM (accessed at PTN3460_EDID_ADDR) */
92 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_SRAM_LOAD_ADDR,
93 ptn_bridge->edid_emulation);
94 if (ret) {
95 DRM_ERROR("Failed to transfer edid to sram, ret=%d\n", ret);
96 return ret;
97 }
98
99 /* Enable EDID emulation and select the desired EDID */
100 val = 1 << PTN3460_EDID_ENABLE_EMULATION |
101 ptn_bridge->edid_emulation << PTN3460_EDID_EMULATION_SELECTION;
102
103 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_EMULATION_ADDR, val);
104 if (ret) {
105 DRM_ERROR("Failed to write edid value, ret=%d\n", ret);
106 return ret;
107 }
108
109 return 0;
110}
111
112static void ptn3460_pre_enable(struct drm_bridge *bridge)
113{
114 struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
115 int ret;
116
117 if (ptn_bridge->enabled)
118 return;
119
120 if (gpio_is_valid(ptn_bridge->gpio_pd_n))
121 gpio_set_value(ptn_bridge->gpio_pd_n, 1);
122
123 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) {
124 gpio_set_value(ptn_bridge->gpio_rst_n, 0);
125 udelay(10);
126 gpio_set_value(ptn_bridge->gpio_rst_n, 1);
127 }
128
129 /*
130 * There's a bug in the PTN chip where it falsely asserts hotplug before
131 * it is fully functional. We're forced to wait for the maximum start up
132 * time specified in the chip's datasheet to make sure we're really up.
133 */
134 msleep(90);
135
136 ret = ptn3460_select_edid(ptn_bridge);
137 if (ret)
138 DRM_ERROR("Select edid failed ret=%d\n", ret);
139
140 ptn_bridge->enabled = true;
141}
142
143static void ptn3460_enable(struct drm_bridge *bridge)
144{
145}
146
147static void ptn3460_disable(struct drm_bridge *bridge)
148{
149 struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
150
151 if (!ptn_bridge->enabled)
152 return;
153
154 ptn_bridge->enabled = false;
155
156 if (gpio_is_valid(ptn_bridge->gpio_rst_n))
157 gpio_set_value(ptn_bridge->gpio_rst_n, 1);
158
159 if (gpio_is_valid(ptn_bridge->gpio_pd_n))
160 gpio_set_value(ptn_bridge->gpio_pd_n, 0);
161}
162
163static void ptn3460_post_disable(struct drm_bridge *bridge)
164{
165}
166
167void ptn3460_bridge_destroy(struct drm_bridge *bridge)
168{
169 struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
170
171 drm_bridge_cleanup(bridge);
172 if (gpio_is_valid(ptn_bridge->gpio_pd_n))
173 gpio_free(ptn_bridge->gpio_pd_n);
174 if (gpio_is_valid(ptn_bridge->gpio_rst_n))
175 gpio_free(ptn_bridge->gpio_rst_n);
176 /* Nothing else to free, we've got devm allocated memory */
177}
178
179struct drm_bridge_funcs ptn3460_bridge_funcs = {
180 .pre_enable = ptn3460_pre_enable,
181 .enable = ptn3460_enable,
182 .disable = ptn3460_disable,
183 .post_disable = ptn3460_post_disable,
184 .destroy = ptn3460_bridge_destroy,
185};
186
187int ptn3460_get_modes(struct drm_connector *connector)
188{
189 struct ptn3460_bridge *ptn_bridge;
190 u8 *edid;
191 int ret, num_modes;
192 bool power_off;
193
194 ptn_bridge = container_of(connector, struct ptn3460_bridge, connector);
195
196 if (ptn_bridge->edid)
197 return drm_add_edid_modes(connector, ptn_bridge->edid);
198
199 power_off = !ptn_bridge->enabled;
200 ptn3460_pre_enable(ptn_bridge->bridge);
201
202 edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
203 if (!edid) {
204 DRM_ERROR("Failed to allocate edid\n");
205 return 0;
206 }
207
208 ret = ptn3460_read_bytes(ptn_bridge, PTN3460_EDID_ADDR, edid,
209 EDID_LENGTH);
210 if (ret) {
211 kfree(edid);
212 num_modes = 0;
213 goto out;
214 }
215
216 ptn_bridge->edid = (struct edid *)edid;
217 drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
218
219 num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
220
221out:
222 if (power_off)
223 ptn3460_disable(ptn_bridge->bridge);
224
225 return num_modes;
226}
227
228static int ptn3460_mode_valid(struct drm_connector *connector,
229 struct drm_display_mode *mode)
230{
231 return MODE_OK;
232}
233
234struct drm_encoder *ptn3460_best_encoder(struct drm_connector *connector)
235{
236 struct ptn3460_bridge *ptn_bridge;
237
238 ptn_bridge = container_of(connector, struct ptn3460_bridge, connector);
239
240 return ptn_bridge->encoder;
241}
242
243struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = {
244 .get_modes = ptn3460_get_modes,
245 .mode_valid = ptn3460_mode_valid,
246 .best_encoder = ptn3460_best_encoder,
247};
248
249enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
250 bool force)
251{
252 return connector_status_connected;
253}
254
255void ptn3460_connector_destroy(struct drm_connector *connector)
256{
257 drm_connector_cleanup(connector);
258}
259
260struct drm_connector_funcs ptn3460_connector_funcs = {
261 .dpms = drm_helper_connector_dpms,
262 .fill_modes = drm_helper_probe_single_connector_modes,
263 .detect = ptn3460_detect,
264 .destroy = ptn3460_connector_destroy,
265};
266
267int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
268 struct i2c_client *client, struct device_node *node)
269{
270 int ret;
271 struct drm_bridge *bridge;
272 struct ptn3460_bridge *ptn_bridge;
273
274 bridge = devm_kzalloc(dev->dev, sizeof(*bridge), GFP_KERNEL);
275 if (!bridge) {
276 DRM_ERROR("Failed to allocate drm bridge\n");
277 return -ENOMEM;
278 }
279
280 ptn_bridge = devm_kzalloc(dev->dev, sizeof(*ptn_bridge), GFP_KERNEL);
281 if (!ptn_bridge) {
282 DRM_ERROR("Failed to allocate ptn bridge\n");
283 return -ENOMEM;
284 }
285
286 ptn_bridge->client = client;
287 ptn_bridge->encoder = encoder;
288 ptn_bridge->bridge = bridge;
289 ptn_bridge->gpio_pd_n = of_get_named_gpio(node, "powerdown-gpio", 0);
290 if (gpio_is_valid(ptn_bridge->gpio_pd_n)) {
291 ret = gpio_request_one(ptn_bridge->gpio_pd_n,
292 GPIOF_OUT_INIT_HIGH, "PTN3460_PD_N");
293 if (ret) {
294 DRM_ERROR("Request powerdown-gpio failed (%d)\n", ret);
295 return ret;
296 }
297 }
298
299 ptn_bridge->gpio_rst_n = of_get_named_gpio(node, "reset-gpio", 0);
300 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) {
301 /*
302 * Request the reset pin low to avoid the bridge being
303 * initialized prematurely
304 */
305 ret = gpio_request_one(ptn_bridge->gpio_rst_n,
306 GPIOF_OUT_INIT_LOW, "PTN3460_RST_N");
307 if (ret) {
308 DRM_ERROR("Request reset-gpio failed (%d)\n", ret);
309 gpio_free(ptn_bridge->gpio_pd_n);
310 return ret;
311 }
312 }
313
314 ret = of_property_read_u32(node, "edid-emulation",
315 &ptn_bridge->edid_emulation);
316 if (ret) {
317 DRM_ERROR("Can't read edid emulation value\n");
318 goto err;
319 }
320
321 ret = drm_bridge_init(dev, bridge, &ptn3460_bridge_funcs);
322 if (ret) {
323 DRM_ERROR("Failed to initialize bridge with drm\n");
324 goto err;
325 }
326
327 bridge->driver_private = ptn_bridge;
328 encoder->bridge = bridge;
329
330 ret = drm_connector_init(dev, &ptn_bridge->connector,
331 &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
332 if (ret) {
333 DRM_ERROR("Failed to initialize connector with drm\n");
334 goto err;
335 }
336 drm_connector_helper_add(&ptn_bridge->connector,
337 &ptn3460_connector_helper_funcs);
338 drm_sysfs_connector_add(&ptn_bridge->connector);
339 drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
340
341 return 0;
342
343err:
344 if (gpio_is_valid(ptn_bridge->gpio_pd_n))
345 gpio_free(ptn_bridge->gpio_pd_n);
346 if (gpio_is_valid(ptn_bridge->gpio_rst_n))
347 gpio_free(ptn_bridge->gpio_rst_n);
348 return ret;
349}
350EXPORT_SYMBOL(ptn3460_init);
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 530f78f84dee..2d64aea83df2 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -149,7 +149,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
149 cirrus_bo_unreserve(bo); 149 cirrus_bo_unreserve(bo);
150 } 150 }
151 151
152 cirrus_fb = to_cirrus_framebuffer(crtc->fb); 152 cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
153 obj = cirrus_fb->obj; 153 obj = cirrus_fb->obj;
154 bo = gem_to_cirrus_bo(obj); 154 bo = gem_to_cirrus_bo(obj);
155 155
@@ -268,7 +268,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
268 sr07 = RREG8(SEQ_DATA); 268 sr07 = RREG8(SEQ_DATA);
269 sr07 &= 0xe0; 269 sr07 &= 0xe0;
270 hdr = 0; 270 hdr = 0;
271 switch (crtc->fb->bits_per_pixel) { 271 switch (crtc->primary->fb->bits_per_pixel) {
272 case 8: 272 case 8:
273 sr07 |= 0x11; 273 sr07 |= 0x11;
274 break; 274 break;
@@ -291,13 +291,13 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
291 WREG_SEQ(0x7, sr07); 291 WREG_SEQ(0x7, sr07);
292 292
293 /* Program the pitch */ 293 /* Program the pitch */
294 tmp = crtc->fb->pitches[0] / 8; 294 tmp = crtc->primary->fb->pitches[0] / 8;
295 WREG_CRT(VGA_CRTC_OFFSET, tmp); 295 WREG_CRT(VGA_CRTC_OFFSET, tmp);
296 296
297 /* Enable extended blanking and pitch bits, and enable full memory */ 297 /* Enable extended blanking and pitch bits, and enable full memory */
298 tmp = 0x22; 298 tmp = 0x22;
299 tmp |= (crtc->fb->pitches[0] >> 7) & 0x10; 299 tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
300 tmp |= (crtc->fb->pitches[0] >> 6) & 0x40; 300 tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
301 WREG_CRT(0x1b, tmp); 301 WREG_CRT(0x1b, tmp);
302 302
303 /* Enable high-colour modes */ 303 /* Enable high-colour modes */
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 16ca28ed5ee8..d8b7099abece 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -121,6 +121,13 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] =
121 121
122DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) 122DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
123 123
124static const struct drm_prop_enum_list drm_plane_type_enum_list[] =
125{
126 { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
127 { DRM_PLANE_TYPE_PRIMARY, "Primary" },
128 { DRM_PLANE_TYPE_CURSOR, "Cursor" },
129};
130
124/* 131/*
125 * Optional properties 132 * Optional properties
126 */ 133 */
@@ -662,7 +669,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
662 drm_modeset_lock_all(dev); 669 drm_modeset_lock_all(dev);
663 /* remove from any CRTC */ 670 /* remove from any CRTC */
664 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 671 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
665 if (crtc->fb == fb) { 672 if (crtc->primary->fb == fb) {
666 /* should turn off the crtc */ 673 /* should turn off the crtc */
667 memset(&set, 0, sizeof(struct drm_mode_set)); 674 memset(&set, 0, sizeof(struct drm_mode_set));
668 set.crtc = crtc; 675 set.crtc = crtc;
@@ -685,9 +692,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
685EXPORT_SYMBOL(drm_framebuffer_remove); 692EXPORT_SYMBOL(drm_framebuffer_remove);
686 693
687/** 694/**
688 * drm_crtc_init - Initialise a new CRTC object 695 * drm_crtc_init_with_planes - Initialise a new CRTC object with
696 * specified primary and cursor planes.
689 * @dev: DRM device 697 * @dev: DRM device
690 * @crtc: CRTC object to init 698 * @crtc: CRTC object to init
699 * @primary: Primary plane for CRTC
700 * @cursor: Cursor plane for CRTC
691 * @funcs: callbacks for the new CRTC 701 * @funcs: callbacks for the new CRTC
692 * 702 *
693 * Inits a new object created as base part of a driver crtc object. 703 * Inits a new object created as base part of a driver crtc object.
@@ -695,8 +705,10 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
695 * Returns: 705 * Returns:
696 * Zero on success, error code on failure. 706 * Zero on success, error code on failure.
697 */ 707 */
698int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 708int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
699 const struct drm_crtc_funcs *funcs) 709 struct drm_plane *primary,
710 void *cursor,
711 const struct drm_crtc_funcs *funcs)
700{ 712{
701 int ret; 713 int ret;
702 714
@@ -717,12 +729,16 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
717 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 729 list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
718 dev->mode_config.num_crtc++; 730 dev->mode_config.num_crtc++;
719 731
732 crtc->primary = primary;
733 if (primary)
734 primary->possible_crtcs = 1 << drm_crtc_index(crtc);
735
720 out: 736 out:
721 drm_modeset_unlock_all(dev); 737 drm_modeset_unlock_all(dev);
722 738
723 return ret; 739 return ret;
724} 740}
725EXPORT_SYMBOL(drm_crtc_init); 741EXPORT_SYMBOL(drm_crtc_init_with_planes);
726 742
727/** 743/**
728 * drm_crtc_cleanup - Clean up the core crtc usage 744 * drm_crtc_cleanup - Clean up the core crtc usage
@@ -1000,26 +1016,25 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
1000EXPORT_SYMBOL(drm_encoder_cleanup); 1016EXPORT_SYMBOL(drm_encoder_cleanup);
1001 1017
1002/** 1018/**
1003 * drm_plane_init - Initialise a new plane object 1019 * drm_universal_plane_init - Initialize a new universal plane object
1004 * @dev: DRM device 1020 * @dev: DRM device
1005 * @plane: plane object to init 1021 * @plane: plane object to init
1006 * @possible_crtcs: bitmask of possible CRTCs 1022 * @possible_crtcs: bitmask of possible CRTCs
1007 * @funcs: callbacks for the new plane 1023 * @funcs: callbacks for the new plane
1008 * @formats: array of supported formats (%DRM_FORMAT_*) 1024 * @formats: array of supported formats (%DRM_FORMAT_*)
1009 * @format_count: number of elements in @formats 1025 * @format_count: number of elements in @formats
1010 * @priv: plane is private (hidden from userspace)? 1026 * @type: type of plane (overlay, primary, cursor)
1011 * 1027 *
1012 * Inits a preallocate plane object created as base part of a driver plane 1028 * Initializes a plane object of type @type.
1013 * object.
1014 * 1029 *
1015 * Returns: 1030 * Returns:
1016 * Zero on success, error code on failure. 1031 * Zero on success, error code on failure.
1017 */ 1032 */
1018int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 1033int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1019 unsigned long possible_crtcs, 1034 unsigned long possible_crtcs,
1020 const struct drm_plane_funcs *funcs, 1035 const struct drm_plane_funcs *funcs,
1021 const uint32_t *formats, uint32_t format_count, 1036 const uint32_t *formats, uint32_t format_count,
1022 bool priv) 1037 enum drm_plane_type type)
1023{ 1038{
1024 int ret; 1039 int ret;
1025 1040
@@ -1044,23 +1059,53 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
1044 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 1059 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
1045 plane->format_count = format_count; 1060 plane->format_count = format_count;
1046 plane->possible_crtcs = possible_crtcs; 1061 plane->possible_crtcs = possible_crtcs;
1062 plane->type = type;
1047 1063
1048 /* private planes are not exposed to userspace, but depending on 1064 list_add_tail(&plane->head, &dev->mode_config.plane_list);
1049 * display hardware, might be convenient to allow sharing programming 1065 dev->mode_config.num_total_plane++;
1050 * for the scanout engine with the crtc implementation. 1066 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1051 */ 1067 dev->mode_config.num_overlay_plane++;
1052 if (!priv) { 1068
1053 list_add_tail(&plane->head, &dev->mode_config.plane_list); 1069 drm_object_attach_property(&plane->base,
1054 dev->mode_config.num_plane++; 1070 dev->mode_config.plane_type_property,
1055 } else { 1071 plane->type);
1056 INIT_LIST_HEAD(&plane->head);
1057 }
1058 1072
1059 out: 1073 out:
1060 drm_modeset_unlock_all(dev); 1074 drm_modeset_unlock_all(dev);
1061 1075
1062 return ret; 1076 return ret;
1063} 1077}
1078EXPORT_SYMBOL(drm_universal_plane_init);
1079
1080/**
1081 * drm_plane_init - Initialize a legacy plane
1082 * @dev: DRM device
1083 * @plane: plane object to init
1084 * @possible_crtcs: bitmask of possible CRTCs
1085 * @funcs: callbacks for the new plane
1086 * @formats: array of supported formats (%DRM_FORMAT_*)
1087 * @format_count: number of elements in @formats
1088 * @is_primary: plane type (primary vs overlay)
1089 *
1090 * Legacy API to initialize a DRM plane.
1091 *
1092 * New drivers should call drm_universal_plane_init() instead.
1093 *
1094 * Returns:
1095 * Zero on success, error code on failure.
1096 */
1097int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
1098 unsigned long possible_crtcs,
1099 const struct drm_plane_funcs *funcs,
1100 const uint32_t *formats, uint32_t format_count,
1101 bool is_primary)
1102{
1103 enum drm_plane_type type;
1104
1105 type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
1106 return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
1107 formats, format_count, type);
1108}
1064EXPORT_SYMBOL(drm_plane_init); 1109EXPORT_SYMBOL(drm_plane_init);
1065 1110
1066/** 1111/**
@@ -1078,11 +1123,13 @@ void drm_plane_cleanup(struct drm_plane *plane)
1078 drm_modeset_lock_all(dev); 1123 drm_modeset_lock_all(dev);
1079 kfree(plane->format_types); 1124 kfree(plane->format_types);
1080 drm_mode_object_put(dev, &plane->base); 1125 drm_mode_object_put(dev, &plane->base);
1081 /* if not added to a list, it must be a private plane */ 1126
1082 if (!list_empty(&plane->head)) { 1127 BUG_ON(list_empty(&plane->head));
1083 list_del(&plane->head); 1128
1084 dev->mode_config.num_plane--; 1129 list_del(&plane->head);
1085 } 1130 dev->mode_config.num_total_plane--;
1131 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1132 dev->mode_config.num_overlay_plane--;
1086 drm_modeset_unlock_all(dev); 1133 drm_modeset_unlock_all(dev);
1087} 1134}
1088EXPORT_SYMBOL(drm_plane_cleanup); 1135EXPORT_SYMBOL(drm_plane_cleanup);
@@ -1134,6 +1181,21 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
1134 return 0; 1181 return 0;
1135} 1182}
1136 1183
1184static int drm_mode_create_standard_plane_properties(struct drm_device *dev)
1185{
1186 struct drm_property *type;
1187
1188 /*
1189 * Standard properties (apply to all planes)
1190 */
1191 type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1192 "type", drm_plane_type_enum_list,
1193 ARRAY_SIZE(drm_plane_type_enum_list));
1194 dev->mode_config.plane_type_property = type;
1195
1196 return 0;
1197}
1198
1137/** 1199/**
1138 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 1200 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
1139 * @dev: DRM device 1201 * @dev: DRM device
@@ -1492,9 +1554,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
1492 mutex_unlock(&file_priv->fbs_lock); 1554 mutex_unlock(&file_priv->fbs_lock);
1493 1555
1494 drm_modeset_lock_all(dev); 1556 drm_modeset_lock_all(dev);
1495 mode_group = &file_priv->master->minor->mode_group; 1557 if (!drm_is_primary_client(file_priv)) {
1496 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1497 1558
1559 mode_group = NULL;
1498 list_for_each(lh, &dev->mode_config.crtc_list) 1560 list_for_each(lh, &dev->mode_config.crtc_list)
1499 crtc_count++; 1561 crtc_count++;
1500 1562
@@ -1505,6 +1567,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
1505 encoder_count++; 1567 encoder_count++;
1506 } else { 1568 } else {
1507 1569
1570 mode_group = &file_priv->master->minor->mode_group;
1508 crtc_count = mode_group->num_crtcs; 1571 crtc_count = mode_group->num_crtcs;
1509 connector_count = mode_group->num_connectors; 1572 connector_count = mode_group->num_connectors;
1510 encoder_count = mode_group->num_encoders; 1573 encoder_count = mode_group->num_encoders;
@@ -1519,7 +1582,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
1519 if (card_res->count_crtcs >= crtc_count) { 1582 if (card_res->count_crtcs >= crtc_count) {
1520 copied = 0; 1583 copied = 0;
1521 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; 1584 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1522 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1585 if (!mode_group) {
1523 list_for_each_entry(crtc, &dev->mode_config.crtc_list, 1586 list_for_each_entry(crtc, &dev->mode_config.crtc_list,
1524 head) { 1587 head) {
1525 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1588 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
@@ -1546,7 +1609,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
1546 if (card_res->count_encoders >= encoder_count) { 1609 if (card_res->count_encoders >= encoder_count) {
1547 copied = 0; 1610 copied = 0;
1548 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; 1611 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1549 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1612 if (!mode_group) {
1550 list_for_each_entry(encoder, 1613 list_for_each_entry(encoder,
1551 &dev->mode_config.encoder_list, 1614 &dev->mode_config.encoder_list,
1552 head) { 1615 head) {
@@ -1577,7 +1640,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
1577 if (card_res->count_connectors >= connector_count) { 1640 if (card_res->count_connectors >= connector_count) {
1578 copied = 0; 1641 copied = 0;
1579 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; 1642 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1580 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1643 if (!mode_group) {
1581 list_for_each_entry(connector, 1644 list_for_each_entry(connector,
1582 &dev->mode_config.connector_list, 1645 &dev->mode_config.connector_list,
1583 head) { 1646 head) {
@@ -1651,8 +1714,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
1651 crtc_resp->x = crtc->x; 1714 crtc_resp->x = crtc->x;
1652 crtc_resp->y = crtc->y; 1715 crtc_resp->y = crtc->y;
1653 crtc_resp->gamma_size = crtc->gamma_size; 1716 crtc_resp->gamma_size = crtc->gamma_size;
1654 if (crtc->fb) 1717 if (crtc->primary->fb)
1655 crtc_resp->fb_id = crtc->fb->base.id; 1718 crtc_resp->fb_id = crtc->primary->fb->base.id;
1656 else 1719 else
1657 crtc_resp->fb_id = 0; 1720 crtc_resp->fb_id = 0;
1658 1721
@@ -1896,6 +1959,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1896 struct drm_plane *plane; 1959 struct drm_plane *plane;
1897 uint32_t __user *plane_ptr; 1960 uint32_t __user *plane_ptr;
1898 int copied = 0, ret = 0; 1961 int copied = 0, ret = 0;
1962 unsigned num_planes;
1899 1963
1900 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1964 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1901 return -EINVAL; 1965 return -EINVAL;
@@ -1903,15 +1967,28 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1903 drm_modeset_lock_all(dev); 1967 drm_modeset_lock_all(dev);
1904 config = &dev->mode_config; 1968 config = &dev->mode_config;
1905 1969
1970 if (file_priv->universal_planes)
1971 num_planes = config->num_total_plane;
1972 else
1973 num_planes = config->num_overlay_plane;
1974
1906 /* 1975 /*
1907 * This ioctl is called twice, once to determine how much space is 1976 * This ioctl is called twice, once to determine how much space is
1908 * needed, and the 2nd time to fill it. 1977 * needed, and the 2nd time to fill it.
1909 */ 1978 */
1910 if (config->num_plane && 1979 if (num_planes &&
1911 (plane_resp->count_planes >= config->num_plane)) { 1980 (plane_resp->count_planes >= num_planes)) {
1912 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; 1981 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
1913 1982
1914 list_for_each_entry(plane, &config->plane_list, head) { 1983 list_for_each_entry(plane, &config->plane_list, head) {
1984 /*
1985 * Unless userspace set the 'universal planes'
1986 * capability bit, only advertise overlays.
1987 */
1988 if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
1989 !file_priv->universal_planes)
1990 continue;
1991
1915 if (put_user(plane->base.id, plane_ptr + copied)) { 1992 if (put_user(plane->base.id, plane_ptr + copied)) {
1916 ret = -EFAULT; 1993 ret = -EFAULT;
1917 goto out; 1994 goto out;
@@ -1919,7 +1996,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1919 copied++; 1996 copied++;
1920 } 1997 }
1921 } 1998 }
1922 plane_resp->count_planes = config->num_plane; 1999 plane_resp->count_planes = num_planes;
1923 2000
1924out: 2001out:
1925 drm_modeset_unlock_all(dev); 2002 drm_modeset_unlock_all(dev);
@@ -2155,19 +2232,21 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2155 * crtcs. Atomic modeset will have saner semantics ... 2232 * crtcs. Atomic modeset will have saner semantics ...
2156 */ 2233 */
2157 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) 2234 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
2158 tmp->old_fb = tmp->fb; 2235 tmp->old_fb = tmp->primary->fb;
2159 2236
2160 fb = set->fb; 2237 fb = set->fb;
2161 2238
2162 ret = crtc->funcs->set_config(set); 2239 ret = crtc->funcs->set_config(set);
2163 if (ret == 0) { 2240 if (ret == 0) {
2241 crtc->primary->crtc = crtc;
2242
2164 /* crtc->fb must be updated by ->set_config, enforces this. */ 2243 /* crtc->fb must be updated by ->set_config, enforces this. */
2165 WARN_ON(fb != crtc->fb); 2244 WARN_ON(fb != crtc->primary->fb);
2166 } 2245 }
2167 2246
2168 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { 2247 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
2169 if (tmp->fb) 2248 if (tmp->primary->fb)
2170 drm_framebuffer_reference(tmp->fb); 2249 drm_framebuffer_reference(tmp->primary->fb);
2171 if (tmp->old_fb) 2250 if (tmp->old_fb)
2172 drm_framebuffer_unreference(tmp->old_fb); 2251 drm_framebuffer_unreference(tmp->old_fb);
2173 } 2252 }
@@ -2176,14 +2255,19 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2176} 2255}
2177EXPORT_SYMBOL(drm_mode_set_config_internal); 2256EXPORT_SYMBOL(drm_mode_set_config_internal);
2178 2257
2179/* 2258/**
2180 * Checks that the framebuffer is big enough for the CRTC viewport 2259 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
2181 * (x, y, hdisplay, vdisplay) 2260 * CRTC viewport
2261 * @crtc: CRTC that framebuffer will be displayed on
2262 * @x: x panning
2263 * @y: y panning
2264 * @mode: mode that framebuffer will be displayed under
2265 * @fb: framebuffer to check size of
2182 */ 2266 */
2183static int drm_crtc_check_viewport(const struct drm_crtc *crtc, 2267int drm_crtc_check_viewport(const struct drm_crtc *crtc,
2184 int x, int y, 2268 int x, int y,
2185 const struct drm_display_mode *mode, 2269 const struct drm_display_mode *mode,
2186 const struct drm_framebuffer *fb) 2270 const struct drm_framebuffer *fb)
2187 2271
2188{ 2272{
2189 int hdisplay, vdisplay; 2273 int hdisplay, vdisplay;
@@ -2214,6 +2298,7 @@ static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
2214 2298
2215 return 0; 2299 return 0;
2216} 2300}
2301EXPORT_SYMBOL(drm_crtc_check_viewport);
2217 2302
2218/** 2303/**
2219 * drm_mode_setcrtc - set CRTC configuration 2304 * drm_mode_setcrtc - set CRTC configuration
@@ -2265,12 +2350,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
2265 /* If we have a mode we need a framebuffer. */ 2350 /* If we have a mode we need a framebuffer. */
2266 /* If we pass -1, set the mode with the currently bound fb */ 2351 /* If we pass -1, set the mode with the currently bound fb */
2267 if (crtc_req->fb_id == -1) { 2352 if (crtc_req->fb_id == -1) {
2268 if (!crtc->fb) { 2353 if (!crtc->primary->fb) {
2269 DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); 2354 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
2270 ret = -EINVAL; 2355 ret = -EINVAL;
2271 goto out; 2356 goto out;
2272 } 2357 }
2273 fb = crtc->fb; 2358 fb = crtc->primary->fb;
2274 /* Make refcounting symmetric with the lookup path. */ 2359 /* Make refcounting symmetric with the lookup path. */
2275 drm_framebuffer_reference(fb); 2360 drm_framebuffer_reference(fb);
2276 } else { 2361 } else {
@@ -2846,7 +2931,8 @@ int drm_mode_getfb(struct drm_device *dev,
2846 r->bpp = fb->bits_per_pixel; 2931 r->bpp = fb->bits_per_pixel;
2847 r->pitch = fb->pitches[0]; 2932 r->pitch = fb->pitches[0];
2848 if (fb->funcs->create_handle) { 2933 if (fb->funcs->create_handle) {
2849 if (file_priv->is_master || capable(CAP_SYS_ADMIN)) { 2934 if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
2935 drm_is_control_client(file_priv)) {
2850 ret = fb->funcs->create_handle(fb, file_priv, 2936 ret = fb->funcs->create_handle(fb, file_priv,
2851 &r->handle); 2937 &r->handle);
2852 } else { 2938 } else {
@@ -4063,7 +4149,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4063 crtc = obj_to_crtc(obj); 4149 crtc = obj_to_crtc(obj);
4064 4150
4065 mutex_lock(&crtc->mutex); 4151 mutex_lock(&crtc->mutex);
4066 if (crtc->fb == NULL) { 4152 if (crtc->primary->fb == NULL) {
4067 /* The framebuffer is currently unbound, presumably 4153 /* The framebuffer is currently unbound, presumably
4068 * due to a hotplug event, that userspace has not 4154 * due to a hotplug event, that userspace has not
4069 * yet discovered. 4155 * yet discovered.
@@ -4085,7 +4171,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4085 if (ret) 4171 if (ret)
4086 goto out; 4172 goto out;
4087 4173
4088 if (crtc->fb->pixel_format != fb->pixel_format) { 4174 if (crtc->primary->fb->pixel_format != fb->pixel_format) {
4089 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); 4175 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
4090 ret = -EINVAL; 4176 ret = -EINVAL;
4091 goto out; 4177 goto out;
@@ -4118,7 +4204,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4118 (void (*) (struct drm_pending_event *)) kfree; 4204 (void (*) (struct drm_pending_event *)) kfree;
4119 } 4205 }
4120 4206
4121 old_fb = crtc->fb; 4207 old_fb = crtc->primary->fb;
4122 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); 4208 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
4123 if (ret) { 4209 if (ret) {
4124 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 4210 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4136,7 +4222,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4136 * Failing to do so will screw with the reference counting 4222 * Failing to do so will screw with the reference counting
4137 * on framebuffers. 4223 * on framebuffers.
4138 */ 4224 */
4139 WARN_ON(crtc->fb != fb); 4225 WARN_ON(crtc->primary->fb != fb);
4140 /* Unref only the old framebuffer. */ 4226 /* Unref only the old framebuffer. */
4141 fb = NULL; 4227 fb = NULL;
4142 } 4228 }
@@ -4525,6 +4611,7 @@ void drm_mode_config_init(struct drm_device *dev)
4525 4611
4526 drm_modeset_lock_all(dev); 4612 drm_modeset_lock_all(dev);
4527 drm_mode_create_standard_connector_properties(dev); 4613 drm_mode_create_standard_connector_properties(dev);
4614 drm_mode_create_standard_plane_properties(dev);
4528 drm_modeset_unlock_all(dev); 4615 drm_modeset_unlock_all(dev);
4529 4616
4530 /* Just to be sure */ 4617 /* Just to be sure */
@@ -4532,6 +4619,8 @@ void drm_mode_config_init(struct drm_device *dev)
4532 dev->mode_config.num_connector = 0; 4619 dev->mode_config.num_connector = 0;
4533 dev->mode_config.num_crtc = 0; 4620 dev->mode_config.num_crtc = 0;
4534 dev->mode_config.num_encoder = 0; 4621 dev->mode_config.num_encoder = 0;
4622 dev->mode_config.num_overlay_plane = 0;
4623 dev->mode_config.num_total_plane = 0;
4535} 4624}
4536EXPORT_SYMBOL(drm_mode_config_init); 4625EXPORT_SYMBOL(drm_mode_config_init);
4537 4626
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index a85517854073..1fbe8427c70e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -278,17 +278,7 @@ drm_encoder_disable(struct drm_encoder *encoder)
278 encoder->bridge->funcs->post_disable(encoder->bridge); 278 encoder->bridge->funcs->post_disable(encoder->bridge);
279} 279}
280 280
281/** 281static void __drm_helper_disable_unused_functions(struct drm_device *dev)
282 * drm_helper_disable_unused_functions - disable unused objects
283 * @dev: DRM device
284 *
285 * This function walks through the entire mode setting configuration of @dev. It
286 * will remove any crtc links of unused encoders and encoder links of
287 * disconnected connectors. Then it will disable all unused encoders and crtcs
288 * either by calling their disable callback if available or by calling their
289 * dpms callback with DRM_MODE_DPMS_OFF.
290 */
291void drm_helper_disable_unused_functions(struct drm_device *dev)
292{ 282{
293 struct drm_encoder *encoder; 283 struct drm_encoder *encoder;
294 struct drm_connector *connector; 284 struct drm_connector *connector;
@@ -299,8 +289,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
299 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 289 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
300 if (!connector->encoder) 290 if (!connector->encoder)
301 continue; 291 continue;
302 if (connector->status == connector_status_disconnected)
303 connector->encoder = NULL;
304 } 292 }
305 293
306 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 294 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -319,10 +307,27 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
319 (*crtc_funcs->disable)(crtc); 307 (*crtc_funcs->disable)(crtc);
320 else 308 else
321 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); 309 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
322 crtc->fb = NULL; 310 crtc->primary->fb = NULL;
323 } 311 }
324 } 312 }
325} 313}
314
315/**
316 * drm_helper_disable_unused_functions - disable unused objects
317 * @dev: DRM device
318 *
319 * This function walks through the entire mode setting configuration of @dev. It
320 * will remove any crtc links of unused encoders and encoder links of
321 * disconnected connectors. Then it will disable all unused encoders and crtcs
322 * either by calling their disable callback if available or by calling their
323 * dpms callback with DRM_MODE_DPMS_OFF.
324 */
325void drm_helper_disable_unused_functions(struct drm_device *dev)
326{
327 drm_modeset_lock_all(dev);
328 __drm_helper_disable_unused_functions(dev);
329 drm_modeset_unlock_all(dev);
330}
326EXPORT_SYMBOL(drm_helper_disable_unused_functions); 331EXPORT_SYMBOL(drm_helper_disable_unused_functions);
327 332
328/* 333/*
@@ -552,7 +557,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
552 } 557 }
553 } 558 }
554 559
555 drm_helper_disable_unused_functions(dev); 560 __drm_helper_disable_unused_functions(dev);
556 return 0; 561 return 0;
557} 562}
558 563
@@ -646,19 +651,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
646 save_set.mode = &set->crtc->mode; 651 save_set.mode = &set->crtc->mode;
647 save_set.x = set->crtc->x; 652 save_set.x = set->crtc->x;
648 save_set.y = set->crtc->y; 653 save_set.y = set->crtc->y;
649 save_set.fb = set->crtc->fb; 654 save_set.fb = set->crtc->primary->fb;
650 655
651 /* We should be able to check here if the fb has the same properties 656 /* We should be able to check here if the fb has the same properties
652 * and then just flip_or_move it */ 657 * and then just flip_or_move it */
653 if (set->crtc->fb != set->fb) { 658 if (set->crtc->primary->fb != set->fb) {
654 /* If we have no fb then treat it as a full mode set */ 659 /* If we have no fb then treat it as a full mode set */
655 if (set->crtc->fb == NULL) { 660 if (set->crtc->primary->fb == NULL) {
656 DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); 661 DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
657 mode_changed = true; 662 mode_changed = true;
658 } else if (set->fb == NULL) { 663 } else if (set->fb == NULL) {
659 mode_changed = true; 664 mode_changed = true;
660 } else if (set->fb->pixel_format != 665 } else if (set->fb->pixel_format !=
661 set->crtc->fb->pixel_format) { 666 set->crtc->primary->fb->pixel_format) {
662 mode_changed = true; 667 mode_changed = true;
663 } else 668 } else
664 fb_changed = true; 669 fb_changed = true;
@@ -688,12 +693,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
688 if (new_encoder == NULL) 693 if (new_encoder == NULL)
689 /* don't break so fail path works correct */ 694 /* don't break so fail path works correct */
690 fail = 1; 695 fail = 1;
691 break;
692 696
693 if (connector->dpms != DRM_MODE_DPMS_ON) { 697 if (connector->dpms != DRM_MODE_DPMS_ON) {
694 DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); 698 DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
695 mode_changed = true; 699 mode_changed = true;
696 } 700 }
701
702 break;
697 } 703 }
698 } 704 }
699 705
@@ -759,13 +765,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
759 DRM_DEBUG_KMS("attempting to set mode from" 765 DRM_DEBUG_KMS("attempting to set mode from"
760 " userspace\n"); 766 " userspace\n");
761 drm_mode_debug_printmodeline(set->mode); 767 drm_mode_debug_printmodeline(set->mode);
762 set->crtc->fb = set->fb; 768 set->crtc->primary->fb = set->fb;
763 if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 769 if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
764 set->x, set->y, 770 set->x, set->y,
765 save_set.fb)) { 771 save_set.fb)) {
766 DRM_ERROR("failed to set mode on [CRTC:%d]\n", 772 DRM_ERROR("failed to set mode on [CRTC:%d]\n",
767 set->crtc->base.id); 773 set->crtc->base.id);
768 set->crtc->fb = save_set.fb; 774 set->crtc->primary->fb = save_set.fb;
769 ret = -EINVAL; 775 ret = -EINVAL;
770 goto fail; 776 goto fail;
771 } 777 }
@@ -776,17 +782,17 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
776 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); 782 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
777 } 783 }
778 } 784 }
779 drm_helper_disable_unused_functions(dev); 785 __drm_helper_disable_unused_functions(dev);
780 } else if (fb_changed) { 786 } else if (fb_changed) {
781 set->crtc->x = set->x; 787 set->crtc->x = set->x;
782 set->crtc->y = set->y; 788 set->crtc->y = set->y;
783 set->crtc->fb = set->fb; 789 set->crtc->primary->fb = set->fb;
784 ret = crtc_funcs->mode_set_base(set->crtc, 790 ret = crtc_funcs->mode_set_base(set->crtc,
785 set->x, set->y, save_set.fb); 791 set->x, set->y, save_set.fb);
786 if (ret != 0) { 792 if (ret != 0) {
787 set->crtc->x = save_set.x; 793 set->crtc->x = save_set.x;
788 set->crtc->y = save_set.y; 794 set->crtc->y = save_set.y;
789 set->crtc->fb = save_set.fb; 795 set->crtc->primary->fb = save_set.fb;
790 goto fail; 796 goto fail;
791 } 797 }
792 } 798 }
@@ -976,13 +982,14 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
976 int encoder_dpms; 982 int encoder_dpms;
977 bool ret; 983 bool ret;
978 984
985 drm_modeset_lock_all(dev);
979 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 986 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
980 987
981 if (!crtc->enabled) 988 if (!crtc->enabled)
982 continue; 989 continue;
983 990
984 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, 991 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
985 crtc->x, crtc->y, crtc->fb); 992 crtc->x, crtc->y, crtc->primary->fb);
986 993
987 /* Restoring the old config should never fail! */ 994 /* Restoring the old config should never fail! */
988 if (ret == false) 995 if (ret == false)
@@ -1009,7 +1016,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
1009 } 1016 }
1010 1017
1011 /* disable the unused connectors while restoring the modesetting */ 1018 /* disable the unused connectors while restoring the modesetting */
1012 drm_helper_disable_unused_functions(dev); 1019 __drm_helper_disable_unused_functions(dev);
1020 drm_modeset_unlock_all(dev);
1013} 1021}
1014EXPORT_SYMBOL(drm_helper_resume_force_mode); 1022EXPORT_SYMBOL(drm_helper_resume_force_mode);
1015 1023
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 17832d048147..27671489477d 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -386,11 +386,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
386 return err; 386 return err;
387 } 387 }
388 388
389 if (err < size)
390 return -EPROTO;
391 389
392 switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { 390 switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
393 case DP_AUX_NATIVE_REPLY_ACK: 391 case DP_AUX_NATIVE_REPLY_ACK:
392 if (err < size)
393 return -EPROTO;
394 return err; 394 return err;
395 395
396 case DP_AUX_NATIVE_REPLY_NACK: 396 case DP_AUX_NATIVE_REPLY_NACK:
@@ -402,7 +402,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
402 } 402 }
403 } 403 }
404 404
405 DRM_ERROR("too many retries, giving up\n"); 405 DRM_DEBUG_KMS("too many retries, giving up\n");
406 return -EIO; 406 return -EIO;
407} 407}
408 408
@@ -599,8 +599,6 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
599 return err; 599 return err;
600 } 600 }
601 601
602 if (err < msg->size)
603 return -EPROTO;
604 602
605 switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) { 603 switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) {
606 case DP_AUX_NATIVE_REPLY_ACK: 604 case DP_AUX_NATIVE_REPLY_ACK:
@@ -639,6 +637,8 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
639 * Both native ACK and I2C ACK replies received. We 637 * Both native ACK and I2C ACK replies received. We
640 * can assume the transfer was successful. 638 * can assume the transfer was successful.
641 */ 639 */
640 if (err < msg->size)
641 return -EPROTO;
642 return 0; 642 return 0;
643 643
644 case DP_AUX_I2C_REPLY_NACK: 644 case DP_AUX_I2C_REPLY_NACK:
@@ -656,7 +656,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
656 } 656 }
657 } 657 }
658 658
659 DRM_ERROR("too many retries, giving up\n"); 659 DRM_DEBUG_KMS("too many retries, giving up\n");
660 return -EREMOTEIO; 660 return -EREMOTEIO;
661} 661}
662 662
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index ec651be2f3cb..03711d00aaae 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -286,6 +286,45 @@ static int drm_version(struct drm_device *dev, void *data,
286} 286}
287 287
288/** 288/**
289 * drm_ioctl_permit - Check ioctl permissions against caller
290 *
291 * @flags: ioctl permission flags.
292 * @file_priv: Pointer to struct drm_file identifying the caller.
293 *
294 * Checks whether the caller is allowed to run an ioctl with the
295 * indicated permissions. If so, returns zero. Otherwise returns an
296 * error code suitable for ioctl return.
297 */
298static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
299{
300 /* ROOT_ONLY is only for CAP_SYS_ADMIN */
301 if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
302 return -EACCES;
303
304 /* AUTH is only for authenticated or render client */
305 if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
306 !file_priv->authenticated))
307 return -EACCES;
308
309 /* MASTER is only for master or control clients */
310 if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
311 !drm_is_control_client(file_priv)))
312 return -EACCES;
313
314 /* Control clients must be explicitly allowed */
315 if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
316 drm_is_control_client(file_priv)))
317 return -EACCES;
318
319 /* Render clients must be explicitly allowed */
320 if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
321 drm_is_render_client(file_priv)))
322 return -EACCES;
323
324 return 0;
325}
326
327/**
289 * Called whenever a process performs an ioctl on /dev/drm. 328 * Called whenever a process performs an ioctl on /dev/drm.
290 * 329 *
291 * \param inode device inode. 330 * \param inode device inode.
@@ -350,52 +389,51 @@ long drm_ioctl(struct file *filp,
350 /* Do not trust userspace, use our own definition */ 389 /* Do not trust userspace, use our own definition */
351 func = ioctl->func; 390 func = ioctl->func;
352 391
353 if (!func) { 392 if (unlikely(!func)) {
354 DRM_DEBUG("no function\n"); 393 DRM_DEBUG("no function\n");
355 retcode = -EINVAL; 394 retcode = -EINVAL;
356 } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || 395 goto err_i1;
357 ((ioctl->flags & DRM_AUTH) && !drm_is_render_client(file_priv) && !file_priv->authenticated) || 396 }
358 ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
359 (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL)) ||
360 (!(ioctl->flags & DRM_RENDER_ALLOW) && drm_is_render_client(file_priv))) {
361 retcode = -EACCES;
362 } else {
363 if (cmd & (IOC_IN | IOC_OUT)) {
364 if (asize <= sizeof(stack_kdata)) {
365 kdata = stack_kdata;
366 } else {
367 kdata = kmalloc(asize, GFP_KERNEL);
368 if (!kdata) {
369 retcode = -ENOMEM;
370 goto err_i1;
371 }
372 }
373 if (asize > usize)
374 memset(kdata + usize, 0, asize - usize);
375 }
376 397
377 if (cmd & IOC_IN) { 398 retcode = drm_ioctl_permit(ioctl->flags, file_priv);
378 if (copy_from_user(kdata, (void __user *)arg, 399 if (unlikely(retcode))
379 usize) != 0) { 400 goto err_i1;
380 retcode = -EFAULT; 401
402 if (cmd & (IOC_IN | IOC_OUT)) {
403 if (asize <= sizeof(stack_kdata)) {
404 kdata = stack_kdata;
405 } else {
406 kdata = kmalloc(asize, GFP_KERNEL);
407 if (!kdata) {
408 retcode = -ENOMEM;
381 goto err_i1; 409 goto err_i1;
382 } 410 }
383 } else
384 memset(kdata, 0, usize);
385
386 if (ioctl->flags & DRM_UNLOCKED)
387 retcode = func(dev, kdata, file_priv);
388 else {
389 mutex_lock(&drm_global_mutex);
390 retcode = func(dev, kdata, file_priv);
391 mutex_unlock(&drm_global_mutex);
392 } 411 }
412 if (asize > usize)
413 memset(kdata + usize, 0, asize - usize);
414 }
393 415
394 if (cmd & IOC_OUT) { 416 if (cmd & IOC_IN) {
395 if (copy_to_user((void __user *)arg, kdata, 417 if (copy_from_user(kdata, (void __user *)arg,
396 usize) != 0) 418 usize) != 0) {
397 retcode = -EFAULT; 419 retcode = -EFAULT;
420 goto err_i1;
398 } 421 }
422 } else
423 memset(kdata, 0, usize);
424
425 if (ioctl->flags & DRM_UNLOCKED)
426 retcode = func(dev, kdata, file_priv);
427 else {
428 mutex_lock(&drm_global_mutex);
429 retcode = func(dev, kdata, file_priv);
430 mutex_unlock(&drm_global_mutex);
431 }
432
433 if (cmd & IOC_OUT) {
434 if (copy_to_user((void __user *)arg, kdata,
435 usize) != 0)
436 retcode = -EFAULT;
399 } 437 }
400 438
401 err_i1: 439 err_i1:
@@ -412,3 +450,21 @@ long drm_ioctl(struct file *filp,
412 return retcode; 450 return retcode;
413} 451}
414EXPORT_SYMBOL(drm_ioctl); 452EXPORT_SYMBOL(drm_ioctl);
453
454/**
455 * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
456 *
457 * @nr: Ioctl number.
458 * @flags: Where to return the ioctl permission flags
459 */
460bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
461{
462 if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
463 (nr < DRM_COMMAND_BASE)) {
464 *flags = drm_ioctls[nr].flags;
465 return true;
466 }
467
468 return false;
469}
470EXPORT_SYMBOL(drm_ioctl_flags);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 87876198801d..04d3fd3658f3 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
232 232
233 list_for_each_entry(c, &dev->mode_config.crtc_list, head) { 233 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
234 if (crtc->base.id == c->base.id) 234 if (crtc->base.id == c->base.id)
235 return c->fb; 235 return c->primary->fb;
236 } 236 }
237 237
238 return NULL; 238 return NULL;
@@ -291,7 +291,8 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
291 drm_warn_on_modeset_not_all_locked(dev); 291 drm_warn_on_modeset_not_all_locked(dev);
292 292
293 list_for_each_entry(plane, &dev->mode_config.plane_list, head) 293 list_for_each_entry(plane, &dev->mode_config.plane_list, head)
294 drm_plane_force_disable(plane); 294 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
295 drm_plane_force_disable(plane);
295 296
296 for (i = 0; i < fb_helper->crtc_count; i++) { 297 for (i = 0; i < fb_helper->crtc_count; i++) {
297 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; 298 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
@@ -365,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
365 return false; 366 return false;
366 367
367 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 368 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
368 if (crtc->fb) 369 if (crtc->primary->fb)
369 crtcs_bound++; 370 crtcs_bound++;
370 if (crtc->fb == fb_helper->fb) 371 if (crtc->primary->fb == fb_helper->fb)
371 bound++; 372 bound++;
372 } 373 }
373 374
@@ -1158,6 +1159,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
1158{ 1159{
1159 struct drm_cmdline_mode *cmdline_mode; 1160 struct drm_cmdline_mode *cmdline_mode;
1160 struct drm_display_mode *mode = NULL; 1161 struct drm_display_mode *mode = NULL;
1162 bool prefer_non_interlace;
1161 1163
1162 cmdline_mode = &fb_helper_conn->cmdline_mode; 1164 cmdline_mode = &fb_helper_conn->cmdline_mode;
1163 if (cmdline_mode->specified == false) 1165 if (cmdline_mode->specified == false)
@@ -1169,6 +1171,8 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
1169 if (cmdline_mode->rb || cmdline_mode->margins) 1171 if (cmdline_mode->rb || cmdline_mode->margins)
1170 goto create_mode; 1172 goto create_mode;
1171 1173
1174 prefer_non_interlace = !cmdline_mode->interlace;
1175 again:
1172 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { 1176 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
1173 /* check width/height */ 1177 /* check width/height */
1174 if (mode->hdisplay != cmdline_mode->xres || 1178 if (mode->hdisplay != cmdline_mode->xres ||
@@ -1183,10 +1187,18 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
1183 if (cmdline_mode->interlace) { 1187 if (cmdline_mode->interlace) {
1184 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 1188 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
1185 continue; 1189 continue;
1190 } else if (prefer_non_interlace) {
1191 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1192 continue;
1186 } 1193 }
1187 return mode; 1194 return mode;
1188 } 1195 }
1189 1196
1197 if (prefer_non_interlace) {
1198 prefer_non_interlace = false;
1199 goto again;
1200 }
1201
1190create_mode: 1202create_mode:
1191 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, 1203 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
1192 cmdline_mode); 1204 cmdline_mode);
@@ -1536,9 +1548,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1536 1548
1537 drm_fb_helper_parse_command_line(fb_helper); 1549 drm_fb_helper_parse_command_line(fb_helper);
1538 1550
1551 mutex_lock(&dev->mode_config.mutex);
1539 count = drm_fb_helper_probe_connector_modes(fb_helper, 1552 count = drm_fb_helper_probe_connector_modes(fb_helper,
1540 dev->mode_config.max_width, 1553 dev->mode_config.max_width,
1541 dev->mode_config.max_height); 1554 dev->mode_config.max_height);
1555 mutex_unlock(&dev->mode_config.mutex);
1542 /* 1556 /*
1543 * we shouldn't end up with no modes here. 1557 * we shouldn't end up with no modes here.
1544 */ 1558 */
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 9b02f126fb0d..a0ce39c96f8e 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -231,12 +231,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
231 231
232 /* if there is no current master make this fd it, but do not create 232 /* if there is no current master make this fd it, but do not create
233 * any master object for render clients */ 233 * any master object for render clients */
234 mutex_lock(&dev->struct_mutex); 234 mutex_lock(&dev->master_mutex);
235 if (!priv->minor->master && !drm_is_render_client(priv)) { 235 if (drm_is_primary_client(priv) && !priv->minor->master) {
236 /* create a new master */ 236 /* create a new master */
237 priv->minor->master = drm_master_create(priv->minor); 237 priv->minor->master = drm_master_create(priv->minor);
238 if (!priv->minor->master) { 238 if (!priv->minor->master) {
239 mutex_unlock(&dev->struct_mutex);
240 ret = -ENOMEM; 239 ret = -ENOMEM;
241 goto out_close; 240 goto out_close;
242 } 241 }
@@ -244,37 +243,31 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
244 priv->is_master = 1; 243 priv->is_master = 1;
245 /* take another reference for the copy in the local file priv */ 244 /* take another reference for the copy in the local file priv */
246 priv->master = drm_master_get(priv->minor->master); 245 priv->master = drm_master_get(priv->minor->master);
247
248 priv->authenticated = 1; 246 priv->authenticated = 1;
249 247
250 mutex_unlock(&dev->struct_mutex);
251 if (dev->driver->master_create) { 248 if (dev->driver->master_create) {
252 ret = dev->driver->master_create(dev, priv->master); 249 ret = dev->driver->master_create(dev, priv->master);
253 if (ret) { 250 if (ret) {
254 mutex_lock(&dev->struct_mutex);
255 /* drop both references if this fails */ 251 /* drop both references if this fails */
256 drm_master_put(&priv->minor->master); 252 drm_master_put(&priv->minor->master);
257 drm_master_put(&priv->master); 253 drm_master_put(&priv->master);
258 mutex_unlock(&dev->struct_mutex);
259 goto out_close; 254 goto out_close;
260 } 255 }
261 } 256 }
262 mutex_lock(&dev->struct_mutex);
263 if (dev->driver->master_set) { 257 if (dev->driver->master_set) {
264 ret = dev->driver->master_set(dev, priv, true); 258 ret = dev->driver->master_set(dev, priv, true);
265 if (ret) { 259 if (ret) {
266 /* drop both references if this fails */ 260 /* drop both references if this fails */
267 drm_master_put(&priv->minor->master); 261 drm_master_put(&priv->minor->master);
268 drm_master_put(&priv->master); 262 drm_master_put(&priv->master);
269 mutex_unlock(&dev->struct_mutex);
270 goto out_close; 263 goto out_close;
271 } 264 }
272 } 265 }
273 } else if (!drm_is_render_client(priv)) { 266 } else if (drm_is_primary_client(priv)) {
274 /* get a reference to the master */ 267 /* get a reference to the master */
275 priv->master = drm_master_get(priv->minor->master); 268 priv->master = drm_master_get(priv->minor->master);
276 } 269 }
277 mutex_unlock(&dev->struct_mutex); 270 mutex_unlock(&dev->master_mutex);
278 271
279 mutex_lock(&dev->struct_mutex); 272 mutex_lock(&dev->struct_mutex);
280 list_add(&priv->lhead, &dev->filelist); 273 list_add(&priv->lhead, &dev->filelist);
@@ -302,6 +295,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
302 return 0; 295 return 0;
303 296
304out_close: 297out_close:
298 mutex_unlock(&dev->master_mutex);
305 if (dev->driver->postclose) 299 if (dev->driver->postclose)
306 dev->driver->postclose(dev, priv); 300 dev->driver->postclose(dev, priv);
307out_prime_destroy: 301out_prime_destroy:
@@ -489,11 +483,13 @@ int drm_release(struct inode *inode, struct file *filp)
489 } 483 }
490 mutex_unlock(&dev->ctxlist_mutex); 484 mutex_unlock(&dev->ctxlist_mutex);
491 485
492 mutex_lock(&dev->struct_mutex); 486 mutex_lock(&dev->master_mutex);
493 487
494 if (file_priv->is_master) { 488 if (file_priv->is_master) {
495 struct drm_master *master = file_priv->master; 489 struct drm_master *master = file_priv->master;
496 struct drm_file *temp; 490 struct drm_file *temp;
491
492 mutex_lock(&dev->struct_mutex);
497 list_for_each_entry(temp, &dev->filelist, lhead) { 493 list_for_each_entry(temp, &dev->filelist, lhead) {
498 if ((temp->master == file_priv->master) && 494 if ((temp->master == file_priv->master) &&
499 (temp != file_priv)) 495 (temp != file_priv))
@@ -512,6 +508,7 @@ int drm_release(struct inode *inode, struct file *filp)
512 master->lock.file_priv = NULL; 508 master->lock.file_priv = NULL;
513 wake_up_interruptible_all(&master->lock.lock_queue); 509 wake_up_interruptible_all(&master->lock.lock_queue);
514 } 510 }
511 mutex_unlock(&dev->struct_mutex);
515 512
516 if (file_priv->minor->master == file_priv->master) { 513 if (file_priv->minor->master == file_priv->master) {
517 /* drop the reference held my the minor */ 514 /* drop the reference held my the minor */
@@ -521,10 +518,13 @@ int drm_release(struct inode *inode, struct file *filp)
521 } 518 }
522 } 519 }
523 520
524 /* drop the reference held my the file priv */ 521 /* drop the master reference held by the file priv */
525 if (file_priv->master) 522 if (file_priv->master)
526 drm_master_put(&file_priv->master); 523 drm_master_put(&file_priv->master);
527 file_priv->is_master = 0; 524 file_priv->is_master = 0;
525 mutex_unlock(&dev->master_mutex);
526
527 mutex_lock(&dev->struct_mutex);
528 list_del(&file_priv->lhead); 528 list_del(&file_priv->lhead);
529 mutex_unlock(&dev->struct_mutex); 529 mutex_unlock(&dev->struct_mutex);
530 530
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 2c07cb9550ef..05c97c5350a1 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -234,8 +234,17 @@ static int drm_gem_cma_mmap_obj(struct drm_gem_cma_object *cma_obj,
234{ 234{
235 int ret; 235 int ret;
236 236
237 ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT, 237 /*
238 vma->vm_end - vma->vm_start, vma->vm_page_prot); 238 * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
239 * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
240 * the whole buffer.
241 */
242 vma->vm_flags &= ~VM_PFNMAP;
243 vma->vm_pgoff = 0;
244
245 ret = dma_mmap_writecombine(cma_obj->base.dev->dev, vma,
246 cma_obj->vaddr, cma_obj->paddr,
247 vma->vm_end - vma->vm_start);
239 if (ret) 248 if (ret)
240 drm_gem_vm_close(vma); 249 drm_gem_vm_close(vma);
241 250
@@ -273,9 +282,9 @@ void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m
273 282
274 off = drm_vma_node_start(&obj->vma_node); 283 off = drm_vma_node_start(&obj->vma_node);
275 284
276 seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d", 285 seq_printf(m, "%2d (%2d) %08llx %pad %p %d",
277 obj->name, obj->refcount.refcount.counter, 286 obj->name, obj->refcount.refcount.counter,
278 off, cma_obj->paddr, cma_obj->vaddr, obj->size); 287 off, &cma_obj->paddr, cma_obj->vaddr, obj->size);
279 288
280 seq_printf(m, "\n"); 289 seq_printf(m, "\n");
281} 290}
@@ -323,7 +332,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size,
323 cma_obj->paddr = sg_dma_address(sgt->sgl); 332 cma_obj->paddr = sg_dma_address(sgt->sgl);
324 cma_obj->sgt = sgt; 333 cma_obj->sgt = sgt;
325 334
326 DRM_DEBUG_PRIME("dma_addr = 0x%x, size = %zu\n", cma_obj->paddr, size); 335 DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, size);
327 336
328 return &cma_obj->base; 337 return &cma_obj->base;
329} 338}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index f4dc9b7a3831..93a42040bedb 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -328,6 +328,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
328 return -EINVAL; 328 return -EINVAL;
329 file_priv->stereo_allowed = req->value; 329 file_priv->stereo_allowed = req->value;
330 break; 330 break;
331 case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
332 if (!drm_universal_planes)
333 return -EINVAL;
334 if (req->value > 1)
335 return -EINVAL;
336 file_priv->universal_planes = req->value;
337 break;
331 default: 338 default:
332 return -EINVAL; 339 return -EINVAL;
333 } 340 }
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index b155ee2ffa17..09821f46d768 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -142,8 +142,12 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
142{ 142{
143 struct device_node *node; 143 struct device_node *node;
144 144
145 for_each_available_child_of_node(host->dev->of_node, node) 145 for_each_available_child_of_node(host->dev->of_node, node) {
146 /* skip nodes without reg property */
147 if (!of_find_property(node, "reg", NULL))
148 continue;
146 of_mipi_dsi_device_add(host, node); 149 of_mipi_dsi_device_add(host, node);
150 }
147 151
148 return 0; 152 return 0;
149} 153}
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index a2d45b748f86..71e2d3fcd6ee 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -82,6 +82,10 @@
82 * this to implement guard pages between incompatible caching domains in the 82 * this to implement guard pages between incompatible caching domains in the
83 * graphics TT. 83 * graphics TT.
84 * 84 *
85 * Two behaviors are supported for searching and allocating: bottom-up and top-down.
86 * The default is bottom-up. Top-down allocation can be used if the memory area
87 * has different restrictions, or just to reduce fragmentation.
88 *
85 * Finally iteration helpers to walk all nodes and all holes are provided as are 89 * Finally iteration helpers to walk all nodes and all holes are provided as are
86 * some basic allocator dumpers for debugging. 90 * some basic allocator dumpers for debugging.
87 */ 91 */
@@ -102,7 +106,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
102static void drm_mm_insert_helper(struct drm_mm_node *hole_node, 106static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
103 struct drm_mm_node *node, 107 struct drm_mm_node *node,
104 unsigned long size, unsigned alignment, 108 unsigned long size, unsigned alignment,
105 unsigned long color) 109 unsigned long color,
110 enum drm_mm_allocator_flags flags)
106{ 111{
107 struct drm_mm *mm = hole_node->mm; 112 struct drm_mm *mm = hole_node->mm;
108 unsigned long hole_start = drm_mm_hole_node_start(hole_node); 113 unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -115,12 +120,22 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
115 if (mm->color_adjust) 120 if (mm->color_adjust)
116 mm->color_adjust(hole_node, color, &adj_start, &adj_end); 121 mm->color_adjust(hole_node, color, &adj_start, &adj_end);
117 122
123 if (flags & DRM_MM_CREATE_TOP)
124 adj_start = adj_end - size;
125
118 if (alignment) { 126 if (alignment) {
119 unsigned tmp = adj_start % alignment; 127 unsigned tmp = adj_start % alignment;
120 if (tmp) 128 if (tmp) {
121 adj_start += alignment - tmp; 129 if (flags & DRM_MM_CREATE_TOP)
130 adj_start -= tmp;
131 else
132 adj_start += alignment - tmp;
133 }
122 } 134 }
123 135
136 BUG_ON(adj_start < hole_start);
137 BUG_ON(adj_end > hole_end);
138
124 if (adj_start == hole_start) { 139 if (adj_start == hole_start) {
125 hole_node->hole_follows = 0; 140 hole_node->hole_follows = 0;
126 list_del(&hole_node->hole_stack); 141 list_del(&hole_node->hole_stack);
@@ -205,7 +220,8 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
205 * @size: size of the allocation 220 * @size: size of the allocation
206 * @alignment: alignment of the allocation 221 * @alignment: alignment of the allocation
207 * @color: opaque tag value to use for this node 222 * @color: opaque tag value to use for this node
208 * @flags: flags to fine-tune the allocation 223 * @sflags: flags to fine-tune the allocation search
224 * @aflags: flags to fine-tune the allocation behavior
209 * 225 *
210 * The preallocated node must be cleared to 0. 226 * The preallocated node must be cleared to 0.
211 * 227 *
@@ -215,16 +231,17 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
215int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, 231int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
216 unsigned long size, unsigned alignment, 232 unsigned long size, unsigned alignment,
217 unsigned long color, 233 unsigned long color,
218 enum drm_mm_search_flags flags) 234 enum drm_mm_search_flags sflags,
235 enum drm_mm_allocator_flags aflags)
219{ 236{
220 struct drm_mm_node *hole_node; 237 struct drm_mm_node *hole_node;
221 238
222 hole_node = drm_mm_search_free_generic(mm, size, alignment, 239 hole_node = drm_mm_search_free_generic(mm, size, alignment,
223 color, flags); 240 color, sflags);
224 if (!hole_node) 241 if (!hole_node)
225 return -ENOSPC; 242 return -ENOSPC;
226 243
227 drm_mm_insert_helper(hole_node, node, size, alignment, color); 244 drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags);
228 return 0; 245 return 0;
229} 246}
230EXPORT_SYMBOL(drm_mm_insert_node_generic); 247EXPORT_SYMBOL(drm_mm_insert_node_generic);
@@ -233,7 +250,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
233 struct drm_mm_node *node, 250 struct drm_mm_node *node,
234 unsigned long size, unsigned alignment, 251 unsigned long size, unsigned alignment,
235 unsigned long color, 252 unsigned long color,
236 unsigned long start, unsigned long end) 253 unsigned long start, unsigned long end,
254 enum drm_mm_allocator_flags flags)
237{ 255{
238 struct drm_mm *mm = hole_node->mm; 256 struct drm_mm *mm = hole_node->mm;
239 unsigned long hole_start = drm_mm_hole_node_start(hole_node); 257 unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -248,13 +266,20 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
248 if (adj_end > end) 266 if (adj_end > end)
249 adj_end = end; 267 adj_end = end;
250 268
269 if (flags & DRM_MM_CREATE_TOP)
270 adj_start = adj_end - size;
271
251 if (mm->color_adjust) 272 if (mm->color_adjust)
252 mm->color_adjust(hole_node, color, &adj_start, &adj_end); 273 mm->color_adjust(hole_node, color, &adj_start, &adj_end);
253 274
254 if (alignment) { 275 if (alignment) {
255 unsigned tmp = adj_start % alignment; 276 unsigned tmp = adj_start % alignment;
256 if (tmp) 277 if (tmp) {
257 adj_start += alignment - tmp; 278 if (flags & DRM_MM_CREATE_TOP)
279 adj_start -= tmp;
280 else
281 adj_start += alignment - tmp;
282 }
258 } 283 }
259 284
260 if (adj_start == hole_start) { 285 if (adj_start == hole_start) {
@@ -271,6 +296,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
271 INIT_LIST_HEAD(&node->hole_stack); 296 INIT_LIST_HEAD(&node->hole_stack);
272 list_add(&node->node_list, &hole_node->node_list); 297 list_add(&node->node_list, &hole_node->node_list);
273 298
299 BUG_ON(node->start < start);
300 BUG_ON(node->start < adj_start);
274 BUG_ON(node->start + node->size > adj_end); 301 BUG_ON(node->start + node->size > adj_end);
275 BUG_ON(node->start + node->size > end); 302 BUG_ON(node->start + node->size > end);
276 303
@@ -290,7 +317,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
290 * @color: opaque tag value to use for this node 317 * @color: opaque tag value to use for this node
291 * @start: start of the allowed range for this node 318 * @start: start of the allowed range for this node
292 * @end: end of the allowed range for this node 319 * @end: end of the allowed range for this node
293 * @flags: flags to fine-tune the allocation 320 * @sflags: flags to fine-tune the allocation search
321 * @aflags: flags to fine-tune the allocation behavior
294 * 322 *
295 * The preallocated node must be cleared to 0. 323 * The preallocated node must be cleared to 0.
296 * 324 *
@@ -298,21 +326,23 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
298 * 0 on success, -ENOSPC if there's no suitable hole. 326 * 0 on success, -ENOSPC if there's no suitable hole.
299 */ 327 */
300int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, 328int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
301 unsigned long size, unsigned alignment, unsigned long color, 329 unsigned long size, unsigned alignment,
330 unsigned long color,
302 unsigned long start, unsigned long end, 331 unsigned long start, unsigned long end,
303 enum drm_mm_search_flags flags) 332 enum drm_mm_search_flags sflags,
333 enum drm_mm_allocator_flags aflags)
304{ 334{
305 struct drm_mm_node *hole_node; 335 struct drm_mm_node *hole_node;
306 336
307 hole_node = drm_mm_search_free_in_range_generic(mm, 337 hole_node = drm_mm_search_free_in_range_generic(mm,
308 size, alignment, color, 338 size, alignment, color,
309 start, end, flags); 339 start, end, sflags);
310 if (!hole_node) 340 if (!hole_node)
311 return -ENOSPC; 341 return -ENOSPC;
312 342
313 drm_mm_insert_helper_range(hole_node, node, 343 drm_mm_insert_helper_range(hole_node, node,
314 size, alignment, color, 344 size, alignment, color,
315 start, end); 345 start, end, aflags);
316 return 0; 346 return 0;
317} 347}
318EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); 348EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
@@ -391,7 +421,10 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
391 best = NULL; 421 best = NULL;
392 best_size = ~0UL; 422 best_size = ~0UL;
393 423
394 drm_mm_for_each_hole(entry, mm, adj_start, adj_end) { 424 __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
425 flags & DRM_MM_SEARCH_BELOW) {
426 unsigned long hole_size = adj_end - adj_start;
427
395 if (mm->color_adjust) { 428 if (mm->color_adjust) {
396 mm->color_adjust(entry, color, &adj_start, &adj_end); 429 mm->color_adjust(entry, color, &adj_start, &adj_end);
397 if (adj_end <= adj_start) 430 if (adj_end <= adj_start)
@@ -404,9 +437,9 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
404 if (!(flags & DRM_MM_SEARCH_BEST)) 437 if (!(flags & DRM_MM_SEARCH_BEST))
405 return entry; 438 return entry;
406 439
407 if (entry->size < best_size) { 440 if (hole_size < best_size) {
408 best = entry; 441 best = entry;
409 best_size = entry->size; 442 best_size = hole_size;
410 } 443 }
411 } 444 }
412 445
@@ -432,7 +465,10 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
432 best = NULL; 465 best = NULL;
433 best_size = ~0UL; 466 best_size = ~0UL;
434 467
435 drm_mm_for_each_hole(entry, mm, adj_start, adj_end) { 468 __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
469 flags & DRM_MM_SEARCH_BELOW) {
470 unsigned long hole_size = adj_end - adj_start;
471
436 if (adj_start < start) 472 if (adj_start < start)
437 adj_start = start; 473 adj_start = start;
438 if (adj_end > end) 474 if (adj_end > end)
@@ -450,9 +486,9 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
450 if (!(flags & DRM_MM_SEARCH_BEST)) 486 if (!(flags & DRM_MM_SEARCH_BEST))
451 return entry; 487 return entry;
452 488
453 if (entry->size < best_size) { 489 if (hole_size < best_size) {
454 best = entry; 490 best = entry;
455 best_size = entry->size; 491 best_size = hole_size;
456 } 492 }
457 } 493 }
458 494
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
new file mode 100644
index 000000000000..e768d35ff22e
--- /dev/null
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -0,0 +1,333 @@
1/*
2 * Copyright (C) 2014 Intel Corporation
3 *
4 * DRM universal plane helper functions
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26#include <linux/list.h>
27#include <drm/drmP.h>
28#include <drm/drm_rect.h>
29
30#define SUBPIXEL_MASK 0xffff
31
32/*
33 * This is the minimal list of formats that seem to be safe for modeset use
34 * with all current DRM drivers. Most hardware can actually support more
35 * formats than this and drivers may specify a more accurate list when
36 * creating the primary plane. However drivers that still call
37 * drm_plane_init() will use this minimal format list as the default.
38 */
39const static uint32_t safe_modeset_formats[] = {
40 DRM_FORMAT_XRGB8888,
41 DRM_FORMAT_ARGB8888,
42};
43
44/*
45 * Returns the connectors currently associated with a CRTC. This function
46 * should be called twice: once with a NULL connector list to retrieve
47 * the list size, and once with the properly allocated list to be filled in.
48 */
49static int get_connectors_for_crtc(struct drm_crtc *crtc,
50 struct drm_connector **connector_list,
51 int num_connectors)
52{
53 struct drm_device *dev = crtc->dev;
54 struct drm_connector *connector;
55 int count = 0;
56
57 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
58 if (connector->encoder && connector->encoder->crtc == crtc) {
59 if (connector_list != NULL && count < num_connectors)
60 *(connector_list++) = connector;
61
62 count++;
63 }
64
65 return count;
66}
67
68/**
69 * drm_primary_helper_update() - Helper for primary plane update
70 * @plane: plane object to update
71 * @crtc: owning CRTC of owning plane
72 * @fb: framebuffer to flip onto plane
73 * @crtc_x: x offset of primary plane on crtc
74 * @crtc_y: y offset of primary plane on crtc
75 * @crtc_w: width of primary plane rectangle on crtc
76 * @crtc_h: height of primary plane rectangle on crtc
77 * @src_x: x offset of @fb for panning
78 * @src_y: y offset of @fb for panning
79 * @src_w: width of source rectangle in @fb
80 * @src_h: height of source rectangle in @fb
81 *
82 * Provides a default plane update handler for primary planes. This is handler
83 * is called in response to a userspace SetPlane operation on the plane with a
84 * non-NULL framebuffer. We call the driver's modeset handler to update the
85 * framebuffer.
86 *
87 * SetPlane() on a primary plane of a disabled CRTC is not supported, and will
88 * return an error.
89 *
90 * Note that we make some assumptions about hardware limitations that may not be
91 * true for all hardware --
92 * 1) Primary plane cannot be repositioned.
93 * 2) Primary plane cannot be scaled.
94 * 3) Primary plane must cover the entire CRTC.
95 * 4) Subpixel positioning is not supported.
96 * Drivers for hardware that don't have these restrictions can provide their
97 * own implementation rather than using this helper.
98 *
99 * RETURNS:
100 * Zero on success, error code on failure
101 */
102int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
103 struct drm_framebuffer *fb,
104 int crtc_x, int crtc_y,
105 unsigned int crtc_w, unsigned int crtc_h,
106 uint32_t src_x, uint32_t src_y,
107 uint32_t src_w, uint32_t src_h)
108{
109 struct drm_mode_set set = {
110 .crtc = crtc,
111 .fb = fb,
112 .mode = &crtc->mode,
113 .x = src_x >> 16,
114 .y = src_y >> 16,
115 };
116 struct drm_rect dest = {
117 .x1 = crtc_x,
118 .y1 = crtc_y,
119 .x2 = crtc_x + crtc_w,
120 .y2 = crtc_y + crtc_h,
121 };
122 struct drm_rect clip = {
123 .x2 = crtc->mode.hdisplay,
124 .y2 = crtc->mode.vdisplay,
125 };
126 struct drm_connector **connector_list;
127 struct drm_framebuffer *tmpfb;
128 int num_connectors, ret;
129
130 if (!crtc->enabled) {
131 DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n");
132 return -EINVAL;
133 }
134
135 /* Disallow subpixel positioning */
136 if ((src_x | src_y | src_w | src_h) & SUBPIXEL_MASK) {
137 DRM_DEBUG_KMS("Primary plane does not support subpixel positioning\n");
138 return -EINVAL;
139 }
140
141 /* Primary planes are locked to their owning CRTC */
142 if (plane->possible_crtcs != drm_crtc_mask(crtc)) {
143 DRM_DEBUG_KMS("Cannot change primary plane CRTC\n");
144 return -EINVAL;
145 }
146
147 /* Disallow scaling */
148 if (crtc_w != src_w || crtc_h != src_h) {
149 DRM_DEBUG_KMS("Can't scale primary plane\n");
150 return -EINVAL;
151 }
152
153 /* Make sure primary plane covers entire CRTC */
154 drm_rect_intersect(&dest, &clip);
155 if (dest.x1 != 0 || dest.y1 != 0 ||
156 dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) {
157 DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n");
158 return -EINVAL;
159 }
160
161 /* Framebuffer must be big enough to cover entire plane */
162 ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb);
163 if (ret)
164 return ret;
165
166 /* Find current connectors for CRTC */
167 num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
168 BUG_ON(num_connectors == 0);
169 connector_list = kzalloc(num_connectors * sizeof(*connector_list),
170 GFP_KERNEL);
171 if (!connector_list)
172 return -ENOMEM;
173 get_connectors_for_crtc(crtc, connector_list, num_connectors);
174
175 set.connectors = connector_list;
176 set.num_connectors = num_connectors;
177
178 /*
179 * set_config() adjusts crtc->primary->fb; however the DRM setplane
180 * code that called us expects to handle the framebuffer update and
181 * reference counting; save and restore the current fb before
182 * calling it.
183 *
184 * N.B., we call set_config() directly here rather than using
185 * drm_mode_set_config_internal. We're reprogramming the same
186 * connectors that were already in use, so we shouldn't need the extra
187 * cross-CRTC fb refcounting to accomodate stealing connectors.
188 * drm_mode_setplane() already handles the basic refcounting for the
189 * framebuffers involved in this operation.
190 */
191 tmpfb = plane->fb;
192 ret = crtc->funcs->set_config(&set);
193 plane->fb = tmpfb;
194
195 kfree(connector_list);
196 return ret;
197}
198EXPORT_SYMBOL(drm_primary_helper_update);
199
200/**
201 * drm_primary_helper_disable() - Helper for primary plane disable
202 * @plane: plane to disable
203 *
204 * Provides a default plane disable handler for primary planes. This is handler
205 * is called in response to a userspace SetPlane operation on the plane with a
206 * NULL framebuffer parameter. We call the driver's modeset handler with a NULL
207 * framebuffer to disable the CRTC if no other planes are currently enabled.
208 * If other planes are still enabled on the same CRTC, we return -EBUSY.
209 *
210 * Note that some hardware may be able to disable the primary plane without
211 * disabling the whole CRTC. Drivers for such hardware should provide their
212 * own disable handler that disables just the primary plane (and they'll likely
213 * need to provide their own update handler as well to properly re-enable a
214 * disabled primary plane).
215 *
216 * RETURNS:
217 * Zero on success, error code on failure
218 */
219int drm_primary_helper_disable(struct drm_plane *plane)
220{
221 struct drm_plane *p;
222 struct drm_mode_set set = {
223 .crtc = plane->crtc,
224 .fb = NULL,
225 };
226
227 if (plane->crtc == NULL || plane->fb == NULL)
228 /* Already disabled */
229 return 0;
230
231 list_for_each_entry(p, &plane->dev->mode_config.plane_list, head)
232 if (p != plane && p->fb) {
233 DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n");
234 return -EBUSY;
235 }
236
237 /*
238 * N.B. We call set_config() directly here rather than
239 * drm_mode_set_config_internal() since drm_mode_setplane() already
240 * handles the basic refcounting and we don't need the special
241 * cross-CRTC refcounting (no chance of stealing connectors from
242 * other CRTC's with this update).
243 */
244 return plane->crtc->funcs->set_config(&set);
245}
246EXPORT_SYMBOL(drm_primary_helper_disable);
247
248/**
249 * drm_primary_helper_destroy() - Helper for primary plane destruction
250 * @plane: plane to destroy
251 *
252 * Provides a default plane destroy handler for primary planes. This handler
253 * is called during CRTC destruction. We disable the primary plane, remove
254 * it from the DRM plane list, and deallocate the plane structure.
255 */
256void drm_primary_helper_destroy(struct drm_plane *plane)
257{
258 plane->funcs->disable_plane(plane);
259 drm_plane_cleanup(plane);
260 kfree(plane);
261}
262EXPORT_SYMBOL(drm_primary_helper_destroy);
263
264const struct drm_plane_funcs drm_primary_helper_funcs = {
265 .update_plane = drm_primary_helper_update,
266 .disable_plane = drm_primary_helper_disable,
267 .destroy = drm_primary_helper_destroy,
268};
269EXPORT_SYMBOL(drm_primary_helper_funcs);
270
271/**
272 * drm_primary_helper_create_plane() - Create a generic primary plane
273 * @dev: drm device
274 * @formats: pixel formats supported, or NULL for a default safe list
275 * @num_formats: size of @formats; ignored if @formats is NULL
276 *
277 * Allocates and initializes a primary plane that can be used with the primary
278 * plane helpers. Drivers that wish to use driver-specific plane structures or
279 * provide custom handler functions may perform their own allocation and
280 * initialization rather than calling this function.
281 */
282struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
283 const uint32_t *formats,
284 int num_formats)
285{
286 struct drm_plane *primary;
287 int ret;
288
289 primary = kzalloc(sizeof(*primary), GFP_KERNEL);
290 if (primary == NULL) {
291 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
292 return NULL;
293 }
294
295 if (formats == NULL) {
296 formats = safe_modeset_formats;
297 num_formats = ARRAY_SIZE(safe_modeset_formats);
298 }
299
300 /* possible_crtc's will be filled in later by crtc_init */
301 ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs,
302 formats, num_formats,
303 DRM_PLANE_TYPE_PRIMARY);
304 if (ret) {
305 kfree(primary);
306 primary = NULL;
307 }
308
309 return primary;
310}
311EXPORT_SYMBOL(drm_primary_helper_create_plane);
312
313/**
314 * drm_crtc_init - Legacy CRTC initialization function
315 * @dev: DRM device
316 * @crtc: CRTC object to init
317 * @funcs: callbacks for the new CRTC
318 *
319 * Initialize a CRTC object with a default helper-provided primary plane and no
320 * cursor plane.
321 *
322 * Returns:
323 * Zero on success, error code on failure.
324 */
325int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
326 const struct drm_crtc_funcs *funcs)
327{
328 struct drm_plane *primary;
329
330 primary = drm_primary_helper_create_plane(dev, NULL, 0);
331 return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs);
332}
333EXPORT_SYMBOL(drm_crtc_init);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index dc2c6095d850..4c24c3ac1efa 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -45,6 +45,10 @@ EXPORT_SYMBOL(drm_debug);
45unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */ 45unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */
46EXPORT_SYMBOL(drm_rnodes); 46EXPORT_SYMBOL(drm_rnodes);
47 47
48/* 1 to allow user space to request universal planes (experimental) */
49unsigned int drm_universal_planes = 0;
50EXPORT_SYMBOL(drm_universal_planes);
51
48unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ 52unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
49EXPORT_SYMBOL(drm_vblank_offdelay); 53EXPORT_SYMBOL(drm_vblank_offdelay);
50 54
@@ -68,6 +72,7 @@ MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
68 72
69module_param_named(debug, drm_debug, int, 0600); 73module_param_named(debug, drm_debug, int, 0600);
70module_param_named(rnodes, drm_rnodes, int, 0600); 74module_param_named(rnodes, drm_rnodes, int, 0600);
75module_param_named(universal_planes, drm_universal_planes, int, 0600);
71module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); 76module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
72module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 77module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
73module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); 78module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
@@ -97,26 +102,18 @@ int drm_err(const char *func, const char *format, ...)
97} 102}
98EXPORT_SYMBOL(drm_err); 103EXPORT_SYMBOL(drm_err);
99 104
100void drm_ut_debug_printk(unsigned int request_level, 105void drm_ut_debug_printk(const char *function_name, const char *format, ...)
101 const char *prefix,
102 const char *function_name,
103 const char *format, ...)
104{ 106{
105 struct va_format vaf; 107 struct va_format vaf;
106 va_list args; 108 va_list args;
107 109
108 if (drm_debug & request_level) { 110 va_start(args, format);
109 va_start(args, format); 111 vaf.fmt = format;
110 vaf.fmt = format; 112 vaf.va = &args;
111 vaf.va = &args; 113
112 114 printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
113 if (function_name) 115
114 printk(KERN_DEBUG "[%s:%s], %pV", prefix, 116 va_end(args);
115 function_name, &vaf);
116 else
117 printk(KERN_DEBUG "%pV", &vaf);
118 va_end(args);
119 }
120} 117}
121EXPORT_SYMBOL(drm_ut_debug_printk); 118EXPORT_SYMBOL(drm_ut_debug_printk);
122 119
@@ -135,8 +132,6 @@ struct drm_master *drm_master_create(struct drm_minor *minor)
135 INIT_LIST_HEAD(&master->magicfree); 132 INIT_LIST_HEAD(&master->magicfree);
136 master->minor = minor; 133 master->minor = minor;
137 134
138 list_add_tail(&master->head, &minor->master_list);
139
140 return master; 135 return master;
141} 136}
142 137
@@ -154,8 +149,7 @@ static void drm_master_destroy(struct kref *kref)
154 struct drm_device *dev = master->minor->dev; 149 struct drm_device *dev = master->minor->dev;
155 struct drm_map_list *r_list, *list_temp; 150 struct drm_map_list *r_list, *list_temp;
156 151
157 list_del(&master->head); 152 mutex_lock(&dev->struct_mutex);
158
159 if (dev->driver->master_destroy) 153 if (dev->driver->master_destroy)
160 dev->driver->master_destroy(dev, master); 154 dev->driver->master_destroy(dev, master);
161 155
@@ -183,6 +177,7 @@ static void drm_master_destroy(struct kref *kref)
183 177
184 drm_ht_remove(&master->magiclist); 178 drm_ht_remove(&master->magiclist);
185 179
180 mutex_unlock(&dev->struct_mutex);
186 kfree(master); 181 kfree(master);
187} 182}
188 183
@@ -198,19 +193,20 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
198{ 193{
199 int ret = 0; 194 int ret = 0;
200 195
196 mutex_lock(&dev->master_mutex);
201 if (file_priv->is_master) 197 if (file_priv->is_master)
202 return 0; 198 goto out_unlock;
203
204 if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
205 return -EINVAL;
206 199
207 if (!file_priv->master) 200 if (file_priv->minor->master) {
208 return -EINVAL; 201 ret = -EINVAL;
202 goto out_unlock;
203 }
209 204
210 if (file_priv->minor->master) 205 if (!file_priv->master) {
211 return -EINVAL; 206 ret = -EINVAL;
207 goto out_unlock;
208 }
212 209
213 mutex_lock(&dev->struct_mutex);
214 file_priv->minor->master = drm_master_get(file_priv->master); 210 file_priv->minor->master = drm_master_get(file_priv->master);
215 file_priv->is_master = 1; 211 file_priv->is_master = 1;
216 if (dev->driver->master_set) { 212 if (dev->driver->master_set) {
@@ -220,27 +216,33 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
220 drm_master_put(&file_priv->minor->master); 216 drm_master_put(&file_priv->minor->master);
221 } 217 }
222 } 218 }
223 mutex_unlock(&dev->struct_mutex);
224 219
220out_unlock:
221 mutex_unlock(&dev->master_mutex);
225 return ret; 222 return ret;
226} 223}
227 224
228int drm_dropmaster_ioctl(struct drm_device *dev, void *data, 225int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
229 struct drm_file *file_priv) 226 struct drm_file *file_priv)
230{ 227{
228 int ret = -EINVAL;
229
230 mutex_lock(&dev->master_mutex);
231 if (!file_priv->is_master) 231 if (!file_priv->is_master)
232 return -EINVAL; 232 goto out_unlock;
233 233
234 if (!file_priv->minor->master) 234 if (!file_priv->minor->master)
235 return -EINVAL; 235 goto out_unlock;
236 236
237 mutex_lock(&dev->struct_mutex); 237 ret = 0;
238 if (dev->driver->master_drop) 238 if (dev->driver->master_drop)
239 dev->driver->master_drop(dev, file_priv, false); 239 dev->driver->master_drop(dev, file_priv, false);
240 drm_master_put(&file_priv->minor->master); 240 drm_master_put(&file_priv->minor->master);
241 file_priv->is_master = 0; 241 file_priv->is_master = 0;
242 mutex_unlock(&dev->struct_mutex); 242
243 return 0; 243out_unlock:
244 mutex_unlock(&dev->master_mutex);
245 return ret;
244} 246}
245 247
246/* 248/*
@@ -281,7 +283,6 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
281 283
282 minor->type = type; 284 minor->type = type;
283 minor->dev = dev; 285 minor->dev = dev;
284 INIT_LIST_HEAD(&minor->master_list);
285 286
286 *drm_minor_get_slot(dev, type) = minor; 287 *drm_minor_get_slot(dev, type) = minor;
287 return 0; 288 return 0;
@@ -572,6 +573,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
572 spin_lock_init(&dev->event_lock); 573 spin_lock_init(&dev->event_lock);
573 mutex_init(&dev->struct_mutex); 574 mutex_init(&dev->struct_mutex);
574 mutex_init(&dev->ctxlist_mutex); 575 mutex_init(&dev->ctxlist_mutex);
576 mutex_init(&dev->master_mutex);
575 577
576 dev->anon_inode = drm_fs_inode_new(); 578 dev->anon_inode = drm_fs_inode_new();
577 if (IS_ERR(dev->anon_inode)) { 579 if (IS_ERR(dev->anon_inode)) {
@@ -625,6 +627,7 @@ err_minors:
625 drm_minor_free(dev, DRM_MINOR_CONTROL); 627 drm_minor_free(dev, DRM_MINOR_CONTROL);
626 drm_fs_inode_free(dev->anon_inode); 628 drm_fs_inode_free(dev->anon_inode);
627err_free: 629err_free:
630 mutex_destroy(&dev->master_mutex);
628 kfree(dev); 631 kfree(dev);
629 return NULL; 632 return NULL;
630} 633}
@@ -646,6 +649,8 @@ static void drm_dev_release(struct kref *ref)
646 drm_minor_free(dev, DRM_MINOR_CONTROL); 649 drm_minor_free(dev, DRM_MINOR_CONTROL);
647 650
648 kfree(dev->devname); 651 kfree(dev->devname);
652
653 mutex_destroy(&dev->master_mutex);
649 kfree(dev); 654 kfree(dev);
650} 655}
651 656
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 6e1a1a20cf6b..5bf5bca94f56 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -31,6 +31,30 @@ config DRM_EXYNOS_FIMD
31 help 31 help
32 Choose this option if you want to use Exynos FIMD for DRM. 32 Choose this option if you want to use Exynos FIMD for DRM.
33 33
34config DRM_EXYNOS_DPI
35 bool "EXYNOS DRM parallel output support"
36 depends on DRM_EXYNOS
37 select DRM_PANEL
38 default n
39 help
40 This enables support for Exynos parallel output.
41
42config DRM_EXYNOS_DSI
43 bool "EXYNOS DRM MIPI-DSI driver support"
44 depends on DRM_EXYNOS
45 select DRM_MIPI_DSI
46 select DRM_PANEL
47 default n
48 help
49 This enables support for Exynos MIPI-DSI device.
50
51config DRM_EXYNOS_DP
52 bool "EXYNOS DRM DP driver support"
53 depends on DRM_EXYNOS && ARCH_EXYNOS
54 default DRM_EXYNOS
55 help
56 This enables support for DP device.
57
34config DRM_EXYNOS_HDMI 58config DRM_EXYNOS_HDMI
35 bool "Exynos DRM HDMI" 59 bool "Exynos DRM HDMI"
36 depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV 60 depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 639b49e1ec05..33ae3652b8da 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -3,7 +3,7 @@
3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. 3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
4 4
5ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos 5ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
6exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ 6exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \
7 exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ 7 exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
8 exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ 8 exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
9 exynos_drm_plane.o 9 exynos_drm_plane.o
@@ -11,9 +11,10 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
11exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o 11exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
12exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o 12exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
13exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o 13exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
14exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ 14exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o
15 exynos_ddc.o exynos_hdmiphy.o \ 15exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o
16 exynos_drm_hdmi.o 16exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
17exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o
17exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o 18exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
18exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o 19exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
19exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o 20exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 5e1a71580051..aed533bbfd31 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -12,7 +12,6 @@
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/err.h> 15#include <linux/err.h>
17#include <linux/clk.h> 16#include <linux/clk.h>
18#include <linux/io.h> 17#include <linux/io.h>
@@ -20,9 +19,25 @@
20#include <linux/delay.h> 19#include <linux/delay.h>
21#include <linux/of.h> 20#include <linux/of.h>
22#include <linux/phy/phy.h> 21#include <linux/phy/phy.h>
22#include <video/of_display_timing.h>
23#include <video/of_videomode.h>
23 24
25#include <drm/drmP.h>
26#include <drm/drm_crtc.h>
27#include <drm/drm_crtc_helper.h>
28#include <drm/bridge/ptn3460.h>
29
30#include "exynos_drm_drv.h"
24#include "exynos_dp_core.h" 31#include "exynos_dp_core.h"
25 32
33#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \
34 connector)
35
36struct bridge_init {
37 struct i2c_client *client;
38 struct device_node *node;
39};
40
26static int exynos_dp_init_dp(struct exynos_dp_device *dp) 41static int exynos_dp_init_dp(struct exynos_dp_device *dp)
27{ 42{
28 exynos_dp_reset(dp); 43 exynos_dp_reset(dp);
@@ -893,6 +908,214 @@ static void exynos_dp_hotplug(struct work_struct *work)
893 dev_err(dp->dev, "unable to config video\n"); 908 dev_err(dp->dev, "unable to config video\n");
894} 909}
895 910
911static enum drm_connector_status exynos_dp_detect(
912 struct drm_connector *connector, bool force)
913{
914 return connector_status_connected;
915}
916
917static void exynos_dp_connector_destroy(struct drm_connector *connector)
918{
919}
920
921static struct drm_connector_funcs exynos_dp_connector_funcs = {
922 .dpms = drm_helper_connector_dpms,
923 .fill_modes = drm_helper_probe_single_connector_modes,
924 .detect = exynos_dp_detect,
925 .destroy = exynos_dp_connector_destroy,
926};
927
928static int exynos_dp_get_modes(struct drm_connector *connector)
929{
930 struct exynos_dp_device *dp = ctx_from_connector(connector);
931 struct drm_display_mode *mode;
932
933 mode = drm_mode_create(connector->dev);
934 if (!mode) {
935 DRM_ERROR("failed to create a new display mode.\n");
936 return 0;
937 }
938
939 drm_display_mode_from_videomode(&dp->panel.vm, mode);
940 mode->width_mm = dp->panel.width_mm;
941 mode->height_mm = dp->panel.height_mm;
942 connector->display_info.width_mm = mode->width_mm;
943 connector->display_info.height_mm = mode->height_mm;
944
945 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
946 drm_mode_set_name(mode);
947 drm_mode_probed_add(connector, mode);
948
949 return 1;
950}
951
952static int exynos_dp_mode_valid(struct drm_connector *connector,
953 struct drm_display_mode *mode)
954{
955 return MODE_OK;
956}
957
958static struct drm_encoder *exynos_dp_best_encoder(
959 struct drm_connector *connector)
960{
961 struct exynos_dp_device *dp = ctx_from_connector(connector);
962
963 return dp->encoder;
964}
965
966static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
967 .get_modes = exynos_dp_get_modes,
968 .mode_valid = exynos_dp_mode_valid,
969 .best_encoder = exynos_dp_best_encoder,
970};
971
972static int exynos_dp_initialize(struct exynos_drm_display *display,
973 struct drm_device *drm_dev)
974{
975 struct exynos_dp_device *dp = display->ctx;
976
977 dp->drm_dev = drm_dev;
978
979 return 0;
980}
981
982static bool find_bridge(const char *compat, struct bridge_init *bridge)
983{
984 bridge->client = NULL;
985 bridge->node = of_find_compatible_node(NULL, NULL, compat);
986 if (!bridge->node)
987 return false;
988
989 bridge->client = of_find_i2c_device_by_node(bridge->node);
990 if (!bridge->client)
991 return false;
992
993 return true;
994}
995
996/* returns the number of bridges attached */
997static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
998 struct drm_encoder *encoder)
999{
1000 struct bridge_init bridge;
1001 int ret;
1002
1003 if (find_bridge("nxp,ptn3460", &bridge)) {
1004 ret = ptn3460_init(dev, encoder, bridge.client, bridge.node);
1005 if (!ret)
1006 return 1;
1007 }
1008 return 0;
1009}
1010
1011static int exynos_dp_create_connector(struct exynos_drm_display *display,
1012 struct drm_encoder *encoder)
1013{
1014 struct exynos_dp_device *dp = display->ctx;
1015 struct drm_connector *connector = &dp->connector;
1016 int ret;
1017
1018 dp->encoder = encoder;
1019
1020 /* Pre-empt DP connector creation if there's a bridge */
1021 ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder);
1022 if (ret)
1023 return 0;
1024
1025 connector->polled = DRM_CONNECTOR_POLL_HPD;
1026
1027 ret = drm_connector_init(dp->drm_dev, connector,
1028 &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
1029 if (ret) {
1030 DRM_ERROR("Failed to initialize connector with drm\n");
1031 return ret;
1032 }
1033
1034 drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
1035 drm_sysfs_connector_add(connector);
1036 drm_mode_connector_attach_encoder(connector, encoder);
1037
1038 return 0;
1039}
1040
1041static void exynos_dp_phy_init(struct exynos_dp_device *dp)
1042{
1043 if (dp->phy) {
1044 phy_power_on(dp->phy);
1045 } else if (dp->phy_addr) {
1046 u32 reg;
1047
1048 reg = __raw_readl(dp->phy_addr);
1049 reg |= dp->enable_mask;
1050 __raw_writel(reg, dp->phy_addr);
1051 }
1052}
1053
1054static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
1055{
1056 if (dp->phy) {
1057 phy_power_off(dp->phy);
1058 } else if (dp->phy_addr) {
1059 u32 reg;
1060
1061 reg = __raw_readl(dp->phy_addr);
1062 reg &= ~(dp->enable_mask);
1063 __raw_writel(reg, dp->phy_addr);
1064 }
1065}
1066
1067static void exynos_dp_poweron(struct exynos_dp_device *dp)
1068{
1069 if (dp->dpms_mode == DRM_MODE_DPMS_ON)
1070 return;
1071
1072 clk_prepare_enable(dp->clock);
1073 exynos_dp_phy_init(dp);
1074 exynos_dp_init_dp(dp);
1075 enable_irq(dp->irq);
1076}
1077
1078static void exynos_dp_poweroff(struct exynos_dp_device *dp)
1079{
1080 if (dp->dpms_mode != DRM_MODE_DPMS_ON)
1081 return;
1082
1083 disable_irq(dp->irq);
1084 flush_work(&dp->hotplug_work);
1085 exynos_dp_phy_exit(dp);
1086 clk_disable_unprepare(dp->clock);
1087}
1088
1089static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
1090{
1091 struct exynos_dp_device *dp = display->ctx;
1092
1093 switch (mode) {
1094 case DRM_MODE_DPMS_ON:
1095 exynos_dp_poweron(dp);
1096 break;
1097 case DRM_MODE_DPMS_STANDBY:
1098 case DRM_MODE_DPMS_SUSPEND:
1099 case DRM_MODE_DPMS_OFF:
1100 exynos_dp_poweroff(dp);
1101 break;
1102 default:
1103 break;
1104 };
1105 dp->dpms_mode = mode;
1106}
1107
1108static struct exynos_drm_display_ops exynos_dp_display_ops = {
1109 .initialize = exynos_dp_initialize,
1110 .create_connector = exynos_dp_create_connector,
1111 .dpms = exynos_dp_dpms,
1112};
1113
1114static struct exynos_drm_display exynos_dp_display = {
1115 .type = EXYNOS_DISPLAY_TYPE_LCD,
1116 .ops = &exynos_dp_display_ops,
1117};
1118
896static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) 1119static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
897{ 1120{
898 struct device_node *dp_node = dev->of_node; 1121 struct device_node *dp_node = dev->of_node;
@@ -994,30 +1217,17 @@ err:
994 return ret; 1217 return ret;
995} 1218}
996 1219
997static void exynos_dp_phy_init(struct exynos_dp_device *dp) 1220static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
998{
999 if (dp->phy) {
1000 phy_power_on(dp->phy);
1001 } else if (dp->phy_addr) {
1002 u32 reg;
1003
1004 reg = __raw_readl(dp->phy_addr);
1005 reg |= dp->enable_mask;
1006 __raw_writel(reg, dp->phy_addr);
1007 }
1008}
1009
1010static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
1011{ 1221{
1012 if (dp->phy) { 1222 int ret;
1013 phy_power_off(dp->phy);
1014 } else if (dp->phy_addr) {
1015 u32 reg;
1016 1223
1017 reg = __raw_readl(dp->phy_addr); 1224 ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm,
1018 reg &= ~(dp->enable_mask); 1225 OF_USE_NATIVE_MODE);
1019 __raw_writel(reg, dp->phy_addr); 1226 if (ret) {
1227 DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
1228 return ret;
1020 } 1229 }
1230 return 0;
1021} 1231}
1022 1232
1023static int exynos_dp_probe(struct platform_device *pdev) 1233static int exynos_dp_probe(struct platform_device *pdev)
@@ -1035,6 +1245,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
1035 } 1245 }
1036 1246
1037 dp->dev = &pdev->dev; 1247 dp->dev = &pdev->dev;
1248 dp->dpms_mode = DRM_MODE_DPMS_OFF;
1038 1249
1039 dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); 1250 dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
1040 if (IS_ERR(dp->video_info)) 1251 if (IS_ERR(dp->video_info))
@@ -1044,6 +1255,10 @@ static int exynos_dp_probe(struct platform_device *pdev)
1044 if (ret) 1255 if (ret)
1045 return ret; 1256 return ret;
1046 1257
1258 ret = exynos_dp_dt_parse_panel(dp);
1259 if (ret)
1260 return ret;
1261
1047 dp->clock = devm_clk_get(&pdev->dev, "dp"); 1262 dp->clock = devm_clk_get(&pdev->dev, "dp");
1048 if (IS_ERR(dp->clock)) { 1263 if (IS_ERR(dp->clock)) {
1049 dev_err(&pdev->dev, "failed to get clock\n"); 1264 dev_err(&pdev->dev, "failed to get clock\n");
@@ -1076,22 +1291,22 @@ static int exynos_dp_probe(struct platform_device *pdev)
1076 dev_err(&pdev->dev, "failed to request irq\n"); 1291 dev_err(&pdev->dev, "failed to request irq\n");
1077 return ret; 1292 return ret;
1078 } 1293 }
1294 disable_irq(dp->irq);
1295
1296 exynos_dp_display.ctx = dp;
1079 1297
1080 platform_set_drvdata(pdev, dp); 1298 platform_set_drvdata(pdev, &exynos_dp_display);
1299 exynos_drm_display_register(&exynos_dp_display);
1081 1300
1082 return 0; 1301 return 0;
1083} 1302}
1084 1303
1085static int exynos_dp_remove(struct platform_device *pdev) 1304static int exynos_dp_remove(struct platform_device *pdev)
1086{ 1305{
1087 struct exynos_dp_device *dp = platform_get_drvdata(pdev); 1306 struct exynos_drm_display *display = platform_get_drvdata(pdev);
1088
1089 flush_work(&dp->hotplug_work);
1090
1091 exynos_dp_phy_exit(dp);
1092
1093 clk_disable_unprepare(dp->clock);
1094 1307
1308 exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
1309 exynos_drm_display_unregister(&exynos_dp_display);
1095 1310
1096 return 0; 1311 return 0;
1097} 1312}
@@ -1099,31 +1314,19 @@ static int exynos_dp_remove(struct platform_device *pdev)
1099#ifdef CONFIG_PM_SLEEP 1314#ifdef CONFIG_PM_SLEEP
1100static int exynos_dp_suspend(struct device *dev) 1315static int exynos_dp_suspend(struct device *dev)
1101{ 1316{
1102 struct exynos_dp_device *dp = dev_get_drvdata(dev); 1317 struct platform_device *pdev = to_platform_device(dev);
1103 1318 struct exynos_drm_display *display = platform_get_drvdata(pdev);
1104 disable_irq(dp->irq);
1105
1106 flush_work(&dp->hotplug_work);
1107
1108 exynos_dp_phy_exit(dp);
1109
1110 clk_disable_unprepare(dp->clock);
1111 1319
1320 exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
1112 return 0; 1321 return 0;
1113} 1322}
1114 1323
1115static int exynos_dp_resume(struct device *dev) 1324static int exynos_dp_resume(struct device *dev)
1116{ 1325{
1117 struct exynos_dp_device *dp = dev_get_drvdata(dev); 1326 struct platform_device *pdev = to_platform_device(dev);
1118 1327 struct exynos_drm_display *display = platform_get_drvdata(pdev);
1119 exynos_dp_phy_init(dp);
1120
1121 clk_prepare_enable(dp->clock);
1122
1123 exynos_dp_init_dp(dp);
1124
1125 enable_irq(dp->irq);
1126 1328
1329 exynos_dp_dpms(display, DRM_MODE_DPMS_ON);
1127 return 0; 1330 return 0;
1128} 1331}
1129#endif 1332#endif
@@ -1136,9 +1339,8 @@ static const struct of_device_id exynos_dp_match[] = {
1136 { .compatible = "samsung,exynos5-dp" }, 1339 { .compatible = "samsung,exynos5-dp" },
1137 {}, 1340 {},
1138}; 1341};
1139MODULE_DEVICE_TABLE(of, exynos_dp_match);
1140 1342
1141static struct platform_driver exynos_dp_driver = { 1343struct platform_driver dp_driver = {
1142 .probe = exynos_dp_probe, 1344 .probe = exynos_dp_probe,
1143 .remove = exynos_dp_remove, 1345 .remove = exynos_dp_remove,
1144 .driver = { 1346 .driver = {
@@ -1149,8 +1351,6 @@ static struct platform_driver exynos_dp_driver = {
1149 }, 1351 },
1150}; 1352};
1151 1353
1152module_platform_driver(exynos_dp_driver);
1153
1154MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); 1354MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1155MODULE_DESCRIPTION("Samsung SoC DP Driver"); 1355MODULE_DESCRIPTION("Samsung SoC DP Driver");
1156MODULE_LICENSE("GPL"); 1356MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 607e36d0c147..d6a900d4ee40 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -13,6 +13,9 @@
13#ifndef _EXYNOS_DP_CORE_H 13#ifndef _EXYNOS_DP_CORE_H
14#define _EXYNOS_DP_CORE_H 14#define _EXYNOS_DP_CORE_H
15 15
16#include <drm/drm_crtc.h>
17#include <drm/exynos_drm.h>
18
16#define DP_TIMEOUT_LOOP_COUNT 100 19#define DP_TIMEOUT_LOOP_COUNT 100
17#define MAX_CR_LOOP 5 20#define MAX_CR_LOOP 5
18#define MAX_EQ_LOOP 5 21#define MAX_EQ_LOOP 5
@@ -142,6 +145,9 @@ struct link_train {
142 145
143struct exynos_dp_device { 146struct exynos_dp_device {
144 struct device *dev; 147 struct device *dev;
148 struct drm_device *drm_dev;
149 struct drm_connector connector;
150 struct drm_encoder *encoder;
145 struct clk *clock; 151 struct clk *clock;
146 unsigned int irq; 152 unsigned int irq;
147 void __iomem *reg_base; 153 void __iomem *reg_base;
@@ -152,6 +158,9 @@ struct exynos_dp_device {
152 struct link_train link_train; 158 struct link_train link_train;
153 struct work_struct hotplug_work; 159 struct work_struct hotplug_work;
154 struct phy *phy; 160 struct phy *phy;
161 int dpms_mode;
162
163 struct exynos_drm_panel_info panel;
155}; 164};
156 165
157/* exynos_dp_reg.c */ 166/* exynos_dp_reg.c */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c
index b70da5052ff0..b70da5052ff0 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/gpu/drm/exynos/exynos_dp_reg.h
index 2e9bd0e0b9f2..2e9bd0e0b9f2 100644
--- a/drivers/video/exynos/exynos_dp_reg.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_reg.h
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index e082efb2fece..9a16dbe121d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -23,27 +23,20 @@
23 drm_connector) 23 drm_connector)
24 24
25struct exynos_drm_connector { 25struct exynos_drm_connector {
26 struct drm_connector drm_connector; 26 struct drm_connector drm_connector;
27 uint32_t encoder_id; 27 uint32_t encoder_id;
28 struct exynos_drm_manager *manager; 28 struct exynos_drm_display *display;
29 uint32_t dpms;
30}; 29};
31 30
32static int exynos_drm_connector_get_modes(struct drm_connector *connector) 31static int exynos_drm_connector_get_modes(struct drm_connector *connector)
33{ 32{
34 struct exynos_drm_connector *exynos_connector = 33 struct exynos_drm_connector *exynos_connector =
35 to_exynos_connector(connector); 34 to_exynos_connector(connector);
36 struct exynos_drm_manager *manager = exynos_connector->manager; 35 struct exynos_drm_display *display = exynos_connector->display;
37 struct exynos_drm_display_ops *display_ops = manager->display_ops;
38 struct edid *edid = NULL; 36 struct edid *edid = NULL;
39 unsigned int count = 0; 37 unsigned int count = 0;
40 int ret; 38 int ret;
41 39
42 if (!display_ops) {
43 DRM_DEBUG_KMS("display_ops is null.\n");
44 return 0;
45 }
46
47 /* 40 /*
48 * if get_edid() exists then get_edid() callback of hdmi side 41 * if get_edid() exists then get_edid() callback of hdmi side
49 * is called to get edid data through i2c interface else 42 * is called to get edid data through i2c interface else
@@ -52,8 +45,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
52 * P.S. in case of lcd panel, count is always 1 if success 45 * P.S. in case of lcd panel, count is always 1 if success
53 * because lcd panel has only one mode. 46 * because lcd panel has only one mode.
54 */ 47 */
55 if (display_ops->get_edid) { 48 if (display->ops->get_edid) {
56 edid = display_ops->get_edid(manager->dev, connector); 49 edid = display->ops->get_edid(display, connector);
57 if (IS_ERR_OR_NULL(edid)) { 50 if (IS_ERR_OR_NULL(edid)) {
58 ret = PTR_ERR(edid); 51 ret = PTR_ERR(edid);
59 edid = NULL; 52 edid = NULL;
@@ -76,8 +69,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
76 return 0; 69 return 0;
77 } 70 }
78 71
79 if (display_ops->get_panel) 72 if (display->ops->get_panel)
80 panel = display_ops->get_panel(manager->dev); 73 panel = display->ops->get_panel(display);
81 else { 74 else {
82 drm_mode_destroy(connector->dev, mode); 75 drm_mode_destroy(connector->dev, mode);
83 return 0; 76 return 0;
@@ -106,20 +99,20 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
106{ 99{
107 struct exynos_drm_connector *exynos_connector = 100 struct exynos_drm_connector *exynos_connector =
108 to_exynos_connector(connector); 101 to_exynos_connector(connector);
109 struct exynos_drm_manager *manager = exynos_connector->manager; 102 struct exynos_drm_display *display = exynos_connector->display;
110 struct exynos_drm_display_ops *display_ops = manager->display_ops;
111 int ret = MODE_BAD; 103 int ret = MODE_BAD;
112 104
113 DRM_DEBUG_KMS("%s\n", __FILE__); 105 DRM_DEBUG_KMS("%s\n", __FILE__);
114 106
115 if (display_ops && display_ops->check_mode) 107 if (display->ops->check_mode)
116 if (!display_ops->check_mode(manager->dev, mode)) 108 if (!display->ops->check_mode(display, mode))
117 ret = MODE_OK; 109 ret = MODE_OK;
118 110
119 return ret; 111 return ret;
120} 112}
121 113
122struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) 114static struct drm_encoder *exynos_drm_best_encoder(
115 struct drm_connector *connector)
123{ 116{
124 struct drm_device *dev = connector->dev; 117 struct drm_device *dev = connector->dev;
125 struct exynos_drm_connector *exynos_connector = 118 struct exynos_drm_connector *exynos_connector =
@@ -146,48 +139,12 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
146 .best_encoder = exynos_drm_best_encoder, 139 .best_encoder = exynos_drm_best_encoder,
147}; 140};
148 141
149void exynos_drm_display_power(struct drm_connector *connector, int mode)
150{
151 struct drm_encoder *encoder = exynos_drm_best_encoder(connector);
152 struct exynos_drm_connector *exynos_connector;
153 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
154 struct exynos_drm_display_ops *display_ops = manager->display_ops;
155
156 exynos_connector = to_exynos_connector(connector);
157
158 if (exynos_connector->dpms == mode) {
159 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
160 return;
161 }
162
163 if (display_ops && display_ops->power_on)
164 display_ops->power_on(manager->dev, mode);
165
166 exynos_connector->dpms = mode;
167}
168
169static void exynos_drm_connector_dpms(struct drm_connector *connector,
170 int mode)
171{
172 /*
173 * in case that drm_crtc_helper_set_mode() is called,
174 * encoder/crtc->funcs->dpms() will be just returned
175 * because they already were DRM_MODE_DPMS_ON so only
176 * exynos_drm_display_power() will be called.
177 */
178 drm_helper_connector_dpms(connector, mode);
179
180 exynos_drm_display_power(connector, mode);
181
182}
183
184static int exynos_drm_connector_fill_modes(struct drm_connector *connector, 142static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
185 unsigned int max_width, unsigned int max_height) 143 unsigned int max_width, unsigned int max_height)
186{ 144{
187 struct exynos_drm_connector *exynos_connector = 145 struct exynos_drm_connector *exynos_connector =
188 to_exynos_connector(connector); 146 to_exynos_connector(connector);
189 struct exynos_drm_manager *manager = exynos_connector->manager; 147 struct exynos_drm_display *display = exynos_connector->display;
190 struct exynos_drm_manager_ops *ops = manager->ops;
191 unsigned int width, height; 148 unsigned int width, height;
192 149
193 width = max_width; 150 width = max_width;
@@ -197,8 +154,8 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
197 * if specific driver want to find desired_mode using maxmum 154 * if specific driver want to find desired_mode using maxmum
198 * resolution then get max width and height from that driver. 155 * resolution then get max width and height from that driver.
199 */ 156 */
200 if (ops && ops->get_max_resol) 157 if (display->ops->get_max_resol)
201 ops->get_max_resol(manager->dev, &width, &height); 158 display->ops->get_max_resol(display, &width, &height);
202 159
203 return drm_helper_probe_single_connector_modes(connector, width, 160 return drm_helper_probe_single_connector_modes(connector, width,
204 height); 161 height);
@@ -210,13 +167,11 @@ exynos_drm_connector_detect(struct drm_connector *connector, bool force)
210{ 167{
211 struct exynos_drm_connector *exynos_connector = 168 struct exynos_drm_connector *exynos_connector =
212 to_exynos_connector(connector); 169 to_exynos_connector(connector);
213 struct exynos_drm_manager *manager = exynos_connector->manager; 170 struct exynos_drm_display *display = exynos_connector->display;
214 struct exynos_drm_display_ops *display_ops =
215 manager->display_ops;
216 enum drm_connector_status status = connector_status_disconnected; 171 enum drm_connector_status status = connector_status_disconnected;
217 172
218 if (display_ops && display_ops->is_connected) { 173 if (display->ops->is_connected) {
219 if (display_ops->is_connected(manager->dev)) 174 if (display->ops->is_connected(display))
220 status = connector_status_connected; 175 status = connector_status_connected;
221 else 176 else
222 status = connector_status_disconnected; 177 status = connector_status_disconnected;
@@ -236,7 +191,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
236} 191}
237 192
238static struct drm_connector_funcs exynos_connector_funcs = { 193static struct drm_connector_funcs exynos_connector_funcs = {
239 .dpms = exynos_drm_connector_dpms, 194 .dpms = drm_helper_connector_dpms,
240 .fill_modes = exynos_drm_connector_fill_modes, 195 .fill_modes = exynos_drm_connector_fill_modes,
241 .detect = exynos_drm_connector_detect, 196 .detect = exynos_drm_connector_detect,
242 .destroy = exynos_drm_connector_destroy, 197 .destroy = exynos_drm_connector_destroy,
@@ -246,7 +201,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
246 struct drm_encoder *encoder) 201 struct drm_encoder *encoder)
247{ 202{
248 struct exynos_drm_connector *exynos_connector; 203 struct exynos_drm_connector *exynos_connector;
249 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); 204 struct exynos_drm_display *display = exynos_drm_get_display(encoder);
250 struct drm_connector *connector; 205 struct drm_connector *connector;
251 int type; 206 int type;
252 int err; 207 int err;
@@ -257,7 +212,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
257 212
258 connector = &exynos_connector->drm_connector; 213 connector = &exynos_connector->drm_connector;
259 214
260 switch (manager->display_ops->type) { 215 switch (display->type) {
261 case EXYNOS_DISPLAY_TYPE_HDMI: 216 case EXYNOS_DISPLAY_TYPE_HDMI:
262 type = DRM_MODE_CONNECTOR_HDMIA; 217 type = DRM_MODE_CONNECTOR_HDMIA;
263 connector->interlace_allowed = true; 218 connector->interlace_allowed = true;
@@ -280,8 +235,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
280 goto err_connector; 235 goto err_connector;
281 236
282 exynos_connector->encoder_id = encoder->base.id; 237 exynos_connector->encoder_id = encoder->base.id;
283 exynos_connector->manager = manager; 238 exynos_connector->display = display;
284 exynos_connector->dpms = DRM_MODE_DPMS_OFF;
285 connector->dpms = DRM_MODE_DPMS_OFF; 239 connector->dpms = DRM_MODE_DPMS_OFF;
286 connector->encoder = encoder; 240 connector->encoder = encoder;
287 241
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
index 547c6b590357..4eb20d78379a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.h
@@ -17,8 +17,4 @@
17struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, 17struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
18 struct drm_encoder *encoder); 18 struct drm_encoder *encoder);
19 19
20struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector);
21
22void exynos_drm_display_power(struct drm_connector *connector, int mode);
23
24#endif 20#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 1bef6dc77478..0e9e06ce36b8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -14,43 +14,42 @@
14 14
15#include <drm/drmP.h> 15#include <drm/drmP.h>
16#include "exynos_drm_drv.h" 16#include "exynos_drm_drv.h"
17#include "exynos_drm_crtc.h"
17#include "exynos_drm_encoder.h" 18#include "exynos_drm_encoder.h"
18#include "exynos_drm_connector.h"
19#include "exynos_drm_fbdev.h" 19#include "exynos_drm_fbdev.h"
20 20
21static LIST_HEAD(exynos_drm_subdrv_list); 21static LIST_HEAD(exynos_drm_subdrv_list);
22static LIST_HEAD(exynos_drm_manager_list);
23static LIST_HEAD(exynos_drm_display_list);
22 24
23static int exynos_drm_create_enc_conn(struct drm_device *dev, 25static int exynos_drm_create_enc_conn(struct drm_device *dev,
24 struct exynos_drm_subdrv *subdrv) 26 struct exynos_drm_display *display)
25{ 27{
26 struct drm_encoder *encoder; 28 struct drm_encoder *encoder;
27 struct drm_connector *connector; 29 struct exynos_drm_manager *manager;
28 int ret; 30 int ret;
31 unsigned long possible_crtcs = 0;
29 32
30 subdrv->manager->dev = subdrv->dev; 33 /* Find possible crtcs for this display */
34 list_for_each_entry(manager, &exynos_drm_manager_list, list)
35 if (manager->type == display->type)
36 possible_crtcs |= 1 << manager->pipe;
31 37
32 /* create and initialize a encoder for this sub driver. */ 38 /* create and initialize a encoder for this sub driver. */
33 encoder = exynos_drm_encoder_create(dev, subdrv->manager, 39 encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
34 (1 << MAX_CRTC) - 1);
35 if (!encoder) { 40 if (!encoder) {
36 DRM_ERROR("failed to create encoder\n"); 41 DRM_ERROR("failed to create encoder\n");
37 return -EFAULT; 42 return -EFAULT;
38 } 43 }
39 44
40 /* 45 display->encoder = encoder;
41 * create and initialize a connector for this sub driver and 46
42 * attach the encoder created above to the connector. 47 ret = display->ops->create_connector(display, encoder);
43 */ 48 if (ret) {
44 connector = exynos_drm_connector_create(dev, encoder); 49 DRM_ERROR("failed to create connector ret = %d\n", ret);
45 if (!connector) {
46 DRM_ERROR("failed to create connector\n");
47 ret = -EFAULT;
48 goto err_destroy_encoder; 50 goto err_destroy_encoder;
49 } 51 }
50 52
51 subdrv->encoder = encoder;
52 subdrv->connector = connector;
53
54 return 0; 53 return 0;
55 54
56err_destroy_encoder: 55err_destroy_encoder:
@@ -58,21 +57,6 @@ err_destroy_encoder:
58 return ret; 57 return ret;
59} 58}
60 59
61static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
62{
63 if (subdrv->encoder) {
64 struct drm_encoder *encoder = subdrv->encoder;
65 encoder->funcs->destroy(encoder);
66 subdrv->encoder = NULL;
67 }
68
69 if (subdrv->connector) {
70 struct drm_connector *connector = subdrv->connector;
71 connector->funcs->destroy(connector);
72 subdrv->connector = NULL;
73 }
74}
75
76static int exynos_drm_subdrv_probe(struct drm_device *dev, 60static int exynos_drm_subdrv_probe(struct drm_device *dev,
77 struct exynos_drm_subdrv *subdrv) 61 struct exynos_drm_subdrv *subdrv)
78{ 62{
@@ -104,10 +88,98 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
104 subdrv->remove(dev, subdrv->dev); 88 subdrv->remove(dev, subdrv->dev);
105} 89}
106 90
91int exynos_drm_initialize_managers(struct drm_device *dev)
92{
93 struct exynos_drm_manager *manager, *n;
94 int ret, pipe = 0;
95
96 list_for_each_entry(manager, &exynos_drm_manager_list, list) {
97 if (manager->ops->initialize) {
98 ret = manager->ops->initialize(manager, dev, pipe);
99 if (ret) {
100 DRM_ERROR("Mgr init [%d] failed with %d\n",
101 manager->type, ret);
102 goto err;
103 }
104 }
105
106 manager->drm_dev = dev;
107 manager->pipe = pipe++;
108
109 ret = exynos_drm_crtc_create(manager);
110 if (ret) {
111 DRM_ERROR("CRTC create [%d] failed with %d\n",
112 manager->type, ret);
113 goto err;
114 }
115 }
116 return 0;
117
118err:
119 list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) {
120 if (pipe-- > 0)
121 exynos_drm_manager_unregister(manager);
122 else
123 list_del(&manager->list);
124 }
125 return ret;
126}
127
128void exynos_drm_remove_managers(struct drm_device *dev)
129{
130 struct exynos_drm_manager *manager, *n;
131
132 list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list)
133 exynos_drm_manager_unregister(manager);
134}
135
136int exynos_drm_initialize_displays(struct drm_device *dev)
137{
138 struct exynos_drm_display *display, *n;
139 int ret, initialized = 0;
140
141 list_for_each_entry(display, &exynos_drm_display_list, list) {
142 if (display->ops->initialize) {
143 ret = display->ops->initialize(display, dev);
144 if (ret) {
145 DRM_ERROR("Display init [%d] failed with %d\n",
146 display->type, ret);
147 goto err;
148 }
149 }
150
151 initialized++;
152
153 ret = exynos_drm_create_enc_conn(dev, display);
154 if (ret) {
155 DRM_ERROR("Encoder create [%d] failed with %d\n",
156 display->type, ret);
157 goto err;
158 }
159 }
160 return 0;
161
162err:
163 list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) {
164 if (initialized-- > 0)
165 exynos_drm_display_unregister(display);
166 else
167 list_del(&display->list);
168 }
169 return ret;
170}
171
172void exynos_drm_remove_displays(struct drm_device *dev)
173{
174 struct exynos_drm_display *display, *n;
175
176 list_for_each_entry_safe(display, n, &exynos_drm_display_list, list)
177 exynos_drm_display_unregister(display);
178}
179
107int exynos_drm_device_register(struct drm_device *dev) 180int exynos_drm_device_register(struct drm_device *dev)
108{ 181{
109 struct exynos_drm_subdrv *subdrv, *n; 182 struct exynos_drm_subdrv *subdrv, *n;
110 unsigned int fine_cnt = 0;
111 int err; 183 int err;
112 184
113 if (!dev) 185 if (!dev)
@@ -120,30 +192,8 @@ int exynos_drm_device_register(struct drm_device *dev)
120 list_del(&subdrv->list); 192 list_del(&subdrv->list);
121 continue; 193 continue;
122 } 194 }
123
124 /*
125 * if manager is null then it means that this sub driver
126 * doesn't need encoder and connector.
127 */
128 if (!subdrv->manager) {
129 fine_cnt++;
130 continue;
131 }
132
133 err = exynos_drm_create_enc_conn(dev, subdrv);
134 if (err) {
135 DRM_DEBUG("failed to create encoder and connector.\n");
136 exynos_drm_subdrv_remove(dev, subdrv);
137 list_del(&subdrv->list);
138 continue;
139 }
140
141 fine_cnt++;
142 } 195 }
143 196
144 if (!fine_cnt)
145 return -EINVAL;
146
147 return 0; 197 return 0;
148} 198}
149EXPORT_SYMBOL_GPL(exynos_drm_device_register); 199EXPORT_SYMBOL_GPL(exynos_drm_device_register);
@@ -159,13 +209,44 @@ int exynos_drm_device_unregister(struct drm_device *dev)
159 209
160 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { 210 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
161 exynos_drm_subdrv_remove(dev, subdrv); 211 exynos_drm_subdrv_remove(dev, subdrv);
162 exynos_drm_destroy_enc_conn(subdrv);
163 } 212 }
164 213
165 return 0; 214 return 0;
166} 215}
167EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); 216EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
168 217
218int exynos_drm_manager_register(struct exynos_drm_manager *manager)
219{
220 BUG_ON(!manager->ops);
221 list_add_tail(&manager->list, &exynos_drm_manager_list);
222 return 0;
223}
224
225int exynos_drm_manager_unregister(struct exynos_drm_manager *manager)
226{
227 if (manager->ops->remove)
228 manager->ops->remove(manager);
229
230 list_del(&manager->list);
231 return 0;
232}
233
234int exynos_drm_display_register(struct exynos_drm_display *display)
235{
236 BUG_ON(!display->ops);
237 list_add_tail(&display->list, &exynos_drm_display_list);
238 return 0;
239}
240
241int exynos_drm_display_unregister(struct exynos_drm_display *display)
242{
243 if (display->ops->remove)
244 display->ops->remove(display);
245
246 list_del(&display->list);
247 return 0;
248}
249
169int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) 250int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
170{ 251{
171 if (!subdrv) 252 if (!subdrv)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 6f3400f3978a..e930d4fe29c7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -33,6 +33,7 @@ enum exynos_crtc_mode {
33 * 33 *
34 * @drm_crtc: crtc object. 34 * @drm_crtc: crtc object.
35 * @drm_plane: pointer of private plane object for this crtc 35 * @drm_plane: pointer of private plane object for this crtc
36 * @manager: the manager associated with this crtc
36 * @pipe: a crtc index created at load() with a new crtc object creation 37 * @pipe: a crtc index created at load() with a new crtc object creation
37 * and the crtc object would be set to private->crtc array 38 * and the crtc object would be set to private->crtc array
38 * to get a crtc object corresponding to this pipe from private->crtc 39 * to get a crtc object corresponding to this pipe from private->crtc
@@ -46,6 +47,7 @@ enum exynos_crtc_mode {
46struct exynos_drm_crtc { 47struct exynos_drm_crtc {
47 struct drm_crtc drm_crtc; 48 struct drm_crtc drm_crtc;
48 struct drm_plane *plane; 49 struct drm_plane *plane;
50 struct exynos_drm_manager *manager;
49 unsigned int pipe; 51 unsigned int pipe;
50 unsigned int dpms; 52 unsigned int dpms;
51 enum exynos_crtc_mode mode; 53 enum exynos_crtc_mode mode;
@@ -56,6 +58,7 @@ struct exynos_drm_crtc {
56static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 58static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
57{ 59{
58 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 60 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
61 struct exynos_drm_manager *manager = exynos_crtc->manager;
59 62
60 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 63 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
61 64
@@ -71,7 +74,9 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
71 drm_vblank_off(crtc->dev, exynos_crtc->pipe); 74 drm_vblank_off(crtc->dev, exynos_crtc->pipe);
72 } 75 }
73 76
74 exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); 77 if (manager->ops->dpms)
78 manager->ops->dpms(manager, mode);
79
75 exynos_crtc->dpms = mode; 80 exynos_crtc->dpms = mode;
76} 81}
77 82
@@ -83,9 +88,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
83static void exynos_drm_crtc_commit(struct drm_crtc *crtc) 88static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
84{ 89{
85 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 90 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
91 struct exynos_drm_manager *manager = exynos_crtc->manager;
86 92
87 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 93 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
94
88 exynos_plane_commit(exynos_crtc->plane); 95 exynos_plane_commit(exynos_crtc->plane);
96
97 if (manager->ops->commit)
98 manager->ops->commit(manager);
99
89 exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); 100 exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
90} 101}
91 102
@@ -94,7 +105,12 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
94 const struct drm_display_mode *mode, 105 const struct drm_display_mode *mode,
95 struct drm_display_mode *adjusted_mode) 106 struct drm_display_mode *adjusted_mode)
96{ 107{
97 /* drm framework doesn't check NULL */ 108 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
109 struct exynos_drm_manager *manager = exynos_crtc->manager;
110
111 if (manager->ops->mode_fixup)
112 return manager->ops->mode_fixup(manager, mode, adjusted_mode);
113
98 return true; 114 return true;
99} 115}
100 116
@@ -104,10 +120,10 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
104 struct drm_framebuffer *old_fb) 120 struct drm_framebuffer *old_fb)
105{ 121{
106 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 122 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
123 struct exynos_drm_manager *manager = exynos_crtc->manager;
107 struct drm_plane *plane = exynos_crtc->plane; 124 struct drm_plane *plane = exynos_crtc->plane;
108 unsigned int crtc_w; 125 unsigned int crtc_w;
109 unsigned int crtc_h; 126 unsigned int crtc_h;
110 int pipe = exynos_crtc->pipe;
111 int ret; 127 int ret;
112 128
113 /* 129 /*
@@ -116,18 +132,19 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
116 */ 132 */
117 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); 133 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
118 134
119 crtc_w = crtc->fb->width - x; 135 crtc_w = crtc->primary->fb->width - x;
120 crtc_h = crtc->fb->height - y; 136 crtc_h = crtc->primary->fb->height - y;
137
138 if (manager->ops->mode_set)
139 manager->ops->mode_set(manager, &crtc->mode);
121 140
122 ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, 141 ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h,
123 x, y, crtc_w, crtc_h); 142 x, y, crtc_w, crtc_h);
124 if (ret) 143 if (ret)
125 return ret; 144 return ret;
126 145
127 plane->crtc = crtc; 146 plane->crtc = crtc;
128 plane->fb = crtc->fb; 147 plane->fb = crtc->primary->fb;
129
130 exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe);
131 148
132 return 0; 149 return 0;
133} 150}
@@ -147,10 +164,10 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
147 return -EPERM; 164 return -EPERM;
148 } 165 }
149 166
150 crtc_w = crtc->fb->width - x; 167 crtc_w = crtc->primary->fb->width - x;
151 crtc_h = crtc->fb->height - y; 168 crtc_h = crtc->primary->fb->height - y;
152 169
153 ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, 170 ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h,
154 x, y, crtc_w, crtc_h); 171 x, y, crtc_w, crtc_h);
155 if (ret) 172 if (ret)
156 return ret; 173 return ret;
@@ -168,10 +185,19 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
168 185
169static void exynos_drm_crtc_disable(struct drm_crtc *crtc) 186static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
170{ 187{
171 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 188 struct drm_plane *plane;
189 int ret;
172 190
173 exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
174 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 191 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
192
193 drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) {
194 if (plane->crtc != crtc)
195 continue;
196
197 ret = plane->funcs->disable_plane(plane);
198 if (ret)
199 DRM_ERROR("Failed to disable plane %d\n", ret);
200 }
175} 201}
176 202
177static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { 203static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
@@ -192,7 +218,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
192 struct drm_device *dev = crtc->dev; 218 struct drm_device *dev = crtc->dev;
193 struct exynos_drm_private *dev_priv = dev->dev_private; 219 struct exynos_drm_private *dev_priv = dev->dev_private;
194 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 220 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
195 struct drm_framebuffer *old_fb = crtc->fb; 221 struct drm_framebuffer *old_fb = crtc->primary->fb;
196 int ret = -EINVAL; 222 int ret = -EINVAL;
197 223
198 /* when the page flip is requested, crtc's dpms should be on */ 224 /* when the page flip is requested, crtc's dpms should be on */
@@ -223,11 +249,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
223 atomic_set(&exynos_crtc->pending_flip, 1); 249 atomic_set(&exynos_crtc->pending_flip, 1);
224 spin_unlock_irq(&dev->event_lock); 250 spin_unlock_irq(&dev->event_lock);
225 251
226 crtc->fb = fb; 252 crtc->primary->fb = fb;
227 ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y, 253 ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
228 NULL); 254 NULL);
229 if (ret) { 255 if (ret) {
230 crtc->fb = old_fb; 256 crtc->primary->fb = old_fb;
231 257
232 spin_lock_irq(&dev->event_lock); 258 spin_lock_irq(&dev->event_lock);
233 drm_vblank_put(dev, exynos_crtc->pipe); 259 drm_vblank_put(dev, exynos_crtc->pipe);
@@ -318,21 +344,24 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
318 drm_object_attach_property(&crtc->base, prop, 0); 344 drm_object_attach_property(&crtc->base, prop, 0);
319} 345}
320 346
321int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) 347int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
322{ 348{
323 struct exynos_drm_crtc *exynos_crtc; 349 struct exynos_drm_crtc *exynos_crtc;
324 struct exynos_drm_private *private = dev->dev_private; 350 struct exynos_drm_private *private = manager->drm_dev->dev_private;
325 struct drm_crtc *crtc; 351 struct drm_crtc *crtc;
326 352
327 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); 353 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
328 if (!exynos_crtc) 354 if (!exynos_crtc)
329 return -ENOMEM; 355 return -ENOMEM;
330 356
331 exynos_crtc->pipe = nr;
332 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
333 init_waitqueue_head(&exynos_crtc->pending_flip_queue); 357 init_waitqueue_head(&exynos_crtc->pending_flip_queue);
334 atomic_set(&exynos_crtc->pending_flip, 0); 358 atomic_set(&exynos_crtc->pending_flip, 0);
335 exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); 359
360 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
361 exynos_crtc->manager = manager;
362 exynos_crtc->pipe = manager->pipe;
363 exynos_crtc->plane = exynos_plane_init(manager->drm_dev,
364 1 << manager->pipe, true);
336 if (!exynos_crtc->plane) { 365 if (!exynos_crtc->plane) {
337 kfree(exynos_crtc); 366 kfree(exynos_crtc);
338 return -ENOMEM; 367 return -ENOMEM;
@@ -340,9 +369,9 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
340 369
341 crtc = &exynos_crtc->drm_crtc; 370 crtc = &exynos_crtc->drm_crtc;
342 371
343 private->crtc[nr] = crtc; 372 private->crtc[manager->pipe] = crtc;
344 373
345 drm_crtc_init(dev, crtc, &exynos_crtc_funcs); 374 drm_crtc_init(manager->drm_dev, crtc, &exynos_crtc_funcs);
346 drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); 375 drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
347 376
348 exynos_drm_crtc_attach_mode_property(crtc); 377 exynos_drm_crtc_attach_mode_property(crtc);
@@ -350,39 +379,41 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
350 return 0; 379 return 0;
351} 380}
352 381
353int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) 382int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
354{ 383{
355 struct exynos_drm_private *private = dev->dev_private; 384 struct exynos_drm_private *private = dev->dev_private;
356 struct exynos_drm_crtc *exynos_crtc = 385 struct exynos_drm_crtc *exynos_crtc =
357 to_exynos_crtc(private->crtc[crtc]); 386 to_exynos_crtc(private->crtc[pipe]);
387 struct exynos_drm_manager *manager = exynos_crtc->manager;
358 388
359 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 389 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
360 return -EPERM; 390 return -EPERM;
361 391
362 exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 392 if (manager->ops->enable_vblank)
363 exynos_drm_enable_vblank); 393 manager->ops->enable_vblank(manager);
364 394
365 return 0; 395 return 0;
366} 396}
367 397
368void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) 398void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
369{ 399{
370 struct exynos_drm_private *private = dev->dev_private; 400 struct exynos_drm_private *private = dev->dev_private;
371 struct exynos_drm_crtc *exynos_crtc = 401 struct exynos_drm_crtc *exynos_crtc =
372 to_exynos_crtc(private->crtc[crtc]); 402 to_exynos_crtc(private->crtc[pipe]);
403 struct exynos_drm_manager *manager = exynos_crtc->manager;
373 404
374 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 405 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
375 return; 406 return;
376 407
377 exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 408 if (manager->ops->disable_vblank)
378 exynos_drm_disable_vblank); 409 manager->ops->disable_vblank(manager);
379} 410}
380 411
381void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) 412void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
382{ 413{
383 struct exynos_drm_private *dev_priv = dev->dev_private; 414 struct exynos_drm_private *dev_priv = dev->dev_private;
384 struct drm_pending_vblank_event *e, *t; 415 struct drm_pending_vblank_event *e, *t;
385 struct drm_crtc *drm_crtc = dev_priv->crtc[crtc]; 416 struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
386 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); 417 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
387 unsigned long flags; 418 unsigned long flags;
388 419
@@ -391,15 +422,71 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
391 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, 422 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
392 base.link) { 423 base.link) {
393 /* if event's pipe isn't same as crtc then ignore it. */ 424 /* if event's pipe isn't same as crtc then ignore it. */
394 if (crtc != e->pipe) 425 if (pipe != e->pipe)
395 continue; 426 continue;
396 427
397 list_del(&e->base.link); 428 list_del(&e->base.link);
398 drm_send_vblank_event(dev, -1, e); 429 drm_send_vblank_event(dev, -1, e);
399 drm_vblank_put(dev, crtc); 430 drm_vblank_put(dev, pipe);
400 atomic_set(&exynos_crtc->pending_flip, 0); 431 atomic_set(&exynos_crtc->pending_flip, 0);
401 wake_up(&exynos_crtc->pending_flip_queue); 432 wake_up(&exynos_crtc->pending_flip_queue);
402 } 433 }
403 434
404 spin_unlock_irqrestore(&dev->event_lock, flags); 435 spin_unlock_irqrestore(&dev->event_lock, flags);
405} 436}
437
438void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
439 struct exynos_drm_overlay *overlay)
440{
441 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
442
443 if (manager->ops->win_mode_set)
444 manager->ops->win_mode_set(manager, overlay);
445}
446
447void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
448{
449 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
450
451 if (manager->ops->win_commit)
452 manager->ops->win_commit(manager, zpos);
453}
454
455void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
456{
457 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
458
459 if (manager->ops->win_enable)
460 manager->ops->win_enable(manager, zpos);
461}
462
463void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
464{
465 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
466
467 if (manager->ops->win_disable)
468 manager->ops->win_disable(manager, zpos);
469}
470
471void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
472{
473 struct exynos_drm_manager *manager;
474 struct drm_device *dev = fb->dev;
475 struct drm_crtc *crtc;
476
477 /*
478 * make sure that overlay data are updated to real hardware
479 * for all encoders.
480 */
481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
482 manager = to_exynos_crtc(crtc)->manager;
483
484 /*
485 * wait for vblank interrupt
486 * - this makes sure that overlay data are updated to
487 * real hardware.
488 */
489 if (manager->ops->wait_for_vblank)
490 manager->ops->wait_for_vblank(manager);
491 }
492}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 3e197e6ae7d9..c27b66cc5d24 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -15,9 +15,21 @@
15#ifndef _EXYNOS_DRM_CRTC_H_ 15#ifndef _EXYNOS_DRM_CRTC_H_
16#define _EXYNOS_DRM_CRTC_H_ 16#define _EXYNOS_DRM_CRTC_H_
17 17
18int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); 18struct drm_device;
19int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); 19struct drm_crtc;
20void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); 20struct exynos_drm_manager;
21void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc); 21struct exynos_drm_overlay;
22
23int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
24int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
25void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
26void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
27void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
28
29void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
30 struct exynos_drm_overlay *overlay);
31void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
32void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
33void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
22 34
23#endif 35#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
new file mode 100644
index 000000000000..2b09c7c0bfcc
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -0,0 +1,339 @@
1/*
2 * Exynos DRM Parallel output support.
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 *
6 * Contacts: Andrzej Hajda <a.hajda@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <drm/drmP.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_panel.h>
16
17#include <linux/regulator/consumer.h>
18
19#include <video/of_videomode.h>
20#include <video/videomode.h>
21
22#include "exynos_drm_drv.h"
23
24struct exynos_dpi {
25 struct device *dev;
26 struct device_node *panel_node;
27
28 struct drm_panel *panel;
29 struct drm_connector connector;
30 struct drm_encoder *encoder;
31
32 struct videomode *vm;
33 int dpms_mode;
34};
35
36#define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector)
37
38static enum drm_connector_status
39exynos_dpi_detect(struct drm_connector *connector, bool force)
40{
41 struct exynos_dpi *ctx = connector_to_dpi(connector);
42
43 /* panels supported only by boot-loader are always connected */
44 if (!ctx->panel_node)
45 return connector_status_connected;
46
47 if (!ctx->panel) {
48 ctx->panel = of_drm_find_panel(ctx->panel_node);
49 if (ctx->panel)
50 drm_panel_attach(ctx->panel, &ctx->connector);
51 }
52
53 if (ctx->panel)
54 return connector_status_connected;
55
56 return connector_status_disconnected;
57}
58
59static void exynos_dpi_connector_destroy(struct drm_connector *connector)
60{
61 drm_sysfs_connector_remove(connector);
62 drm_connector_cleanup(connector);
63}
64
65static struct drm_connector_funcs exynos_dpi_connector_funcs = {
66 .dpms = drm_helper_connector_dpms,
67 .detect = exynos_dpi_detect,
68 .fill_modes = drm_helper_probe_single_connector_modes,
69 .destroy = exynos_dpi_connector_destroy,
70};
71
72static int exynos_dpi_get_modes(struct drm_connector *connector)
73{
74 struct exynos_dpi *ctx = connector_to_dpi(connector);
75
76 /* fimd timings gets precedence over panel modes */
77 if (ctx->vm) {
78 struct drm_display_mode *mode;
79
80 mode = drm_mode_create(connector->dev);
81 if (!mode) {
82 DRM_ERROR("failed to create a new display mode\n");
83 return 0;
84 }
85 drm_display_mode_from_videomode(ctx->vm, mode);
86 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
87 drm_mode_probed_add(connector, mode);
88 return 1;
89 }
90
91 if (ctx->panel)
92 return ctx->panel->funcs->get_modes(ctx->panel);
93
94 return 0;
95}
96
97static int exynos_dpi_mode_valid(struct drm_connector *connector,
98 struct drm_display_mode *mode)
99{
100 return MODE_OK;
101}
102
103static struct drm_encoder *
104exynos_dpi_best_encoder(struct drm_connector *connector)
105{
106 struct exynos_dpi *ctx = connector_to_dpi(connector);
107
108 return ctx->encoder;
109}
110
111static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
112 .get_modes = exynos_dpi_get_modes,
113 .mode_valid = exynos_dpi_mode_valid,
114 .best_encoder = exynos_dpi_best_encoder,
115};
116
117static int exynos_dpi_create_connector(struct exynos_drm_display *display,
118 struct drm_encoder *encoder)
119{
120 struct exynos_dpi *ctx = display->ctx;
121 struct drm_connector *connector = &ctx->connector;
122 int ret;
123
124 ctx->encoder = encoder;
125
126 if (ctx->panel_node)
127 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
128 else
129 connector->polled = DRM_CONNECTOR_POLL_HPD;
130
131 ret = drm_connector_init(encoder->dev, connector,
132 &exynos_dpi_connector_funcs,
133 DRM_MODE_CONNECTOR_VGA);
134 if (ret) {
135 DRM_ERROR("failed to initialize connector with drm\n");
136 return ret;
137 }
138
139 drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
140 drm_sysfs_connector_add(connector);
141 drm_mode_connector_attach_encoder(connector, encoder);
142
143 return 0;
144}
145
146static void exynos_dpi_poweron(struct exynos_dpi *ctx)
147{
148 if (ctx->panel)
149 drm_panel_enable(ctx->panel);
150}
151
152static void exynos_dpi_poweroff(struct exynos_dpi *ctx)
153{
154 if (ctx->panel)
155 drm_panel_disable(ctx->panel);
156}
157
158static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode)
159{
160 struct exynos_dpi *ctx = display->ctx;
161
162 switch (mode) {
163 case DRM_MODE_DPMS_ON:
164 if (ctx->dpms_mode != DRM_MODE_DPMS_ON)
165 exynos_dpi_poweron(ctx);
166 break;
167 case DRM_MODE_DPMS_STANDBY:
168 case DRM_MODE_DPMS_SUSPEND:
169 case DRM_MODE_DPMS_OFF:
170 if (ctx->dpms_mode == DRM_MODE_DPMS_ON)
171 exynos_dpi_poweroff(ctx);
172 break;
173 default:
174 break;
175 };
176 ctx->dpms_mode = mode;
177}
178
179static struct exynos_drm_display_ops exynos_dpi_display_ops = {
180 .create_connector = exynos_dpi_create_connector,
181 .dpms = exynos_dpi_dpms
182};
183
184static struct exynos_drm_display exynos_dpi_display = {
185 .type = EXYNOS_DISPLAY_TYPE_LCD,
186 .ops = &exynos_dpi_display_ops,
187};
188
189/* of_* functions will be removed after merge of of_graph patches */
190static struct device_node *
191of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
192{
193 struct device_node *np;
194
195 for_each_child_of_node(parent, np) {
196 u32 r;
197
198 if (!np->name || of_node_cmp(np->name, name))
199 continue;
200
201 if (of_property_read_u32(np, "reg", &r) < 0)
202 r = 0;
203
204 if (reg == r)
205 break;
206 }
207
208 return np;
209}
210
211static struct device_node *of_graph_get_port_by_reg(struct device_node *parent,
212 u32 reg)
213{
214 struct device_node *ports, *port;
215
216 ports = of_get_child_by_name(parent, "ports");
217 if (ports)
218 parent = ports;
219
220 port = of_get_child_by_name_reg(parent, "port", reg);
221
222 of_node_put(ports);
223
224 return port;
225}
226
227static struct device_node *
228of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg)
229{
230 return of_get_child_by_name_reg(port, "endpoint", reg);
231}
232
233static struct device_node *
234of_graph_get_remote_port_parent(const struct device_node *node)
235{
236 struct device_node *np;
237 unsigned int depth;
238
239 np = of_parse_phandle(node, "remote-endpoint", 0);
240
241 /* Walk 3 levels up only if there is 'ports' node. */
242 for (depth = 3; depth && np; depth--) {
243 np = of_get_next_parent(np);
244 if (depth == 2 && of_node_cmp(np->name, "ports"))
245 break;
246 }
247 return np;
248}
249
250enum {
251 FIMD_PORT_IN0,
252 FIMD_PORT_IN1,
253 FIMD_PORT_IN2,
254 FIMD_PORT_RGB,
255 FIMD_PORT_WRB,
256};
257
258static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev)
259{
260 struct device_node *np, *ep;
261
262 np = of_graph_get_port_by_reg(dev->of_node, FIMD_PORT_RGB);
263 if (!np)
264 return NULL;
265
266 ep = of_graph_get_endpoint_by_reg(np, 0);
267 of_node_put(np);
268 if (!ep)
269 return NULL;
270
271 np = of_graph_get_remote_port_parent(ep);
272 of_node_put(ep);
273
274 return np;
275}
276
277static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
278{
279 struct device *dev = ctx->dev;
280 struct device_node *dn = dev->of_node;
281 struct device_node *np;
282
283 ctx->panel_node = exynos_dpi_of_find_panel_node(dev);
284
285 np = of_get_child_by_name(dn, "display-timings");
286 if (np) {
287 struct videomode *vm;
288 int ret;
289
290 of_node_put(np);
291
292 vm = devm_kzalloc(dev, sizeof(*ctx->vm), GFP_KERNEL);
293 if (!vm)
294 return -ENOMEM;
295
296 ret = of_get_videomode(dn, vm, 0);
297 if (ret < 0)
298 return ret;
299
300 ctx->vm = vm;
301
302 return 0;
303 }
304
305 if (!ctx->panel_node)
306 return -EINVAL;
307
308 return 0;
309}
310
311int exynos_dpi_probe(struct device *dev)
312{
313 struct exynos_dpi *ctx;
314 int ret;
315
316 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
317 if (!ctx)
318 return -ENOMEM;
319
320 ctx->dev = dev;
321 exynos_dpi_display.ctx = ctx;
322 ctx->dpms_mode = DRM_MODE_DPMS_OFF;
323
324 ret = exynos_dpi_parse_dt(ctx);
325 if (ret < 0)
326 return ret;
327
328 exynos_drm_display_register(&exynos_dpi_display);
329
330 return 0;
331}
332
333int exynos_dpi_remove(struct device *dev)
334{
335 exynos_dpi_dpms(&exynos_dpi_display, DRM_MODE_DPMS_OFF);
336 exynos_drm_display_unregister(&exynos_dpi_display);
337
338 return 0;
339}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index c204b4e3356e..2d27ba23a6a8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -11,6 +11,7 @@
11 * option) any later version. 11 * option) any later version.
12 */ 12 */
13 13
14#include <linux/pm_runtime.h>
14#include <drm/drmP.h> 15#include <drm/drmP.h>
15#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
16 17
@@ -53,6 +54,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
53 return -ENOMEM; 54 return -ENOMEM;
54 55
55 INIT_LIST_HEAD(&private->pageflip_event_list); 56 INIT_LIST_HEAD(&private->pageflip_event_list);
57 dev_set_drvdata(dev->dev, dev);
56 dev->dev_private = (void *)private; 58 dev->dev_private = (void *)private;
57 59
58 /* 60 /*
@@ -64,38 +66,36 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
64 ret = drm_create_iommu_mapping(dev); 66 ret = drm_create_iommu_mapping(dev);
65 if (ret < 0) { 67 if (ret < 0) {
66 DRM_ERROR("failed to create iommu mapping.\n"); 68 DRM_ERROR("failed to create iommu mapping.\n");
67 goto err_crtc; 69 goto err_free_private;
68 } 70 }
69 71
70 drm_mode_config_init(dev); 72 drm_mode_config_init(dev);
71 73
72 /* init kms poll for handling hpd */
73 drm_kms_helper_poll_init(dev);
74
75 exynos_drm_mode_config_init(dev); 74 exynos_drm_mode_config_init(dev);
76 75
77 /* 76 ret = exynos_drm_initialize_managers(dev);
78 * EXYNOS4 is enough to have two CRTCs and each crtc would be used 77 if (ret)
79 * without dependency of hardware. 78 goto err_mode_config_cleanup;
80 */
81 for (nr = 0; nr < MAX_CRTC; nr++) {
82 ret = exynos_drm_crtc_create(dev, nr);
83 if (ret)
84 goto err_release_iommu_mapping;
85 }
86 79
87 for (nr = 0; nr < MAX_PLANE; nr++) { 80 for (nr = 0; nr < MAX_PLANE; nr++) {
88 struct drm_plane *plane; 81 struct drm_plane *plane;
89 unsigned int possible_crtcs = (1 << MAX_CRTC) - 1; 82 unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
90 83
91 plane = exynos_plane_init(dev, possible_crtcs, false); 84 plane = exynos_plane_init(dev, possible_crtcs, false);
92 if (!plane) 85 if (!plane)
93 goto err_release_iommu_mapping; 86 goto err_manager_cleanup;
94 } 87 }
95 88
89 ret = exynos_drm_initialize_displays(dev);
90 if (ret)
91 goto err_manager_cleanup;
92
93 /* init kms poll for handling hpd */
94 drm_kms_helper_poll_init(dev);
95
96 ret = drm_vblank_init(dev, MAX_CRTC); 96 ret = drm_vblank_init(dev, MAX_CRTC);
97 if (ret) 97 if (ret)
98 goto err_release_iommu_mapping; 98 goto err_display_cleanup;
99 99
100 /* 100 /*
101 * probe sub drivers such as display controller and hdmi driver, 101 * probe sub drivers such as display controller and hdmi driver,
@@ -109,30 +109,25 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
109 /* setup possible_clones. */ 109 /* setup possible_clones. */
110 exynos_drm_encoder_setup(dev); 110 exynos_drm_encoder_setup(dev);
111 111
112 /*
113 * create and configure fb helper and also exynos specific
114 * fbdev object.
115 */
116 ret = exynos_drm_fbdev_init(dev);
117 if (ret) {
118 DRM_ERROR("failed to initialize drm fbdev\n");
119 goto err_drm_device;
120 }
121
122 drm_vblank_offdelay = VBLANK_OFF_DELAY; 112 drm_vblank_offdelay = VBLANK_OFF_DELAY;
123 113
124 platform_set_drvdata(dev->platformdev, dev); 114 platform_set_drvdata(dev->platformdev, dev);
125 115
116 /* force connectors detection */
117 drm_helper_hpd_irq_event(dev);
118
126 return 0; 119 return 0;
127 120
128err_drm_device:
129 exynos_drm_device_unregister(dev);
130err_vblank: 121err_vblank:
131 drm_vblank_cleanup(dev); 122 drm_vblank_cleanup(dev);
132err_release_iommu_mapping: 123err_display_cleanup:
133 drm_release_iommu_mapping(dev); 124 exynos_drm_remove_displays(dev);
134err_crtc: 125err_manager_cleanup:
126 exynos_drm_remove_managers(dev);
127err_mode_config_cleanup:
135 drm_mode_config_cleanup(dev); 128 drm_mode_config_cleanup(dev);
129 drm_release_iommu_mapping(dev);
130err_free_private:
136 kfree(private); 131 kfree(private);
137 132
138 return ret; 133 return ret;
@@ -144,6 +139,8 @@ static int exynos_drm_unload(struct drm_device *dev)
144 exynos_drm_device_unregister(dev); 139 exynos_drm_device_unregister(dev);
145 drm_vblank_cleanup(dev); 140 drm_vblank_cleanup(dev);
146 drm_kms_helper_poll_fini(dev); 141 drm_kms_helper_poll_fini(dev);
142 exynos_drm_remove_displays(dev);
143 exynos_drm_remove_managers(dev);
147 drm_mode_config_cleanup(dev); 144 drm_mode_config_cleanup(dev);
148 145
149 drm_release_iommu_mapping(dev); 146 drm_release_iommu_mapping(dev);
@@ -158,6 +155,41 @@ static const struct file_operations exynos_drm_gem_fops = {
158 .mmap = exynos_drm_gem_mmap_buffer, 155 .mmap = exynos_drm_gem_mmap_buffer,
159}; 156};
160 157
158static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
159{
160 struct drm_connector *connector;
161
162 drm_modeset_lock_all(dev);
163 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
164 int old_dpms = connector->dpms;
165
166 if (connector->funcs->dpms)
167 connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
168
169 /* Set the old mode back to the connector for resume */
170 connector->dpms = old_dpms;
171 }
172 drm_modeset_unlock_all(dev);
173
174 return 0;
175}
176
177static int exynos_drm_resume(struct drm_device *dev)
178{
179 struct drm_connector *connector;
180
181 drm_modeset_lock_all(dev);
182 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
183 if (connector->funcs->dpms)
184 connector->funcs->dpms(connector, connector->dpms);
185 }
186
187 drm_helper_resume_force_mode(dev);
188 drm_modeset_unlock_all(dev);
189
190 return 0;
191}
192
161static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) 193static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
162{ 194{
163 struct drm_exynos_file_private *file_priv; 195 struct drm_exynos_file_private *file_priv;
@@ -295,6 +327,8 @@ static struct drm_driver exynos_drm_driver = {
295 DRIVER_GEM | DRIVER_PRIME, 327 DRIVER_GEM | DRIVER_PRIME,
296 .load = exynos_drm_load, 328 .load = exynos_drm_load,
297 .unload = exynos_drm_unload, 329 .unload = exynos_drm_unload,
330 .suspend = exynos_drm_suspend,
331 .resume = exynos_drm_resume,
298 .open = exynos_drm_open, 332 .open = exynos_drm_open,
299 .preclose = exynos_drm_preclose, 333 .preclose = exynos_drm_preclose,
300 .lastclose = exynos_drm_lastclose, 334 .lastclose = exynos_drm_lastclose,
@@ -329,6 +363,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
329 if (ret) 363 if (ret)
330 return ret; 364 return ret;
331 365
366 pm_runtime_enable(&pdev->dev);
367 pm_runtime_get_sync(&pdev->dev);
368
332 return drm_platform_init(&exynos_drm_driver, pdev); 369 return drm_platform_init(&exynos_drm_driver, pdev);
333} 370}
334 371
@@ -339,12 +376,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
339 return 0; 376 return 0;
340} 377}
341 378
379#ifdef CONFIG_PM_SLEEP
380static int exynos_drm_sys_suspend(struct device *dev)
381{
382 struct drm_device *drm_dev = dev_get_drvdata(dev);
383 pm_message_t message;
384
385 if (pm_runtime_suspended(dev))
386 return 0;
387
388 message.event = PM_EVENT_SUSPEND;
389 return exynos_drm_suspend(drm_dev, message);
390}
391
392static int exynos_drm_sys_resume(struct device *dev)
393{
394 struct drm_device *drm_dev = dev_get_drvdata(dev);
395
396 if (pm_runtime_suspended(dev))
397 return 0;
398
399 return exynos_drm_resume(drm_dev);
400}
401#endif
402
403#ifdef CONFIG_PM_RUNTIME
404static int exynos_drm_runtime_suspend(struct device *dev)
405{
406 struct drm_device *drm_dev = dev_get_drvdata(dev);
407 pm_message_t message;
408
409 if (pm_runtime_suspended(dev))
410 return 0;
411
412 message.event = PM_EVENT_SUSPEND;
413 return exynos_drm_suspend(drm_dev, message);
414}
415
416static int exynos_drm_runtime_resume(struct device *dev)
417{
418 struct drm_device *drm_dev = dev_get_drvdata(dev);
419
420 if (!pm_runtime_suspended(dev))
421 return 0;
422
423 return exynos_drm_resume(drm_dev);
424}
425#endif
426
427static const struct dev_pm_ops exynos_drm_pm_ops = {
428 SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
429 SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
430 exynos_drm_runtime_resume, NULL)
431};
432
342static struct platform_driver exynos_drm_platform_driver = { 433static struct platform_driver exynos_drm_platform_driver = {
343 .probe = exynos_drm_platform_probe, 434 .probe = exynos_drm_platform_probe,
344 .remove = exynos_drm_platform_remove, 435 .remove = exynos_drm_platform_remove,
345 .driver = { 436 .driver = {
346 .owner = THIS_MODULE, 437 .owner = THIS_MODULE,
347 .name = "exynos-drm", 438 .name = "exynos-drm",
439 .pm = &exynos_drm_pm_ops,
348 }, 440 },
349}; 441};
350 442
@@ -352,6 +444,18 @@ static int __init exynos_drm_init(void)
352{ 444{
353 int ret; 445 int ret;
354 446
447#ifdef CONFIG_DRM_EXYNOS_DP
448 ret = platform_driver_register(&dp_driver);
449 if (ret < 0)
450 goto out_dp;
451#endif
452
453#ifdef CONFIG_DRM_EXYNOS_DSI
454 ret = platform_driver_register(&dsi_driver);
455 if (ret < 0)
456 goto out_dsi;
457#endif
458
355#ifdef CONFIG_DRM_EXYNOS_FIMD 459#ifdef CONFIG_DRM_EXYNOS_FIMD
356 ret = platform_driver_register(&fimd_driver); 460 ret = platform_driver_register(&fimd_driver);
357 if (ret < 0) 461 if (ret < 0)
@@ -365,13 +469,6 @@ static int __init exynos_drm_init(void)
365 ret = platform_driver_register(&mixer_driver); 469 ret = platform_driver_register(&mixer_driver);
366 if (ret < 0) 470 if (ret < 0)
367 goto out_mixer; 471 goto out_mixer;
368 ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
369 if (ret < 0)
370 goto out_common_hdmi;
371
372 ret = exynos_platform_device_hdmi_register();
373 if (ret < 0)
374 goto out_common_hdmi_dev;
375#endif 472#endif
376 473
377#ifdef CONFIG_DRM_EXYNOS_VIDI 474#ifdef CONFIG_DRM_EXYNOS_VIDI
@@ -464,10 +561,6 @@ out_vidi:
464#endif 561#endif
465 562
466#ifdef CONFIG_DRM_EXYNOS_HDMI 563#ifdef CONFIG_DRM_EXYNOS_HDMI
467 exynos_platform_device_hdmi_unregister();
468out_common_hdmi_dev:
469 platform_driver_unregister(&exynos_drm_common_hdmi_driver);
470out_common_hdmi:
471 platform_driver_unregister(&mixer_driver); 564 platform_driver_unregister(&mixer_driver);
472out_mixer: 565out_mixer:
473 platform_driver_unregister(&hdmi_driver); 566 platform_driver_unregister(&hdmi_driver);
@@ -478,6 +571,16 @@ out_hdmi:
478 platform_driver_unregister(&fimd_driver); 571 platform_driver_unregister(&fimd_driver);
479out_fimd: 572out_fimd:
480#endif 573#endif
574
575#ifdef CONFIG_DRM_EXYNOS_DSI
576 platform_driver_unregister(&dsi_driver);
577out_dsi:
578#endif
579
580#ifdef CONFIG_DRM_EXYNOS_DP
581 platform_driver_unregister(&dp_driver);
582out_dp:
583#endif
481 return ret; 584 return ret;
482} 585}
483 586
@@ -509,8 +612,6 @@ static void __exit exynos_drm_exit(void)
509#endif 612#endif
510 613
511#ifdef CONFIG_DRM_EXYNOS_HDMI 614#ifdef CONFIG_DRM_EXYNOS_HDMI
512 exynos_platform_device_hdmi_unregister();
513 platform_driver_unregister(&exynos_drm_common_hdmi_driver);
514 platform_driver_unregister(&mixer_driver); 615 platform_driver_unregister(&mixer_driver);
515 platform_driver_unregister(&hdmi_driver); 616 platform_driver_unregister(&hdmi_driver);
516#endif 617#endif
@@ -522,6 +623,14 @@ static void __exit exynos_drm_exit(void)
522#ifdef CONFIG_DRM_EXYNOS_FIMD 623#ifdef CONFIG_DRM_EXYNOS_FIMD
523 platform_driver_unregister(&fimd_driver); 624 platform_driver_unregister(&fimd_driver);
524#endif 625#endif
626
627#ifdef CONFIG_DRM_EXYNOS_DSI
628 platform_driver_unregister(&dsi_driver);
629#endif
630
631#ifdef CONFIG_DRM_EXYNOS_DP
632 platform_driver_unregister(&dp_driver);
633#endif
525} 634}
526 635
527module_init(exynos_drm_init); 636module_init(exynos_drm_init);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 0eaf5a27e120..4c5cf6843137 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -54,22 +54,6 @@ enum exynos_drm_output_type {
54}; 54};
55 55
56/* 56/*
57 * Exynos drm overlay ops structure.
58 *
59 * @mode_set: copy drm overlay info to hw specific overlay info.
60 * @commit: apply hardware specific overlay data to registers.
61 * @enable: enable hardware specific overlay.
62 * @disable: disable hardware specific overlay.
63 */
64struct exynos_drm_overlay_ops {
65 void (*mode_set)(struct device *subdrv_dev,
66 struct exynos_drm_overlay *overlay);
67 void (*commit)(struct device *subdrv_dev, int zpos);
68 void (*enable)(struct device *subdrv_dev, int zpos);
69 void (*disable)(struct device *subdrv_dev, int zpos);
70};
71
72/*
73 * Exynos drm common overlay structure. 57 * Exynos drm common overlay structure.
74 * 58 *
75 * @fb_x: offset x on a framebuffer to be displayed. 59 * @fb_x: offset x on a framebuffer to be displayed.
@@ -138,77 +122,110 @@ struct exynos_drm_overlay {
138 * Exynos DRM Display Structure. 122 * Exynos DRM Display Structure.
139 * - this structure is common to analog tv, digital tv and lcd panel. 123 * - this structure is common to analog tv, digital tv and lcd panel.
140 * 124 *
141 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. 125 * @initialize: initializes the display with drm_dev
142 * @is_connected: check for that display is connected or not. 126 * @remove: cleans up the display for removal
143 * @get_edid: get edid modes from display driver. 127 * @mode_fixup: fix mode data comparing to hw specific display mode.
144 * @get_panel: get panel object from display driver. 128 * @mode_set: convert drm_display_mode to hw specific display mode and
129 * would be called by encoder->mode_set().
145 * @check_mode: check if mode is valid or not. 130 * @check_mode: check if mode is valid or not.
146 * @power_on: display device on or off. 131 * @dpms: display device on or off.
132 * @commit: apply changes to hw
147 */ 133 */
134struct exynos_drm_display;
148struct exynos_drm_display_ops { 135struct exynos_drm_display_ops {
136 int (*initialize)(struct exynos_drm_display *display,
137 struct drm_device *drm_dev);
138 int (*create_connector)(struct exynos_drm_display *display,
139 struct drm_encoder *encoder);
140 void (*remove)(struct exynos_drm_display *display);
141 void (*mode_fixup)(struct exynos_drm_display *display,
142 struct drm_connector *connector,
143 const struct drm_display_mode *mode,
144 struct drm_display_mode *adjusted_mode);
145 void (*mode_set)(struct exynos_drm_display *display,
146 struct drm_display_mode *mode);
147 int (*check_mode)(struct exynos_drm_display *display,
148 struct drm_display_mode *mode);
149 void (*dpms)(struct exynos_drm_display *display, int mode);
150 void (*commit)(struct exynos_drm_display *display);
151};
152
153/*
154 * Exynos drm display structure, maps 1:1 with an encoder/connector
155 *
156 * @list: the list entry for this manager
157 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
158 * @encoder: encoder object this display maps to
159 * @connector: connector object this display maps to
160 * @ops: pointer to callbacks for exynos drm specific functionality
161 * @ctx: A pointer to the display's implementation specific context
162 */
163struct exynos_drm_display {
164 struct list_head list;
149 enum exynos_drm_output_type type; 165 enum exynos_drm_output_type type;
150 bool (*is_connected)(struct device *dev); 166 struct drm_encoder *encoder;
151 struct edid *(*get_edid)(struct device *dev, 167 struct drm_connector *connector;
152 struct drm_connector *connector); 168 struct exynos_drm_display_ops *ops;
153 void *(*get_panel)(struct device *dev); 169 void *ctx;
154 int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
155 int (*power_on)(struct device *dev, int mode);
156}; 170};
157 171
158/* 172/*
159 * Exynos drm manager ops 173 * Exynos drm manager ops
160 * 174 *
175 * @initialize: initializes the manager with drm_dev
176 * @remove: cleans up the manager for removal
161 * @dpms: control device power. 177 * @dpms: control device power.
162 * @apply: set timing, vblank and overlay data to registers. 178 * @mode_fixup: fix mode data before applying it
163 * @mode_fixup: fix mode data comparing to hw specific display mode. 179 * @mode_set: set the given mode to the manager
164 * @mode_set: convert drm_display_mode to hw specific display mode and
165 * would be called by encoder->mode_set().
166 * @get_max_resol: get maximum resolution to specific hardware.
167 * @commit: set current hw specific display mode to hw. 180 * @commit: set current hw specific display mode to hw.
168 * @enable_vblank: specific driver callback for enabling vblank interrupt. 181 * @enable_vblank: specific driver callback for enabling vblank interrupt.
169 * @disable_vblank: specific driver callback for disabling vblank interrupt. 182 * @disable_vblank: specific driver callback for disabling vblank interrupt.
170 * @wait_for_vblank: wait for vblank interrupt to make sure that 183 * @wait_for_vblank: wait for vblank interrupt to make sure that
171 * hardware overlay is updated. 184 * hardware overlay is updated.
185 * @win_mode_set: copy drm overlay info to hw specific overlay info.
186 * @win_commit: apply hardware specific overlay data to registers.
187 * @win_enable: enable hardware specific overlay.
188 * @win_disable: disable hardware specific overlay.
172 */ 189 */
190struct exynos_drm_manager;
173struct exynos_drm_manager_ops { 191struct exynos_drm_manager_ops {
174 void (*dpms)(struct device *subdrv_dev, int mode); 192 int (*initialize)(struct exynos_drm_manager *mgr,
175 void (*apply)(struct device *subdrv_dev); 193 struct drm_device *drm_dev, int pipe);
176 void (*mode_fixup)(struct device *subdrv_dev, 194 void (*remove)(struct exynos_drm_manager *mgr);
177 struct drm_connector *connector, 195 void (*dpms)(struct exynos_drm_manager *mgr, int mode);
196 bool (*mode_fixup)(struct exynos_drm_manager *mgr,
178 const struct drm_display_mode *mode, 197 const struct drm_display_mode *mode,
179 struct drm_display_mode *adjusted_mode); 198 struct drm_display_mode *adjusted_mode);
180 void (*mode_set)(struct device *subdrv_dev, void *mode); 199 void (*mode_set)(struct exynos_drm_manager *mgr,
181 void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, 200 const struct drm_display_mode *mode);
182 unsigned int *height); 201 void (*commit)(struct exynos_drm_manager *mgr);
183 void (*commit)(struct device *subdrv_dev); 202 int (*enable_vblank)(struct exynos_drm_manager *mgr);
184 int (*enable_vblank)(struct device *subdrv_dev); 203 void (*disable_vblank)(struct exynos_drm_manager *mgr);
185 void (*disable_vblank)(struct device *subdrv_dev); 204 void (*wait_for_vblank)(struct exynos_drm_manager *mgr);
186 void (*wait_for_vblank)(struct device *subdrv_dev); 205 void (*win_mode_set)(struct exynos_drm_manager *mgr,
206 struct exynos_drm_overlay *overlay);
207 void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
208 void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
209 void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
187}; 210};
188 211
189/* 212/*
190 * Exynos drm common manager structure. 213 * Exynos drm common manager structure, maps 1:1 with a crtc
191 * 214 *
192 * @dev: pointer to device object for subdrv device driver. 215 * @list: the list entry for this manager
193 * sub drivers such as display controller or hdmi driver, 216 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
194 * have their own device object. 217 * @drm_dev: pointer to the drm device
195 * @ops: pointer to callbacks for exynos drm specific framebuffer. 218 * @pipe: the pipe number for this crtc/manager
196 * these callbacks should be set by specific drivers such fimd 219 * @ops: pointer to callbacks for exynos drm specific functionality
197 * or hdmi driver and are used to control hardware global registers. 220 * @ctx: A pointer to the manager's implementation specific context
198 * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
199 * these callbacks should be set by specific drivers such fimd
200 * or hdmi driver and are used to control hardware overlay reigsters.
201 * @display: pointer to callbacks for exynos drm specific framebuffer.
202 * these callbacks should be set by specific drivers such fimd
203 * or hdmi driver and are used to control display devices such as
204 * analog tv, digital tv and lcd panel and also get timing data for them.
205 */ 221 */
206struct exynos_drm_manager { 222struct exynos_drm_manager {
207 struct device *dev; 223 struct list_head list;
224 enum exynos_drm_output_type type;
225 struct drm_device *drm_dev;
208 int pipe; 226 int pipe;
209 struct exynos_drm_manager_ops *ops; 227 struct exynos_drm_manager_ops *ops;
210 struct exynos_drm_overlay_ops *overlay_ops; 228 void *ctx;
211 struct exynos_drm_display_ops *display_ops;
212}; 229};
213 230
214struct exynos_drm_g2d_private { 231struct exynos_drm_g2d_private {
@@ -273,14 +290,11 @@ struct exynos_drm_private {
273 * by probe callback. 290 * by probe callback.
274 * @open: this would be called with drm device file open. 291 * @open: this would be called with drm device file open.
275 * @close: this would be called with drm device file close. 292 * @close: this would be called with drm device file close.
276 * @encoder: encoder object owned by this sub driver.
277 * @connector: connector object owned by this sub driver.
278 */ 293 */
279struct exynos_drm_subdrv { 294struct exynos_drm_subdrv {
280 struct list_head list; 295 struct list_head list;
281 struct device *dev; 296 struct device *dev;
282 struct drm_device *drm_dev; 297 struct drm_device *drm_dev;
283 struct exynos_drm_manager *manager;
284 298
285 int (*probe)(struct drm_device *drm_dev, struct device *dev); 299 int (*probe)(struct drm_device *drm_dev, struct device *dev);
286 void (*remove)(struct drm_device *drm_dev, struct device *dev); 300 void (*remove)(struct drm_device *drm_dev, struct device *dev);
@@ -288,9 +302,6 @@ struct exynos_drm_subdrv {
288 struct drm_file *file); 302 struct drm_file *file);
289 void (*close)(struct drm_device *drm_dev, struct device *dev, 303 void (*close)(struct drm_device *drm_dev, struct device *dev,
290 struct drm_file *file); 304 struct drm_file *file);
291
292 struct drm_encoder *encoder;
293 struct drm_connector *connector;
294}; 305};
295 306
296/* 307/*
@@ -305,6 +316,16 @@ int exynos_drm_device_register(struct drm_device *dev);
305 */ 316 */
306int exynos_drm_device_unregister(struct drm_device *dev); 317int exynos_drm_device_unregister(struct drm_device *dev);
307 318
319int exynos_drm_initialize_managers(struct drm_device *dev);
320void exynos_drm_remove_managers(struct drm_device *dev);
321int exynos_drm_initialize_displays(struct drm_device *dev);
322void exynos_drm_remove_displays(struct drm_device *dev);
323
324int exynos_drm_manager_register(struct exynos_drm_manager *manager);
325int exynos_drm_manager_unregister(struct exynos_drm_manager *manager);
326int exynos_drm_display_register(struct exynos_drm_display *display);
327int exynos_drm_display_unregister(struct exynos_drm_display *display);
328
308/* 329/*
309 * this function would be called by sub drivers such as display controller 330 * this function would be called by sub drivers such as display controller
310 * or hdmi driver to register this sub driver object to exynos drm driver 331 * or hdmi driver to register this sub driver object to exynos drm driver
@@ -340,6 +361,16 @@ int exynos_platform_device_ipp_register(void);
340 */ 361 */
341void exynos_platform_device_ipp_unregister(void); 362void exynos_platform_device_ipp_unregister(void);
342 363
364#ifdef CONFIG_DRM_EXYNOS_DPI
365int exynos_dpi_probe(struct device *dev);
366int exynos_dpi_remove(struct device *dev);
367#else
368static inline int exynos_dpi_probe(struct device *dev) { return 0; }
369static inline int exynos_dpi_remove(struct device *dev) { return 0; }
370#endif
371
372extern struct platform_driver dp_driver;
373extern struct platform_driver dsi_driver;
343extern struct platform_driver fimd_driver; 374extern struct platform_driver fimd_driver;
344extern struct platform_driver hdmi_driver; 375extern struct platform_driver hdmi_driver;
345extern struct platform_driver mixer_driver; 376extern struct platform_driver mixer_driver;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
new file mode 100644
index 000000000000..eb73e3bf2a0c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -0,0 +1,1524 @@
1/*
2 * Samsung SoC MIPI DSI Master driver.
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 *
6 * Contacts: Tomasz Figa <t.figa@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <drm/drmP.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_mipi_dsi.h>
16#include <drm/drm_panel.h>
17
18#include <linux/clk.h>
19#include <linux/irq.h>
20#include <linux/phy/phy.h>
21#include <linux/regulator/consumer.h>
22
23#include <video/mipi_display.h>
24#include <video/videomode.h>
25
26#include "exynos_drm_drv.h"
27
28/* returns true iff both arguments logically differs */
29#define NEQV(a, b) (!(a) ^ !(b))
30
31#define DSIM_STATUS_REG 0x0 /* Status register */
32#define DSIM_SWRST_REG 0x4 /* Software reset register */
33#define DSIM_CLKCTRL_REG 0x8 /* Clock control register */
34#define DSIM_TIMEOUT_REG 0xc /* Time out register */
35#define DSIM_CONFIG_REG 0x10 /* Configuration register */
36#define DSIM_ESCMODE_REG 0x14 /* Escape mode register */
37
38/* Main display image resolution register */
39#define DSIM_MDRESOL_REG 0x18
40#define DSIM_MVPORCH_REG 0x1c /* Main display Vporch register */
41#define DSIM_MHPORCH_REG 0x20 /* Main display Hporch register */
42#define DSIM_MSYNC_REG 0x24 /* Main display sync area register */
43
44/* Sub display image resolution register */
45#define DSIM_SDRESOL_REG 0x28
46#define DSIM_INTSRC_REG 0x2c /* Interrupt source register */
47#define DSIM_INTMSK_REG 0x30 /* Interrupt mask register */
48#define DSIM_PKTHDR_REG 0x34 /* Packet Header FIFO register */
49#define DSIM_PAYLOAD_REG 0x38 /* Payload FIFO register */
50#define DSIM_RXFIFO_REG 0x3c /* Read FIFO register */
51#define DSIM_FIFOTHLD_REG 0x40 /* FIFO threshold level register */
52#define DSIM_FIFOCTRL_REG 0x44 /* FIFO status and control register */
53
54/* FIFO memory AC characteristic register */
55#define DSIM_PLLCTRL_REG 0x4c /* PLL control register */
56#define DSIM_PLLTMR_REG 0x50 /* PLL timer register */
57#define DSIM_PHYACCHR_REG 0x54 /* D-PHY AC characteristic register */
58#define DSIM_PHYACCHR1_REG 0x58 /* D-PHY AC characteristic register1 */
59
60/* DSIM_STATUS */
61#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
62#define DSIM_STOP_STATE_CLK (1 << 8)
63#define DSIM_TX_READY_HS_CLK (1 << 10)
64#define DSIM_PLL_STABLE (1 << 31)
65
66/* DSIM_SWRST */
67#define DSIM_FUNCRST (1 << 16)
68#define DSIM_SWRST (1 << 0)
69
70/* DSIM_TIMEOUT */
71#define DSIM_LPDR_TIMEOUT(x) ((x) << 0)
72#define DSIM_BTA_TIMEOUT(x) ((x) << 16)
73
74/* DSIM_CLKCTRL */
75#define DSIM_ESC_PRESCALER(x) (((x) & 0xffff) << 0)
76#define DSIM_ESC_PRESCALER_MASK (0xffff << 0)
77#define DSIM_LANE_ESC_CLK_EN_CLK (1 << 19)
78#define DSIM_LANE_ESC_CLK_EN_DATA(x) (((x) & 0xf) << 20)
79#define DSIM_LANE_ESC_CLK_EN_DATA_MASK (0xf << 20)
80#define DSIM_BYTE_CLKEN (1 << 24)
81#define DSIM_BYTE_CLK_SRC(x) (((x) & 0x3) << 25)
82#define DSIM_BYTE_CLK_SRC_MASK (0x3 << 25)
83#define DSIM_PLL_BYPASS (1 << 27)
84#define DSIM_ESC_CLKEN (1 << 28)
85#define DSIM_TX_REQUEST_HSCLK (1 << 31)
86
87/* DSIM_CONFIG */
88#define DSIM_LANE_EN_CLK (1 << 0)
89#define DSIM_LANE_EN(x) (((x) & 0xf) << 1)
90#define DSIM_NUM_OF_DATA_LANE(x) (((x) & 0x3) << 5)
91#define DSIM_SUB_PIX_FORMAT(x) (((x) & 0x7) << 8)
92#define DSIM_MAIN_PIX_FORMAT_MASK (0x7 << 12)
93#define DSIM_MAIN_PIX_FORMAT_RGB888 (0x7 << 12)
94#define DSIM_MAIN_PIX_FORMAT_RGB666 (0x6 << 12)
95#define DSIM_MAIN_PIX_FORMAT_RGB666_P (0x5 << 12)
96#define DSIM_MAIN_PIX_FORMAT_RGB565 (0x4 << 12)
97#define DSIM_SUB_VC (((x) & 0x3) << 16)
98#define DSIM_MAIN_VC (((x) & 0x3) << 18)
99#define DSIM_HSA_MODE (1 << 20)
100#define DSIM_HBP_MODE (1 << 21)
101#define DSIM_HFP_MODE (1 << 22)
102#define DSIM_HSE_MODE (1 << 23)
103#define DSIM_AUTO_MODE (1 << 24)
104#define DSIM_VIDEO_MODE (1 << 25)
105#define DSIM_BURST_MODE (1 << 26)
106#define DSIM_SYNC_INFORM (1 << 27)
107#define DSIM_EOT_DISABLE (1 << 28)
108#define DSIM_MFLUSH_VS (1 << 29)
109
110/* DSIM_ESCMODE */
111#define DSIM_TX_TRIGGER_RST (1 << 4)
112#define DSIM_TX_LPDT_LP (1 << 6)
113#define DSIM_CMD_LPDT_LP (1 << 7)
114#define DSIM_FORCE_BTA (1 << 16)
115#define DSIM_FORCE_STOP_STATE (1 << 20)
116#define DSIM_STOP_STATE_CNT(x) (((x) & 0x7ff) << 21)
117#define DSIM_STOP_STATE_CNT_MASK (0x7ff << 21)
118
119/* DSIM_MDRESOL */
120#define DSIM_MAIN_STAND_BY (1 << 31)
121#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
122#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
123
124/* DSIM_MVPORCH */
125#define DSIM_CMD_ALLOW(x) ((x) << 28)
126#define DSIM_STABLE_VFP(x) ((x) << 16)
127#define DSIM_MAIN_VBP(x) ((x) << 0)
128#define DSIM_CMD_ALLOW_MASK (0xf << 28)
129#define DSIM_STABLE_VFP_MASK (0x7ff << 16)
130#define DSIM_MAIN_VBP_MASK (0x7ff << 0)
131
132/* DSIM_MHPORCH */
133#define DSIM_MAIN_HFP(x) ((x) << 16)
134#define DSIM_MAIN_HBP(x) ((x) << 0)
135#define DSIM_MAIN_HFP_MASK ((0xffff) << 16)
136#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
137
138/* DSIM_MSYNC */
139#define DSIM_MAIN_VSA(x) ((x) << 22)
140#define DSIM_MAIN_HSA(x) ((x) << 0)
141#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
142#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
143
144/* DSIM_SDRESOL */
145#define DSIM_SUB_STANDY(x) ((x) << 31)
146#define DSIM_SUB_VRESOL(x) ((x) << 16)
147#define DSIM_SUB_HRESOL(x) ((x) << 0)
148#define DSIM_SUB_STANDY_MASK ((0x1) << 31)
149#define DSIM_SUB_VRESOL_MASK ((0x7ff) << 16)
150#define DSIM_SUB_HRESOL_MASK ((0x7ff) << 0)
151
152/* DSIM_INTSRC */
153#define DSIM_INT_PLL_STABLE (1 << 31)
154#define DSIM_INT_SW_RST_RELEASE (1 << 30)
155#define DSIM_INT_SFR_FIFO_EMPTY (1 << 29)
156#define DSIM_INT_BTA (1 << 25)
157#define DSIM_INT_FRAME_DONE (1 << 24)
158#define DSIM_INT_RX_TIMEOUT (1 << 21)
159#define DSIM_INT_BTA_TIMEOUT (1 << 20)
160#define DSIM_INT_RX_DONE (1 << 18)
161#define DSIM_INT_RX_TE (1 << 17)
162#define DSIM_INT_RX_ACK (1 << 16)
163#define DSIM_INT_RX_ECC_ERR (1 << 15)
164#define DSIM_INT_RX_CRC_ERR (1 << 14)
165
166/* DSIM_FIFOCTRL */
167#define DSIM_RX_DATA_FULL (1 << 25)
168#define DSIM_RX_DATA_EMPTY (1 << 24)
169#define DSIM_SFR_HEADER_FULL (1 << 23)
170#define DSIM_SFR_HEADER_EMPTY (1 << 22)
171#define DSIM_SFR_PAYLOAD_FULL (1 << 21)
172#define DSIM_SFR_PAYLOAD_EMPTY (1 << 20)
173#define DSIM_I80_HEADER_FULL (1 << 19)
174#define DSIM_I80_HEADER_EMPTY (1 << 18)
175#define DSIM_I80_PAYLOAD_FULL (1 << 17)
176#define DSIM_I80_PAYLOAD_EMPTY (1 << 16)
177#define DSIM_SD_HEADER_FULL (1 << 15)
178#define DSIM_SD_HEADER_EMPTY (1 << 14)
179#define DSIM_SD_PAYLOAD_FULL (1 << 13)
180#define DSIM_SD_PAYLOAD_EMPTY (1 << 12)
181#define DSIM_MD_HEADER_FULL (1 << 11)
182#define DSIM_MD_HEADER_EMPTY (1 << 10)
183#define DSIM_MD_PAYLOAD_FULL (1 << 9)
184#define DSIM_MD_PAYLOAD_EMPTY (1 << 8)
185#define DSIM_RX_FIFO (1 << 4)
186#define DSIM_SFR_FIFO (1 << 3)
187#define DSIM_I80_FIFO (1 << 2)
188#define DSIM_SD_FIFO (1 << 1)
189#define DSIM_MD_FIFO (1 << 0)
190
191/* DSIM_PHYACCHR */
192#define DSIM_AFC_EN (1 << 14)
193#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
194
195/* DSIM_PLLCTRL */
196#define DSIM_FREQ_BAND(x) ((x) << 24)
197#define DSIM_PLL_EN (1 << 23)
198#define DSIM_PLL_P(x) ((x) << 13)
199#define DSIM_PLL_M(x) ((x) << 4)
200#define DSIM_PLL_S(x) ((x) << 1)
201
202#define DSI_MAX_BUS_WIDTH 4
203#define DSI_NUM_VIRTUAL_CHANNELS 4
204#define DSI_TX_FIFO_SIZE 2048
205#define DSI_RX_FIFO_SIZE 256
206#define DSI_XFER_TIMEOUT_MS 100
207#define DSI_RX_FIFO_EMPTY 0x30800002
208
209enum exynos_dsi_transfer_type {
210 EXYNOS_DSI_TX,
211 EXYNOS_DSI_RX,
212};
213
214struct exynos_dsi_transfer {
215 struct list_head list;
216 struct completion completed;
217 int result;
218 u8 data_id;
219 u8 data[2];
220 u16 flags;
221
222 const u8 *tx_payload;
223 u16 tx_len;
224 u16 tx_done;
225
226 u8 *rx_payload;
227 u16 rx_len;
228 u16 rx_done;
229};
230
231#define DSIM_STATE_ENABLED BIT(0)
232#define DSIM_STATE_INITIALIZED BIT(1)
233#define DSIM_STATE_CMD_LPM BIT(2)
234
235struct exynos_dsi {
236 struct mipi_dsi_host dsi_host;
237 struct drm_connector connector;
238 struct drm_encoder *encoder;
239 struct device_node *panel_node;
240 struct drm_panel *panel;
241 struct device *dev;
242
243 void __iomem *reg_base;
244 struct phy *phy;
245 struct clk *pll_clk;
246 struct clk *bus_clk;
247 struct regulator_bulk_data supplies[2];
248 int irq;
249
250 u32 pll_clk_rate;
251 u32 burst_clk_rate;
252 u32 esc_clk_rate;
253 u32 lanes;
254 u32 mode_flags;
255 u32 format;
256 struct videomode vm;
257
258 int state;
259 struct drm_property *brightness;
260 struct completion completed;
261
262 spinlock_t transfer_lock; /* protects transfer_list */
263 struct list_head transfer_list;
264};
265
266#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
267#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
268
269static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
270{
271 if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
272 return;
273
274 dev_err(dsi->dev, "timeout waiting for reset\n");
275}
276
277static void exynos_dsi_reset(struct exynos_dsi *dsi)
278{
279 reinit_completion(&dsi->completed);
280 writel(DSIM_SWRST, dsi->reg_base + DSIM_SWRST_REG);
281}
282
283#ifndef MHZ
284#define MHZ (1000*1000)
285#endif
286
287static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
288 unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
289{
290 unsigned long best_freq = 0;
291 u32 min_delta = 0xffffffff;
292 u8 p_min, p_max;
293 u8 _p, uninitialized_var(best_p);
294 u16 _m, uninitialized_var(best_m);
295 u8 _s, uninitialized_var(best_s);
296
297 p_min = DIV_ROUND_UP(fin, (12 * MHZ));
298 p_max = fin / (6 * MHZ);
299
300 for (_p = p_min; _p <= p_max; ++_p) {
301 for (_s = 0; _s <= 5; ++_s) {
302 u64 tmp;
303 u32 delta;
304
305 tmp = (u64)fout * (_p << _s);
306 do_div(tmp, fin);
307 _m = tmp;
308 if (_m < 41 || _m > 125)
309 continue;
310
311 tmp = (u64)_m * fin;
312 do_div(tmp, _p);
313 if (tmp < 500 * MHZ || tmp > 1000 * MHZ)
314 continue;
315
316 tmp = (u64)_m * fin;
317 do_div(tmp, _p << _s);
318
319 delta = abs(fout - tmp);
320 if (delta < min_delta) {
321 best_p = _p;
322 best_m = _m;
323 best_s = _s;
324 min_delta = delta;
325 best_freq = tmp;
326 }
327 }
328 }
329
330 if (best_freq) {
331 *p = best_p;
332 *m = best_m;
333 *s = best_s;
334 }
335
336 return best_freq;
337}
338
339static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
340 unsigned long freq)
341{
342 static const unsigned long freq_bands[] = {
343 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
344 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
345 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
346 770 * MHZ, 870 * MHZ, 950 * MHZ,
347 };
348 unsigned long fin, fout;
349 int timeout, band;
350 u8 p, s;
351 u16 m;
352 u32 reg;
353
354 clk_set_rate(dsi->pll_clk, dsi->pll_clk_rate);
355
356 fin = clk_get_rate(dsi->pll_clk);
357 if (!fin) {
358 dev_err(dsi->dev, "failed to get PLL clock frequency\n");
359 return 0;
360 }
361
362 dev_dbg(dsi->dev, "PLL input frequency: %lu\n", fin);
363
364 fout = exynos_dsi_pll_find_pms(dsi, fin, freq, &p, &m, &s);
365 if (!fout) {
366 dev_err(dsi->dev,
367 "failed to find PLL PMS for requested frequency\n");
368 return -EFAULT;
369 }
370
371 for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
372 if (fout < freq_bands[band])
373 break;
374
375 dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d), band %d\n", fout,
376 p, m, s, band);
377
378 writel(500, dsi->reg_base + DSIM_PLLTMR_REG);
379
380 reg = DSIM_FREQ_BAND(band) | DSIM_PLL_EN
381 | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
382 writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
383
384 timeout = 1000;
385 do {
386 if (timeout-- == 0) {
387 dev_err(dsi->dev, "PLL failed to stabilize\n");
388 return -EFAULT;
389 }
390 reg = readl(dsi->reg_base + DSIM_STATUS_REG);
391 } while ((reg & DSIM_PLL_STABLE) == 0);
392
393 return fout;
394}
395
396static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
397{
398 unsigned long hs_clk, byte_clk, esc_clk;
399 unsigned long esc_div;
400 u32 reg;
401
402 hs_clk = exynos_dsi_set_pll(dsi, dsi->burst_clk_rate);
403 if (!hs_clk) {
404 dev_err(dsi->dev, "failed to configure DSI PLL\n");
405 return -EFAULT;
406 }
407
408 byte_clk = hs_clk / 8;
409 esc_div = DIV_ROUND_UP(byte_clk, dsi->esc_clk_rate);
410 esc_clk = byte_clk / esc_div;
411
412 if (esc_clk > 20 * MHZ) {
413 ++esc_div;
414 esc_clk = byte_clk / esc_div;
415 }
416
417 dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu, esc_clk = %lu\n",
418 hs_clk, byte_clk, esc_clk);
419
420 reg = readl(dsi->reg_base + DSIM_CLKCTRL_REG);
421 reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK
422 | DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS
423 | DSIM_BYTE_CLK_SRC_MASK);
424 reg |= DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN
425 | DSIM_ESC_PRESCALER(esc_div)
426 | DSIM_LANE_ESC_CLK_EN_CLK
427 | DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1)
428 | DSIM_BYTE_CLK_SRC(0)
429 | DSIM_TX_REQUEST_HSCLK;
430 writel(reg, dsi->reg_base + DSIM_CLKCTRL_REG);
431
432 return 0;
433}
434
435static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
436{
437 u32 reg;
438
439 reg = readl(dsi->reg_base + DSIM_CLKCTRL_REG);
440 reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK
441 | DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN);
442 writel(reg, dsi->reg_base + DSIM_CLKCTRL_REG);
443
444 reg = readl(dsi->reg_base + DSIM_PLLCTRL_REG);
445 reg &= ~DSIM_PLL_EN;
446 writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
447}
448
449static int exynos_dsi_init_link(struct exynos_dsi *dsi)
450{
451 int timeout;
452 u32 reg;
453 u32 lanes_mask;
454
455 /* Initialize FIFO pointers */
456 reg = readl(dsi->reg_base + DSIM_FIFOCTRL_REG);
457 reg &= ~0x1f;
458 writel(reg, dsi->reg_base + DSIM_FIFOCTRL_REG);
459
460 usleep_range(9000, 11000);
461
462 reg |= 0x1f;
463 writel(reg, dsi->reg_base + DSIM_FIFOCTRL_REG);
464
465 usleep_range(9000, 11000);
466
467 /* DSI configuration */
468 reg = 0;
469
470 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
471 reg |= DSIM_VIDEO_MODE;
472
473 if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
474 reg |= DSIM_MFLUSH_VS;
475 if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
476 reg |= DSIM_EOT_DISABLE;
477 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
478 reg |= DSIM_SYNC_INFORM;
479 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
480 reg |= DSIM_BURST_MODE;
481 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT)
482 reg |= DSIM_AUTO_MODE;
483 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
484 reg |= DSIM_HSE_MODE;
485 if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HFP))
486 reg |= DSIM_HFP_MODE;
487 if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HBP))
488 reg |= DSIM_HBP_MODE;
489 if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSA))
490 reg |= DSIM_HSA_MODE;
491 }
492
493 switch (dsi->format) {
494 case MIPI_DSI_FMT_RGB888:
495 reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
496 break;
497 case MIPI_DSI_FMT_RGB666:
498 reg |= DSIM_MAIN_PIX_FORMAT_RGB666;
499 break;
500 case MIPI_DSI_FMT_RGB666_PACKED:
501 reg |= DSIM_MAIN_PIX_FORMAT_RGB666_P;
502 break;
503 case MIPI_DSI_FMT_RGB565:
504 reg |= DSIM_MAIN_PIX_FORMAT_RGB565;
505 break;
506 default:
507 dev_err(dsi->dev, "invalid pixel format\n");
508 return -EINVAL;
509 }
510
511 reg |= DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1);
512
513 writel(reg, dsi->reg_base + DSIM_CONFIG_REG);
514
515 reg |= DSIM_LANE_EN_CLK;
516 writel(reg, dsi->reg_base + DSIM_CONFIG_REG);
517
518 lanes_mask = BIT(dsi->lanes) - 1;
519 reg |= DSIM_LANE_EN(lanes_mask);
520 writel(reg, dsi->reg_base + DSIM_CONFIG_REG);
521
522 /* Check clock and data lane state are stop state */
523 timeout = 100;
524 do {
525 if (timeout-- == 0) {
526 dev_err(dsi->dev, "waiting for bus lanes timed out\n");
527 return -EFAULT;
528 }
529
530 reg = readl(dsi->reg_base + DSIM_STATUS_REG);
531 if ((reg & DSIM_STOP_STATE_DAT(lanes_mask))
532 != DSIM_STOP_STATE_DAT(lanes_mask))
533 continue;
534 } while (!(reg & (DSIM_STOP_STATE_CLK | DSIM_TX_READY_HS_CLK)));
535
536 reg = readl(dsi->reg_base + DSIM_ESCMODE_REG);
537 reg &= ~DSIM_STOP_STATE_CNT_MASK;
538 reg |= DSIM_STOP_STATE_CNT(0xf);
539 writel(reg, dsi->reg_base + DSIM_ESCMODE_REG);
540
541 reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
542 writel(reg, dsi->reg_base + DSIM_TIMEOUT_REG);
543
544 return 0;
545}
546
547static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
548{
549 struct videomode *vm = &dsi->vm;
550 u32 reg;
551
552 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
553 reg = DSIM_CMD_ALLOW(0xf)
554 | DSIM_STABLE_VFP(vm->vfront_porch)
555 | DSIM_MAIN_VBP(vm->vback_porch);
556 writel(reg, dsi->reg_base + DSIM_MVPORCH_REG);
557
558 reg = DSIM_MAIN_HFP(vm->hfront_porch)
559 | DSIM_MAIN_HBP(vm->hback_porch);
560 writel(reg, dsi->reg_base + DSIM_MHPORCH_REG);
561
562 reg = DSIM_MAIN_VSA(vm->vsync_len)
563 | DSIM_MAIN_HSA(vm->hsync_len);
564 writel(reg, dsi->reg_base + DSIM_MSYNC_REG);
565 }
566
567 reg = DSIM_MAIN_HRESOL(vm->hactive) | DSIM_MAIN_VRESOL(vm->vactive);
568 writel(reg, dsi->reg_base + DSIM_MDRESOL_REG);
569
570 dev_dbg(dsi->dev, "LCD size = %dx%d\n", vm->hactive, vm->vactive);
571}
572
573static void exynos_dsi_set_display_enable(struct exynos_dsi *dsi, bool enable)
574{
575 u32 reg;
576
577 reg = readl(dsi->reg_base + DSIM_MDRESOL_REG);
578 if (enable)
579 reg |= DSIM_MAIN_STAND_BY;
580 else
581 reg &= ~DSIM_MAIN_STAND_BY;
582 writel(reg, dsi->reg_base + DSIM_MDRESOL_REG);
583}
584
585static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi)
586{
587 int timeout = 2000;
588
589 do {
590 u32 reg = readl(dsi->reg_base + DSIM_FIFOCTRL_REG);
591
592 if (!(reg & DSIM_SFR_HEADER_FULL))
593 return 0;
594
595 if (!cond_resched())
596 usleep_range(950, 1050);
597 } while (--timeout);
598
599 return -ETIMEDOUT;
600}
601
602static void exynos_dsi_set_cmd_lpm(struct exynos_dsi *dsi, bool lpm)
603{
604 u32 v = readl(dsi->reg_base + DSIM_ESCMODE_REG);
605
606 if (lpm)
607 v |= DSIM_CMD_LPDT_LP;
608 else
609 v &= ~DSIM_CMD_LPDT_LP;
610
611 writel(v, dsi->reg_base + DSIM_ESCMODE_REG);
612}
613
614static void exynos_dsi_force_bta(struct exynos_dsi *dsi)
615{
616 u32 v = readl(dsi->reg_base + DSIM_ESCMODE_REG);
617
618 v |= DSIM_FORCE_BTA;
619 writel(v, dsi->reg_base + DSIM_ESCMODE_REG);
620}
621
622static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
623 struct exynos_dsi_transfer *xfer)
624{
625 struct device *dev = dsi->dev;
626 const u8 *payload = xfer->tx_payload + xfer->tx_done;
627 u16 length = xfer->tx_len - xfer->tx_done;
628 bool first = !xfer->tx_done;
629 u32 reg;
630
631 dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n",
632 xfer, xfer->tx_len, xfer->tx_done, xfer->rx_len, xfer->rx_done);
633
634 if (length > DSI_TX_FIFO_SIZE)
635 length = DSI_TX_FIFO_SIZE;
636
637 xfer->tx_done += length;
638
639 /* Send payload */
640 while (length >= 4) {
641 reg = (payload[3] << 24) | (payload[2] << 16)
642 | (payload[1] << 8) | payload[0];
643 writel(reg, dsi->reg_base + DSIM_PAYLOAD_REG);
644 payload += 4;
645 length -= 4;
646 }
647
648 reg = 0;
649 switch (length) {
650 case 3:
651 reg |= payload[2] << 16;
652 /* Fall through */
653 case 2:
654 reg |= payload[1] << 8;
655 /* Fall through */
656 case 1:
657 reg |= payload[0];
658 writel(reg, dsi->reg_base + DSIM_PAYLOAD_REG);
659 break;
660 case 0:
661 /* Do nothing */
662 break;
663 }
664
665 /* Send packet header */
666 if (!first)
667 return;
668
669 reg = (xfer->data[1] << 16) | (xfer->data[0] << 8) | xfer->data_id;
670 if (exynos_dsi_wait_for_hdr_fifo(dsi)) {
671 dev_err(dev, "waiting for header FIFO timed out\n");
672 return;
673 }
674
675 if (NEQV(xfer->flags & MIPI_DSI_MSG_USE_LPM,
676 dsi->state & DSIM_STATE_CMD_LPM)) {
677 exynos_dsi_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM);
678 dsi->state ^= DSIM_STATE_CMD_LPM;
679 }
680
681 writel(reg, dsi->reg_base + DSIM_PKTHDR_REG);
682
683 if (xfer->flags & MIPI_DSI_MSG_REQ_ACK)
684 exynos_dsi_force_bta(dsi);
685}
686
687static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
688 struct exynos_dsi_transfer *xfer)
689{
690 u8 *payload = xfer->rx_payload + xfer->rx_done;
691 bool first = !xfer->rx_done;
692 struct device *dev = dsi->dev;
693 u16 length;
694 u32 reg;
695
696 if (first) {
697 reg = readl(dsi->reg_base + DSIM_RXFIFO_REG);
698
699 switch (reg & 0x3f) {
700 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
701 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
702 if (xfer->rx_len >= 2) {
703 payload[1] = reg >> 16;
704 ++xfer->rx_done;
705 }
706 /* Fall through */
707 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
708 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
709 payload[0] = reg >> 8;
710 ++xfer->rx_done;
711 xfer->rx_len = xfer->rx_done;
712 xfer->result = 0;
713 goto clear_fifo;
714 case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
715 dev_err(dev, "DSI Error Report: 0x%04x\n",
716 (reg >> 8) & 0xffff);
717 xfer->result = 0;
718 goto clear_fifo;
719 }
720
721 length = (reg >> 8) & 0xffff;
722 if (length > xfer->rx_len) {
723 dev_err(dev,
724 "response too long (%u > %u bytes), stripping\n",
725 xfer->rx_len, length);
726 length = xfer->rx_len;
727 } else if (length < xfer->rx_len)
728 xfer->rx_len = length;
729 }
730
731 length = xfer->rx_len - xfer->rx_done;
732 xfer->rx_done += length;
733
734 /* Receive payload */
735 while (length >= 4) {
736 reg = readl(dsi->reg_base + DSIM_RXFIFO_REG);
737 payload[0] = (reg >> 0) & 0xff;
738 payload[1] = (reg >> 8) & 0xff;
739 payload[2] = (reg >> 16) & 0xff;
740 payload[3] = (reg >> 24) & 0xff;
741 payload += 4;
742 length -= 4;
743 }
744
745 if (length) {
746 reg = readl(dsi->reg_base + DSIM_RXFIFO_REG);
747 switch (length) {
748 case 3:
749 payload[2] = (reg >> 16) & 0xff;
750 /* Fall through */
751 case 2:
752 payload[1] = (reg >> 8) & 0xff;
753 /* Fall through */
754 case 1:
755 payload[0] = reg & 0xff;
756 }
757 }
758
759 if (xfer->rx_done == xfer->rx_len)
760 xfer->result = 0;
761
762clear_fifo:
763 length = DSI_RX_FIFO_SIZE / 4;
764 do {
765 reg = readl(dsi->reg_base + DSIM_RXFIFO_REG);
766 if (reg == DSI_RX_FIFO_EMPTY)
767 break;
768 } while (--length);
769}
770
771static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
772{
773 unsigned long flags;
774 struct exynos_dsi_transfer *xfer;
775 bool start = false;
776
777again:
778 spin_lock_irqsave(&dsi->transfer_lock, flags);
779
780 if (list_empty(&dsi->transfer_list)) {
781 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
782 return;
783 }
784
785 xfer = list_first_entry(&dsi->transfer_list,
786 struct exynos_dsi_transfer, list);
787
788 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
789
790 if (xfer->tx_len && xfer->tx_done == xfer->tx_len)
791 /* waiting for RX */
792 return;
793
794 exynos_dsi_send_to_fifo(dsi, xfer);
795
796 if (xfer->tx_len || xfer->rx_len)
797 return;
798
799 xfer->result = 0;
800 complete(&xfer->completed);
801
802 spin_lock_irqsave(&dsi->transfer_lock, flags);
803
804 list_del_init(&xfer->list);
805 start = !list_empty(&dsi->transfer_list);
806
807 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
808
809 if (start)
810 goto again;
811}
812
813static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
814{
815 struct exynos_dsi_transfer *xfer;
816 unsigned long flags;
817 bool start = true;
818
819 spin_lock_irqsave(&dsi->transfer_lock, flags);
820
821 if (list_empty(&dsi->transfer_list)) {
822 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
823 return false;
824 }
825
826 xfer = list_first_entry(&dsi->transfer_list,
827 struct exynos_dsi_transfer, list);
828
829 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
830
831 dev_dbg(dsi->dev,
832 "> xfer %p, tx_len %u, tx_done %u, rx_len %u, rx_done %u\n",
833 xfer, xfer->tx_len, xfer->tx_done, xfer->rx_len, xfer->rx_done);
834
835 if (xfer->tx_done != xfer->tx_len)
836 return true;
837
838 if (xfer->rx_done != xfer->rx_len)
839 exynos_dsi_read_from_fifo(dsi, xfer);
840
841 if (xfer->rx_done != xfer->rx_len)
842 return true;
843
844 spin_lock_irqsave(&dsi->transfer_lock, flags);
845
846 list_del_init(&xfer->list);
847 start = !list_empty(&dsi->transfer_list);
848
849 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
850
851 if (!xfer->rx_len)
852 xfer->result = 0;
853 complete(&xfer->completed);
854
855 return start;
856}
857
858static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
859 struct exynos_dsi_transfer *xfer)
860{
861 unsigned long flags;
862 bool start;
863
864 spin_lock_irqsave(&dsi->transfer_lock, flags);
865
866 if (!list_empty(&dsi->transfer_list) &&
867 xfer == list_first_entry(&dsi->transfer_list,
868 struct exynos_dsi_transfer, list)) {
869 list_del_init(&xfer->list);
870 start = !list_empty(&dsi->transfer_list);
871 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
872 if (start)
873 exynos_dsi_transfer_start(dsi);
874 return;
875 }
876
877 list_del_init(&xfer->list);
878
879 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
880}
881
882static int exynos_dsi_transfer(struct exynos_dsi *dsi,
883 struct exynos_dsi_transfer *xfer)
884{
885 unsigned long flags;
886 bool stopped;
887
888 xfer->tx_done = 0;
889 xfer->rx_done = 0;
890 xfer->result = -ETIMEDOUT;
891 init_completion(&xfer->completed);
892
893 spin_lock_irqsave(&dsi->transfer_lock, flags);
894
895 stopped = list_empty(&dsi->transfer_list);
896 list_add_tail(&xfer->list, &dsi->transfer_list);
897
898 spin_unlock_irqrestore(&dsi->transfer_lock, flags);
899
900 if (stopped)
901 exynos_dsi_transfer_start(dsi);
902
903 wait_for_completion_timeout(&xfer->completed,
904 msecs_to_jiffies(DSI_XFER_TIMEOUT_MS));
905 if (xfer->result == -ETIMEDOUT) {
906 exynos_dsi_remove_transfer(dsi, xfer);
907 dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 2, xfer->data,
908 xfer->tx_len, xfer->tx_payload);
909 return -ETIMEDOUT;
910 }
911
912 /* Also covers hardware timeout condition */
913 return xfer->result;
914}
915
916static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
917{
918 struct exynos_dsi *dsi = dev_id;
919 u32 status;
920
921 status = readl(dsi->reg_base + DSIM_INTSRC_REG);
922 if (!status) {
923 static unsigned long int j;
924 if (printk_timed_ratelimit(&j, 500))
925 dev_warn(dsi->dev, "spurious interrupt\n");
926 return IRQ_HANDLED;
927 }
928 writel(status, dsi->reg_base + DSIM_INTSRC_REG);
929
930 if (status & DSIM_INT_SW_RST_RELEASE) {
931 u32 mask = ~(DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY);
932 writel(mask, dsi->reg_base + DSIM_INTMSK_REG);
933 complete(&dsi->completed);
934 return IRQ_HANDLED;
935 }
936
937 if (!(status & (DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY)))
938 return IRQ_HANDLED;
939
940 if (exynos_dsi_transfer_finish(dsi))
941 exynos_dsi_transfer_start(dsi);
942
943 return IRQ_HANDLED;
944}
945
946static int exynos_dsi_init(struct exynos_dsi *dsi)
947{
948 exynos_dsi_enable_clock(dsi);
949 exynos_dsi_reset(dsi);
950 enable_irq(dsi->irq);
951 exynos_dsi_wait_for_reset(dsi);
952 exynos_dsi_init_link(dsi);
953
954 return 0;
955}
956
957static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
958 struct mipi_dsi_device *device)
959{
960 struct exynos_dsi *dsi = host_to_dsi(host);
961
962 dsi->lanes = device->lanes;
963 dsi->format = device->format;
964 dsi->mode_flags = device->mode_flags;
965 dsi->panel_node = device->dev.of_node;
966
967 if (dsi->connector.dev)
968 drm_helper_hpd_irq_event(dsi->connector.dev);
969
970 return 0;
971}
972
973static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
974 struct mipi_dsi_device *device)
975{
976 struct exynos_dsi *dsi = host_to_dsi(host);
977
978 dsi->panel_node = NULL;
979
980 if (dsi->connector.dev)
981 drm_helper_hpd_irq_event(dsi->connector.dev);
982
983 return 0;
984}
985
986/* distinguish between short and long DSI packet types */
987static bool exynos_dsi_is_short_dsi_type(u8 type)
988{
989 return (type & 0x0f) <= 8;
990}
991
992static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
993 struct mipi_dsi_msg *msg)
994{
995 struct exynos_dsi *dsi = host_to_dsi(host);
996 struct exynos_dsi_transfer xfer;
997 int ret;
998
999 if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
1000 ret = exynos_dsi_init(dsi);
1001 if (ret)
1002 return ret;
1003 dsi->state |= DSIM_STATE_INITIALIZED;
1004 }
1005
1006 if (msg->tx_len == 0)
1007 return -EINVAL;
1008
1009 xfer.data_id = msg->type | (msg->channel << 6);
1010
1011 if (exynos_dsi_is_short_dsi_type(msg->type)) {
1012 const char *tx_buf = msg->tx_buf;
1013
1014 if (msg->tx_len > 2)
1015 return -EINVAL;
1016 xfer.tx_len = 0;
1017 xfer.data[0] = tx_buf[0];
1018 xfer.data[1] = (msg->tx_len == 2) ? tx_buf[1] : 0;
1019 } else {
1020 xfer.tx_len = msg->tx_len;
1021 xfer.data[0] = msg->tx_len & 0xff;
1022 xfer.data[1] = msg->tx_len >> 8;
1023 xfer.tx_payload = msg->tx_buf;
1024 }
1025
1026 xfer.rx_len = msg->rx_len;
1027 xfer.rx_payload = msg->rx_buf;
1028 xfer.flags = msg->flags;
1029
1030 ret = exynos_dsi_transfer(dsi, &xfer);
1031 return (ret < 0) ? ret : xfer.rx_done;
1032}
1033
1034static const struct mipi_dsi_host_ops exynos_dsi_ops = {
1035 .attach = exynos_dsi_host_attach,
1036 .detach = exynos_dsi_host_detach,
1037 .transfer = exynos_dsi_host_transfer,
1038};
1039
1040static int exynos_dsi_poweron(struct exynos_dsi *dsi)
1041{
1042 int ret;
1043
1044 ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
1045 if (ret < 0) {
1046 dev_err(dsi->dev, "cannot enable regulators %d\n", ret);
1047 return ret;
1048 }
1049
1050 ret = clk_prepare_enable(dsi->bus_clk);
1051 if (ret < 0) {
1052 dev_err(dsi->dev, "cannot enable bus clock %d\n", ret);
1053 goto err_bus_clk;
1054 }
1055
1056 ret = clk_prepare_enable(dsi->pll_clk);
1057 if (ret < 0) {
1058 dev_err(dsi->dev, "cannot enable pll clock %d\n", ret);
1059 goto err_pll_clk;
1060 }
1061
1062 ret = phy_power_on(dsi->phy);
1063 if (ret < 0) {
1064 dev_err(dsi->dev, "cannot enable phy %d\n", ret);
1065 goto err_phy;
1066 }
1067
1068 return 0;
1069
1070err_phy:
1071 clk_disable_unprepare(dsi->pll_clk);
1072err_pll_clk:
1073 clk_disable_unprepare(dsi->bus_clk);
1074err_bus_clk:
1075 regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
1076
1077 return ret;
1078}
1079
1080static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
1081{
1082 int ret;
1083
1084 usleep_range(10000, 20000);
1085
1086 if (dsi->state & DSIM_STATE_INITIALIZED) {
1087 dsi->state &= ~DSIM_STATE_INITIALIZED;
1088
1089 exynos_dsi_disable_clock(dsi);
1090
1091 disable_irq(dsi->irq);
1092 }
1093
1094 dsi->state &= ~DSIM_STATE_CMD_LPM;
1095
1096 phy_power_off(dsi->phy);
1097
1098 clk_disable_unprepare(dsi->pll_clk);
1099 clk_disable_unprepare(dsi->bus_clk);
1100
1101 ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
1102 if (ret < 0)
1103 dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
1104}
1105
1106static int exynos_dsi_enable(struct exynos_dsi *dsi)
1107{
1108 int ret;
1109
1110 if (dsi->state & DSIM_STATE_ENABLED)
1111 return 0;
1112
1113 ret = exynos_dsi_poweron(dsi);
1114 if (ret < 0)
1115 return ret;
1116
1117 ret = drm_panel_enable(dsi->panel);
1118 if (ret < 0) {
1119 exynos_dsi_poweroff(dsi);
1120 return ret;
1121 }
1122
1123 exynos_dsi_set_display_mode(dsi);
1124 exynos_dsi_set_display_enable(dsi, true);
1125
1126 dsi->state |= DSIM_STATE_ENABLED;
1127
1128 return 0;
1129}
1130
1131static void exynos_dsi_disable(struct exynos_dsi *dsi)
1132{
1133 if (!(dsi->state & DSIM_STATE_ENABLED))
1134 return;
1135
1136 exynos_dsi_set_display_enable(dsi, false);
1137 drm_panel_disable(dsi->panel);
1138 exynos_dsi_poweroff(dsi);
1139
1140 dsi->state &= ~DSIM_STATE_ENABLED;
1141}
1142
1143static void exynos_dsi_dpms(struct exynos_drm_display *display, int mode)
1144{
1145 struct exynos_dsi *dsi = display->ctx;
1146
1147 if (dsi->panel) {
1148 switch (mode) {
1149 case DRM_MODE_DPMS_ON:
1150 exynos_dsi_enable(dsi);
1151 break;
1152 case DRM_MODE_DPMS_STANDBY:
1153 case DRM_MODE_DPMS_SUSPEND:
1154 case DRM_MODE_DPMS_OFF:
1155 exynos_dsi_disable(dsi);
1156 break;
1157 default:
1158 break;
1159 }
1160 }
1161}
1162
1163static enum drm_connector_status
1164exynos_dsi_detect(struct drm_connector *connector, bool force)
1165{
1166 struct exynos_dsi *dsi = connector_to_dsi(connector);
1167
1168 if (!dsi->panel) {
1169 dsi->panel = of_drm_find_panel(dsi->panel_node);
1170 if (dsi->panel)
1171 drm_panel_attach(dsi->panel, &dsi->connector);
1172 } else if (!dsi->panel_node) {
1173 struct exynos_drm_display *display;
1174
1175 display = platform_get_drvdata(to_platform_device(dsi->dev));
1176 exynos_dsi_dpms(display, DRM_MODE_DPMS_OFF);
1177 drm_panel_detach(dsi->panel);
1178 dsi->panel = NULL;
1179 }
1180
1181 if (dsi->panel)
1182 return connector_status_connected;
1183
1184 return connector_status_disconnected;
1185}
1186
1187static void exynos_dsi_connector_destroy(struct drm_connector *connector)
1188{
1189}
1190
1191static struct drm_connector_funcs exynos_dsi_connector_funcs = {
1192 .dpms = drm_helper_connector_dpms,
1193 .detect = exynos_dsi_detect,
1194 .fill_modes = drm_helper_probe_single_connector_modes,
1195 .destroy = exynos_dsi_connector_destroy,
1196};
1197
1198static int exynos_dsi_get_modes(struct drm_connector *connector)
1199{
1200 struct exynos_dsi *dsi = connector_to_dsi(connector);
1201
1202 if (dsi->panel)
1203 return dsi->panel->funcs->get_modes(dsi->panel);
1204
1205 return 0;
1206}
1207
1208static int exynos_dsi_mode_valid(struct drm_connector *connector,
1209 struct drm_display_mode *mode)
1210{
1211 return MODE_OK;
1212}
1213
1214static struct drm_encoder *
1215exynos_dsi_best_encoder(struct drm_connector *connector)
1216{
1217 struct exynos_dsi *dsi = connector_to_dsi(connector);
1218
1219 return dsi->encoder;
1220}
1221
1222static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
1223 .get_modes = exynos_dsi_get_modes,
1224 .mode_valid = exynos_dsi_mode_valid,
1225 .best_encoder = exynos_dsi_best_encoder,
1226};
1227
1228static int exynos_dsi_create_connector(struct exynos_drm_display *display,
1229 struct drm_encoder *encoder)
1230{
1231 struct exynos_dsi *dsi = display->ctx;
1232 struct drm_connector *connector = &dsi->connector;
1233 int ret;
1234
1235 dsi->encoder = encoder;
1236
1237 connector->polled = DRM_CONNECTOR_POLL_HPD;
1238
1239 ret = drm_connector_init(encoder->dev, connector,
1240 &exynos_dsi_connector_funcs,
1241 DRM_MODE_CONNECTOR_DSI);
1242 if (ret) {
1243 DRM_ERROR("Failed to initialize connector with drm\n");
1244 return ret;
1245 }
1246
1247 drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
1248 drm_sysfs_connector_add(connector);
1249 drm_mode_connector_attach_encoder(connector, encoder);
1250
1251 return 0;
1252}
1253
1254static void exynos_dsi_mode_set(struct exynos_drm_display *display,
1255 struct drm_display_mode *mode)
1256{
1257 struct exynos_dsi *dsi = display->ctx;
1258 struct videomode *vm = &dsi->vm;
1259
1260 vm->hactive = mode->hdisplay;
1261 vm->vactive = mode->vdisplay;
1262 vm->vfront_porch = mode->vsync_start - mode->vdisplay;
1263 vm->vback_porch = mode->vtotal - mode->vsync_end;
1264 vm->vsync_len = mode->vsync_end - mode->vsync_start;
1265 vm->hfront_porch = mode->hsync_start - mode->hdisplay;
1266 vm->hback_porch = mode->htotal - mode->hsync_end;
1267 vm->hsync_len = mode->hsync_end - mode->hsync_start;
1268}
1269
1270static struct exynos_drm_display_ops exynos_dsi_display_ops = {
1271 .create_connector = exynos_dsi_create_connector,
1272 .mode_set = exynos_dsi_mode_set,
1273 .dpms = exynos_dsi_dpms
1274};
1275
1276static struct exynos_drm_display exynos_dsi_display = {
1277 .type = EXYNOS_DISPLAY_TYPE_LCD,
1278 .ops = &exynos_dsi_display_ops,
1279};
1280
1281/* of_* functions will be removed after merge of of_graph patches */
1282static struct device_node *
1283of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
1284{
1285 struct device_node *np;
1286
1287 for_each_child_of_node(parent, np) {
1288 u32 r;
1289
1290 if (!np->name || of_node_cmp(np->name, name))
1291 continue;
1292
1293 if (of_property_read_u32(np, "reg", &r) < 0)
1294 r = 0;
1295
1296 if (reg == r)
1297 break;
1298 }
1299
1300 return np;
1301}
1302
1303static struct device_node *of_graph_get_port_by_reg(struct device_node *parent,
1304 u32 reg)
1305{
1306 struct device_node *ports, *port;
1307
1308 ports = of_get_child_by_name(parent, "ports");
1309 if (ports)
1310 parent = ports;
1311
1312 port = of_get_child_by_name_reg(parent, "port", reg);
1313
1314 of_node_put(ports);
1315
1316 return port;
1317}
1318
1319static struct device_node *
1320of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg)
1321{
1322 return of_get_child_by_name_reg(port, "endpoint", reg);
1323}
1324
1325static int exynos_dsi_of_read_u32(const struct device_node *np,
1326 const char *propname, u32 *out_value)
1327{
1328 int ret = of_property_read_u32(np, propname, out_value);
1329
1330 if (ret < 0)
1331 pr_err("%s: failed to get '%s' property\n", np->full_name,
1332 propname);
1333
1334 return ret;
1335}
1336
1337enum {
1338 DSI_PORT_IN,
1339 DSI_PORT_OUT
1340};
1341
1342static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
1343{
1344 struct device *dev = dsi->dev;
1345 struct device_node *node = dev->of_node;
1346 struct device_node *port, *ep;
1347 int ret;
1348
1349 ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency",
1350 &dsi->pll_clk_rate);
1351 if (ret < 0)
1352 return ret;
1353
1354 port = of_graph_get_port_by_reg(node, DSI_PORT_OUT);
1355 if (!port) {
1356 dev_err(dev, "no output port specified\n");
1357 return -EINVAL;
1358 }
1359
1360 ep = of_graph_get_endpoint_by_reg(port, 0);
1361 of_node_put(port);
1362 if (!ep) {
1363 dev_err(dev, "no endpoint specified in output port\n");
1364 return -EINVAL;
1365 }
1366
1367 ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency",
1368 &dsi->burst_clk_rate);
1369 if (ret < 0)
1370 goto end;
1371
1372 ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
1373 &dsi->esc_clk_rate);
1374
1375end:
1376 of_node_put(ep);
1377
1378 return ret;
1379}
1380
1381static int exynos_dsi_probe(struct platform_device *pdev)
1382{
1383 struct resource *res;
1384 struct exynos_dsi *dsi;
1385 int ret;
1386
1387 dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
1388 if (!dsi) {
1389 dev_err(&pdev->dev, "failed to allocate dsi object.\n");
1390 return -ENOMEM;
1391 }
1392
1393 init_completion(&dsi->completed);
1394 spin_lock_init(&dsi->transfer_lock);
1395 INIT_LIST_HEAD(&dsi->transfer_list);
1396
1397 dsi->dsi_host.ops = &exynos_dsi_ops;
1398 dsi->dsi_host.dev = &pdev->dev;
1399
1400 dsi->dev = &pdev->dev;
1401
1402 ret = exynos_dsi_parse_dt(dsi);
1403 if (ret)
1404 return ret;
1405
1406 dsi->supplies[0].supply = "vddcore";
1407 dsi->supplies[1].supply = "vddio";
1408 ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(dsi->supplies),
1409 dsi->supplies);
1410 if (ret) {
1411 dev_info(&pdev->dev, "failed to get regulators: %d\n", ret);
1412 return -EPROBE_DEFER;
1413 }
1414
1415 dsi->pll_clk = devm_clk_get(&pdev->dev, "pll_clk");
1416 if (IS_ERR(dsi->pll_clk)) {
1417 dev_info(&pdev->dev, "failed to get dsi pll input clock\n");
1418 return -EPROBE_DEFER;
1419 }
1420
1421 dsi->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
1422 if (IS_ERR(dsi->bus_clk)) {
1423 dev_info(&pdev->dev, "failed to get dsi bus clock\n");
1424 return -EPROBE_DEFER;
1425 }
1426
1427 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1428 dsi->reg_base = devm_ioremap_resource(&pdev->dev, res);
1429 if (!dsi->reg_base) {
1430 dev_err(&pdev->dev, "failed to remap io region\n");
1431 return -EADDRNOTAVAIL;
1432 }
1433
1434 dsi->phy = devm_phy_get(&pdev->dev, "dsim");
1435 if (IS_ERR(dsi->phy)) {
1436 dev_info(&pdev->dev, "failed to get dsim phy\n");
1437 return -EPROBE_DEFER;
1438 }
1439
1440 dsi->irq = platform_get_irq(pdev, 0);
1441 if (dsi->irq < 0) {
1442 dev_err(&pdev->dev, "failed to request dsi irq resource\n");
1443 return dsi->irq;
1444 }
1445
1446 irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN);
1447 ret = devm_request_threaded_irq(&pdev->dev, dsi->irq, NULL,
1448 exynos_dsi_irq, IRQF_ONESHOT,
1449 dev_name(&pdev->dev), dsi);
1450 if (ret) {
1451 dev_err(&pdev->dev, "failed to request dsi irq\n");
1452 return ret;
1453 }
1454
1455 exynos_dsi_display.ctx = dsi;
1456
1457 platform_set_drvdata(pdev, &exynos_dsi_display);
1458 exynos_drm_display_register(&exynos_dsi_display);
1459
1460 return mipi_dsi_host_register(&dsi->dsi_host);
1461}
1462
1463static int exynos_dsi_remove(struct platform_device *pdev)
1464{
1465 struct exynos_dsi *dsi = exynos_dsi_display.ctx;
1466
1467 exynos_dsi_dpms(&exynos_dsi_display, DRM_MODE_DPMS_OFF);
1468
1469 exynos_drm_display_unregister(&exynos_dsi_display);
1470 mipi_dsi_host_unregister(&dsi->dsi_host);
1471
1472 return 0;
1473}
1474
1475#if CONFIG_PM_SLEEP
1476static int exynos_dsi_resume(struct device *dev)
1477{
1478 struct exynos_dsi *dsi = exynos_dsi_display.ctx;
1479
1480 if (dsi->state & DSIM_STATE_ENABLED) {
1481 dsi->state &= ~DSIM_STATE_ENABLED;
1482 exynos_dsi_enable(dsi);
1483 }
1484
1485 return 0;
1486}
1487
1488static int exynos_dsi_suspend(struct device *dev)
1489{
1490 struct exynos_dsi *dsi = exynos_dsi_display.ctx;
1491
1492 if (dsi->state & DSIM_STATE_ENABLED) {
1493 exynos_dsi_disable(dsi);
1494 dsi->state |= DSIM_STATE_ENABLED;
1495 }
1496
1497 return 0;
1498}
1499#endif
1500
1501static const struct dev_pm_ops exynos_dsi_pm_ops = {
1502 SET_SYSTEM_SLEEP_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume)
1503};
1504
1505static struct of_device_id exynos_dsi_of_match[] = {
1506 { .compatible = "samsung,exynos4210-mipi-dsi" },
1507 { }
1508};
1509
1510struct platform_driver dsi_driver = {
1511 .probe = exynos_dsi_probe,
1512 .remove = exynos_dsi_remove,
1513 .driver = {
1514 .name = "exynos-dsi",
1515 .owner = THIS_MODULE,
1516 .pm = &exynos_dsi_pm_ops,
1517 .of_match_table = exynos_dsi_of_match,
1518 },
1519};
1520
1521MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1522MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1523MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
1524MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 06f1b2a09da7..7e282e3d6038 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -17,7 +17,6 @@
17 17
18#include "exynos_drm_drv.h" 18#include "exynos_drm_drv.h"
19#include "exynos_drm_encoder.h" 19#include "exynos_drm_encoder.h"
20#include "exynos_drm_connector.h"
21 20
22#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ 21#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\
23 drm_encoder) 22 drm_encoder)
@@ -26,72 +25,22 @@
26 * exynos specific encoder structure. 25 * exynos specific encoder structure.
27 * 26 *
28 * @drm_encoder: encoder object. 27 * @drm_encoder: encoder object.
29 * @manager: specific encoder has its own manager to control a hardware 28 * @display: the display structure that maps to this encoder
30 * appropriately and we can access a hardware drawing on this manager.
31 * @dpms: store the encoder dpms value.
32 * @updated: indicate whether overlay data updating is needed or not.
33 */ 29 */
34struct exynos_drm_encoder { 30struct exynos_drm_encoder {
35 struct drm_crtc *old_crtc;
36 struct drm_encoder drm_encoder; 31 struct drm_encoder drm_encoder;
37 struct exynos_drm_manager *manager; 32 struct exynos_drm_display *display;
38 int dpms;
39 bool updated;
40}; 33};
41 34
42static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
43{
44 struct drm_device *dev = encoder->dev;
45 struct drm_connector *connector;
46
47 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
48 if (exynos_drm_best_encoder(connector) == encoder) {
49 DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
50 connector->base.id, mode);
51
52 exynos_drm_display_power(connector, mode);
53 }
54 }
55}
56
57static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) 35static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
58{ 36{
59 struct drm_device *dev = encoder->dev;
60 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
61 struct exynos_drm_manager_ops *manager_ops = manager->ops;
62 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 37 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
38 struct exynos_drm_display *display = exynos_encoder->display;
63 39
64 DRM_DEBUG_KMS("encoder dpms: %d\n", mode); 40 DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
65 41
66 if (exynos_encoder->dpms == mode) { 42 if (display->ops->dpms)
67 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); 43 display->ops->dpms(display, mode);
68 return;
69 }
70
71 mutex_lock(&dev->struct_mutex);
72
73 switch (mode) {
74 case DRM_MODE_DPMS_ON:
75 if (manager_ops && manager_ops->apply)
76 if (!exynos_encoder->updated)
77 manager_ops->apply(manager->dev);
78
79 exynos_drm_connector_power(encoder, mode);
80 exynos_encoder->dpms = mode;
81 break;
82 case DRM_MODE_DPMS_STANDBY:
83 case DRM_MODE_DPMS_SUSPEND:
84 case DRM_MODE_DPMS_OFF:
85 exynos_drm_connector_power(encoder, mode);
86 exynos_encoder->dpms = mode;
87 exynos_encoder->updated = false;
88 break;
89 default:
90 DRM_ERROR("unspecified mode %d\n", mode);
91 break;
92 }
93
94 mutex_unlock(&dev->struct_mutex);
95} 44}
96 45
97static bool 46static bool
@@ -100,87 +49,31 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
100 struct drm_display_mode *adjusted_mode) 49 struct drm_display_mode *adjusted_mode)
101{ 50{
102 struct drm_device *dev = encoder->dev; 51 struct drm_device *dev = encoder->dev;
52 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
53 struct exynos_drm_display *display = exynos_encoder->display;
103 struct drm_connector *connector; 54 struct drm_connector *connector;
104 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
105 struct exynos_drm_manager_ops *manager_ops = manager->ops;
106 55
107 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 56 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
108 if (connector->encoder == encoder) 57 if (connector->encoder != encoder)
109 if (manager_ops && manager_ops->mode_fixup) 58 continue;
110 manager_ops->mode_fixup(manager->dev, connector, 59
111 mode, adjusted_mode); 60 if (display->ops->mode_fixup)
61 display->ops->mode_fixup(display, connector, mode,
62 adjusted_mode);
112 } 63 }
113 64
114 return true; 65 return true;
115} 66}
116 67
117static void disable_plane_to_crtc(struct drm_device *dev,
118 struct drm_crtc *old_crtc,
119 struct drm_crtc *new_crtc)
120{
121 struct drm_plane *plane;
122
123 /*
124 * if old_crtc isn't same as encoder->crtc then it means that
125 * user changed crtc id to another one so the plane to old_crtc
126 * should be disabled and plane->crtc should be set to new_crtc
127 * (encoder->crtc)
128 */
129 list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
130 if (plane->crtc == old_crtc) {
131 /*
132 * do not change below call order.
133 *
134 * plane->funcs->disable_plane call checks
135 * if encoder->crtc is same as plane->crtc and if same
136 * then overlay_ops->disable callback will be called
137 * to diasble current hw overlay so plane->crtc should
138 * have new_crtc because new_crtc was set to
139 * encoder->crtc in advance.
140 */
141 plane->crtc = new_crtc;
142 plane->funcs->disable_plane(plane);
143 }
144 }
145}
146
147static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, 68static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
148 struct drm_display_mode *mode, 69 struct drm_display_mode *mode,
149 struct drm_display_mode *adjusted_mode) 70 struct drm_display_mode *adjusted_mode)
150{ 71{
151 struct drm_device *dev = encoder->dev; 72 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
152 struct drm_connector *connector; 73 struct exynos_drm_display *display = exynos_encoder->display;
153 struct exynos_drm_manager *manager;
154 struct exynos_drm_manager_ops *manager_ops;
155
156 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
157 if (connector->encoder == encoder) {
158 struct exynos_drm_encoder *exynos_encoder;
159
160 exynos_encoder = to_exynos_encoder(encoder);
161
162 if (exynos_encoder->old_crtc != encoder->crtc &&
163 exynos_encoder->old_crtc) {
164
165 /*
166 * disable a plane to old crtc and change
167 * crtc of the plane to new one.
168 */
169 disable_plane_to_crtc(dev,
170 exynos_encoder->old_crtc,
171 encoder->crtc);
172 }
173
174 manager = exynos_drm_get_manager(encoder);
175 manager_ops = manager->ops;
176
177 if (manager_ops && manager_ops->mode_set)
178 manager_ops->mode_set(manager->dev,
179 adjusted_mode);
180 74
181 exynos_encoder->old_crtc = encoder->crtc; 75 if (display->ops->mode_set)
182 } 76 display->ops->mode_set(display, adjusted_mode);
183 }
184} 77}
185 78
186static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) 79static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
@@ -191,53 +84,15 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
191static void exynos_drm_encoder_commit(struct drm_encoder *encoder) 84static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
192{ 85{
193 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 86 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
194 struct exynos_drm_manager *manager = exynos_encoder->manager; 87 struct exynos_drm_display *display = exynos_encoder->display;
195 struct exynos_drm_manager_ops *manager_ops = manager->ops;
196
197 if (manager_ops && manager_ops->commit)
198 manager_ops->commit(manager->dev);
199
200 /*
201 * this will avoid one issue that overlay data is updated to
202 * real hardware two times.
203 * And this variable will be used to check if the data was
204 * already updated or not by exynos_drm_encoder_dpms function.
205 */
206 exynos_encoder->updated = true;
207
208 /*
209 * In case of setcrtc, there is no way to update encoder's dpms
210 * so update it here.
211 */
212 exynos_encoder->dpms = DRM_MODE_DPMS_ON;
213}
214 88
215void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) 89 if (display->ops->dpms)
216{ 90 display->ops->dpms(display, DRM_MODE_DPMS_ON);
217 struct exynos_drm_encoder *exynos_encoder;
218 struct exynos_drm_manager_ops *ops;
219 struct drm_device *dev = fb->dev;
220 struct drm_encoder *encoder;
221 91
222 /* 92 if (display->ops->commit)
223 * make sure that overlay data are updated to real hardware 93 display->ops->commit(display);
224 * for all encoders.
225 */
226 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
227 exynos_encoder = to_exynos_encoder(encoder);
228 ops = exynos_encoder->manager->ops;
229
230 /*
231 * wait for vblank interrupt
232 * - this makes sure that overlay data are updated to
233 * real hardware.
234 */
235 if (ops->wait_for_vblank)
236 ops->wait_for_vblank(exynos_encoder->manager->dev);
237 }
238} 94}
239 95
240
241static void exynos_drm_encoder_disable(struct drm_encoder *encoder) 96static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
242{ 97{
243 struct drm_plane *plane; 98 struct drm_plane *plane;
@@ -246,7 +101,7 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
246 exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 101 exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
247 102
248 /* all planes connected to this encoder should be also disabled. */ 103 /* all planes connected to this encoder should be also disabled. */
249 list_for_each_entry(plane, &dev->mode_config.plane_list, head) { 104 drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
250 if (plane->crtc == encoder->crtc) 105 if (plane->crtc == encoder->crtc)
251 plane->funcs->disable_plane(plane); 106 plane->funcs->disable_plane(plane);
252 } 107 }
@@ -263,10 +118,7 @@ static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
263 118
264static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) 119static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
265{ 120{
266 struct exynos_drm_encoder *exynos_encoder = 121 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
267 to_exynos_encoder(encoder);
268
269 exynos_encoder->manager->pipe = -1;
270 122
271 drm_encoder_cleanup(encoder); 123 drm_encoder_cleanup(encoder);
272 kfree(exynos_encoder); 124 kfree(exynos_encoder);
@@ -281,13 +133,12 @@ static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
281 struct drm_encoder *clone; 133 struct drm_encoder *clone;
282 struct drm_device *dev = encoder->dev; 134 struct drm_device *dev = encoder->dev;
283 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 135 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
284 struct exynos_drm_display_ops *display_ops = 136 struct exynos_drm_display *display = exynos_encoder->display;
285 exynos_encoder->manager->display_ops;
286 unsigned int clone_mask = 0; 137 unsigned int clone_mask = 0;
287 int cnt = 0; 138 int cnt = 0;
288 139
289 list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { 140 list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
290 switch (display_ops->type) { 141 switch (display->type) {
291 case EXYNOS_DISPLAY_TYPE_LCD: 142 case EXYNOS_DISPLAY_TYPE_LCD:
292 case EXYNOS_DISPLAY_TYPE_HDMI: 143 case EXYNOS_DISPLAY_TYPE_HDMI:
293 case EXYNOS_DISPLAY_TYPE_VIDI: 144 case EXYNOS_DISPLAY_TYPE_VIDI:
@@ -311,24 +162,20 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
311 162
312struct drm_encoder * 163struct drm_encoder *
313exynos_drm_encoder_create(struct drm_device *dev, 164exynos_drm_encoder_create(struct drm_device *dev,
314 struct exynos_drm_manager *manager, 165 struct exynos_drm_display *display,
315 unsigned int possible_crtcs) 166 unsigned long possible_crtcs)
316{ 167{
317 struct drm_encoder *encoder; 168 struct drm_encoder *encoder;
318 struct exynos_drm_encoder *exynos_encoder; 169 struct exynos_drm_encoder *exynos_encoder;
319 170
320 if (!manager || !possible_crtcs) 171 if (!possible_crtcs)
321 return NULL;
322
323 if (!manager->dev)
324 return NULL; 172 return NULL;
325 173
326 exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); 174 exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
327 if (!exynos_encoder) 175 if (!exynos_encoder)
328 return NULL; 176 return NULL;
329 177
330 exynos_encoder->dpms = DRM_MODE_DPMS_OFF; 178 exynos_encoder->display = display;
331 exynos_encoder->manager = manager;
332 encoder = &exynos_encoder->drm_encoder; 179 encoder = &exynos_encoder->drm_encoder;
333 encoder->possible_crtcs = possible_crtcs; 180 encoder->possible_crtcs = possible_crtcs;
334 181
@@ -344,149 +191,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
344 return encoder; 191 return encoder;
345} 192}
346 193
347struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) 194struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder)
348{
349 return to_exynos_encoder(encoder)->manager;
350}
351
352void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
353 void (*fn)(struct drm_encoder *, void *))
354{
355 struct drm_device *dev = crtc->dev;
356 struct drm_encoder *encoder;
357 struct exynos_drm_private *private = dev->dev_private;
358 struct exynos_drm_manager *manager;
359
360 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
361 /*
362 * if crtc is detached from encoder, check pipe,
363 * otherwise check crtc attached to encoder
364 */
365 if (!encoder->crtc) {
366 manager = to_exynos_encoder(encoder)->manager;
367 if (manager->pipe < 0 ||
368 private->crtc[manager->pipe] != crtc)
369 continue;
370 } else {
371 if (encoder->crtc != crtc)
372 continue;
373 }
374
375 fn(encoder, data);
376 }
377}
378
379void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
380{
381 struct exynos_drm_manager *manager =
382 to_exynos_encoder(encoder)->manager;
383 struct exynos_drm_manager_ops *manager_ops = manager->ops;
384 int crtc = *(int *)data;
385
386 if (manager->pipe != crtc)
387 return;
388
389 if (manager_ops->enable_vblank)
390 manager_ops->enable_vblank(manager->dev);
391}
392
393void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
394{
395 struct exynos_drm_manager *manager =
396 to_exynos_encoder(encoder)->manager;
397 struct exynos_drm_manager_ops *manager_ops = manager->ops;
398 int crtc = *(int *)data;
399
400 if (manager->pipe != crtc)
401 return;
402
403 if (manager_ops->disable_vblank)
404 manager_ops->disable_vblank(manager->dev);
405}
406
407void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
408{
409 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
410 struct exynos_drm_manager *manager = exynos_encoder->manager;
411 struct exynos_drm_manager_ops *manager_ops = manager->ops;
412 int mode = *(int *)data;
413
414 if (manager_ops && manager_ops->dpms)
415 manager_ops->dpms(manager->dev, mode);
416
417 /*
418 * if this condition is ok then it means that the crtc is already
419 * detached from encoder and last function for detaching is properly
420 * done, so clear pipe from manager to prevent repeated call.
421 */
422 if (mode > DRM_MODE_DPMS_ON) {
423 if (!encoder->crtc)
424 manager->pipe = -1;
425 }
426}
427
428void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
429{
430 struct exynos_drm_manager *manager =
431 to_exynos_encoder(encoder)->manager;
432 int pipe = *(int *)data;
433
434 /*
435 * when crtc is detached from encoder, this pipe is used
436 * to select manager operation
437 */
438 manager->pipe = pipe;
439}
440
441void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
442{
443 struct exynos_drm_manager *manager =
444 to_exynos_encoder(encoder)->manager;
445 struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
446 struct exynos_drm_overlay *overlay = data;
447
448 if (overlay_ops && overlay_ops->mode_set)
449 overlay_ops->mode_set(manager->dev, overlay);
450}
451
452void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
453{ 195{
454 struct exynos_drm_manager *manager = 196 return to_exynos_encoder(encoder)->display;
455 to_exynos_encoder(encoder)->manager;
456 struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
457 int zpos = DEFAULT_ZPOS;
458
459 if (data)
460 zpos = *(int *)data;
461
462 if (overlay_ops && overlay_ops->commit)
463 overlay_ops->commit(manager->dev, zpos);
464}
465
466void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
467{
468 struct exynos_drm_manager *manager =
469 to_exynos_encoder(encoder)->manager;
470 struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
471 int zpos = DEFAULT_ZPOS;
472
473 if (data)
474 zpos = *(int *)data;
475
476 if (overlay_ops && overlay_ops->enable)
477 overlay_ops->enable(manager->dev, zpos);
478}
479
480void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
481{
482 struct exynos_drm_manager *manager =
483 to_exynos_encoder(encoder)->manager;
484 struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
485 int zpos = DEFAULT_ZPOS;
486
487 if (data)
488 zpos = *(int *)data;
489
490 if (overlay_ops && overlay_ops->disable)
491 overlay_ops->disable(manager->dev, zpos);
492} 197}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
index 89e2fb0770af..b7a1620a7e79 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
@@ -18,20 +18,8 @@ struct exynos_drm_manager;
18 18
19void exynos_drm_encoder_setup(struct drm_device *dev); 19void exynos_drm_encoder_setup(struct drm_device *dev);
20struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, 20struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
21 struct exynos_drm_manager *mgr, 21 struct exynos_drm_display *mgr,
22 unsigned int possible_crtcs); 22 unsigned long possible_crtcs);
23struct exynos_drm_manager * 23struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder);
24exynos_drm_get_manager(struct drm_encoder *encoder);
25void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
26 void (*fn)(struct drm_encoder *, void *));
27void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
28void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
29void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
30void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data);
31void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data);
32void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data);
33void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data);
34void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data);
35void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb);
36 24
37#endif 25#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index ea39e0ef2ae4..65a22cad7b36 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -20,9 +20,10 @@
20 20
21#include "exynos_drm_drv.h" 21#include "exynos_drm_drv.h"
22#include "exynos_drm_fb.h" 22#include "exynos_drm_fb.h"
23#include "exynos_drm_fbdev.h"
23#include "exynos_drm_gem.h" 24#include "exynos_drm_gem.h"
24#include "exynos_drm_iommu.h" 25#include "exynos_drm_iommu.h"
25#include "exynos_drm_encoder.h" 26#include "exynos_drm_crtc.h"
26 27
27#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) 28#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
28 29
@@ -71,7 +72,7 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
71 unsigned int i; 72 unsigned int i;
72 73
73 /* make sure that overlay data are updated before relesing fb. */ 74 /* make sure that overlay data are updated before relesing fb. */
74 exynos_drm_encoder_complete_scanout(fb); 75 exynos_drm_crtc_complete_scanout(fb);
75 76
76 drm_framebuffer_cleanup(fb); 77 drm_framebuffer_cleanup(fb);
77 78
@@ -300,6 +301,8 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev)
300 301
301 if (fb_helper) 302 if (fb_helper)
302 drm_fb_helper_hotplug_event(fb_helper); 303 drm_fb_helper_hotplug_event(fb_helper);
304 else
305 exynos_drm_fbdev_init(dev);
303} 306}
304 307
305static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { 308static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index e7c2f2d07f19..addbf7536da4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -90,7 +90,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
90 /* RGB formats use only one buffer */ 90 /* RGB formats use only one buffer */
91 buffer = exynos_drm_fb_buffer(fb, 0); 91 buffer = exynos_drm_fb_buffer(fb, 0);
92 if (!buffer) { 92 if (!buffer) {
93 DRM_LOG_KMS("buffer is null.\n"); 93 DRM_DEBUG_KMS("buffer is null.\n");
94 return -EFAULT; 94 return -EFAULT;
95 } 95 }
96 96
@@ -237,6 +237,24 @@ static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
237 .fb_probe = exynos_drm_fbdev_create, 237 .fb_probe = exynos_drm_fbdev_create,
238}; 238};
239 239
240bool exynos_drm_fbdev_is_anything_connected(struct drm_device *dev)
241{
242 struct drm_connector *connector;
243 bool ret = false;
244
245 mutex_lock(&dev->mode_config.mutex);
246 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
247 if (connector->status != connector_status_connected)
248 continue;
249
250 ret = true;
251 break;
252 }
253 mutex_unlock(&dev->mode_config.mutex);
254
255 return ret;
256}
257
240int exynos_drm_fbdev_init(struct drm_device *dev) 258int exynos_drm_fbdev_init(struct drm_device *dev)
241{ 259{
242 struct exynos_drm_fbdev *fbdev; 260 struct exynos_drm_fbdev *fbdev;
@@ -248,6 +266,9 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
248 if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) 266 if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
249 return 0; 267 return 0;
250 268
269 if (!exynos_drm_fbdev_is_anything_connected(dev))
270 return 0;
271
251 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); 272 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
252 if (!fbdev) 273 if (!fbdev)
253 return -ENOMEM; 274 return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index a20440ce32e6..40fd6ccfcd6f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -62,7 +62,7 @@
62/* FIMD has totally five hardware windows. */ 62/* FIMD has totally five hardware windows. */
63#define WINDOWS_NR 5 63#define WINDOWS_NR 5
64 64
65#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev)) 65#define get_fimd_manager(mgr) platform_get_drvdata(to_platform_device(dev))
66 66
67struct fimd_driver_data { 67struct fimd_driver_data {
68 unsigned int timing_base; 68 unsigned int timing_base;
@@ -105,20 +105,18 @@ struct fimd_win_data {
105}; 105};
106 106
107struct fimd_context { 107struct fimd_context {
108 struct exynos_drm_subdrv subdrv; 108 struct device *dev;
109 int irq; 109 struct drm_device *drm_dev;
110 struct drm_crtc *crtc;
111 struct clk *bus_clk; 110 struct clk *bus_clk;
112 struct clk *lcd_clk; 111 struct clk *lcd_clk;
113 void __iomem *regs; 112 void __iomem *regs;
113 struct drm_display_mode mode;
114 struct fimd_win_data win_data[WINDOWS_NR]; 114 struct fimd_win_data win_data[WINDOWS_NR];
115 unsigned int clkdiv;
116 unsigned int default_win; 115 unsigned int default_win;
117 unsigned long irq_flags; 116 unsigned long irq_flags;
118 u32 vidcon0;
119 u32 vidcon1; 117 u32 vidcon1;
120 bool suspended; 118 bool suspended;
121 struct mutex lock; 119 int pipe;
122 wait_queue_head_t wait_vsync_queue; 120 wait_queue_head_t wait_vsync_queue;
123 atomic_t wait_vsync_event; 121 atomic_t wait_vsync_event;
124 122
@@ -145,153 +143,147 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
145 return (struct fimd_driver_data *)of_id->data; 143 return (struct fimd_driver_data *)of_id->data;
146} 144}
147 145
148static bool fimd_display_is_connected(struct device *dev) 146static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
147 struct drm_device *drm_dev, int pipe)
149{ 148{
150 /* TODO. */ 149 struct fimd_context *ctx = mgr->ctx;
151 150
152 return true; 151 ctx->drm_dev = drm_dev;
153} 152 ctx->pipe = pipe;
154 153
155static void *fimd_get_panel(struct device *dev) 154 /*
156{ 155 * enable drm irq mode.
157 struct fimd_context *ctx = get_fimd_context(dev); 156 * - with irq_enabled = true, we can use the vblank feature.
157 *
158 * P.S. note that we wouldn't use drm irq handler but
159 * just specific driver own one instead because
160 * drm framework supports only one irq handler.
161 */
162 drm_dev->irq_enabled = true;
158 163
159 return &ctx->panel; 164 /*
160} 165 * with vblank_disable_allowed = true, vblank interrupt will be disabled
166 * by drm timer once a current process gives up ownership of
167 * vblank event.(after drm_vblank_put function is called)
168 */
169 drm_dev->vblank_disable_allowed = true;
161 170
162static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode) 171 /* attach this sub driver to iommu mapping if supported. */
163{ 172 if (is_drm_iommu_supported(ctx->drm_dev))
164 /* TODO. */ 173 drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
165 174
166 return 0; 175 return 0;
167} 176}
168 177
169static int fimd_display_power_on(struct device *dev, int mode) 178static void fimd_mgr_remove(struct exynos_drm_manager *mgr)
170{ 179{
171 /* TODO */ 180 struct fimd_context *ctx = mgr->ctx;
172 181
173 return 0; 182 /* detach this sub driver from iommu mapping if supported. */
183 if (is_drm_iommu_supported(ctx->drm_dev))
184 drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
174} 185}
175 186
176static struct exynos_drm_display_ops fimd_display_ops = { 187static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
177 .type = EXYNOS_DISPLAY_TYPE_LCD, 188 const struct drm_display_mode *mode)
178 .is_connected = fimd_display_is_connected,
179 .get_panel = fimd_get_panel,
180 .check_mode = fimd_check_mode,
181 .power_on = fimd_display_power_on,
182};
183
184static void fimd_dpms(struct device *subdrv_dev, int mode)
185{ 189{
186 struct fimd_context *ctx = get_fimd_context(subdrv_dev); 190 unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
191 u32 clkdiv;
187 192
188 DRM_DEBUG_KMS("%d\n", mode); 193 /* Find the clock divider value that gets us closest to ideal_clk */
194 clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
189 195
190 mutex_lock(&ctx->lock); 196 return (clkdiv < 0x100) ? clkdiv : 0xff;
197}
191 198
192 switch (mode) { 199static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
193 case DRM_MODE_DPMS_ON: 200 const struct drm_display_mode *mode,
194 /* 201 struct drm_display_mode *adjusted_mode)
195 * enable fimd hardware only if suspended status. 202{
196 * 203 if (adjusted_mode->vrefresh == 0)
197 * P.S. fimd_dpms function would be called at booting time so 204 adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
198 * clk_enable could be called double time.
199 */
200 if (ctx->suspended)
201 pm_runtime_get_sync(subdrv_dev);
202 break;
203 case DRM_MODE_DPMS_STANDBY:
204 case DRM_MODE_DPMS_SUSPEND:
205 case DRM_MODE_DPMS_OFF:
206 if (!ctx->suspended)
207 pm_runtime_put_sync(subdrv_dev);
208 break;
209 default:
210 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
211 break;
212 }
213 205
214 mutex_unlock(&ctx->lock); 206 return true;
215} 207}
216 208
217static void fimd_apply(struct device *subdrv_dev) 209static void fimd_mode_set(struct exynos_drm_manager *mgr,
210 const struct drm_display_mode *in_mode)
218{ 211{
219 struct fimd_context *ctx = get_fimd_context(subdrv_dev); 212 struct fimd_context *ctx = mgr->ctx;
220 struct exynos_drm_manager *mgr = ctx->subdrv.manager;
221 struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
222 struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
223 struct fimd_win_data *win_data;
224 int i;
225
226 for (i = 0; i < WINDOWS_NR; i++) {
227 win_data = &ctx->win_data[i];
228 if (win_data->enabled && (ovl_ops && ovl_ops->commit))
229 ovl_ops->commit(subdrv_dev, i);
230 }
231 213
232 if (mgr_ops && mgr_ops->commit) 214 drm_mode_copy(&ctx->mode, in_mode);
233 mgr_ops->commit(subdrv_dev);
234} 215}
235 216
236static void fimd_commit(struct device *dev) 217static void fimd_commit(struct exynos_drm_manager *mgr)
237{ 218{
238 struct fimd_context *ctx = get_fimd_context(dev); 219 struct fimd_context *ctx = mgr->ctx;
239 struct exynos_drm_panel_info *panel = &ctx->panel; 220 struct drm_display_mode *mode = &ctx->mode;
240 struct videomode *vm = &panel->vm;
241 struct fimd_driver_data *driver_data; 221 struct fimd_driver_data *driver_data;
242 u32 val; 222 u32 val, clkdiv, vidcon1;
223 int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
243 224
244 driver_data = ctx->driver_data; 225 driver_data = ctx->driver_data;
245 if (ctx->suspended) 226 if (ctx->suspended)
246 return; 227 return;
247 228
248 /* setup polarity values from machine code. */ 229 /* nothing to do if we haven't set the mode yet */
249 writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); 230 if (mode->htotal == 0 || mode->vtotal == 0)
231 return;
232
233 /* setup polarity values */
234 vidcon1 = ctx->vidcon1;
235 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
236 vidcon1 |= VIDCON1_INV_VSYNC;
237 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
238 vidcon1 |= VIDCON1_INV_HSYNC;
239 writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
250 240
251 /* setup vertical timing values. */ 241 /* setup vertical timing values. */
252 val = VIDTCON0_VBPD(vm->vback_porch - 1) | 242 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
253 VIDTCON0_VFPD(vm->vfront_porch - 1) | 243 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
254 VIDTCON0_VSPW(vm->vsync_len - 1); 244 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
245
246 val = VIDTCON0_VBPD(vbpd - 1) |
247 VIDTCON0_VFPD(vfpd - 1) |
248 VIDTCON0_VSPW(vsync_len - 1);
255 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0); 249 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
256 250
257 /* setup horizontal timing values. */ 251 /* setup horizontal timing values. */
258 val = VIDTCON1_HBPD(vm->hback_porch - 1) | 252 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
259 VIDTCON1_HFPD(vm->hfront_porch - 1) | 253 hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
260 VIDTCON1_HSPW(vm->hsync_len - 1); 254 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
255
256 val = VIDTCON1_HBPD(hbpd - 1) |
257 VIDTCON1_HFPD(hfpd - 1) |
258 VIDTCON1_HSPW(hsync_len - 1);
261 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1); 259 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
262 260
263 /* setup horizontal and vertical display size. */ 261 /* setup horizontal and vertical display size. */
264 val = VIDTCON2_LINEVAL(vm->vactive - 1) | 262 val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
265 VIDTCON2_HOZVAL(vm->hactive - 1) | 263 VIDTCON2_HOZVAL(mode->hdisplay - 1) |
266 VIDTCON2_LINEVAL_E(vm->vactive - 1) | 264 VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
267 VIDTCON2_HOZVAL_E(vm->hactive - 1); 265 VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
268 writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); 266 writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
269 267
270 /* setup clock source, clock divider, enable dma. */
271 val = ctx->vidcon0;
272 val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
273
274 if (ctx->driver_data->has_clksel) {
275 val &= ~VIDCON0_CLKSEL_MASK;
276 val |= VIDCON0_CLKSEL_LCD;
277 }
278
279 if (ctx->clkdiv > 1)
280 val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
281 else
282 val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
283
284 /* 268 /*
285 * fields of register with prefix '_F' would be updated 269 * fields of register with prefix '_F' would be updated
286 * at vsync(same as dma start) 270 * at vsync(same as dma start)
287 */ 271 */
288 val |= VIDCON0_ENVID | VIDCON0_ENVID_F; 272 val = VIDCON0_ENVID | VIDCON0_ENVID_F;
273
274 if (ctx->driver_data->has_clksel)
275 val |= VIDCON0_CLKSEL_LCD;
276
277 clkdiv = fimd_calc_clkdiv(ctx, mode);
278 if (clkdiv > 1)
279 val |= VIDCON0_CLKVAL_F(clkdiv - 1) | VIDCON0_CLKDIR;
280
289 writel(val, ctx->regs + VIDCON0); 281 writel(val, ctx->regs + VIDCON0);
290} 282}
291 283
292static int fimd_enable_vblank(struct device *dev) 284static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
293{ 285{
294 struct fimd_context *ctx = get_fimd_context(dev); 286 struct fimd_context *ctx = mgr->ctx;
295 u32 val; 287 u32 val;
296 288
297 if (ctx->suspended) 289 if (ctx->suspended)
@@ -314,9 +306,9 @@ static int fimd_enable_vblank(struct device *dev)
314 return 0; 306 return 0;
315} 307}
316 308
317static void fimd_disable_vblank(struct device *dev) 309static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
318{ 310{
319 struct fimd_context *ctx = get_fimd_context(dev); 311 struct fimd_context *ctx = mgr->ctx;
320 u32 val; 312 u32 val;
321 313
322 if (ctx->suspended) 314 if (ctx->suspended)
@@ -332,9 +324,9 @@ static void fimd_disable_vblank(struct device *dev)
332 } 324 }
333} 325}
334 326
335static void fimd_wait_for_vblank(struct device *dev) 327static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
336{ 328{
337 struct fimd_context *ctx = get_fimd_context(dev); 329 struct fimd_context *ctx = mgr->ctx;
338 330
339 if (ctx->suspended) 331 if (ctx->suspended)
340 return; 332 return;
@@ -351,25 +343,16 @@ static void fimd_wait_for_vblank(struct device *dev)
351 DRM_DEBUG_KMS("vblank wait timed out.\n"); 343 DRM_DEBUG_KMS("vblank wait timed out.\n");
352} 344}
353 345
354static struct exynos_drm_manager_ops fimd_manager_ops = { 346static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
355 .dpms = fimd_dpms, 347 struct exynos_drm_overlay *overlay)
356 .apply = fimd_apply,
357 .commit = fimd_commit,
358 .enable_vblank = fimd_enable_vblank,
359 .disable_vblank = fimd_disable_vblank,
360 .wait_for_vblank = fimd_wait_for_vblank,
361};
362
363static void fimd_win_mode_set(struct device *dev,
364 struct exynos_drm_overlay *overlay)
365{ 348{
366 struct fimd_context *ctx = get_fimd_context(dev); 349 struct fimd_context *ctx = mgr->ctx;
367 struct fimd_win_data *win_data; 350 struct fimd_win_data *win_data;
368 int win; 351 int win;
369 unsigned long offset; 352 unsigned long offset;
370 353
371 if (!overlay) { 354 if (!overlay) {
372 dev_err(dev, "overlay is NULL\n"); 355 DRM_ERROR("overlay is NULL\n");
373 return; 356 return;
374 } 357 }
375 358
@@ -409,9 +392,8 @@ static void fimd_win_mode_set(struct device *dev,
409 overlay->fb_width, overlay->crtc_width); 392 overlay->fb_width, overlay->crtc_width);
410} 393}
411 394
412static void fimd_win_set_pixfmt(struct device *dev, unsigned int win) 395static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
413{ 396{
414 struct fimd_context *ctx = get_fimd_context(dev);
415 struct fimd_win_data *win_data = &ctx->win_data[win]; 397 struct fimd_win_data *win_data = &ctx->win_data[win];
416 unsigned long val; 398 unsigned long val;
417 399
@@ -467,9 +449,8 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
467 writel(val, ctx->regs + WINCON(win)); 449 writel(val, ctx->regs + WINCON(win));
468} 450}
469 451
470static void fimd_win_set_colkey(struct device *dev, unsigned int win) 452static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
471{ 453{
472 struct fimd_context *ctx = get_fimd_context(dev);
473 unsigned int keycon0 = 0, keycon1 = 0; 454 unsigned int keycon0 = 0, keycon1 = 0;
474 455
475 keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F | 456 keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
@@ -508,9 +489,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
508 writel(val, ctx->regs + reg); 489 writel(val, ctx->regs + reg);
509} 490}
510 491
511static void fimd_win_commit(struct device *dev, int zpos) 492static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
512{ 493{
513 struct fimd_context *ctx = get_fimd_context(dev); 494 struct fimd_context *ctx = mgr->ctx;
514 struct fimd_win_data *win_data; 495 struct fimd_win_data *win_data;
515 int win = zpos; 496 int win = zpos;
516 unsigned long val, alpha, size; 497 unsigned long val, alpha, size;
@@ -528,6 +509,12 @@ static void fimd_win_commit(struct device *dev, int zpos)
528 509
529 win_data = &ctx->win_data[win]; 510 win_data = &ctx->win_data[win];
530 511
512 /* If suspended, enable this on resume */
513 if (ctx->suspended) {
514 win_data->resume = true;
515 return;
516 }
517
531 /* 518 /*
532 * SHADOWCON/PRTCON register is used for enabling timing. 519 * SHADOWCON/PRTCON register is used for enabling timing.
533 * 520 *
@@ -605,11 +592,11 @@ static void fimd_win_commit(struct device *dev, int zpos)
605 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); 592 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
606 } 593 }
607 594
608 fimd_win_set_pixfmt(dev, win); 595 fimd_win_set_pixfmt(ctx, win);
609 596
610 /* hardware window 0 doesn't support color key. */ 597 /* hardware window 0 doesn't support color key. */
611 if (win != 0) 598 if (win != 0)
612 fimd_win_set_colkey(dev, win); 599 fimd_win_set_colkey(ctx, win);
613 600
614 /* wincon */ 601 /* wincon */
615 val = readl(ctx->regs + WINCON(win)); 602 val = readl(ctx->regs + WINCON(win));
@@ -628,9 +615,9 @@ static void fimd_win_commit(struct device *dev, int zpos)
628 win_data->enabled = true; 615 win_data->enabled = true;
629} 616}
630 617
631static void fimd_win_disable(struct device *dev, int zpos) 618static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
632{ 619{
633 struct fimd_context *ctx = get_fimd_context(dev); 620 struct fimd_context *ctx = mgr->ctx;
634 struct fimd_win_data *win_data; 621 struct fimd_win_data *win_data;
635 int win = zpos; 622 int win = zpos;
636 u32 val; 623 u32 val;
@@ -669,132 +656,6 @@ static void fimd_win_disable(struct device *dev, int zpos)
669 win_data->enabled = false; 656 win_data->enabled = false;
670} 657}
671 658
672static struct exynos_drm_overlay_ops fimd_overlay_ops = {
673 .mode_set = fimd_win_mode_set,
674 .commit = fimd_win_commit,
675 .disable = fimd_win_disable,
676};
677
678static struct exynos_drm_manager fimd_manager = {
679 .pipe = -1,
680 .ops = &fimd_manager_ops,
681 .overlay_ops = &fimd_overlay_ops,
682 .display_ops = &fimd_display_ops,
683};
684
685static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
686{
687 struct fimd_context *ctx = (struct fimd_context *)dev_id;
688 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
689 struct drm_device *drm_dev = subdrv->drm_dev;
690 struct exynos_drm_manager *manager = subdrv->manager;
691 u32 val;
692
693 val = readl(ctx->regs + VIDINTCON1);
694
695 if (val & VIDINTCON1_INT_FRAME)
696 /* VSYNC interrupt */
697 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
698
699 /* check the crtc is detached already from encoder */
700 if (manager->pipe < 0)
701 goto out;
702
703 drm_handle_vblank(drm_dev, manager->pipe);
704 exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
705
706 /* set wait vsync event to zero and wake up queue. */
707 if (atomic_read(&ctx->wait_vsync_event)) {
708 atomic_set(&ctx->wait_vsync_event, 0);
709 wake_up(&ctx->wait_vsync_queue);
710 }
711out:
712 return IRQ_HANDLED;
713}
714
715static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
716{
717 /*
718 * enable drm irq mode.
719 * - with irq_enabled = true, we can use the vblank feature.
720 *
721 * P.S. note that we wouldn't use drm irq handler but
722 * just specific driver own one instead because
723 * drm framework supports only one irq handler.
724 */
725 drm_dev->irq_enabled = true;
726
727 /*
728 * with vblank_disable_allowed = true, vblank interrupt will be disabled
729 * by drm timer once a current process gives up ownership of
730 * vblank event.(after drm_vblank_put function is called)
731 */
732 drm_dev->vblank_disable_allowed = true;
733
734 /* attach this sub driver to iommu mapping if supported. */
735 if (is_drm_iommu_supported(drm_dev))
736 drm_iommu_attach_device(drm_dev, dev);
737
738 return 0;
739}
740
741static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
742{
743 /* detach this sub driver from iommu mapping if supported. */
744 if (is_drm_iommu_supported(drm_dev))
745 drm_iommu_detach_device(drm_dev, dev);
746}
747
748static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
749{
750 struct videomode *vm = &ctx->panel.vm;
751 unsigned long clk;
752
753 ctx->bus_clk = devm_clk_get(dev, "fimd");
754 if (IS_ERR(ctx->bus_clk)) {
755 dev_err(dev, "failed to get bus clock\n");
756 return PTR_ERR(ctx->bus_clk);
757 }
758
759 ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
760 if (IS_ERR(ctx->lcd_clk)) {
761 dev_err(dev, "failed to get lcd clock\n");
762 return PTR_ERR(ctx->lcd_clk);
763 }
764
765 clk = clk_get_rate(ctx->lcd_clk);
766 if (clk == 0) {
767 dev_err(dev, "error getting sclk_fimd clock rate\n");
768 return -EINVAL;
769 }
770
771 if (vm->pixelclock == 0) {
772 unsigned long c;
773 c = vm->hactive + vm->hback_porch + vm->hfront_porch +
774 vm->hsync_len;
775 c *= vm->vactive + vm->vback_porch + vm->vfront_porch +
776 vm->vsync_len;
777 vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE;
778 if (vm->pixelclock == 0) {
779 dev_err(dev, "incorrect display timings\n");
780 return -EINVAL;
781 }
782 dev_warn(dev, "pixel clock recalculated to %luHz (%dHz frame rate)\n",
783 vm->pixelclock, FIMD_DEFAULT_FRAMERATE);
784 }
785 ctx->clkdiv = DIV_ROUND_UP(clk, vm->pixelclock);
786 if (ctx->clkdiv > 256) {
787 dev_warn(dev, "calculated pixel clock divider too high (%u), lowered to 256\n",
788 ctx->clkdiv);
789 ctx->clkdiv = 256;
790 }
791 vm->pixelclock = clk / ctx->clkdiv;
792 DRM_DEBUG_KMS("pixel clock = %lu, clkdiv = %d\n", vm->pixelclock,
793 ctx->clkdiv);
794
795 return 0;
796}
797
798static void fimd_clear_win(struct fimd_context *ctx, int win) 659static void fimd_clear_win(struct fimd_context *ctx, int win)
799{ 660{
800 writel(0, ctx->regs + WINCON(win)); 661 writel(0, ctx->regs + WINCON(win));
@@ -808,111 +669,190 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
808 fimd_shadow_protect_win(ctx, win, false); 669 fimd_shadow_protect_win(ctx, win, false);
809} 670}
810 671
811static int fimd_clock(struct fimd_context *ctx, bool enable) 672static void fimd_window_suspend(struct exynos_drm_manager *mgr)
812{ 673{
813 if (enable) { 674 struct fimd_context *ctx = mgr->ctx;
814 int ret; 675 struct fimd_win_data *win_data;
815 676 int i;
816 ret = clk_prepare_enable(ctx->bus_clk);
817 if (ret < 0)
818 return ret;
819 677
820 ret = clk_prepare_enable(ctx->lcd_clk); 678 for (i = 0; i < WINDOWS_NR; i++) {
821 if (ret < 0) { 679 win_data = &ctx->win_data[i];
822 clk_disable_unprepare(ctx->bus_clk); 680 win_data->resume = win_data->enabled;
823 return ret; 681 if (win_data->enabled)
824 } 682 fimd_win_disable(mgr, i);
825 } else {
826 clk_disable_unprepare(ctx->lcd_clk);
827 clk_disable_unprepare(ctx->bus_clk);
828 } 683 }
829 684 fimd_wait_for_vblank(mgr);
830 return 0;
831} 685}
832 686
833static void fimd_window_suspend(struct device *dev) 687static void fimd_window_resume(struct exynos_drm_manager *mgr)
834{ 688{
835 struct fimd_context *ctx = get_fimd_context(dev); 689 struct fimd_context *ctx = mgr->ctx;
836 struct fimd_win_data *win_data; 690 struct fimd_win_data *win_data;
837 int i; 691 int i;
838 692
839 for (i = 0; i < WINDOWS_NR; i++) { 693 for (i = 0; i < WINDOWS_NR; i++) {
840 win_data = &ctx->win_data[i]; 694 win_data = &ctx->win_data[i];
841 win_data->resume = win_data->enabled; 695 win_data->enabled = win_data->resume;
842 fimd_win_disable(dev, i); 696 win_data->resume = false;
843 } 697 }
844 fimd_wait_for_vblank(dev);
845} 698}
846 699
847static void fimd_window_resume(struct device *dev) 700static void fimd_apply(struct exynos_drm_manager *mgr)
848{ 701{
849 struct fimd_context *ctx = get_fimd_context(dev); 702 struct fimd_context *ctx = mgr->ctx;
850 struct fimd_win_data *win_data; 703 struct fimd_win_data *win_data;
851 int i; 704 int i;
852 705
853 for (i = 0; i < WINDOWS_NR; i++) { 706 for (i = 0; i < WINDOWS_NR; i++) {
854 win_data = &ctx->win_data[i]; 707 win_data = &ctx->win_data[i];
855 win_data->enabled = win_data->resume; 708 if (win_data->enabled)
856 win_data->resume = false; 709 fimd_win_commit(mgr, i);
857 } 710 }
711
712 fimd_commit(mgr);
858} 713}
859 714
860static int fimd_activate(struct fimd_context *ctx, bool enable) 715static int fimd_poweron(struct exynos_drm_manager *mgr)
861{ 716{
862 struct device *dev = ctx->subdrv.dev; 717 struct fimd_context *ctx = mgr->ctx;
863 if (enable) { 718 int ret;
864 int ret;
865 719
866 ret = fimd_clock(ctx, true); 720 if (!ctx->suspended)
867 if (ret < 0) 721 return 0;
868 return ret;
869 722
870 ctx->suspended = false; 723 ctx->suspended = false;
871 724
872 /* if vblank was enabled status, enable it again. */ 725 pm_runtime_get_sync(ctx->dev);
873 if (test_and_clear_bit(0, &ctx->irq_flags))
874 fimd_enable_vblank(dev);
875 726
876 fimd_window_resume(dev); 727 ret = clk_prepare_enable(ctx->bus_clk);
877 } else { 728 if (ret < 0) {
878 fimd_window_suspend(dev); 729 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
730 goto bus_clk_err;
731 }
732
733 ret = clk_prepare_enable(ctx->lcd_clk);
734 if (ret < 0) {
735 DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
736 goto lcd_clk_err;
737 }
879 738
880 fimd_clock(ctx, false); 739 /* if vblank was enabled status, enable it again. */
881 ctx->suspended = true; 740 if (test_and_clear_bit(0, &ctx->irq_flags)) {
741 ret = fimd_enable_vblank(mgr);
742 if (ret) {
743 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
744 goto enable_vblank_err;
745 }
882 } 746 }
883 747
748 fimd_window_resume(mgr);
749
750 fimd_apply(mgr);
751
884 return 0; 752 return 0;
753
754enable_vblank_err:
755 clk_disable_unprepare(ctx->lcd_clk);
756lcd_clk_err:
757 clk_disable_unprepare(ctx->bus_clk);
758bus_clk_err:
759 ctx->suspended = true;
760 return ret;
885} 761}
886 762
887static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev) 763static int fimd_poweroff(struct exynos_drm_manager *mgr)
888{ 764{
889 struct videomode *vm; 765 struct fimd_context *ctx = mgr->ctx;
890 int ret;
891 766
892 vm = &ctx->panel.vm; 767 if (ctx->suspended)
893 ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE); 768 return 0;
894 if (ret) {
895 DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
896 return ret;
897 }
898 769
899 if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW) 770 /*
900 ctx->vidcon1 |= VIDCON1_INV_VSYNC; 771 * We need to make sure that all windows are disabled before we
901 if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW) 772 * suspend that connector. Otherwise we might try to scan from
902 ctx->vidcon1 |= VIDCON1_INV_HSYNC; 773 * a destroyed buffer later.
903 if (vm->flags & DISPLAY_FLAGS_DE_LOW) 774 */
904 ctx->vidcon1 |= VIDCON1_INV_VDEN; 775 fimd_window_suspend(mgr);
905 if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
906 ctx->vidcon1 |= VIDCON1_INV_VCLK;
907 776
777 clk_disable_unprepare(ctx->lcd_clk);
778 clk_disable_unprepare(ctx->bus_clk);
779
780 pm_runtime_put_sync(ctx->dev);
781
782 ctx->suspended = true;
908 return 0; 783 return 0;
909} 784}
910 785
786static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
787{
788 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
789
790 switch (mode) {
791 case DRM_MODE_DPMS_ON:
792 fimd_poweron(mgr);
793 break;
794 case DRM_MODE_DPMS_STANDBY:
795 case DRM_MODE_DPMS_SUSPEND:
796 case DRM_MODE_DPMS_OFF:
797 fimd_poweroff(mgr);
798 break;
799 default:
800 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
801 break;
802 }
803}
804
805static struct exynos_drm_manager_ops fimd_manager_ops = {
806 .initialize = fimd_mgr_initialize,
807 .remove = fimd_mgr_remove,
808 .dpms = fimd_dpms,
809 .mode_fixup = fimd_mode_fixup,
810 .mode_set = fimd_mode_set,
811 .commit = fimd_commit,
812 .enable_vblank = fimd_enable_vblank,
813 .disable_vblank = fimd_disable_vblank,
814 .wait_for_vblank = fimd_wait_for_vblank,
815 .win_mode_set = fimd_win_mode_set,
816 .win_commit = fimd_win_commit,
817 .win_disable = fimd_win_disable,
818};
819
820static struct exynos_drm_manager fimd_manager = {
821 .type = EXYNOS_DISPLAY_TYPE_LCD,
822 .ops = &fimd_manager_ops,
823};
824
825static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
826{
827 struct fimd_context *ctx = (struct fimd_context *)dev_id;
828 u32 val;
829
830 val = readl(ctx->regs + VIDINTCON1);
831
832 if (val & VIDINTCON1_INT_FRAME)
833 /* VSYNC interrupt */
834 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
835
836 /* check the crtc is detached already from encoder */
837 if (ctx->pipe < 0 || !ctx->drm_dev)
838 goto out;
839
840 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
841 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
842
843 /* set wait vsync event to zero and wake up queue. */
844 if (atomic_read(&ctx->wait_vsync_event)) {
845 atomic_set(&ctx->wait_vsync_event, 0);
846 wake_up(&ctx->wait_vsync_queue);
847 }
848out:
849 return IRQ_HANDLED;
850}
851
911static int fimd_probe(struct platform_device *pdev) 852static int fimd_probe(struct platform_device *pdev)
912{ 853{
913 struct device *dev = &pdev->dev; 854 struct device *dev = &pdev->dev;
914 struct fimd_context *ctx; 855 struct fimd_context *ctx;
915 struct exynos_drm_subdrv *subdrv;
916 struct resource *res; 856 struct resource *res;
917 int win; 857 int win;
918 int ret = -EINVAL; 858 int ret = -EINVAL;
@@ -924,13 +864,25 @@ static int fimd_probe(struct platform_device *pdev)
924 if (!ctx) 864 if (!ctx)
925 return -ENOMEM; 865 return -ENOMEM;
926 866
927 ret = fimd_get_platform_data(ctx, dev); 867 ctx->dev = dev;
928 if (ret) 868 ctx->suspended = true;
929 return ret;
930 869
931 ret = fimd_configure_clocks(ctx, dev); 870 if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
932 if (ret) 871 ctx->vidcon1 |= VIDCON1_INV_VDEN;
933 return ret; 872 if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
873 ctx->vidcon1 |= VIDCON1_INV_VCLK;
874
875 ctx->bus_clk = devm_clk_get(dev, "fimd");
876 if (IS_ERR(ctx->bus_clk)) {
877 dev_err(dev, "failed to get bus clock\n");
878 return PTR_ERR(ctx->bus_clk);
879 }
880
881 ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
882 if (IS_ERR(ctx->lcd_clk)) {
883 dev_err(dev, "failed to get lcd clock\n");
884 return PTR_ERR(ctx->lcd_clk);
885 }
934 886
935 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 887 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
936 888
@@ -944,9 +896,7 @@ static int fimd_probe(struct platform_device *pdev)
944 return -ENXIO; 896 return -ENXIO;
945 } 897 }
946 898
947 ctx->irq = res->start; 899 ret = devm_request_irq(dev, res->start, fimd_irq_handler,
948
949 ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
950 0, "drm_fimd", ctx); 900 0, "drm_fimd", ctx);
951 if (ret) { 901 if (ret) {
952 dev_err(dev, "irq request failed.\n"); 902 dev_err(dev, "irq request failed.\n");
@@ -957,112 +907,35 @@ static int fimd_probe(struct platform_device *pdev)
957 init_waitqueue_head(&ctx->wait_vsync_queue); 907 init_waitqueue_head(&ctx->wait_vsync_queue);
958 atomic_set(&ctx->wait_vsync_event, 0); 908 atomic_set(&ctx->wait_vsync_event, 0);
959 909
960 subdrv = &ctx->subdrv; 910 platform_set_drvdata(pdev, &fimd_manager);
961 911
962 subdrv->dev = dev; 912 fimd_manager.ctx = ctx;
963 subdrv->manager = &fimd_manager; 913 exynos_drm_manager_register(&fimd_manager);
964 subdrv->probe = fimd_subdrv_probe;
965 subdrv->remove = fimd_subdrv_remove;
966 914
967 mutex_init(&ctx->lock); 915 exynos_dpi_probe(ctx->dev);
968
969 platform_set_drvdata(pdev, ctx);
970 916
971 pm_runtime_enable(dev); 917 pm_runtime_enable(dev);
972 pm_runtime_get_sync(dev);
973 918
974 for (win = 0; win < WINDOWS_NR; win++) 919 for (win = 0; win < WINDOWS_NR; win++)
975 fimd_clear_win(ctx, win); 920 fimd_clear_win(ctx, win);
976 921
977 exynos_drm_subdrv_register(subdrv);
978
979 return 0; 922 return 0;
980} 923}
981 924
982static int fimd_remove(struct platform_device *pdev) 925static int fimd_remove(struct platform_device *pdev)
983{ 926{
984 struct device *dev = &pdev->dev; 927 struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
985 struct fimd_context *ctx = platform_get_drvdata(pdev);
986
987 exynos_drm_subdrv_unregister(&ctx->subdrv);
988
989 if (ctx->suspended)
990 goto out;
991
992 pm_runtime_set_suspended(dev);
993 pm_runtime_put_sync(dev);
994
995out:
996 pm_runtime_disable(dev);
997
998 return 0;
999}
1000
1001#ifdef CONFIG_PM_SLEEP
1002static int fimd_suspend(struct device *dev)
1003{
1004 struct fimd_context *ctx = get_fimd_context(dev);
1005 928
1006 /* 929 exynos_dpi_remove(&pdev->dev);
1007 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
1008 * called here, an error would be returned by that interface
1009 * because the usage_count of pm runtime is more than 1.
1010 */
1011 if (!pm_runtime_suspended(dev))
1012 return fimd_activate(ctx, false);
1013 930
1014 return 0; 931 exynos_drm_manager_unregister(&fimd_manager);
1015}
1016 932
1017static int fimd_resume(struct device *dev) 933 fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
1018{
1019 struct fimd_context *ctx = get_fimd_context(dev);
1020 934
1021 /* 935 pm_runtime_disable(&pdev->dev);
1022 * if entered to sleep when lcd panel was on, the usage_count
1023 * of pm runtime would still be 1 so in this case, fimd driver
1024 * should be on directly not drawing on pm runtime interface.
1025 */
1026 if (!pm_runtime_suspended(dev)) {
1027 int ret;
1028
1029 ret = fimd_activate(ctx, true);
1030 if (ret < 0)
1031 return ret;
1032
1033 /*
1034 * in case of dpms on(standby), fimd_apply function will
1035 * be called by encoder's dpms callback to update fimd's
1036 * registers but in case of sleep wakeup, it's not.
1037 * so fimd_apply function should be called at here.
1038 */
1039 fimd_apply(dev);
1040 }
1041 936
1042 return 0; 937 return 0;
1043} 938}
1044#endif
1045
1046#ifdef CONFIG_PM_RUNTIME
1047static int fimd_runtime_suspend(struct device *dev)
1048{
1049 struct fimd_context *ctx = get_fimd_context(dev);
1050
1051 return fimd_activate(ctx, false);
1052}
1053
1054static int fimd_runtime_resume(struct device *dev)
1055{
1056 struct fimd_context *ctx = get_fimd_context(dev);
1057
1058 return fimd_activate(ctx, true);
1059}
1060#endif
1061
1062static const struct dev_pm_ops fimd_pm_ops = {
1063 SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1064 SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1065};
1066 939
1067struct platform_driver fimd_driver = { 940struct platform_driver fimd_driver = {
1068 .probe = fimd_probe, 941 .probe = fimd_probe,
@@ -1070,7 +943,6 @@ struct platform_driver fimd_driver = {
1070 .driver = { 943 .driver = {
1071 .name = "exynos4-fb", 944 .name = "exynos4-fb",
1072 .owner = THIS_MODULE, 945 .owner = THIS_MODULE,
1073 .pm = &fimd_pm_ops,
1074 .of_match_table = fimd_driver_dt_match, 946 .of_match_table = fimd_driver_dt_match,
1075 }, 947 },
1076}; 948};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
deleted file mode 100644
index 8548b974bd59..000000000000
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ /dev/null
@@ -1,439 +0,0 @@
1/*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Inki Dae <inki.dae@samsung.com>
5 * Seung-Woo Kim <sw0312.kim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <drm/drmP.h>
15
16#include <linux/kernel.h>
17#include <linux/wait.h>
18#include <linux/platform_device.h>
19#include <linux/pm_runtime.h>
20
21#include <drm/exynos_drm.h>
22
23#include "exynos_drm_drv.h"
24#include "exynos_drm_hdmi.h"
25
26#define to_context(dev) platform_get_drvdata(to_platform_device(dev))
27#define to_subdrv(dev) to_context(dev)
28#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
29 struct drm_hdmi_context, subdrv);
30
31/* platform device pointer for common drm hdmi device. */
32static struct platform_device *exynos_drm_hdmi_pdev;
33
34/* Common hdmi subdrv needs to access the hdmi and mixer though context.
35* These should be initialied by the repective drivers */
36static struct exynos_drm_hdmi_context *hdmi_ctx;
37static struct exynos_drm_hdmi_context *mixer_ctx;
38
39/* these callback points shoud be set by specific drivers. */
40static struct exynos_hdmi_ops *hdmi_ops;
41static struct exynos_mixer_ops *mixer_ops;
42
43struct drm_hdmi_context {
44 struct exynos_drm_subdrv subdrv;
45 struct exynos_drm_hdmi_context *hdmi_ctx;
46 struct exynos_drm_hdmi_context *mixer_ctx;
47
48 bool enabled[MIXER_WIN_NR];
49};
50
51int exynos_platform_device_hdmi_register(void)
52{
53 struct platform_device *pdev;
54
55 if (exynos_drm_hdmi_pdev)
56 return -EEXIST;
57
58 pdev = platform_device_register_simple(
59 "exynos-drm-hdmi", -1, NULL, 0);
60 if (IS_ERR(pdev))
61 return PTR_ERR(pdev);
62
63 exynos_drm_hdmi_pdev = pdev;
64
65 return 0;
66}
67
68void exynos_platform_device_hdmi_unregister(void)
69{
70 if (exynos_drm_hdmi_pdev) {
71 platform_device_unregister(exynos_drm_hdmi_pdev);
72 exynos_drm_hdmi_pdev = NULL;
73 }
74}
75
76void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)
77{
78 if (ctx)
79 hdmi_ctx = ctx;
80}
81
82void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
83{
84 if (ctx)
85 mixer_ctx = ctx;
86}
87
88void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
89{
90 if (ops)
91 hdmi_ops = ops;
92}
93
94void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
95{
96 if (ops)
97 mixer_ops = ops;
98}
99
100static bool drm_hdmi_is_connected(struct device *dev)
101{
102 struct drm_hdmi_context *ctx = to_context(dev);
103
104 if (hdmi_ops && hdmi_ops->is_connected)
105 return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
106
107 return false;
108}
109
110static struct edid *drm_hdmi_get_edid(struct device *dev,
111 struct drm_connector *connector)
112{
113 struct drm_hdmi_context *ctx = to_context(dev);
114
115 if (hdmi_ops && hdmi_ops->get_edid)
116 return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
117
118 return NULL;
119}
120
121static int drm_hdmi_check_mode(struct device *dev,
122 struct drm_display_mode *mode)
123{
124 struct drm_hdmi_context *ctx = to_context(dev);
125 int ret = 0;
126
127 /*
128 * Both, mixer and hdmi should be able to handle the requested mode.
129 * If any of the two fails, return mode as BAD.
130 */
131
132 if (mixer_ops && mixer_ops->check_mode)
133 ret = mixer_ops->check_mode(ctx->mixer_ctx->ctx, mode);
134
135 if (ret)
136 return ret;
137
138 if (hdmi_ops && hdmi_ops->check_mode)
139 return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
140
141 return 0;
142}
143
144static int drm_hdmi_power_on(struct device *dev, int mode)
145{
146 struct drm_hdmi_context *ctx = to_context(dev);
147
148 if (hdmi_ops && hdmi_ops->power_on)
149 return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
150
151 return 0;
152}
153
154static struct exynos_drm_display_ops drm_hdmi_display_ops = {
155 .type = EXYNOS_DISPLAY_TYPE_HDMI,
156 .is_connected = drm_hdmi_is_connected,
157 .get_edid = drm_hdmi_get_edid,
158 .check_mode = drm_hdmi_check_mode,
159 .power_on = drm_hdmi_power_on,
160};
161
162static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
163{
164 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
165 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
166 struct exynos_drm_manager *manager = subdrv->manager;
167
168 if (mixer_ops && mixer_ops->enable_vblank)
169 return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
170 manager->pipe);
171
172 return 0;
173}
174
175static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
176{
177 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
178
179 if (mixer_ops && mixer_ops->disable_vblank)
180 return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
181}
182
183static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
184{
185 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
186
187 if (mixer_ops && mixer_ops->wait_for_vblank)
188 mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
189}
190
191static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
192 struct drm_connector *connector,
193 const struct drm_display_mode *mode,
194 struct drm_display_mode *adjusted_mode)
195{
196 struct drm_display_mode *m;
197 int mode_ok;
198
199 drm_mode_set_crtcinfo(adjusted_mode, 0);
200
201 mode_ok = drm_hdmi_check_mode(subdrv_dev, adjusted_mode);
202
203 /* just return if user desired mode exists. */
204 if (mode_ok == 0)
205 return;
206
207 /*
208 * otherwise, find the most suitable mode among modes and change it
209 * to adjusted_mode.
210 */
211 list_for_each_entry(m, &connector->modes, head) {
212 mode_ok = drm_hdmi_check_mode(subdrv_dev, m);
213
214 if (mode_ok == 0) {
215 struct drm_mode_object base;
216 struct list_head head;
217
218 DRM_INFO("desired mode doesn't exist so\n");
219 DRM_INFO("use the most suitable mode among modes.\n");
220
221 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
222 m->hdisplay, m->vdisplay, m->vrefresh);
223
224 /* preserve display mode header while copying. */
225 head = adjusted_mode->head;
226 base = adjusted_mode->base;
227 memcpy(adjusted_mode, m, sizeof(*m));
228 adjusted_mode->head = head;
229 adjusted_mode->base = base;
230 break;
231 }
232 }
233}
234
235static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
236{
237 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
238
239 if (hdmi_ops && hdmi_ops->mode_set)
240 hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
241}
242
243static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
244 unsigned int *width, unsigned int *height)
245{
246 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
247
248 if (hdmi_ops && hdmi_ops->get_max_resol)
249 hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
250}
251
252static void drm_hdmi_commit(struct device *subdrv_dev)
253{
254 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
255
256 if (hdmi_ops && hdmi_ops->commit)
257 hdmi_ops->commit(ctx->hdmi_ctx->ctx);
258}
259
260static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
261{
262 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
263
264 if (mixer_ops && mixer_ops->dpms)
265 mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
266
267 if (hdmi_ops && hdmi_ops->dpms)
268 hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
269}
270
271static void drm_hdmi_apply(struct device *subdrv_dev)
272{
273 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
274 int i;
275
276 for (i = 0; i < MIXER_WIN_NR; i++) {
277 if (!ctx->enabled[i])
278 continue;
279 if (mixer_ops && mixer_ops->win_commit)
280 mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
281 }
282
283 if (hdmi_ops && hdmi_ops->commit)
284 hdmi_ops->commit(ctx->hdmi_ctx->ctx);
285}
286
287static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
288 .dpms = drm_hdmi_dpms,
289 .apply = drm_hdmi_apply,
290 .enable_vblank = drm_hdmi_enable_vblank,
291 .disable_vblank = drm_hdmi_disable_vblank,
292 .wait_for_vblank = drm_hdmi_wait_for_vblank,
293 .mode_fixup = drm_hdmi_mode_fixup,
294 .mode_set = drm_hdmi_mode_set,
295 .get_max_resol = drm_hdmi_get_max_resol,
296 .commit = drm_hdmi_commit,
297};
298
299static void drm_mixer_mode_set(struct device *subdrv_dev,
300 struct exynos_drm_overlay *overlay)
301{
302 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
303
304 if (mixer_ops && mixer_ops->win_mode_set)
305 mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
306}
307
308static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
309{
310 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
311 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
312
313 if (win < 0 || win >= MIXER_WIN_NR) {
314 DRM_ERROR("mixer window[%d] is wrong\n", win);
315 return;
316 }
317
318 if (mixer_ops && mixer_ops->win_commit)
319 mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
320
321 ctx->enabled[win] = true;
322}
323
324static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
325{
326 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
327 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
328
329 if (win < 0 || win >= MIXER_WIN_NR) {
330 DRM_ERROR("mixer window[%d] is wrong\n", win);
331 return;
332 }
333
334 if (mixer_ops && mixer_ops->win_disable)
335 mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
336
337 ctx->enabled[win] = false;
338}
339
340static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
341 .mode_set = drm_mixer_mode_set,
342 .commit = drm_mixer_commit,
343 .disable = drm_mixer_disable,
344};
345
346static struct exynos_drm_manager hdmi_manager = {
347 .pipe = -1,
348 .ops = &drm_hdmi_manager_ops,
349 .overlay_ops = &drm_hdmi_overlay_ops,
350 .display_ops = &drm_hdmi_display_ops,
351};
352
353static int hdmi_subdrv_probe(struct drm_device *drm_dev,
354 struct device *dev)
355{
356 struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
357 struct drm_hdmi_context *ctx;
358
359 if (!hdmi_ctx) {
360 DRM_ERROR("hdmi context not initialized.\n");
361 return -EFAULT;
362 }
363
364 if (!mixer_ctx) {
365 DRM_ERROR("mixer context not initialized.\n");
366 return -EFAULT;
367 }
368
369 ctx = get_ctx_from_subdrv(subdrv);
370
371 if (!ctx) {
372 DRM_ERROR("no drm hdmi context.\n");
373 return -EFAULT;
374 }
375
376 ctx->hdmi_ctx = hdmi_ctx;
377 ctx->mixer_ctx = mixer_ctx;
378
379 ctx->hdmi_ctx->drm_dev = drm_dev;
380 ctx->mixer_ctx->drm_dev = drm_dev;
381
382 if (mixer_ops->iommu_on)
383 mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
384
385 return 0;
386}
387
388static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
389{
390 struct drm_hdmi_context *ctx;
391 struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
392
393 ctx = get_ctx_from_subdrv(subdrv);
394
395 if (mixer_ops->iommu_on)
396 mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
397}
398
399static int exynos_drm_hdmi_probe(struct platform_device *pdev)
400{
401 struct device *dev = &pdev->dev;
402 struct exynos_drm_subdrv *subdrv;
403 struct drm_hdmi_context *ctx;
404
405 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
406 if (!ctx)
407 return -ENOMEM;
408
409 subdrv = &ctx->subdrv;
410
411 subdrv->dev = dev;
412 subdrv->manager = &hdmi_manager;
413 subdrv->probe = hdmi_subdrv_probe;
414 subdrv->remove = hdmi_subdrv_remove;
415
416 platform_set_drvdata(pdev, subdrv);
417
418 exynos_drm_subdrv_register(subdrv);
419
420 return 0;
421}
422
423static int exynos_drm_hdmi_remove(struct platform_device *pdev)
424{
425 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
426
427 exynos_drm_subdrv_unregister(&ctx->subdrv);
428
429 return 0;
430}
431
432struct platform_driver exynos_drm_common_hdmi_driver = {
433 .probe = exynos_drm_hdmi_probe,
434 .remove = exynos_drm_hdmi_remove,
435 .driver = {
436 .name = "exynos-drm-hdmi",
437 .owner = THIS_MODULE,
438 },
439};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
deleted file mode 100644
index 724cab181976..000000000000
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ /dev/null
@@ -1,67 +0,0 @@
1/* exynos_drm_hdmi.h
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Authoer: Inki Dae <inki.dae@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _EXYNOS_DRM_HDMI_H_
13#define _EXYNOS_DRM_HDMI_H_
14
15#define MIXER_WIN_NR 3
16#define MIXER_DEFAULT_WIN 0
17
18/*
19 * exynos hdmi common context structure.
20 *
21 * @drm_dev: pointer to drm_device.
22 * @ctx: pointer to the context of specific device driver.
23 * this context should be hdmi_context or mixer_context.
24 */
25struct exynos_drm_hdmi_context {
26 struct drm_device *drm_dev;
27 void *ctx;
28};
29
30struct exynos_hdmi_ops {
31 /* display */
32 bool (*is_connected)(void *ctx);
33 struct edid *(*get_edid)(void *ctx,
34 struct drm_connector *connector);
35 int (*check_mode)(void *ctx, struct drm_display_mode *mode);
36 int (*power_on)(void *ctx, int mode);
37
38 /* manager */
39 void (*mode_set)(void *ctx, struct drm_display_mode *mode);
40 void (*get_max_resol)(void *ctx, unsigned int *width,
41 unsigned int *height);
42 void (*commit)(void *ctx);
43 void (*dpms)(void *ctx, int mode);
44};
45
46struct exynos_mixer_ops {
47 /* manager */
48 int (*iommu_on)(void *ctx, bool enable);
49 int (*enable_vblank)(void *ctx, int pipe);
50 void (*disable_vblank)(void *ctx);
51 void (*wait_for_vblank)(void *ctx);
52 void (*dpms)(void *ctx, int mode);
53
54 /* overlay */
55 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
56 void (*win_commit)(void *ctx, int zpos);
57 void (*win_disable)(void *ctx, int zpos);
58
59 /* display */
60 int (*check_mode)(void *ctx, struct drm_display_mode *mode);
61};
62
63void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
64void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx);
65void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
66void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
67#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index fcb0652e77d0..8371cbd7631d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -13,7 +13,7 @@
13 13
14#include <drm/exynos_drm.h> 14#include <drm/exynos_drm.h>
15#include "exynos_drm_drv.h" 15#include "exynos_drm_drv.h"
16#include "exynos_drm_encoder.h" 16#include "exynos_drm_crtc.h"
17#include "exynos_drm_fb.h" 17#include "exynos_drm_fb.h"
18#include "exynos_drm_gem.h" 18#include "exynos_drm_gem.h"
19#include "exynos_drm_plane.h" 19#include "exynos_drm_plane.h"
@@ -87,7 +87,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
87 struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); 87 struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
88 88
89 if (!buffer) { 89 if (!buffer) {
90 DRM_LOG_KMS("buffer is null\n"); 90 DRM_DEBUG_KMS("buffer is null\n");
91 return -EFAULT; 91 return -EFAULT;
92 } 92 }
93 93
@@ -139,7 +139,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
139 overlay->crtc_x, overlay->crtc_y, 139 overlay->crtc_x, overlay->crtc_y,
140 overlay->crtc_width, overlay->crtc_height); 140 overlay->crtc_width, overlay->crtc_height);
141 141
142 exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set); 142 exynos_drm_crtc_plane_mode_set(crtc, overlay);
143 143
144 return 0; 144 return 0;
145} 145}
@@ -149,8 +149,7 @@ void exynos_plane_commit(struct drm_plane *plane)
149 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 149 struct exynos_plane *exynos_plane = to_exynos_plane(plane);
150 struct exynos_drm_overlay *overlay = &exynos_plane->overlay; 150 struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
151 151
152 exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 152 exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos);
153 exynos_drm_encoder_plane_commit);
154} 153}
155 154
156void exynos_plane_dpms(struct drm_plane *plane, int mode) 155void exynos_plane_dpms(struct drm_plane *plane, int mode)
@@ -162,17 +161,13 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
162 if (exynos_plane->enabled) 161 if (exynos_plane->enabled)
163 return; 162 return;
164 163
165 exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 164 exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos);
166 exynos_drm_encoder_plane_enable);
167
168 exynos_plane->enabled = true; 165 exynos_plane->enabled = true;
169 } else { 166 } else {
170 if (!exynos_plane->enabled) 167 if (!exynos_plane->enabled)
171 return; 168 return;
172 169
173 exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 170 exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos);
174 exynos_drm_encoder_plane_disable);
175
176 exynos_plane->enabled = false; 171 exynos_plane->enabled = false;
177 } 172 }
178} 173}
@@ -259,7 +254,7 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
259} 254}
260 255
261struct drm_plane *exynos_plane_init(struct drm_device *dev, 256struct drm_plane *exynos_plane_init(struct drm_device *dev,
262 unsigned int possible_crtcs, bool priv) 257 unsigned long possible_crtcs, bool priv)
263{ 258{
264 struct exynos_plane *exynos_plane; 259 struct exynos_plane *exynos_plane;
265 int err; 260 int err;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 88312458580d..84d464c90d3d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -17,4 +17,4 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
17void exynos_plane_commit(struct drm_plane *plane); 17void exynos_plane_commit(struct drm_plane *plane);
18void exynos_plane_dpms(struct drm_plane *plane, int mode); 18void exynos_plane_dpms(struct drm_plane *plane, int mode);
19struct drm_plane *exynos_plane_init(struct drm_device *dev, 19struct drm_plane *exynos_plane_init(struct drm_device *dev,
20 unsigned int possible_crtcs, bool priv); 20 unsigned long possible_crtcs, bool priv);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index ddaaedde173d..7afead9c3f30 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -28,7 +28,9 @@
28/* vidi has totally three virtual windows. */ 28/* vidi has totally three virtual windows. */
29#define WINDOWS_NR 3 29#define WINDOWS_NR 3
30 30
31#define get_vidi_context(dev) platform_get_drvdata(to_platform_device(dev)) 31#define get_vidi_mgr(dev) platform_get_drvdata(to_platform_device(dev))
32#define ctx_from_connector(c) container_of(c, struct vidi_context, \
33 connector)
32 34
33struct vidi_win_data { 35struct vidi_win_data {
34 unsigned int offset_x; 36 unsigned int offset_x;
@@ -45,8 +47,10 @@ struct vidi_win_data {
45}; 47};
46 48
47struct vidi_context { 49struct vidi_context {
48 struct exynos_drm_subdrv subdrv; 50 struct drm_device *drm_dev;
49 struct drm_crtc *crtc; 51 struct drm_crtc *crtc;
52 struct drm_encoder *encoder;
53 struct drm_connector connector;
50 struct vidi_win_data win_data[WINDOWS_NR]; 54 struct vidi_win_data win_data[WINDOWS_NR];
51 struct edid *raw_edid; 55 struct edid *raw_edid;
52 unsigned int clkdiv; 56 unsigned int clkdiv;
@@ -58,6 +62,7 @@ struct vidi_context {
58 bool direct_vblank; 62 bool direct_vblank;
59 struct work_struct work; 63 struct work_struct work;
60 struct mutex lock; 64 struct mutex lock;
65 int pipe;
61}; 66};
62 67
63static const char fake_edid_info[] = { 68static const char fake_edid_info[] = {
@@ -85,126 +90,34 @@ static const char fake_edid_info[] = {
85 0x00, 0x00, 0x00, 0x06 90 0x00, 0x00, 0x00, 0x06
86}; 91};
87 92
88static bool vidi_display_is_connected(struct device *dev) 93static void vidi_apply(struct exynos_drm_manager *mgr)
89{ 94{
90 struct vidi_context *ctx = get_vidi_context(dev); 95 struct vidi_context *ctx = mgr->ctx;
91
92 /*
93 * connection request would come from user side
94 * to do hotplug through specific ioctl.
95 */
96 return ctx->connected ? true : false;
97}
98
99static struct edid *vidi_get_edid(struct device *dev,
100 struct drm_connector *connector)
101{
102 struct vidi_context *ctx = get_vidi_context(dev);
103 struct edid *edid;
104
105 /*
106 * the edid data comes from user side and it would be set
107 * to ctx->raw_edid through specific ioctl.
108 */
109 if (!ctx->raw_edid) {
110 DRM_DEBUG_KMS("raw_edid is null.\n");
111 return ERR_PTR(-EFAULT);
112 }
113
114 edid = drm_edid_duplicate(ctx->raw_edid);
115 if (!edid) {
116 DRM_DEBUG_KMS("failed to allocate edid\n");
117 return ERR_PTR(-ENOMEM);
118 }
119
120 return edid;
121}
122
123static void *vidi_get_panel(struct device *dev)
124{
125 /* TODO. */
126
127 return NULL;
128}
129
130static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
131{
132 /* TODO. */
133
134 return 0;
135}
136
137static int vidi_display_power_on(struct device *dev, int mode)
138{
139 /* TODO */
140
141 return 0;
142}
143
144static struct exynos_drm_display_ops vidi_display_ops = {
145 .type = EXYNOS_DISPLAY_TYPE_VIDI,
146 .is_connected = vidi_display_is_connected,
147 .get_edid = vidi_get_edid,
148 .get_panel = vidi_get_panel,
149 .check_mode = vidi_check_mode,
150 .power_on = vidi_display_power_on,
151};
152
153static void vidi_dpms(struct device *subdrv_dev, int mode)
154{
155 struct vidi_context *ctx = get_vidi_context(subdrv_dev);
156
157 DRM_DEBUG_KMS("%d\n", mode);
158
159 mutex_lock(&ctx->lock);
160
161 switch (mode) {
162 case DRM_MODE_DPMS_ON:
163 /* TODO. */
164 break;
165 case DRM_MODE_DPMS_STANDBY:
166 case DRM_MODE_DPMS_SUSPEND:
167 case DRM_MODE_DPMS_OFF:
168 /* TODO. */
169 break;
170 default:
171 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
172 break;
173 }
174
175 mutex_unlock(&ctx->lock);
176}
177
178static void vidi_apply(struct device *subdrv_dev)
179{
180 struct vidi_context *ctx = get_vidi_context(subdrv_dev);
181 struct exynos_drm_manager *mgr = ctx->subdrv.manager;
182 struct exynos_drm_manager_ops *mgr_ops = mgr->ops; 96 struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
183 struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
184 struct vidi_win_data *win_data; 97 struct vidi_win_data *win_data;
185 int i; 98 int i;
186 99
187 for (i = 0; i < WINDOWS_NR; i++) { 100 for (i = 0; i < WINDOWS_NR; i++) {
188 win_data = &ctx->win_data[i]; 101 win_data = &ctx->win_data[i];
189 if (win_data->enabled && (ovl_ops && ovl_ops->commit)) 102 if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
190 ovl_ops->commit(subdrv_dev, i); 103 mgr_ops->win_commit(mgr, i);
191 } 104 }
192 105
193 if (mgr_ops && mgr_ops->commit) 106 if (mgr_ops && mgr_ops->commit)
194 mgr_ops->commit(subdrv_dev); 107 mgr_ops->commit(mgr);
195} 108}
196 109
197static void vidi_commit(struct device *dev) 110static void vidi_commit(struct exynos_drm_manager *mgr)
198{ 111{
199 struct vidi_context *ctx = get_vidi_context(dev); 112 struct vidi_context *ctx = mgr->ctx;
200 113
201 if (ctx->suspended) 114 if (ctx->suspended)
202 return; 115 return;
203} 116}
204 117
205static int vidi_enable_vblank(struct device *dev) 118static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
206{ 119{
207 struct vidi_context *ctx = get_vidi_context(dev); 120 struct vidi_context *ctx = mgr->ctx;
208 121
209 if (ctx->suspended) 122 if (ctx->suspended)
210 return -EPERM; 123 return -EPERM;
@@ -217,16 +130,16 @@ static int vidi_enable_vblank(struct device *dev)
217 /* 130 /*
218 * in case of page flip request, vidi_finish_pageflip function 131 * in case of page flip request, vidi_finish_pageflip function
219 * will not be called because direct_vblank is true and then 132 * will not be called because direct_vblank is true and then
220 * that function will be called by overlay_ops->commit callback 133 * that function will be called by manager_ops->win_commit callback
221 */ 134 */
222 schedule_work(&ctx->work); 135 schedule_work(&ctx->work);
223 136
224 return 0; 137 return 0;
225} 138}
226 139
227static void vidi_disable_vblank(struct device *dev) 140static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
228{ 141{
229 struct vidi_context *ctx = get_vidi_context(dev); 142 struct vidi_context *ctx = mgr->ctx;
230 143
231 if (ctx->suspended) 144 if (ctx->suspended)
232 return; 145 return;
@@ -235,24 +148,16 @@ static void vidi_disable_vblank(struct device *dev)
235 ctx->vblank_on = false; 148 ctx->vblank_on = false;
236} 149}
237 150
238static struct exynos_drm_manager_ops vidi_manager_ops = { 151static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
239 .dpms = vidi_dpms, 152 struct exynos_drm_overlay *overlay)
240 .apply = vidi_apply,
241 .commit = vidi_commit,
242 .enable_vblank = vidi_enable_vblank,
243 .disable_vblank = vidi_disable_vblank,
244};
245
246static void vidi_win_mode_set(struct device *dev,
247 struct exynos_drm_overlay *overlay)
248{ 153{
249 struct vidi_context *ctx = get_vidi_context(dev); 154 struct vidi_context *ctx = mgr->ctx;
250 struct vidi_win_data *win_data; 155 struct vidi_win_data *win_data;
251 int win; 156 int win;
252 unsigned long offset; 157 unsigned long offset;
253 158
254 if (!overlay) { 159 if (!overlay) {
255 dev_err(dev, "overlay is NULL\n"); 160 DRM_ERROR("overlay is NULL\n");
256 return; 161 return;
257 } 162 }
258 163
@@ -296,9 +201,9 @@ static void vidi_win_mode_set(struct device *dev,
296 overlay->fb_width, overlay->crtc_width); 201 overlay->fb_width, overlay->crtc_width);
297} 202}
298 203
299static void vidi_win_commit(struct device *dev, int zpos) 204static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
300{ 205{
301 struct vidi_context *ctx = get_vidi_context(dev); 206 struct vidi_context *ctx = mgr->ctx;
302 struct vidi_win_data *win_data; 207 struct vidi_win_data *win_data;
303 int win = zpos; 208 int win = zpos;
304 209
@@ -321,9 +226,9 @@ static void vidi_win_commit(struct device *dev, int zpos)
321 schedule_work(&ctx->work); 226 schedule_work(&ctx->work);
322} 227}
323 228
324static void vidi_win_disable(struct device *dev, int zpos) 229static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
325{ 230{
326 struct vidi_context *ctx = get_vidi_context(dev); 231 struct vidi_context *ctx = mgr->ctx;
327 struct vidi_win_data *win_data; 232 struct vidi_win_data *win_data;
328 int win = zpos; 233 int win = zpos;
329 234
@@ -339,98 +244,132 @@ static void vidi_win_disable(struct device *dev, int zpos)
339 /* TODO. */ 244 /* TODO. */
340} 245}
341 246
342static struct exynos_drm_overlay_ops vidi_overlay_ops = { 247static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
343 .mode_set = vidi_win_mode_set, 248{
344 .commit = vidi_win_commit, 249 struct vidi_context *ctx = mgr->ctx;
345 .disable = vidi_win_disable,
346};
347 250
348static struct exynos_drm_manager vidi_manager = { 251 DRM_DEBUG_KMS("%s\n", __FILE__);
349 .pipe = -1,
350 .ops = &vidi_manager_ops,
351 .overlay_ops = &vidi_overlay_ops,
352 .display_ops = &vidi_display_ops,
353};
354 252
355static void vidi_fake_vblank_handler(struct work_struct *work) 253 if (enable != false && enable != true)
356{ 254 return -EINVAL;
357 struct vidi_context *ctx = container_of(work, struct vidi_context,
358 work);
359 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
360 struct exynos_drm_manager *manager = subdrv->manager;
361 255
362 if (manager->pipe < 0) 256 if (enable) {
363 return; 257 ctx->suspended = false;
364 258
365 /* refresh rate is about 50Hz. */ 259 /* if vblank was enabled status, enable it again. */
366 usleep_range(16000, 20000); 260 if (test_and_clear_bit(0, &ctx->irq_flags))
261 vidi_enable_vblank(mgr);
262
263 vidi_apply(mgr);
264 } else {
265 ctx->suspended = true;
266 }
267
268 return 0;
269}
270
271static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
272{
273 struct vidi_context *ctx = mgr->ctx;
274
275 DRM_DEBUG_KMS("%d\n", mode);
367 276
368 mutex_lock(&ctx->lock); 277 mutex_lock(&ctx->lock);
369 278
370 if (ctx->direct_vblank) { 279 switch (mode) {
371 drm_handle_vblank(subdrv->drm_dev, manager->pipe); 280 case DRM_MODE_DPMS_ON:
372 ctx->direct_vblank = false; 281 vidi_power_on(mgr, true);
373 mutex_unlock(&ctx->lock); 282 break;
374 return; 283 case DRM_MODE_DPMS_STANDBY:
284 case DRM_MODE_DPMS_SUSPEND:
285 case DRM_MODE_DPMS_OFF:
286 vidi_power_on(mgr, false);
287 break;
288 default:
289 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
290 break;
375 } 291 }
376 292
377 mutex_unlock(&ctx->lock); 293 mutex_unlock(&ctx->lock);
378
379 exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe);
380} 294}
381 295
382static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev) 296static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
297 struct drm_device *drm_dev, int pipe)
383{ 298{
299 struct vidi_context *ctx = mgr->ctx;
300
301 DRM_ERROR("vidi initialize ct=%p dev=%p pipe=%d\n", ctx, drm_dev, pipe);
302
303 ctx->drm_dev = drm_dev;
304 ctx->pipe = pipe;
305
384 /* 306 /*
385 * enable drm irq mode. 307 * enable drm irq mode.
386 * - with irq_enabled = true, we can use the vblank feature. 308 * - with irq_enabled = 1, we can use the vblank feature.
387 * 309 *
388 * P.S. note that we wouldn't use drm irq handler but 310 * P.S. note that we wouldn't use drm irq handler but
389 * just specific driver own one instead because 311 * just specific driver own one instead because
390 * drm framework supports only one irq handler. 312 * drm framework supports only one irq handler.
391 */ 313 */
392 drm_dev->irq_enabled = true; 314 drm_dev->irq_enabled = 1;
393 315
394 /* 316 /*
395 * with vblank_disable_allowed = true, vblank interrupt will be disabled 317 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
396 * by drm timer once a current process gives up ownership of 318 * by drm timer once a current process gives up ownership of
397 * vblank event.(after drm_vblank_put function is called) 319 * vblank event.(after drm_vblank_put function is called)
398 */ 320 */
399 drm_dev->vblank_disable_allowed = true; 321 drm_dev->vblank_disable_allowed = 1;
400 322
401 return 0; 323 return 0;
402} 324}
403 325
404static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) 326static struct exynos_drm_manager_ops vidi_manager_ops = {
405{ 327 .initialize = vidi_mgr_initialize,
406 /* TODO. */ 328 .dpms = vidi_dpms,
407} 329 .commit = vidi_commit,
330 .enable_vblank = vidi_enable_vblank,
331 .disable_vblank = vidi_disable_vblank,
332 .win_mode_set = vidi_win_mode_set,
333 .win_commit = vidi_win_commit,
334 .win_disable = vidi_win_disable,
335};
408 336
409static int vidi_power_on(struct vidi_context *ctx, bool enable) 337static struct exynos_drm_manager vidi_manager = {
338 .type = EXYNOS_DISPLAY_TYPE_VIDI,
339 .ops = &vidi_manager_ops,
340};
341
342static void vidi_fake_vblank_handler(struct work_struct *work)
410{ 343{
411 struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 344 struct vidi_context *ctx = container_of(work, struct vidi_context,
412 struct device *dev = subdrv->dev; 345 work);
413 346
414 if (enable) { 347 if (ctx->pipe < 0)
415 ctx->suspended = false; 348 return;
416 349
417 /* if vblank was enabled status, enable it again. */ 350 /* refresh rate is about 50Hz. */
418 if (test_and_clear_bit(0, &ctx->irq_flags)) 351 usleep_range(16000, 20000);
419 vidi_enable_vblank(dev);
420 352
421 vidi_apply(dev); 353 mutex_lock(&ctx->lock);
422 } else { 354
423 ctx->suspended = true; 355 if (ctx->direct_vblank) {
356 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
357 ctx->direct_vblank = false;
358 mutex_unlock(&ctx->lock);
359 return;
424 } 360 }
425 361
426 return 0; 362 mutex_unlock(&ctx->lock);
363
364 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
427} 365}
428 366
429static int vidi_show_connection(struct device *dev, 367static int vidi_show_connection(struct device *dev,
430 struct device_attribute *attr, char *buf) 368 struct device_attribute *attr, char *buf)
431{ 369{
432 int rc; 370 int rc;
433 struct vidi_context *ctx = get_vidi_context(dev); 371 struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
372 struct vidi_context *ctx = mgr->ctx;
434 373
435 mutex_lock(&ctx->lock); 374 mutex_lock(&ctx->lock);
436 375
@@ -445,7 +384,8 @@ static int vidi_store_connection(struct device *dev,
445 struct device_attribute *attr, 384 struct device_attribute *attr,
446 const char *buf, size_t len) 385 const char *buf, size_t len)
447{ 386{
448 struct vidi_context *ctx = get_vidi_context(dev); 387 struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
388 struct vidi_context *ctx = mgr->ctx;
449 int ret; 389 int ret;
450 390
451 ret = kstrtoint(buf, 0, &ctx->connected); 391 ret = kstrtoint(buf, 0, &ctx->connected);
@@ -467,7 +407,7 @@ static int vidi_store_connection(struct device *dev,
467 407
468 DRM_DEBUG_KMS("requested connection.\n"); 408 DRM_DEBUG_KMS("requested connection.\n");
469 409
470 drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); 410 drm_helper_hpd_irq_event(ctx->drm_dev);
471 411
472 return len; 412 return len;
473} 413}
@@ -480,8 +420,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
480{ 420{
481 struct vidi_context *ctx = NULL; 421 struct vidi_context *ctx = NULL;
482 struct drm_encoder *encoder; 422 struct drm_encoder *encoder;
483 struct exynos_drm_manager *manager; 423 struct exynos_drm_display *display;
484 struct exynos_drm_display_ops *display_ops;
485 struct drm_exynos_vidi_connection *vidi = data; 424 struct drm_exynos_vidi_connection *vidi = data;
486 425
487 if (!vidi) { 426 if (!vidi) {
@@ -496,11 +435,10 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
496 435
497 list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, 436 list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list,
498 head) { 437 head) {
499 manager = exynos_drm_get_manager(encoder); 438 display = exynos_drm_get_display(encoder);
500 display_ops = manager->display_ops;
501 439
502 if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) { 440 if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) {
503 ctx = get_vidi_context(manager->dev); 441 ctx = display->ctx;
504 break; 442 break;
505 } 443 }
506 } 444 }
@@ -539,16 +477,119 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
539 } 477 }
540 478
541 ctx->connected = vidi->connection; 479 ctx->connected = vidi->connection;
542 drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); 480 drm_helper_hpd_irq_event(ctx->drm_dev);
481
482 return 0;
483}
484
485static enum drm_connector_status vidi_detect(struct drm_connector *connector,
486 bool force)
487{
488 struct vidi_context *ctx = ctx_from_connector(connector);
489
490 /*
491 * connection request would come from user side
492 * to do hotplug through specific ioctl.
493 */
494 return ctx->connected ? connector_status_connected :
495 connector_status_disconnected;
496}
497
498static void vidi_connector_destroy(struct drm_connector *connector)
499{
500}
501
502static struct drm_connector_funcs vidi_connector_funcs = {
503 .dpms = drm_helper_connector_dpms,
504 .fill_modes = drm_helper_probe_single_connector_modes,
505 .detect = vidi_detect,
506 .destroy = vidi_connector_destroy,
507};
508
509static int vidi_get_modes(struct drm_connector *connector)
510{
511 struct vidi_context *ctx = ctx_from_connector(connector);
512 struct edid *edid;
513 int edid_len;
514
515 /*
516 * the edid data comes from user side and it would be set
517 * to ctx->raw_edid through specific ioctl.
518 */
519 if (!ctx->raw_edid) {
520 DRM_DEBUG_KMS("raw_edid is null.\n");
521 return -EFAULT;
522 }
523
524 edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
525 edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
526 if (!edid) {
527 DRM_DEBUG_KMS("failed to allocate edid\n");
528 return -ENOMEM;
529 }
530
531 drm_mode_connector_update_edid_property(connector, edid);
532
533 return drm_add_edid_modes(connector, edid);
534}
535
536static int vidi_mode_valid(struct drm_connector *connector,
537 struct drm_display_mode *mode)
538{
539 return MODE_OK;
540}
541
542static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
543{
544 struct vidi_context *ctx = ctx_from_connector(connector);
545
546 return ctx->encoder;
547}
548
549static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
550 .get_modes = vidi_get_modes,
551 .mode_valid = vidi_mode_valid,
552 .best_encoder = vidi_best_encoder,
553};
554
555static int vidi_create_connector(struct exynos_drm_display *display,
556 struct drm_encoder *encoder)
557{
558 struct vidi_context *ctx = display->ctx;
559 struct drm_connector *connector = &ctx->connector;
560 int ret;
561
562 ctx->encoder = encoder;
563 connector->polled = DRM_CONNECTOR_POLL_HPD;
564
565 ret = drm_connector_init(ctx->drm_dev, connector,
566 &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
567 if (ret) {
568 DRM_ERROR("Failed to initialize connector with drm\n");
569 return ret;
570 }
571
572 drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
573 drm_sysfs_connector_add(connector);
574 drm_mode_connector_attach_encoder(connector, encoder);
543 575
544 return 0; 576 return 0;
545} 577}
546 578
579
580static struct exynos_drm_display_ops vidi_display_ops = {
581 .create_connector = vidi_create_connector,
582};
583
584static struct exynos_drm_display vidi_display = {
585 .type = EXYNOS_DISPLAY_TYPE_VIDI,
586 .ops = &vidi_display_ops,
587};
588
547static int vidi_probe(struct platform_device *pdev) 589static int vidi_probe(struct platform_device *pdev)
548{ 590{
549 struct device *dev = &pdev->dev; 591 struct device *dev = &pdev->dev;
550 struct vidi_context *ctx; 592 struct vidi_context *ctx;
551 struct exynos_drm_subdrv *subdrv;
552 int ret; 593 int ret;
553 594
554 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 595 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
@@ -559,21 +600,19 @@ static int vidi_probe(struct platform_device *pdev)
559 600
560 INIT_WORK(&ctx->work, vidi_fake_vblank_handler); 601 INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
561 602
562 subdrv = &ctx->subdrv; 603 vidi_manager.ctx = ctx;
563 subdrv->dev = dev; 604 vidi_display.ctx = ctx;
564 subdrv->manager = &vidi_manager;
565 subdrv->probe = vidi_subdrv_probe;
566 subdrv->remove = vidi_subdrv_remove;
567 605
568 mutex_init(&ctx->lock); 606 mutex_init(&ctx->lock);
569 607
570 platform_set_drvdata(pdev, ctx); 608 platform_set_drvdata(pdev, &vidi_manager);
571 609
572 ret = device_create_file(dev, &dev_attr_connection); 610 ret = device_create_file(dev, &dev_attr_connection);
573 if (ret < 0) 611 if (ret < 0)
574 DRM_INFO("failed to create connection sysfs.\n"); 612 DRM_INFO("failed to create connection sysfs.\n");
575 613
576 exynos_drm_subdrv_register(subdrv); 614 exynos_drm_manager_register(&vidi_manager);
615 exynos_drm_display_register(&vidi_display);
577 616
578 return 0; 617 return 0;
579} 618}
@@ -582,7 +621,8 @@ static int vidi_remove(struct platform_device *pdev)
582{ 621{
583 struct vidi_context *ctx = platform_get_drvdata(pdev); 622 struct vidi_context *ctx = platform_get_drvdata(pdev);
584 623
585 exynos_drm_subdrv_unregister(&ctx->subdrv); 624 exynos_drm_display_unregister(&vidi_display);
625 exynos_drm_manager_unregister(&vidi_manager);
586 626
587 if (ctx->raw_edid != (struct edid *)fake_edid_info) { 627 if (ctx->raw_edid != (struct edid *)fake_edid_info) {
588 kfree(ctx->raw_edid); 628 kfree(ctx->raw_edid);
@@ -592,32 +632,11 @@ static int vidi_remove(struct platform_device *pdev)
592 return 0; 632 return 0;
593} 633}
594 634
595#ifdef CONFIG_PM_SLEEP
596static int vidi_suspend(struct device *dev)
597{
598 struct vidi_context *ctx = get_vidi_context(dev);
599
600 return vidi_power_on(ctx, false);
601}
602
603static int vidi_resume(struct device *dev)
604{
605 struct vidi_context *ctx = get_vidi_context(dev);
606
607 return vidi_power_on(ctx, true);
608}
609#endif
610
611static const struct dev_pm_ops vidi_pm_ops = {
612 SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
613};
614
615struct platform_driver vidi_driver = { 635struct platform_driver vidi_driver = {
616 .probe = vidi_probe, 636 .probe = vidi_probe,
617 .remove = vidi_remove, 637 .remove = vidi_remove,
618 .driver = { 638 .driver = {
619 .name = "exynos-drm-vidi", 639 .name = "exynos-drm-vidi",
620 .owner = THIS_MODULE, 640 .owner = THIS_MODULE,
621 .pm = &vidi_pm_ops,
622 }, 641 },
623}; 642};
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c021ddc1ffb4..9a6d652a3ef2 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -33,38 +33,42 @@
33#include <linux/regulator/consumer.h> 33#include <linux/regulator/consumer.h>
34#include <linux/io.h> 34#include <linux/io.h>
35#include <linux/of.h> 35#include <linux/of.h>
36#include <linux/i2c.h>
36#include <linux/of_gpio.h> 37#include <linux/of_gpio.h>
37#include <linux/hdmi.h> 38#include <linux/hdmi.h>
38 39
39#include <drm/exynos_drm.h> 40#include <drm/exynos_drm.h>
40 41
41#include "exynos_drm_drv.h" 42#include "exynos_drm_drv.h"
42#include "exynos_drm_hdmi.h" 43#include "exynos_mixer.h"
43
44#include "exynos_hdmi.h"
45 44
46#include <linux/gpio.h> 45#include <linux/gpio.h>
47#include <media/s5p_hdmi.h> 46#include <media/s5p_hdmi.h>
48 47
49#define MAX_WIDTH 1920 48#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
50#define MAX_HEIGHT 1080 49#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
51#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
52 50
53/* AVI header and aspect ratio */ 51/* AVI header and aspect ratio */
54#define HDMI_AVI_VERSION 0x02 52#define HDMI_AVI_VERSION 0x02
55#define HDMI_AVI_LENGTH 0x0D 53#define HDMI_AVI_LENGTH 0x0D
56#define AVI_PIC_ASPECT_RATIO_16_9 (2 << 4)
57#define AVI_SAME_AS_PIC_ASPECT_RATIO 8
58 54
59/* AUI header info */ 55/* AUI header info */
60#define HDMI_AUI_VERSION 0x01 56#define HDMI_AUI_VERSION 0x01
61#define HDMI_AUI_LENGTH 0x0A 57#define HDMI_AUI_LENGTH 0x0A
58#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
59#define AVI_4_3_CENTER_RATIO 0x9
60#define AVI_16_9_CENTER_RATIO 0xa
62 61
63enum hdmi_type { 62enum hdmi_type {
64 HDMI_TYPE13, 63 HDMI_TYPE13,
65 HDMI_TYPE14, 64 HDMI_TYPE14,
66}; 65};
67 66
67struct hdmi_driver_data {
68 unsigned int type;
69 unsigned int is_apb_phy:1;
70};
71
68struct hdmi_resources { 72struct hdmi_resources {
69 struct clk *hdmi; 73 struct clk *hdmi;
70 struct clk *sclk_hdmi; 74 struct clk *sclk_hdmi;
@@ -162,6 +166,7 @@ struct hdmi_v14_conf {
162struct hdmi_conf_regs { 166struct hdmi_conf_regs {
163 int pixel_clock; 167 int pixel_clock;
164 int cea_video_id; 168 int cea_video_id;
169 enum hdmi_picture_aspect aspect_ratio;
165 union { 170 union {
166 struct hdmi_v13_conf v13_conf; 171 struct hdmi_v13_conf v13_conf;
167 struct hdmi_v14_conf v14_conf; 172 struct hdmi_v14_conf v14_conf;
@@ -171,16 +176,17 @@ struct hdmi_conf_regs {
171struct hdmi_context { 176struct hdmi_context {
172 struct device *dev; 177 struct device *dev;
173 struct drm_device *drm_dev; 178 struct drm_device *drm_dev;
179 struct drm_connector connector;
180 struct drm_encoder *encoder;
174 bool hpd; 181 bool hpd;
175 bool powered; 182 bool powered;
176 bool dvi_mode; 183 bool dvi_mode;
177 struct mutex hdmi_mutex; 184 struct mutex hdmi_mutex;
178 185
179 void __iomem *regs; 186 void __iomem *regs;
180 void *parent_ctx;
181 int irq; 187 int irq;
182 188
183 struct i2c_client *ddc_port; 189 struct i2c_adapter *ddc_adpt;
184 struct i2c_client *hdmiphy_port; 190 struct i2c_client *hdmiphy_port;
185 191
186 /* current hdmiphy conf regs */ 192 /* current hdmiphy conf regs */
@@ -198,6 +204,14 @@ struct hdmiphy_config {
198 u8 conf[32]; 204 u8 conf[32];
199}; 205};
200 206
207struct hdmi_driver_data exynos4212_hdmi_driver_data = {
208 .type = HDMI_TYPE14,
209};
210
211struct hdmi_driver_data exynos5_hdmi_driver_data = {
212 .type = HDMI_TYPE14,
213};
214
201/* list of phy config settings */ 215/* list of phy config settings */
202static const struct hdmiphy_config hdmiphy_v13_configs[] = { 216static const struct hdmiphy_config hdmiphy_v13_configs[] = {
203 { 217 {
@@ -303,6 +317,24 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
303 }, 317 },
304 }, 318 },
305 { 319 {
320 .pixel_clock = 71000000,
321 .conf = {
322 0x01, 0x91, 0x1e, 0x15, 0x40, 0x3c, 0xce, 0x08,
323 0x04, 0x20, 0xb2, 0xd8, 0x45, 0xa0, 0xac, 0x80,
324 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
325 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
326 },
327 },
328 {
329 .pixel_clock = 73250000,
330 .conf = {
331 0x01, 0xd1, 0x1f, 0x15, 0x40, 0x18, 0xe9, 0x08,
332 0x02, 0xa0, 0xb7, 0xd8, 0x45, 0xa0, 0xac, 0x80,
333 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
334 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
335 },
336 },
337 {
306 .pixel_clock = 74176000, 338 .pixel_clock = 74176000,
307 .conf = { 339 .conf = {
308 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08, 340 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
@@ -330,6 +362,15 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
330 }, 362 },
331 }, 363 },
332 { 364 {
365 .pixel_clock = 88750000,
366 .conf = {
367 0x01, 0x91, 0x25, 0x17, 0x40, 0x30, 0xfe, 0x08,
368 0x06, 0x20, 0xde, 0xd8, 0x45, 0xa0, 0xac, 0x80,
369 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
370 0x54, 0x8a, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
371 },
372 },
373 {
333 .pixel_clock = 106500000, 374 .pixel_clock = 106500000,
334 .conf = { 375 .conf = {
335 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08, 376 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
@@ -348,6 +389,24 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
348 }, 389 },
349 }, 390 },
350 { 391 {
392 .pixel_clock = 115500000,
393 .conf = {
394 0x01, 0xd1, 0x30, 0x1a, 0x40, 0x40, 0x10, 0x04,
395 0x04, 0xa0, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
396 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
397 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
398 },
399 },
400 {
401 .pixel_clock = 119000000,
402 .conf = {
403 0x01, 0x91, 0x32, 0x14, 0x40, 0x60, 0xd8, 0x08,
404 0x06, 0x20, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
405 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
406 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
407 },
408 },
409 {
351 .pixel_clock = 146250000, 410 .pixel_clock = 146250000,
352 .conf = { 411 .conf = {
353 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08, 412 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
@@ -668,7 +727,6 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
668{ 727{
669 u32 hdr_sum; 728 u32 hdr_sum;
670 u8 chksum; 729 u8 chksum;
671 u32 aspect_ratio;
672 u32 mod; 730 u32 mod;
673 u32 vic; 731 u32 vic;
674 732
@@ -697,10 +755,28 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
697 AVI_ACTIVE_FORMAT_VALID | 755 AVI_ACTIVE_FORMAT_VALID |
698 AVI_UNDERSCANNED_DISPLAY_VALID); 756 AVI_UNDERSCANNED_DISPLAY_VALID);
699 757
700 aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9; 758 /*
701 759 * Set the aspect ratio as per the mode, mentioned in
702 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio | 760 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
703 AVI_SAME_AS_PIC_ASPECT_RATIO); 761 */
762 switch (hdata->mode_conf.aspect_ratio) {
763 case HDMI_PICTURE_ASPECT_4_3:
764 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
765 hdata->mode_conf.aspect_ratio |
766 AVI_4_3_CENTER_RATIO);
767 break;
768 case HDMI_PICTURE_ASPECT_16_9:
769 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
770 hdata->mode_conf.aspect_ratio |
771 AVI_16_9_CENTER_RATIO);
772 break;
773 case HDMI_PICTURE_ASPECT_NONE:
774 default:
775 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
776 hdata->mode_conf.aspect_ratio |
777 AVI_SAME_AS_PIC_ASPECT_RATIO);
778 break;
779 }
704 780
705 vic = hdata->mode_conf.cea_video_id; 781 vic = hdata->mode_conf.cea_video_id;
706 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); 782 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
@@ -728,31 +804,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
728 } 804 }
729} 805}
730 806
731static bool hdmi_is_connected(void *ctx) 807static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
808 bool force)
732{ 809{
733 struct hdmi_context *hdata = ctx; 810 struct hdmi_context *hdata = ctx_from_connector(connector);
811
812 return hdata->hpd ? connector_status_connected :
813 connector_status_disconnected;
814}
734 815
735 return hdata->hpd; 816static void hdmi_connector_destroy(struct drm_connector *connector)
817{
736} 818}
737 819
738static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) 820static struct drm_connector_funcs hdmi_connector_funcs = {
821 .dpms = drm_helper_connector_dpms,
822 .fill_modes = drm_helper_probe_single_connector_modes,
823 .detect = hdmi_detect,
824 .destroy = hdmi_connector_destroy,
825};
826
827static int hdmi_get_modes(struct drm_connector *connector)
739{ 828{
740 struct edid *raw_edid; 829 struct hdmi_context *hdata = ctx_from_connector(connector);
741 struct hdmi_context *hdata = ctx; 830 struct edid *edid;
742 831
743 if (!hdata->ddc_port) 832 if (!hdata->ddc_adpt)
744 return ERR_PTR(-ENODEV); 833 return -ENODEV;
745 834
746 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); 835 edid = drm_get_edid(connector, hdata->ddc_adpt);
747 if (!raw_edid) 836 if (!edid)
748 return ERR_PTR(-ENODEV); 837 return -ENODEV;
749 838
750 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); 839 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
751 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", 840 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
752 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), 841 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
753 raw_edid->width_cm, raw_edid->height_cm); 842 edid->width_cm, edid->height_cm);
754 843
755 return raw_edid; 844 drm_mode_connector_update_edid_property(connector, edid);
845
846 return drm_add_edid_modes(connector, edid);
756} 847}
757 848
758static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) 849static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
@@ -777,9 +868,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
777 return -EINVAL; 868 return -EINVAL;
778} 869}
779 870
780static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode) 871static int hdmi_mode_valid(struct drm_connector *connector,
872 struct drm_display_mode *mode)
781{ 873{
782 struct hdmi_context *hdata = ctx; 874 struct hdmi_context *hdata = ctx_from_connector(connector);
783 int ret; 875 int ret;
784 876
785 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", 877 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
@@ -787,12 +879,103 @@ static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
787 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true : 879 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
788 false, mode->clock * 1000); 880 false, mode->clock * 1000);
789 881
882 ret = mixer_check_mode(mode);
883 if (ret)
884 return MODE_BAD;
885
790 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000); 886 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
791 if (ret < 0) 887 if (ret < 0)
888 return MODE_BAD;
889
890 return MODE_OK;
891}
892
893static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
894{
895 struct hdmi_context *hdata = ctx_from_connector(connector);
896
897 return hdata->encoder;
898}
899
900static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
901 .get_modes = hdmi_get_modes,
902 .mode_valid = hdmi_mode_valid,
903 .best_encoder = hdmi_best_encoder,
904};
905
906static int hdmi_create_connector(struct exynos_drm_display *display,
907 struct drm_encoder *encoder)
908{
909 struct hdmi_context *hdata = display->ctx;
910 struct drm_connector *connector = &hdata->connector;
911 int ret;
912
913 hdata->encoder = encoder;
914 connector->interlace_allowed = true;
915 connector->polled = DRM_CONNECTOR_POLL_HPD;
916
917 ret = drm_connector_init(hdata->drm_dev, connector,
918 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
919 if (ret) {
920 DRM_ERROR("Failed to initialize connector with drm\n");
792 return ret; 921 return ret;
922 }
923
924 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
925 drm_sysfs_connector_add(connector);
926 drm_mode_connector_attach_encoder(connector, encoder);
927
928 return 0;
929}
930
931static int hdmi_initialize(struct exynos_drm_display *display,
932 struct drm_device *drm_dev)
933{
934 struct hdmi_context *hdata = display->ctx;
935
936 hdata->drm_dev = drm_dev;
937
793 return 0; 938 return 0;
794} 939}
795 940
941static void hdmi_mode_fixup(struct exynos_drm_display *display,
942 struct drm_connector *connector,
943 const struct drm_display_mode *mode,
944 struct drm_display_mode *adjusted_mode)
945{
946 struct drm_display_mode *m;
947 int mode_ok;
948
949 DRM_DEBUG_KMS("%s\n", __FILE__);
950
951 drm_mode_set_crtcinfo(adjusted_mode, 0);
952
953 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
954
955 /* just return if user desired mode exists. */
956 if (mode_ok == MODE_OK)
957 return;
958
959 /*
960 * otherwise, find the most suitable mode among modes and change it
961 * to adjusted_mode.
962 */
963 list_for_each_entry(m, &connector->modes, head) {
964 mode_ok = hdmi_mode_valid(connector, m);
965
966 if (mode_ok == MODE_OK) {
967 DRM_INFO("desired mode doesn't exist so\n");
968 DRM_INFO("use the most suitable mode among modes.\n");
969
970 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
971 m->hdisplay, m->vdisplay, m->vrefresh);
972
973 drm_mode_copy(adjusted_mode, m);
974 break;
975 }
976 }
977}
978
796static void hdmi_set_acr(u32 freq, u8 *acr) 979static void hdmi_set_acr(u32 freq, u8 *acr)
797{ 980{
798 u32 n, cts; 981 u32 n, cts;
@@ -1421,6 +1604,7 @@ static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1421 hdata->mode_conf.cea_video_id = 1604 hdata->mode_conf.cea_video_id =
1422 drm_match_cea_mode((struct drm_display_mode *)m); 1605 drm_match_cea_mode((struct drm_display_mode *)m);
1423 hdata->mode_conf.pixel_clock = m->clock * 1000; 1606 hdata->mode_conf.pixel_clock = m->clock * 1000;
1607 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
1424 1608
1425 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); 1609 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1426 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal); 1610 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
@@ -1517,6 +1701,7 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1517 hdata->mode_conf.cea_video_id = 1701 hdata->mode_conf.cea_video_id =
1518 drm_match_cea_mode((struct drm_display_mode *)m); 1702 drm_match_cea_mode((struct drm_display_mode *)m);
1519 hdata->mode_conf.pixel_clock = m->clock * 1000; 1703 hdata->mode_conf.pixel_clock = m->clock * 1000;
1704 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
1520 1705
1521 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); 1706 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1522 hdmi_set_reg(core->v_line, 2, m->vtotal); 1707 hdmi_set_reg(core->v_line, 2, m->vtotal);
@@ -1618,9 +1803,10 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1618 hdmi_set_reg(tg->tg_3d, 1, 0x0); 1803 hdmi_set_reg(tg->tg_3d, 1, 0x0);
1619} 1804}
1620 1805
1621static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode) 1806static void hdmi_mode_set(struct exynos_drm_display *display,
1807 struct drm_display_mode *mode)
1622{ 1808{
1623 struct hdmi_context *hdata = ctx; 1809 struct hdmi_context *hdata = display->ctx;
1624 struct drm_display_mode *m = mode; 1810 struct drm_display_mode *m = mode;
1625 1811
1626 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", 1812 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
@@ -1634,16 +1820,9 @@ static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
1634 hdmi_v14_mode_set(hdata, mode); 1820 hdmi_v14_mode_set(hdata, mode);
1635} 1821}
1636 1822
1637static void hdmi_get_max_resol(void *ctx, unsigned int *width, 1823static void hdmi_commit(struct exynos_drm_display *display)
1638 unsigned int *height)
1639{
1640 *width = MAX_WIDTH;
1641 *height = MAX_HEIGHT;
1642}
1643
1644static void hdmi_commit(void *ctx)
1645{ 1824{
1646 struct hdmi_context *hdata = ctx; 1825 struct hdmi_context *hdata = display->ctx;
1647 1826
1648 mutex_lock(&hdata->hdmi_mutex); 1827 mutex_lock(&hdata->hdmi_mutex);
1649 if (!hdata->powered) { 1828 if (!hdata->powered) {
@@ -1655,8 +1834,9 @@ static void hdmi_commit(void *ctx)
1655 hdmi_conf_apply(hdata); 1834 hdmi_conf_apply(hdata);
1656} 1835}
1657 1836
1658static void hdmi_poweron(struct hdmi_context *hdata) 1837static void hdmi_poweron(struct exynos_drm_display *display)
1659{ 1838{
1839 struct hdmi_context *hdata = display->ctx;
1660 struct hdmi_resources *res = &hdata->res; 1840 struct hdmi_resources *res = &hdata->res;
1661 1841
1662 mutex_lock(&hdata->hdmi_mutex); 1842 mutex_lock(&hdata->hdmi_mutex);
@@ -1669,6 +1849,8 @@ static void hdmi_poweron(struct hdmi_context *hdata)
1669 1849
1670 mutex_unlock(&hdata->hdmi_mutex); 1850 mutex_unlock(&hdata->hdmi_mutex);
1671 1851
1852 pm_runtime_get_sync(hdata->dev);
1853
1672 if (regulator_bulk_enable(res->regul_count, res->regul_bulk)) 1854 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1673 DRM_DEBUG_KMS("failed to enable regulator bulk\n"); 1855 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1674 1856
@@ -1677,10 +1859,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
1677 clk_prepare_enable(res->sclk_hdmi); 1859 clk_prepare_enable(res->sclk_hdmi);
1678 1860
1679 hdmiphy_poweron(hdata); 1861 hdmiphy_poweron(hdata);
1862 hdmi_commit(display);
1680} 1863}
1681 1864
1682static void hdmi_poweroff(struct hdmi_context *hdata) 1865static void hdmi_poweroff(struct exynos_drm_display *display)
1683{ 1866{
1867 struct hdmi_context *hdata = display->ctx;
1684 struct hdmi_resources *res = &hdata->res; 1868 struct hdmi_resources *res = &hdata->res;
1685 1869
1686 mutex_lock(&hdata->hdmi_mutex); 1870 mutex_lock(&hdata->hdmi_mutex);
@@ -1700,30 +1884,27 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
1700 clk_disable_unprepare(res->hdmiphy); 1884 clk_disable_unprepare(res->hdmiphy);
1701 regulator_bulk_disable(res->regul_count, res->regul_bulk); 1885 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1702 1886
1703 mutex_lock(&hdata->hdmi_mutex); 1887 pm_runtime_put_sync(hdata->dev);
1704 1888
1889 mutex_lock(&hdata->hdmi_mutex);
1705 hdata->powered = false; 1890 hdata->powered = false;
1706 1891
1707out: 1892out:
1708 mutex_unlock(&hdata->hdmi_mutex); 1893 mutex_unlock(&hdata->hdmi_mutex);
1709} 1894}
1710 1895
1711static void hdmi_dpms(void *ctx, int mode) 1896static void hdmi_dpms(struct exynos_drm_display *display, int mode)
1712{ 1897{
1713 struct hdmi_context *hdata = ctx;
1714
1715 DRM_DEBUG_KMS("mode %d\n", mode); 1898 DRM_DEBUG_KMS("mode %d\n", mode);
1716 1899
1717 switch (mode) { 1900 switch (mode) {
1718 case DRM_MODE_DPMS_ON: 1901 case DRM_MODE_DPMS_ON:
1719 if (pm_runtime_suspended(hdata->dev)) 1902 hdmi_poweron(display);
1720 pm_runtime_get_sync(hdata->dev);
1721 break; 1903 break;
1722 case DRM_MODE_DPMS_STANDBY: 1904 case DRM_MODE_DPMS_STANDBY:
1723 case DRM_MODE_DPMS_SUSPEND: 1905 case DRM_MODE_DPMS_SUSPEND:
1724 case DRM_MODE_DPMS_OFF: 1906 case DRM_MODE_DPMS_OFF:
1725 if (!pm_runtime_suspended(hdata->dev)) 1907 hdmi_poweroff(display);
1726 pm_runtime_put_sync(hdata->dev);
1727 break; 1908 break;
1728 default: 1909 default:
1729 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1910 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -1731,30 +1912,30 @@ static void hdmi_dpms(void *ctx, int mode)
1731 } 1912 }
1732} 1913}
1733 1914
1734static struct exynos_hdmi_ops hdmi_ops = { 1915static struct exynos_drm_display_ops hdmi_display_ops = {
1735 /* display */ 1916 .initialize = hdmi_initialize,
1736 .is_connected = hdmi_is_connected, 1917 .create_connector = hdmi_create_connector,
1737 .get_edid = hdmi_get_edid, 1918 .mode_fixup = hdmi_mode_fixup,
1738 .check_mode = hdmi_check_mode,
1739
1740 /* manager */
1741 .mode_set = hdmi_mode_set, 1919 .mode_set = hdmi_mode_set,
1742 .get_max_resol = hdmi_get_max_resol,
1743 .commit = hdmi_commit,
1744 .dpms = hdmi_dpms, 1920 .dpms = hdmi_dpms,
1921 .commit = hdmi_commit,
1922};
1923
1924static struct exynos_drm_display hdmi_display = {
1925 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1926 .ops = &hdmi_display_ops,
1745}; 1927};
1746 1928
1747static irqreturn_t hdmi_irq_thread(int irq, void *arg) 1929static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1748{ 1930{
1749 struct exynos_drm_hdmi_context *ctx = arg; 1931 struct hdmi_context *hdata = arg;
1750 struct hdmi_context *hdata = ctx->ctx;
1751 1932
1752 mutex_lock(&hdata->hdmi_mutex); 1933 mutex_lock(&hdata->hdmi_mutex);
1753 hdata->hpd = gpio_get_value(hdata->hpd_gpio); 1934 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
1754 mutex_unlock(&hdata->hdmi_mutex); 1935 mutex_unlock(&hdata->hdmi_mutex);
1755 1936
1756 if (ctx->drm_dev) 1937 if (hdata->drm_dev)
1757 drm_helper_hpd_irq_event(ctx->drm_dev); 1938 drm_helper_hpd_irq_event(hdata->drm_dev);
1758 1939
1759 return IRQ_HANDLED; 1940 return IRQ_HANDLED;
1760} 1941}
@@ -1830,20 +2011,6 @@ fail:
1830 return -ENODEV; 2011 return -ENODEV;
1831} 2012}
1832 2013
1833static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
1834
1835void hdmi_attach_ddc_client(struct i2c_client *ddc)
1836{
1837 if (ddc)
1838 hdmi_ddc = ddc;
1839}
1840
1841void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
1842{
1843 if (hdmiphy)
1844 hdmi_hdmiphy = hdmiphy;
1845}
1846
1847static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata 2014static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
1848 (struct device *dev) 2015 (struct device *dev)
1849{ 2016{
@@ -1871,10 +2038,10 @@ err_data:
1871static struct of_device_id hdmi_match_types[] = { 2038static struct of_device_id hdmi_match_types[] = {
1872 { 2039 {
1873 .compatible = "samsung,exynos5-hdmi", 2040 .compatible = "samsung,exynos5-hdmi",
1874 .data = (void *)HDMI_TYPE14, 2041 .data = &exynos5_hdmi_driver_data,
1875 }, { 2042 }, {
1876 .compatible = "samsung,exynos4212-hdmi", 2043 .compatible = "samsung,exynos4212-hdmi",
1877 .data = (void *)HDMI_TYPE14, 2044 .data = &exynos4212_hdmi_driver_data,
1878 }, { 2045 }, {
1879 /* end node */ 2046 /* end node */
1880 } 2047 }
@@ -1883,11 +2050,12 @@ static struct of_device_id hdmi_match_types[] = {
1883static int hdmi_probe(struct platform_device *pdev) 2050static int hdmi_probe(struct platform_device *pdev)
1884{ 2051{
1885 struct device *dev = &pdev->dev; 2052 struct device *dev = &pdev->dev;
1886 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1887 struct hdmi_context *hdata; 2053 struct hdmi_context *hdata;
1888 struct s5p_hdmi_platform_data *pdata; 2054 struct s5p_hdmi_platform_data *pdata;
1889 struct resource *res; 2055 struct resource *res;
1890 const struct of_device_id *match; 2056 const struct of_device_id *match;
2057 struct device_node *ddc_node, *phy_node;
2058 struct hdmi_driver_data *drv_data;
1891 int ret; 2059 int ret;
1892 2060
1893 if (!dev->of_node) 2061 if (!dev->of_node)
@@ -1897,25 +2065,20 @@ static int hdmi_probe(struct platform_device *pdev)
1897 if (!pdata) 2065 if (!pdata)
1898 return -EINVAL; 2066 return -EINVAL;
1899 2067
1900 drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1901 if (!drm_hdmi_ctx)
1902 return -ENOMEM;
1903
1904 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); 2068 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
1905 if (!hdata) 2069 if (!hdata)
1906 return -ENOMEM; 2070 return -ENOMEM;
1907 2071
1908 mutex_init(&hdata->hdmi_mutex); 2072 mutex_init(&hdata->hdmi_mutex);
1909 2073
1910 drm_hdmi_ctx->ctx = (void *)hdata; 2074 platform_set_drvdata(pdev, &hdmi_display);
1911 hdata->parent_ctx = (void *)drm_hdmi_ctx;
1912
1913 platform_set_drvdata(pdev, drm_hdmi_ctx);
1914 2075
1915 match = of_match_node(hdmi_match_types, dev->of_node); 2076 match = of_match_node(hdmi_match_types, dev->of_node);
1916 if (!match) 2077 if (!match)
1917 return -ENODEV; 2078 return -ENODEV;
1918 hdata->type = (enum hdmi_type)match->data; 2079
2080 drv_data = (struct hdmi_driver_data *)match->data;
2081 hdata->type = drv_data->type;
1919 2082
1920 hdata->hpd_gpio = pdata->hpd_gpio; 2083 hdata->hpd_gpio = pdata->hpd_gpio;
1921 hdata->dev = dev; 2084 hdata->dev = dev;
@@ -1938,21 +2101,34 @@ static int hdmi_probe(struct platform_device *pdev)
1938 } 2101 }
1939 2102
1940 /* DDC i2c driver */ 2103 /* DDC i2c driver */
1941 if (i2c_add_driver(&ddc_driver)) { 2104 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
1942 DRM_ERROR("failed to register ddc i2c driver\n"); 2105 if (!ddc_node) {
1943 return -ENOENT; 2106 DRM_ERROR("Failed to find ddc node in device tree\n");
2107 return -ENODEV;
2108 }
2109 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
2110 if (!hdata->ddc_adpt) {
2111 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
2112 return -ENODEV;
1944 } 2113 }
1945 2114
1946 hdata->ddc_port = hdmi_ddc; 2115 /* Not support APB PHY yet. */
2116 if (drv_data->is_apb_phy)
2117 return -EPERM;
1947 2118
1948 /* hdmiphy i2c driver */ 2119 /* hdmiphy i2c driver */
1949 if (i2c_add_driver(&hdmiphy_driver)) { 2120 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
1950 DRM_ERROR("failed to register hdmiphy i2c driver\n"); 2121 if (!phy_node) {
1951 ret = -ENOENT; 2122 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
2123 ret = -ENODEV;
2124 goto err_ddc;
2125 }
2126 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
2127 if (!hdata->hdmiphy_port) {
2128 DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
2129 ret = -ENODEV;
1952 goto err_ddc; 2130 goto err_ddc;
1953 } 2131 }
1954
1955 hdata->hdmiphy_port = hdmi_hdmiphy;
1956 2132
1957 hdata->irq = gpio_to_irq(hdata->hpd_gpio); 2133 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
1958 if (hdata->irq < 0) { 2134 if (hdata->irq < 0) {
@@ -1966,119 +2142,45 @@ static int hdmi_probe(struct platform_device *pdev)
1966 ret = devm_request_threaded_irq(dev, hdata->irq, NULL, 2142 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
1967 hdmi_irq_thread, IRQF_TRIGGER_RISING | 2143 hdmi_irq_thread, IRQF_TRIGGER_RISING |
1968 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 2144 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1969 "hdmi", drm_hdmi_ctx); 2145 "hdmi", hdata);
1970 if (ret) { 2146 if (ret) {
1971 DRM_ERROR("failed to register hdmi interrupt\n"); 2147 DRM_ERROR("failed to register hdmi interrupt\n");
1972 goto err_hdmiphy; 2148 goto err_hdmiphy;
1973 } 2149 }
1974 2150
1975 /* Attach HDMI Driver to common hdmi. */
1976 exynos_hdmi_drv_attach(drm_hdmi_ctx);
1977
1978 /* register specific callbacks to common hdmi. */
1979 exynos_hdmi_ops_register(&hdmi_ops);
1980
1981 pm_runtime_enable(dev); 2151 pm_runtime_enable(dev);
1982 2152
2153 hdmi_display.ctx = hdata;
2154 exynos_drm_display_register(&hdmi_display);
2155
1983 return 0; 2156 return 0;
1984 2157
1985err_hdmiphy: 2158err_hdmiphy:
1986 i2c_del_driver(&hdmiphy_driver); 2159 put_device(&hdata->hdmiphy_port->dev);
1987err_ddc: 2160err_ddc:
1988 i2c_del_driver(&ddc_driver); 2161 put_device(&hdata->ddc_adpt->dev);
1989 return ret; 2162 return ret;
1990} 2163}
1991 2164
1992static int hdmi_remove(struct platform_device *pdev) 2165static int hdmi_remove(struct platform_device *pdev)
1993{ 2166{
1994 struct device *dev = &pdev->dev; 2167 struct device *dev = &pdev->dev;
2168 struct exynos_drm_display *display = get_hdmi_display(dev);
2169 struct hdmi_context *hdata = display->ctx;
1995 2170
1996 pm_runtime_disable(dev); 2171 put_device(&hdata->hdmiphy_port->dev);
1997 2172 put_device(&hdata->ddc_adpt->dev);
1998 /* hdmiphy i2c driver */ 2173 pm_runtime_disable(&pdev->dev);
1999 i2c_del_driver(&hdmiphy_driver);
2000 /* DDC i2c driver */
2001 i2c_del_driver(&ddc_driver);
2002
2003 return 0;
2004}
2005
2006#ifdef CONFIG_PM_SLEEP
2007static int hdmi_suspend(struct device *dev)
2008{
2009 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2010 struct hdmi_context *hdata = ctx->ctx;
2011
2012 disable_irq(hdata->irq);
2013
2014 hdata->hpd = false;
2015 if (ctx->drm_dev)
2016 drm_helper_hpd_irq_event(ctx->drm_dev);
2017
2018 if (pm_runtime_suspended(dev)) {
2019 DRM_DEBUG_KMS("Already suspended\n");
2020 return 0;
2021 }
2022
2023 hdmi_poweroff(hdata);
2024 2174
2025 return 0; 2175 return 0;
2026} 2176}
2027 2177
2028static int hdmi_resume(struct device *dev)
2029{
2030 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2031 struct hdmi_context *hdata = ctx->ctx;
2032
2033 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2034
2035 enable_irq(hdata->irq);
2036
2037 if (!pm_runtime_suspended(dev)) {
2038 DRM_DEBUG_KMS("Already resumed\n");
2039 return 0;
2040 }
2041
2042 hdmi_poweron(hdata);
2043
2044 return 0;
2045}
2046#endif
2047
2048#ifdef CONFIG_PM_RUNTIME
2049static int hdmi_runtime_suspend(struct device *dev)
2050{
2051 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2052 struct hdmi_context *hdata = ctx->ctx;
2053
2054 hdmi_poweroff(hdata);
2055
2056 return 0;
2057}
2058
2059static int hdmi_runtime_resume(struct device *dev)
2060{
2061 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2062 struct hdmi_context *hdata = ctx->ctx;
2063
2064 hdmi_poweron(hdata);
2065
2066 return 0;
2067}
2068#endif
2069
2070static const struct dev_pm_ops hdmi_pm_ops = {
2071 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2072 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2073};
2074
2075struct platform_driver hdmi_driver = { 2178struct platform_driver hdmi_driver = {
2076 .probe = hdmi_probe, 2179 .probe = hdmi_probe,
2077 .remove = hdmi_remove, 2180 .remove = hdmi_remove,
2078 .driver = { 2181 .driver = {
2079 .name = "exynos-hdmi", 2182 .name = "exynos-hdmi",
2080 .owner = THIS_MODULE, 2183 .owner = THIS_MODULE,
2081 .pm = &hdmi_pm_ops,
2082 .of_match_table = hdmi_match_types, 2184 .of_match_table = hdmi_match_types,
2083 }, 2185 },
2084}; 2186};
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 2dfa48c76f54..ce288818d2c0 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -36,10 +36,13 @@
36 36
37#include "exynos_drm_drv.h" 37#include "exynos_drm_drv.h"
38#include "exynos_drm_crtc.h" 38#include "exynos_drm_crtc.h"
39#include "exynos_drm_hdmi.h"
40#include "exynos_drm_iommu.h" 39#include "exynos_drm_iommu.h"
40#include "exynos_mixer.h"
41 41
42#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) 42#define get_mixer_manager(dev) platform_get_drvdata(to_platform_device(dev))
43
44#define MIXER_WIN_NR 3
45#define MIXER_DEFAULT_WIN 0
43 46
44struct hdmi_win_data { 47struct hdmi_win_data {
45 dma_addr_t dma_addr; 48 dma_addr_t dma_addr;
@@ -82,6 +85,7 @@ enum mixer_version_id {
82}; 85};
83 86
84struct mixer_context { 87struct mixer_context {
88 struct platform_device *pdev;
85 struct device *dev; 89 struct device *dev;
86 struct drm_device *drm_dev; 90 struct drm_device *drm_dev;
87 int pipe; 91 int pipe;
@@ -94,7 +98,6 @@ struct mixer_context {
94 struct mixer_resources mixer_res; 98 struct mixer_resources mixer_res;
95 struct hdmi_win_data win_data[MIXER_WIN_NR]; 99 struct hdmi_win_data win_data[MIXER_WIN_NR];
96 enum mixer_version_id mxr_ver; 100 enum mixer_version_id mxr_ver;
97 void *parent_ctx;
98 wait_queue_head_t wait_vsync_queue; 101 wait_queue_head_t wait_vsync_queue;
99 atomic_t wait_vsync_event; 102 atomic_t wait_vsync_event;
100}; 103};
@@ -685,31 +688,196 @@ static void mixer_win_reset(struct mixer_context *ctx)
685 spin_unlock_irqrestore(&res->reg_slock, flags); 688 spin_unlock_irqrestore(&res->reg_slock, flags);
686} 689}
687 690
688static int mixer_iommu_on(void *ctx, bool enable) 691static irqreturn_t mixer_irq_handler(int irq, void *arg)
692{
693 struct mixer_context *ctx = arg;
694 struct mixer_resources *res = &ctx->mixer_res;
695 u32 val, base, shadow;
696
697 spin_lock(&res->reg_slock);
698
699 /* read interrupt status for handling and clearing flags for VSYNC */
700 val = mixer_reg_read(res, MXR_INT_STATUS);
701
702 /* handling VSYNC */
703 if (val & MXR_INT_STATUS_VSYNC) {
704 /* interlace scan need to check shadow register */
705 if (ctx->interlace) {
706 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
707 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
708 if (base != shadow)
709 goto out;
710
711 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
712 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
713 if (base != shadow)
714 goto out;
715 }
716
717 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
718 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
719
720 /* set wait vsync event to zero and wake up queue. */
721 if (atomic_read(&ctx->wait_vsync_event)) {
722 atomic_set(&ctx->wait_vsync_event, 0);
723 wake_up(&ctx->wait_vsync_queue);
724 }
725 }
726
727out:
728 /* clear interrupts */
729 if (~val & MXR_INT_EN_VSYNC) {
730 /* vsync interrupt use different bit for read and clear */
731 val &= ~MXR_INT_EN_VSYNC;
732 val |= MXR_INT_CLEAR_VSYNC;
733 }
734 mixer_reg_write(res, MXR_INT_STATUS, val);
735
736 spin_unlock(&res->reg_slock);
737
738 return IRQ_HANDLED;
739}
740
741static int mixer_resources_init(struct mixer_context *mixer_ctx)
689{ 742{
690 struct exynos_drm_hdmi_context *drm_hdmi_ctx; 743 struct device *dev = &mixer_ctx->pdev->dev;
691 struct mixer_context *mdata = ctx; 744 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
692 struct drm_device *drm_dev; 745 struct resource *res;
746 int ret;
693 747
694 drm_hdmi_ctx = mdata->parent_ctx; 748 spin_lock_init(&mixer_res->reg_slock);
695 drm_dev = drm_hdmi_ctx->drm_dev;
696 749
697 if (is_drm_iommu_supported(drm_dev)) { 750 mixer_res->mixer = devm_clk_get(dev, "mixer");
698 if (enable) 751 if (IS_ERR(mixer_res->mixer)) {
699 return drm_iommu_attach_device(drm_dev, mdata->dev); 752 dev_err(dev, "failed to get clock 'mixer'\n");
753 return -ENODEV;
754 }
700 755
701 drm_iommu_detach_device(drm_dev, mdata->dev); 756 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
757 if (IS_ERR(mixer_res->sclk_hdmi)) {
758 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
759 return -ENODEV;
760 }
761 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
762 if (res == NULL) {
763 dev_err(dev, "get memory resource failed.\n");
764 return -ENXIO;
702 } 765 }
766
767 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
768 resource_size(res));
769 if (mixer_res->mixer_regs == NULL) {
770 dev_err(dev, "register mapping failed.\n");
771 return -ENXIO;
772 }
773
774 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
775 if (res == NULL) {
776 dev_err(dev, "get interrupt resource failed.\n");
777 return -ENXIO;
778 }
779
780 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
781 0, "drm_mixer", mixer_ctx);
782 if (ret) {
783 dev_err(dev, "request interrupt failed.\n");
784 return ret;
785 }
786 mixer_res->irq = res->start;
787
703 return 0; 788 return 0;
704} 789}
705 790
706static int mixer_enable_vblank(void *ctx, int pipe) 791static int vp_resources_init(struct mixer_context *mixer_ctx)
707{ 792{
708 struct mixer_context *mixer_ctx = ctx; 793 struct device *dev = &mixer_ctx->pdev->dev;
709 struct mixer_resources *res = &mixer_ctx->mixer_res; 794 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
795 struct resource *res;
796
797 mixer_res->vp = devm_clk_get(dev, "vp");
798 if (IS_ERR(mixer_res->vp)) {
799 dev_err(dev, "failed to get clock 'vp'\n");
800 return -ENODEV;
801 }
802 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
803 if (IS_ERR(mixer_res->sclk_mixer)) {
804 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
805 return -ENODEV;
806 }
807 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
808 if (IS_ERR(mixer_res->sclk_dac)) {
809 dev_err(dev, "failed to get clock 'sclk_dac'\n");
810 return -ENODEV;
811 }
812
813 if (mixer_res->sclk_hdmi)
814 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
815
816 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
817 if (res == NULL) {
818 dev_err(dev, "get memory resource failed.\n");
819 return -ENXIO;
820 }
710 821
822 mixer_res->vp_regs = devm_ioremap(dev, res->start,
823 resource_size(res));
824 if (mixer_res->vp_regs == NULL) {
825 dev_err(dev, "register mapping failed.\n");
826 return -ENXIO;
827 }
828
829 return 0;
830}
831
832static int mixer_initialize(struct exynos_drm_manager *mgr,
833 struct drm_device *drm_dev, int pipe)
834{
835 int ret;
836 struct mixer_context *mixer_ctx = mgr->ctx;
837
838 mixer_ctx->drm_dev = drm_dev;
711 mixer_ctx->pipe = pipe; 839 mixer_ctx->pipe = pipe;
712 840
841 /* acquire resources: regs, irqs, clocks */
842 ret = mixer_resources_init(mixer_ctx);
843 if (ret) {
844 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
845 return ret;
846 }
847
848 if (mixer_ctx->vp_enabled) {
849 /* acquire vp resources: regs, irqs, clocks */
850 ret = vp_resources_init(mixer_ctx);
851 if (ret) {
852 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
853 return ret;
854 }
855 }
856
857 if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
858 return 0;
859
860 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
861}
862
863static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
864{
865 struct mixer_context *mixer_ctx = mgr->ctx;
866
867 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
868 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
869}
870
871static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
872{
873 struct mixer_context *mixer_ctx = mgr->ctx;
874 struct mixer_resources *res = &mixer_ctx->mixer_res;
875
876 if (!mixer_ctx->powered) {
877 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
878 return 0;
879 }
880
713 /* enable vsync interrupt */ 881 /* enable vsync interrupt */
714 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, 882 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
715 MXR_INT_EN_VSYNC); 883 MXR_INT_EN_VSYNC);
@@ -717,19 +885,19 @@ static int mixer_enable_vblank(void *ctx, int pipe)
717 return 0; 885 return 0;
718} 886}
719 887
720static void mixer_disable_vblank(void *ctx) 888static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
721{ 889{
722 struct mixer_context *mixer_ctx = ctx; 890 struct mixer_context *mixer_ctx = mgr->ctx;
723 struct mixer_resources *res = &mixer_ctx->mixer_res; 891 struct mixer_resources *res = &mixer_ctx->mixer_res;
724 892
725 /* disable vsync interrupt */ 893 /* disable vsync interrupt */
726 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 894 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
727} 895}
728 896
729static void mixer_win_mode_set(void *ctx, 897static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
730 struct exynos_drm_overlay *overlay) 898 struct exynos_drm_overlay *overlay)
731{ 899{
732 struct mixer_context *mixer_ctx = ctx; 900 struct mixer_context *mixer_ctx = mgr->ctx;
733 struct hdmi_win_data *win_data; 901 struct hdmi_win_data *win_data;
734 int win; 902 int win;
735 903
@@ -778,9 +946,10 @@ static void mixer_win_mode_set(void *ctx,
778 win_data->scan_flags = overlay->scan_flag; 946 win_data->scan_flags = overlay->scan_flag;
779} 947}
780 948
781static void mixer_win_commit(void *ctx, int win) 949static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
782{ 950{
783 struct mixer_context *mixer_ctx = ctx; 951 struct mixer_context *mixer_ctx = mgr->ctx;
952 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
784 953
785 DRM_DEBUG_KMS("win: %d\n", win); 954 DRM_DEBUG_KMS("win: %d\n", win);
786 955
@@ -799,10 +968,11 @@ static void mixer_win_commit(void *ctx, int win)
799 mixer_ctx->win_data[win].enabled = true; 968 mixer_ctx->win_data[win].enabled = true;
800} 969}
801 970
802static void mixer_win_disable(void *ctx, int win) 971static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
803{ 972{
804 struct mixer_context *mixer_ctx = ctx; 973 struct mixer_context *mixer_ctx = mgr->ctx;
805 struct mixer_resources *res = &mixer_ctx->mixer_res; 974 struct mixer_resources *res = &mixer_ctx->mixer_res;
975 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
806 unsigned long flags; 976 unsigned long flags;
807 977
808 DRM_DEBUG_KMS("win: %d\n", win); 978 DRM_DEBUG_KMS("win: %d\n", win);
@@ -826,32 +996,9 @@ static void mixer_win_disable(void *ctx, int win)
826 mixer_ctx->win_data[win].enabled = false; 996 mixer_ctx->win_data[win].enabled = false;
827} 997}
828 998
829static int mixer_check_mode(void *ctx, struct drm_display_mode *mode) 999static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
830{ 1000{
831 struct mixer_context *mixer_ctx = ctx; 1001 struct mixer_context *mixer_ctx = mgr->ctx;
832 u32 w, h;
833
834 w = mode->hdisplay;
835 h = mode->vdisplay;
836
837 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
838 mode->hdisplay, mode->vdisplay, mode->vrefresh,
839 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
840
841 if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16 ||
842 mixer_ctx->mxr_ver == MXR_VER_128_0_0_184)
843 return 0;
844
845 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
846 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
847 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
848 return 0;
849
850 return -EINVAL;
851}
852static void mixer_wait_for_vblank(void *ctx)
853{
854 struct mixer_context *mixer_ctx = ctx;
855 1002
856 mutex_lock(&mixer_ctx->mixer_mutex); 1003 mutex_lock(&mixer_ctx->mixer_mutex);
857 if (!mixer_ctx->powered) { 1004 if (!mixer_ctx->powered) {
@@ -872,21 +1019,23 @@ static void mixer_wait_for_vblank(void *ctx)
872 DRM_DEBUG_KMS("vblank wait timed out.\n"); 1019 DRM_DEBUG_KMS("vblank wait timed out.\n");
873} 1020}
874 1021
875static void mixer_window_suspend(struct mixer_context *ctx) 1022static void mixer_window_suspend(struct exynos_drm_manager *mgr)
876{ 1023{
1024 struct mixer_context *ctx = mgr->ctx;
877 struct hdmi_win_data *win_data; 1025 struct hdmi_win_data *win_data;
878 int i; 1026 int i;
879 1027
880 for (i = 0; i < MIXER_WIN_NR; i++) { 1028 for (i = 0; i < MIXER_WIN_NR; i++) {
881 win_data = &ctx->win_data[i]; 1029 win_data = &ctx->win_data[i];
882 win_data->resume = win_data->enabled; 1030 win_data->resume = win_data->enabled;
883 mixer_win_disable(ctx, i); 1031 mixer_win_disable(mgr, i);
884 } 1032 }
885 mixer_wait_for_vblank(ctx); 1033 mixer_wait_for_vblank(mgr);
886} 1034}
887 1035
888static void mixer_window_resume(struct mixer_context *ctx) 1036static void mixer_window_resume(struct exynos_drm_manager *mgr)
889{ 1037{
1038 struct mixer_context *ctx = mgr->ctx;
890 struct hdmi_win_data *win_data; 1039 struct hdmi_win_data *win_data;
891 int i; 1040 int i;
892 1041
@@ -894,11 +1043,14 @@ static void mixer_window_resume(struct mixer_context *ctx)
894 win_data = &ctx->win_data[i]; 1043 win_data = &ctx->win_data[i];
895 win_data->enabled = win_data->resume; 1044 win_data->enabled = win_data->resume;
896 win_data->resume = false; 1045 win_data->resume = false;
1046 if (win_data->enabled)
1047 mixer_win_commit(mgr, i);
897 } 1048 }
898} 1049}
899 1050
900static void mixer_poweron(struct mixer_context *ctx) 1051static void mixer_poweron(struct exynos_drm_manager *mgr)
901{ 1052{
1053 struct mixer_context *ctx = mgr->ctx;
902 struct mixer_resources *res = &ctx->mixer_res; 1054 struct mixer_resources *res = &ctx->mixer_res;
903 1055
904 mutex_lock(&ctx->mixer_mutex); 1056 mutex_lock(&ctx->mixer_mutex);
@@ -909,6 +1061,8 @@ static void mixer_poweron(struct mixer_context *ctx)
909 ctx->powered = true; 1061 ctx->powered = true;
910 mutex_unlock(&ctx->mixer_mutex); 1062 mutex_unlock(&ctx->mixer_mutex);
911 1063
1064 pm_runtime_get_sync(ctx->dev);
1065
912 clk_prepare_enable(res->mixer); 1066 clk_prepare_enable(res->mixer);
913 if (ctx->vp_enabled) { 1067 if (ctx->vp_enabled) {
914 clk_prepare_enable(res->vp); 1068 clk_prepare_enable(res->vp);
@@ -918,11 +1072,12 @@ static void mixer_poweron(struct mixer_context *ctx)
918 mixer_reg_write(res, MXR_INT_EN, ctx->int_en); 1072 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
919 mixer_win_reset(ctx); 1073 mixer_win_reset(ctx);
920 1074
921 mixer_window_resume(ctx); 1075 mixer_window_resume(mgr);
922} 1076}
923 1077
924static void mixer_poweroff(struct mixer_context *ctx) 1078static void mixer_poweroff(struct exynos_drm_manager *mgr)
925{ 1079{
1080 struct mixer_context *ctx = mgr->ctx;
926 struct mixer_resources *res = &ctx->mixer_res; 1081 struct mixer_resources *res = &ctx->mixer_res;
927 1082
928 mutex_lock(&ctx->mixer_mutex); 1083 mutex_lock(&ctx->mixer_mutex);
@@ -930,7 +1085,7 @@ static void mixer_poweroff(struct mixer_context *ctx)
930 goto out; 1085 goto out;
931 mutex_unlock(&ctx->mixer_mutex); 1086 mutex_unlock(&ctx->mixer_mutex);
932 1087
933 mixer_window_suspend(ctx); 1088 mixer_window_suspend(mgr);
934 1089
935 ctx->int_en = mixer_reg_read(res, MXR_INT_EN); 1090 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
936 1091
@@ -940,6 +1095,8 @@ static void mixer_poweroff(struct mixer_context *ctx)
940 clk_disable_unprepare(res->sclk_mixer); 1095 clk_disable_unprepare(res->sclk_mixer);
941 } 1096 }
942 1097
1098 pm_runtime_put_sync(ctx->dev);
1099
943 mutex_lock(&ctx->mixer_mutex); 1100 mutex_lock(&ctx->mixer_mutex);
944 ctx->powered = false; 1101 ctx->powered = false;
945 1102
@@ -947,20 +1104,16 @@ out:
947 mutex_unlock(&ctx->mixer_mutex); 1104 mutex_unlock(&ctx->mixer_mutex);
948} 1105}
949 1106
950static void mixer_dpms(void *ctx, int mode) 1107static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
951{ 1108{
952 struct mixer_context *mixer_ctx = ctx;
953
954 switch (mode) { 1109 switch (mode) {
955 case DRM_MODE_DPMS_ON: 1110 case DRM_MODE_DPMS_ON:
956 if (pm_runtime_suspended(mixer_ctx->dev)) 1111 mixer_poweron(mgr);
957 pm_runtime_get_sync(mixer_ctx->dev);
958 break; 1112 break;
959 case DRM_MODE_DPMS_STANDBY: 1113 case DRM_MODE_DPMS_STANDBY:
960 case DRM_MODE_DPMS_SUSPEND: 1114 case DRM_MODE_DPMS_SUSPEND:
961 case DRM_MODE_DPMS_OFF: 1115 case DRM_MODE_DPMS_OFF:
962 if (!pm_runtime_suspended(mixer_ctx->dev)) 1116 mixer_poweroff(mgr);
963 pm_runtime_put_sync(mixer_ctx->dev);
964 break; 1117 break;
965 default: 1118 default:
966 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1119 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -968,169 +1121,42 @@ static void mixer_dpms(void *ctx, int mode)
968 } 1121 }
969} 1122}
970 1123
971static struct exynos_mixer_ops mixer_ops = { 1124/* Only valid for Mixer version 16.0.33.0 */
972 /* manager */ 1125int mixer_check_mode(struct drm_display_mode *mode)
973 .iommu_on = mixer_iommu_on,
974 .enable_vblank = mixer_enable_vblank,
975 .disable_vblank = mixer_disable_vblank,
976 .wait_for_vblank = mixer_wait_for_vblank,
977 .dpms = mixer_dpms,
978
979 /* overlay */
980 .win_mode_set = mixer_win_mode_set,
981 .win_commit = mixer_win_commit,
982 .win_disable = mixer_win_disable,
983
984 /* display */
985 .check_mode = mixer_check_mode,
986};
987
988static irqreturn_t mixer_irq_handler(int irq, void *arg)
989{
990 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
991 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
992 struct mixer_resources *res = &ctx->mixer_res;
993 u32 val, base, shadow;
994
995 spin_lock(&res->reg_slock);
996
997 /* read interrupt status for handling and clearing flags for VSYNC */
998 val = mixer_reg_read(res, MXR_INT_STATUS);
999
1000 /* handling VSYNC */
1001 if (val & MXR_INT_STATUS_VSYNC) {
1002 /* interlace scan need to check shadow register */
1003 if (ctx->interlace) {
1004 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
1005 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
1006 if (base != shadow)
1007 goto out;
1008
1009 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
1010 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
1011 if (base != shadow)
1012 goto out;
1013 }
1014
1015 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
1016 exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
1017 ctx->pipe);
1018
1019 /* set wait vsync event to zero and wake up queue. */
1020 if (atomic_read(&ctx->wait_vsync_event)) {
1021 atomic_set(&ctx->wait_vsync_event, 0);
1022 wake_up(&ctx->wait_vsync_queue);
1023 }
1024 }
1025
1026out:
1027 /* clear interrupts */
1028 if (~val & MXR_INT_EN_VSYNC) {
1029 /* vsync interrupt use different bit for read and clear */
1030 val &= ~MXR_INT_EN_VSYNC;
1031 val |= MXR_INT_CLEAR_VSYNC;
1032 }
1033 mixer_reg_write(res, MXR_INT_STATUS, val);
1034
1035 spin_unlock(&res->reg_slock);
1036
1037 return IRQ_HANDLED;
1038}
1039
1040static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
1041 struct platform_device *pdev)
1042{ 1126{
1043 struct mixer_context *mixer_ctx = ctx->ctx; 1127 u32 w, h;
1044 struct device *dev = &pdev->dev;
1045 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1046 struct resource *res;
1047 int ret;
1048
1049 spin_lock_init(&mixer_res->reg_slock);
1050
1051 mixer_res->mixer = devm_clk_get(dev, "mixer");
1052 if (IS_ERR(mixer_res->mixer)) {
1053 dev_err(dev, "failed to get clock 'mixer'\n");
1054 return -ENODEV;
1055 }
1056
1057 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
1058 if (IS_ERR(mixer_res->sclk_hdmi)) {
1059 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1060 return -ENODEV;
1061 }
1062 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1063 if (res == NULL) {
1064 dev_err(dev, "get memory resource failed.\n");
1065 return -ENXIO;
1066 }
1067 1128
1068 mixer_res->mixer_regs = devm_ioremap(dev, res->start, 1129 w = mode->hdisplay;
1069 resource_size(res)); 1130 h = mode->vdisplay;
1070 if (mixer_res->mixer_regs == NULL) {
1071 dev_err(dev, "register mapping failed.\n");
1072 return -ENXIO;
1073 }
1074 1131
1075 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1132 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1076 if (res == NULL) { 1133 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1077 dev_err(dev, "get interrupt resource failed.\n"); 1134 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1078 return -ENXIO;
1079 }
1080 1135
1081 ret = devm_request_irq(dev, res->start, mixer_irq_handler, 1136 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1082 0, "drm_mixer", ctx); 1137 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1083 if (ret) { 1138 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1084 dev_err(dev, "request interrupt failed.\n"); 1139 return 0;
1085 return ret;
1086 }
1087 mixer_res->irq = res->start;
1088 1140
1089 return 0; 1141 return -EINVAL;
1090} 1142}
1091 1143
1092static int vp_resources_init(struct exynos_drm_hdmi_context *ctx, 1144static struct exynos_drm_manager_ops mixer_manager_ops = {
1093 struct platform_device *pdev) 1145 .initialize = mixer_initialize,
1094{ 1146 .remove = mixer_mgr_remove,
1095 struct mixer_context *mixer_ctx = ctx->ctx; 1147 .dpms = mixer_dpms,
1096 struct device *dev = &pdev->dev; 1148 .enable_vblank = mixer_enable_vblank,
1097 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; 1149 .disable_vblank = mixer_disable_vblank,
1098 struct resource *res; 1150 .wait_for_vblank = mixer_wait_for_vblank,
1099 1151 .win_mode_set = mixer_win_mode_set,
1100 mixer_res->vp = devm_clk_get(dev, "vp"); 1152 .win_commit = mixer_win_commit,
1101 if (IS_ERR(mixer_res->vp)) { 1153 .win_disable = mixer_win_disable,
1102 dev_err(dev, "failed to get clock 'vp'\n"); 1154};
1103 return -ENODEV;
1104 }
1105 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
1106 if (IS_ERR(mixer_res->sclk_mixer)) {
1107 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1108 return -ENODEV;
1109 }
1110 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
1111 if (IS_ERR(mixer_res->sclk_dac)) {
1112 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1113 return -ENODEV;
1114 }
1115
1116 if (mixer_res->sclk_hdmi)
1117 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1118
1119 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1120 if (res == NULL) {
1121 dev_err(dev, "get memory resource failed.\n");
1122 return -ENXIO;
1123 }
1124
1125 mixer_res->vp_regs = devm_ioremap(dev, res->start,
1126 resource_size(res));
1127 if (mixer_res->vp_regs == NULL) {
1128 dev_err(dev, "register mapping failed.\n");
1129 return -ENXIO;
1130 }
1131 1155
1132 return 0; 1156static struct exynos_drm_manager mixer_manager = {
1133} 1157 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1158 .ops = &mixer_manager_ops,
1159};
1134 1160
1135static struct mixer_drv_data exynos5420_mxr_drv_data = { 1161static struct mixer_drv_data exynos5420_mxr_drv_data = {
1136 .version = MXR_VER_128_0_0_184, 1162 .version = MXR_VER_128_0_0_184,
@@ -1177,21 +1203,16 @@ static struct of_device_id mixer_match_types[] = {
1177static int mixer_probe(struct platform_device *pdev) 1203static int mixer_probe(struct platform_device *pdev)
1178{ 1204{
1179 struct device *dev = &pdev->dev; 1205 struct device *dev = &pdev->dev;
1180 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1181 struct mixer_context *ctx; 1206 struct mixer_context *ctx;
1182 struct mixer_drv_data *drv; 1207 struct mixer_drv_data *drv;
1183 int ret;
1184 1208
1185 dev_info(dev, "probe start\n"); 1209 dev_info(dev, "probe start\n");
1186 1210
1187 drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), 1211 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1188 GFP_KERNEL); 1212 if (!ctx) {
1189 if (!drm_hdmi_ctx) 1213 DRM_ERROR("failed to alloc mixer context.\n");
1190 return -ENOMEM;
1191
1192 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1193 if (!ctx)
1194 return -ENOMEM; 1214 return -ENOMEM;
1215 }
1195 1216
1196 mutex_init(&ctx->mixer_mutex); 1217 mutex_init(&ctx->mixer_mutex);
1197 1218
@@ -1204,46 +1225,20 @@ static int mixer_probe(struct platform_device *pdev)
1204 platform_get_device_id(pdev)->driver_data; 1225 platform_get_device_id(pdev)->driver_data;
1205 } 1226 }
1206 1227
1228 ctx->pdev = pdev;
1207 ctx->dev = dev; 1229 ctx->dev = dev;
1208 ctx->parent_ctx = (void *)drm_hdmi_ctx;
1209 drm_hdmi_ctx->ctx = (void *)ctx;
1210 ctx->vp_enabled = drv->is_vp_enabled; 1230 ctx->vp_enabled = drv->is_vp_enabled;
1211 ctx->mxr_ver = drv->version; 1231 ctx->mxr_ver = drv->version;
1212 init_waitqueue_head(&ctx->wait_vsync_queue); 1232 init_waitqueue_head(&ctx->wait_vsync_queue);
1213 atomic_set(&ctx->wait_vsync_event, 0); 1233 atomic_set(&ctx->wait_vsync_event, 0);
1214 1234
1215 platform_set_drvdata(pdev, drm_hdmi_ctx); 1235 mixer_manager.ctx = ctx;
1216 1236 platform_set_drvdata(pdev, &mixer_manager);
1217 /* acquire resources: regs, irqs, clocks */ 1237 exynos_drm_manager_register(&mixer_manager);
1218 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1219 if (ret) {
1220 DRM_ERROR("mixer_resources_init failed\n");
1221 goto fail;
1222 }
1223
1224 if (ctx->vp_enabled) {
1225 /* acquire vp resources: regs, irqs, clocks */
1226 ret = vp_resources_init(drm_hdmi_ctx, pdev);
1227 if (ret) {
1228 DRM_ERROR("vp_resources_init failed\n");
1229 goto fail;
1230 }
1231 }
1232
1233 /* attach mixer driver to common hdmi. */
1234 exynos_mixer_drv_attach(drm_hdmi_ctx);
1235
1236 /* register specific callback point to common hdmi. */
1237 exynos_mixer_ops_register(&mixer_ops);
1238 1238
1239 pm_runtime_enable(dev); 1239 pm_runtime_enable(dev);
1240 1240
1241 return 0; 1241 return 0;
1242
1243
1244fail:
1245 dev_info(dev, "probe failed\n");
1246 return ret;
1247} 1242}
1248 1243
1249static int mixer_remove(struct platform_device *pdev) 1244static int mixer_remove(struct platform_device *pdev)
@@ -1255,70 +1250,10 @@ static int mixer_remove(struct platform_device *pdev)
1255 return 0; 1250 return 0;
1256} 1251}
1257 1252
1258#ifdef CONFIG_PM_SLEEP
1259static int mixer_suspend(struct device *dev)
1260{
1261 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1262 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1263
1264 if (pm_runtime_suspended(dev)) {
1265 DRM_DEBUG_KMS("Already suspended\n");
1266 return 0;
1267 }
1268
1269 mixer_poweroff(ctx);
1270
1271 return 0;
1272}
1273
1274static int mixer_resume(struct device *dev)
1275{
1276 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1277 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1278
1279 if (!pm_runtime_suspended(dev)) {
1280 DRM_DEBUG_KMS("Already resumed\n");
1281 return 0;
1282 }
1283
1284 mixer_poweron(ctx);
1285
1286 return 0;
1287}
1288#endif
1289
1290#ifdef CONFIG_PM_RUNTIME
1291static int mixer_runtime_suspend(struct device *dev)
1292{
1293 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1294 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1295
1296 mixer_poweroff(ctx);
1297
1298 return 0;
1299}
1300
1301static int mixer_runtime_resume(struct device *dev)
1302{
1303 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1304 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1305
1306 mixer_poweron(ctx);
1307
1308 return 0;
1309}
1310#endif
1311
1312static const struct dev_pm_ops mixer_pm_ops = {
1313 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1314 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1315};
1316
1317struct platform_driver mixer_driver = { 1253struct platform_driver mixer_driver = {
1318 .driver = { 1254 .driver = {
1319 .name = "exynos-mixer", 1255 .name = "exynos-mixer",
1320 .owner = THIS_MODULE, 1256 .owner = THIS_MODULE,
1321 .pm = &mixer_pm_ops,
1322 .of_match_table = mixer_match_types, 1257 .of_match_table = mixer_match_types,
1323 }, 1258 },
1324 .probe = mixer_probe, 1259 .probe = mixer_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.h b/drivers/gpu/drm/exynos/exynos_mixer.h
new file mode 100644
index 000000000000..3811e417f0e9
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_mixer.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright (C) 2013 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#ifndef _EXYNOS_MIXER_H_
15#define _EXYNOS_MIXER_H_
16
17/* This function returns 0 if the given timing is valid for the mixer */
18int mixer_check_mode(struct drm_display_mode *mode);
19
20#endif
diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile
index e9064dd9045d..b15315576376 100644
--- a/drivers/gpu/drm/gma500/Makefile
+++ b/drivers/gpu/drm/gma500/Makefile
@@ -13,9 +13,11 @@ gma500_gfx-y += \
13 intel_i2c.o \ 13 intel_i2c.o \
14 intel_gmbus.o \ 14 intel_gmbus.o \
15 mmu.o \ 15 mmu.o \
16 blitter.o \
16 power.o \ 17 power.o \
17 psb_drv.o \ 18 psb_drv.o \
18 gma_display.o \ 19 gma_display.o \
20 gma_device.o \
19 psb_intel_display.o \ 21 psb_intel_display.o \
20 psb_intel_lvds.o \ 22 psb_intel_lvds.o \
21 psb_intel_modes.o \ 23 psb_intel_modes.o \
diff --git a/drivers/gpu/drm/gma500/blitter.c b/drivers/gpu/drm/gma500/blitter.c
new file mode 100644
index 000000000000..9cd54a6fb899
--- /dev/null
+++ b/drivers/gpu/drm/gma500/blitter.c
@@ -0,0 +1,51 @@
1/*
2 * Copyright (c) 2014, Patrik Jakobsson
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * Authors: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
15 */
16
17#include "psb_drv.h"
18
19#include "blitter.h"
20#include "psb_reg.h"
21
22/* Wait for the blitter to be completely idle */
23int gma_blt_wait_idle(struct drm_psb_private *dev_priv)
24{
25 unsigned long stop = jiffies + HZ;
26 int busy = 1;
27
28 /* NOP for Cedarview */
29 if (IS_CDV(dev_priv->dev))
30 return 0;
31
32 /* First do a quick check */
33 if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
34 ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
35 return 0;
36
37 do {
38 busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
39 } while (busy && !time_after_eq(jiffies, stop));
40
41 if (busy)
42 return -EBUSY;
43
44 do {
45 busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
46 _PSB_C2B_STATUS_BUSY) != 0);
47 } while (busy && !time_after_eq(jiffies, stop));
48
49 /* If still busy, we probably have a hang */
50 return (busy) ? -EBUSY : 0;
51}
diff --git a/drivers/gpu/drm/gma500/blitter.h b/drivers/gpu/drm/gma500/blitter.h
new file mode 100644
index 000000000000..b83648df590d
--- /dev/null
+++ b/drivers/gpu/drm/gma500/blitter.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (c) 2014, Patrik Jakobsson
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * Authors: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
15 */
16
17#ifndef __BLITTER_H
18#define __BLITTER_H
19
20extern int gma_blt_wait_idle(struct drm_psb_private *dev_priv);
21
22#endif
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
index 5a9a6a3063a8..3531f90e53d0 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -26,6 +26,7 @@
26#include "psb_intel_reg.h" 26#include "psb_intel_reg.h"
27#include "intel_bios.h" 27#include "intel_bios.h"
28#include "cdv_device.h" 28#include "cdv_device.h"
29#include "gma_device.h"
29 30
30#define VGA_SR_INDEX 0x3c4 31#define VGA_SR_INDEX 0x3c4
31#define VGA_SR_DATA 0x3c5 32#define VGA_SR_DATA 0x3c5
@@ -426,43 +427,6 @@ static int cdv_power_up(struct drm_device *dev)
426 return 0; 427 return 0;
427} 428}
428 429
429/* FIXME ? - shared with Poulsbo */
430static void cdv_get_core_freq(struct drm_device *dev)
431{
432 uint32_t clock;
433 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
434 struct drm_psb_private *dev_priv = dev->dev_private;
435
436 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
437 pci_read_config_dword(pci_root, 0xD4, &clock);
438 pci_dev_put(pci_root);
439
440 switch (clock & 0x07) {
441 case 0:
442 dev_priv->core_freq = 100;
443 break;
444 case 1:
445 dev_priv->core_freq = 133;
446 break;
447 case 2:
448 dev_priv->core_freq = 150;
449 break;
450 case 3:
451 dev_priv->core_freq = 178;
452 break;
453 case 4:
454 dev_priv->core_freq = 200;
455 break;
456 case 5:
457 case 6:
458 case 7:
459 dev_priv->core_freq = 266;
460 break;
461 default:
462 dev_priv->core_freq = 0;
463 }
464}
465
466static void cdv_hotplug_work_func(struct work_struct *work) 430static void cdv_hotplug_work_func(struct work_struct *work)
467{ 431{
468 struct drm_psb_private *dev_priv = container_of(work, struct drm_psb_private, 432 struct drm_psb_private *dev_priv = container_of(work, struct drm_psb_private,
@@ -618,7 +582,7 @@ static int cdv_chip_setup(struct drm_device *dev)
618 if (pci_enable_msi(dev->pdev)) 582 if (pci_enable_msi(dev->pdev))
619 dev_warn(dev->dev, "Enabling MSI failed!\n"); 583 dev_warn(dev->dev, "Enabling MSI failed!\n");
620 dev_priv->regmap = cdv_regmap; 584 dev_priv->regmap = cdv_regmap;
621 cdv_get_core_freq(dev); 585 gma_get_core_freq(dev);
622 psb_intel_opregion_init(dev); 586 psb_intel_opregion_init(dev);
623 psb_intel_init_bios(dev); 587 psb_intel_init_bios(dev);
624 cdv_hotplug_enable(dev, false); 588 cdv_hotplug_enable(dev, false);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 661af492173d..c18268cd516e 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -81,13 +81,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
81 return MODE_OK; 81 return MODE_OK;
82} 82}
83 83
84static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
85 const struct drm_display_mode *mode,
86 struct drm_display_mode *adjusted_mode)
87{
88 return true;
89}
90
91static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, 84static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
92 struct drm_display_mode *mode, 85 struct drm_display_mode *mode,
93 struct drm_display_mode *adjusted_mode) 86 struct drm_display_mode *adjusted_mode)
@@ -224,7 +217,7 @@ static int cdv_intel_crt_set_property(struct drm_connector *connector,
224 217
225static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { 218static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
226 .dpms = cdv_intel_crt_dpms, 219 .dpms = cdv_intel_crt_dpms,
227 .mode_fixup = cdv_intel_crt_mode_fixup, 220 .mode_fixup = gma_encoder_mode_fixup,
228 .prepare = gma_encoder_prepare, 221 .prepare = gma_encoder_prepare,
229 .commit = gma_encoder_commit, 222 .commit = gma_encoder_commit,
230 .mode_set = cdv_intel_crt_mode_set, 223 .mode_set = cdv_intel_crt_mode_set,
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
index 8fbfa06da62d..66727328832d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -412,8 +412,11 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
412 int refclk, 412 int refclk,
413 struct gma_clock_t *best_clock) 413 struct gma_clock_t *best_clock)
414{ 414{
415 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
415 struct gma_clock_t clock; 416 struct gma_clock_t clock;
416 if (refclk == 27000) { 417
418 switch (refclk) {
419 case 27000:
417 if (target < 200000) { 420 if (target < 200000) {
418 clock.p1 = 2; 421 clock.p1 = 2;
419 clock.p2 = 10; 422 clock.p2 = 10;
@@ -427,7 +430,9 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
427 clock.m1 = 0; 430 clock.m1 = 0;
428 clock.m2 = 98; 431 clock.m2 = 98;
429 } 432 }
430 } else if (refclk == 100000) { 433 break;
434
435 case 100000:
431 if (target < 200000) { 436 if (target < 200000) {
432 clock.p1 = 2; 437 clock.p1 = 2;
433 clock.p2 = 10; 438 clock.p2 = 10;
@@ -441,12 +446,13 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
441 clock.m1 = 0; 446 clock.m1 = 0;
442 clock.m2 = 133; 447 clock.m2 = 133;
443 } 448 }
444 } else 449 break;
450
451 default:
445 return false; 452 return false;
446 clock.m = clock.m2 + 2; 453 }
447 clock.p = clock.p1 * clock.p2; 454
448 clock.vco = (refclk * clock.m) / clock.n; 455 gma_crtc->clock_funcs->clock(refclk, &clock);
449 clock.dot = clock.vco / clock.p;
450 memcpy(best_clock, &clock, sizeof(struct gma_clock_t)); 456 memcpy(best_clock, &clock, sizeof(struct gma_clock_t));
451 return true; 457 return true;
452} 458}
@@ -463,54 +469,11 @@ static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
463 crtc = dev_priv->pipe_to_crtc_mapping[pipe]; 469 crtc = dev_priv->pipe_to_crtc_mapping[pipe];
464 gma_crtc = to_gma_crtc(crtc); 470 gma_crtc = to_gma_crtc(crtc);
465 471
466 if (crtc->fb == NULL || !gma_crtc->active) 472 if (crtc->primary->fb == NULL || !gma_crtc->active)
467 return false; 473 return false;
468 return true; 474 return true;
469} 475}
470 476
471static bool cdv_intel_single_pipe_active (struct drm_device *dev)
472{
473 uint32_t pipe_enabled = 0;
474
475 if (cdv_intel_pipe_enabled(dev, 0))
476 pipe_enabled |= FIFO_PIPEA;
477
478 if (cdv_intel_pipe_enabled(dev, 1))
479 pipe_enabled |= FIFO_PIPEB;
480
481
482 DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled);
483
484 if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB)
485 return true;
486 else
487 return false;
488}
489
490static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc)
491{
492 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
493 struct drm_mode_config *mode_config = &dev->mode_config;
494 struct drm_connector *connector;
495
496 if (gma_crtc->pipe != 1)
497 return false;
498
499 list_for_each_entry(connector, &mode_config->connector_list, head) {
500 struct gma_encoder *gma_encoder =
501 gma_attached_encoder(connector);
502
503 if (!connector->encoder
504 || connector->encoder->crtc != crtc)
505 continue;
506
507 if (gma_encoder->type == INTEL_OUTPUT_LVDS)
508 return true;
509 }
510
511 return false;
512}
513
514void cdv_disable_sr(struct drm_device *dev) 477void cdv_disable_sr(struct drm_device *dev)
515{ 478{
516 if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) { 479 if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
@@ -535,8 +498,10 @@ void cdv_disable_sr(struct drm_device *dev)
535void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc) 498void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
536{ 499{
537 struct drm_psb_private *dev_priv = dev->dev_private; 500 struct drm_psb_private *dev_priv = dev->dev_private;
501 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
538 502
539 if (cdv_intel_single_pipe_active(dev)) { 503 /* Is only one pipe enabled? */
504 if (cdv_intel_pipe_enabled(dev, 0) ^ cdv_intel_pipe_enabled(dev, 1)) {
540 u32 fw; 505 u32 fw;
541 506
542 fw = REG_READ(DSPFW1); 507 fw = REG_READ(DSPFW1);
@@ -557,7 +522,9 @@ void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
557 522
558 /* ignore FW4 */ 523 /* ignore FW4 */
559 524
560 if (is_pipeb_lvds(dev, crtc)) { 525 /* Is pipe b lvds ? */
526 if (gma_crtc->pipe == 1 &&
527 gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
561 REG_WRITE(DSPFW5, 0x00040330); 528 REG_WRITE(DSPFW5, 0x00040330);
562 } else { 529 } else {
563 fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) | 530 fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 0490ce36b53f..9ff30c2efadb 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1693,7 +1693,7 @@ done:
1693 struct drm_crtc *crtc = encoder->base.crtc; 1693 struct drm_crtc *crtc = encoder->base.crtc;
1694 drm_crtc_helper_set_mode(crtc, &crtc->mode, 1694 drm_crtc_helper_set_mode(crtc, &crtc->mode,
1695 crtc->x, crtc->y, 1695 crtc->x, crtc->y,
1696 crtc->fb); 1696 crtc->primary->fb);
1697 } 1697 }
1698 1698
1699 return 0; 1699 return 0;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 1c0d723b8d24..b99084b3f706 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -89,13 +89,6 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
89 REG_READ(hdmi_priv->hdmi_reg); 89 REG_READ(hdmi_priv->hdmi_reg);
90} 90}
91 91
92static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
93 const struct drm_display_mode *mode,
94 struct drm_display_mode *adjusted_mode)
95{
96 return true;
97}
98
99static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) 92static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
100{ 93{
101 struct drm_device *dev = encoder->dev; 94 struct drm_device *dev = encoder->dev;
@@ -199,7 +192,7 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
199 crtc->saved_mode.vdisplay != 0) { 192 crtc->saved_mode.vdisplay != 0) {
200 if (centre) { 193 if (centre) {
201 if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, 194 if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
202 encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) 195 encoder->crtc->x, encoder->crtc->y, encoder->crtc->primary->fb))
203 return -1; 196 return -1;
204 } else { 197 } else {
205 struct drm_encoder_helper_funcs *helpers 198 struct drm_encoder_helper_funcs *helpers
@@ -262,7 +255,7 @@ static void cdv_hdmi_destroy(struct drm_connector *connector)
262 255
263static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { 256static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
264 .dpms = cdv_hdmi_dpms, 257 .dpms = cdv_hdmi_dpms,
265 .mode_fixup = cdv_hdmi_mode_fixup, 258 .mode_fixup = gma_encoder_mode_fixup,
266 .prepare = gma_encoder_prepare, 259 .prepare = gma_encoder_prepare,
267 .mode_set = cdv_hdmi_mode_set, 260 .mode_set = cdv_hdmi_mode_set,
268 .commit = gma_encoder_commit, 261 .commit = gma_encoder_commit,
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 20e08e65d46c..8ecc920fc26d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -494,7 +494,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
494 &crtc->saved_mode, 494 &crtc->saved_mode,
495 encoder->crtc->x, 495 encoder->crtc->x,
496 encoder->crtc->y, 496 encoder->crtc->y,
497 encoder->crtc->fb)) 497 encoder->crtc->primary->fb))
498 return -1; 498 return -1;
499 } 499 }
500 } else if (!strcmp(property->name, "backlight") && encoder) { 500 } else if (!strcmp(property->name, "backlight") && encoder) {
@@ -712,6 +712,7 @@ void cdv_intel_lvds_init(struct drm_device *dev,
712 * Attempt to get the fixed panel mode from DDC. Assume that the 712 * Attempt to get the fixed panel mode from DDC. Assume that the
713 * preferred mode is the right one. 713 * preferred mode is the right one.
714 */ 714 */
715 mutex_lock(&dev->mode_config.mutex);
715 psb_intel_ddc_get_modes(connector, 716 psb_intel_ddc_get_modes(connector,
716 &gma_encoder->ddc_bus->adapter); 717 &gma_encoder->ddc_bus->adapter);
717 list_for_each_entry(scan, &connector->probed_modes, head) { 718 list_for_each_entry(scan, &connector->probed_modes, head) {
@@ -772,10 +773,12 @@ void cdv_intel_lvds_init(struct drm_device *dev,
772 } 773 }
773 774
774out: 775out:
776 mutex_unlock(&dev->mode_config.mutex);
775 drm_sysfs_connector_add(connector); 777 drm_sysfs_connector_add(connector);
776 return; 778 return;
777 779
778failed_find: 780failed_find:
781 mutex_unlock(&dev->mode_config.mutex);
779 printk(KERN_ERR "Failed find\n"); 782 printk(KERN_ERR "Failed find\n");
780 if (gma_encoder->ddc_bus) 783 if (gma_encoder->ddc_bus)
781 psb_intel_i2c_destroy(gma_encoder->ddc_bus); 784 psb_intel_i2c_destroy(gma_encoder->ddc_bus);
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 94b3fec22c28..e7fcc148f333 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -319,7 +319,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
319{ 319{
320 struct gtt_range *backing; 320 struct gtt_range *backing;
321 /* Begin by trying to use stolen memory backing */ 321 /* Begin by trying to use stolen memory backing */
322 backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); 322 backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1, PAGE_SIZE);
323 if (backing) { 323 if (backing) {
324 drm_gem_private_object_init(dev, &backing->gem, aligned_size); 324 drm_gem_private_object_init(dev, &backing->gem, aligned_size);
325 return backing; 325 return backing;
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index e2db48a81ed0..c707fa6fca85 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -62,9 +62,6 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
62 int ret = 0; 62 int ret = 0;
63 struct drm_gem_object *obj; 63 struct drm_gem_object *obj;
64 64
65 if (!(dev->driver->driver_features & DRIVER_GEM))
66 return -ENODEV;
67
68 mutex_lock(&dev->struct_mutex); 65 mutex_lock(&dev->struct_mutex);
69 66
70 /* GEM does all our handle to object mapping */ 67 /* GEM does all our handle to object mapping */
@@ -98,8 +95,8 @@ unlock:
98 * it so that userspace can speak about it. This does the core work 95 * it so that userspace can speak about it. This does the core work
99 * for the various methods that do/will create GEM objects for things 96 * for the various methods that do/will create GEM objects for things
100 */ 97 */
101static int psb_gem_create(struct drm_file *file, 98int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size,
102 struct drm_device *dev, uint64_t size, uint32_t *handlep) 99 u32 *handlep, int stolen, u32 align)
103{ 100{
104 struct gtt_range *r; 101 struct gtt_range *r;
105 int ret; 102 int ret;
@@ -109,7 +106,7 @@ static int psb_gem_create(struct drm_file *file,
109 106
110 /* Allocate our object - for now a direct gtt range which is not 107 /* Allocate our object - for now a direct gtt range which is not
111 stolen memory backed */ 108 stolen memory backed */
112 r = psb_gtt_alloc_range(dev, size, "gem", 0); 109 r = psb_gtt_alloc_range(dev, size, "gem", 0, PAGE_SIZE);
113 if (r == NULL) { 110 if (r == NULL) {
114 dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); 111 dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
115 return -ENOSPC; 112 return -ENOSPC;
@@ -153,7 +150,8 @@ int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
153{ 150{
154 args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); 151 args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
155 args->size = args->pitch * args->height; 152 args->size = args->pitch * args->height;
156 return psb_gem_create(file, dev, args->size, &args->handle); 153 return psb_gem_create(file, dev, args->size, &args->handle, 0,
154 PAGE_SIZE);
157} 155}
158 156
159/** 157/**
@@ -229,47 +227,3 @@ fail:
229 return VM_FAULT_SIGBUS; 227 return VM_FAULT_SIGBUS;
230 } 228 }
231} 229}
232
233static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
234 int size, u32 *handle)
235{
236 struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
237 if (gtt == NULL)
238 return -ENOMEM;
239
240 drm_gem_private_object_init(dev, &gtt->gem, size);
241 if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
242 return 0;
243
244 drm_gem_object_release(&gtt->gem);
245 psb_gtt_free_range(dev, gtt);
246 return -ENOMEM;
247}
248
249/*
250 * GEM interfaces for our specific client
251 */
252int psb_gem_create_ioctl(struct drm_device *dev, void *data,
253 struct drm_file *file)
254{
255 struct drm_psb_gem_create *args = data;
256 int ret;
257 if (args->flags & GMA_GEM_CREATE_STOLEN) {
258 ret = psb_gem_create_stolen(file, dev, args->size,
259 &args->handle);
260 if (ret == 0)
261 return 0;
262 /* Fall throguh */
263 args->flags &= ~GMA_GEM_CREATE_STOLEN;
264 }
265 return psb_gem_create(file, dev, args->size, &args->handle);
266}
267
268int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
269 struct drm_file *file)
270{
271 struct drm_psb_gem_mmap *args = data;
272 return dev->driver->dumb_map_offset(file, dev,
273 args->handle, &args->offset);
274}
275
diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h
new file mode 100644
index 000000000000..1381c5190f46
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gem.h
@@ -0,0 +1,21 @@
1/**************************************************************************
2 * Copyright (c) 2014 Patrik Jakobsson
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 **************************************************************************/
15
16#ifndef _GEM_H
17#define _GEM_H
18
19extern int psb_gem_create(struct drm_file *file, struct drm_device *dev,
20 u64 size, u32 *handlep, int stolen, u32 align);
21#endif
diff --git a/drivers/gpu/drm/gma500/gma_device.c b/drivers/gpu/drm/gma500/gma_device.c
new file mode 100644
index 000000000000..4a295f9ba067
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_device.c
@@ -0,0 +1,56 @@
1/**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 **************************************************************************/
15
16#include <drm/drmP.h>
17#include "psb_drv.h"
18
19void gma_get_core_freq(struct drm_device *dev)
20{
21 uint32_t clock;
22 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
23 struct drm_psb_private *dev_priv = dev->dev_private;
24
25 /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
26 /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
27
28 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
29 pci_read_config_dword(pci_root, 0xD4, &clock);
30 pci_dev_put(pci_root);
31
32 switch (clock & 0x07) {
33 case 0:
34 dev_priv->core_freq = 100;
35 break;
36 case 1:
37 dev_priv->core_freq = 133;
38 break;
39 case 2:
40 dev_priv->core_freq = 150;
41 break;
42 case 3:
43 dev_priv->core_freq = 178;
44 break;
45 case 4:
46 dev_priv->core_freq = 200;
47 break;
48 case 5:
49 case 6:
50 case 7:
51 dev_priv->core_freq = 266;
52 break;
53 default:
54 dev_priv->core_freq = 0;
55 }
56}
diff --git a/drivers/gpu/drm/gma500/gma_device.h b/drivers/gpu/drm/gma500/gma_device.h
new file mode 100644
index 000000000000..e1dbb007b820
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_device.h
@@ -0,0 +1,21 @@
1/**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 **************************************************************************/
15
16#ifndef _GMA_DEVICE_H
17#define _GMA_DEVICE_H
18
19extern void gma_get_core_freq(struct drm_device *dev);
20
21#endif
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index 386de2c9dc86..9bb9bddd881a 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -59,7 +59,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
59 struct drm_device *dev = crtc->dev; 59 struct drm_device *dev = crtc->dev;
60 struct drm_psb_private *dev_priv = dev->dev_private; 60 struct drm_psb_private *dev_priv = dev->dev_private;
61 struct gma_crtc *gma_crtc = to_gma_crtc(crtc); 61 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
62 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 62 struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
63 int pipe = gma_crtc->pipe; 63 int pipe = gma_crtc->pipe;
64 const struct psb_offset *map = &dev_priv->regmap[pipe]; 64 const struct psb_offset *map = &dev_priv->regmap[pipe];
65 unsigned long start, offset; 65 unsigned long start, offset;
@@ -70,7 +70,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
70 return 0; 70 return 0;
71 71
72 /* no fb bound */ 72 /* no fb bound */
73 if (!crtc->fb) { 73 if (!crtc->primary->fb) {
74 dev_err(dev->dev, "No FB bound\n"); 74 dev_err(dev->dev, "No FB bound\n");
75 goto gma_pipe_cleaner; 75 goto gma_pipe_cleaner;
76 } 76 }
@@ -81,19 +81,19 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
81 if (ret < 0) 81 if (ret < 0)
82 goto gma_pipe_set_base_exit; 82 goto gma_pipe_set_base_exit;
83 start = psbfb->gtt->offset; 83 start = psbfb->gtt->offset;
84 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); 84 offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
85 85
86 REG_WRITE(map->stride, crtc->fb->pitches[0]); 86 REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
87 87
88 dspcntr = REG_READ(map->cntr); 88 dspcntr = REG_READ(map->cntr);
89 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 89 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
90 90
91 switch (crtc->fb->bits_per_pixel) { 91 switch (crtc->primary->fb->bits_per_pixel) {
92 case 8: 92 case 8:
93 dspcntr |= DISPPLANE_8BPP; 93 dspcntr |= DISPPLANE_8BPP;
94 break; 94 break;
95 case 16: 95 case 16:
96 if (crtc->fb->depth == 15) 96 if (crtc->primary->fb->depth == 15)
97 dspcntr |= DISPPLANE_15_16BPP; 97 dspcntr |= DISPPLANE_15_16BPP;
98 else 98 else
99 dspcntr |= DISPPLANE_16BPP; 99 dspcntr |= DISPPLANE_16BPP;
@@ -485,6 +485,13 @@ int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
485 return 0; 485 return 0;
486} 486}
487 487
488bool gma_encoder_mode_fixup(struct drm_encoder *encoder,
489 const struct drm_display_mode *mode,
490 struct drm_display_mode *adjusted_mode)
491{
492 return true;
493}
494
488bool gma_crtc_mode_fixup(struct drm_crtc *crtc, 495bool gma_crtc_mode_fixup(struct drm_crtc *crtc,
489 const struct drm_display_mode *mode, 496 const struct drm_display_mode *mode,
490 struct drm_display_mode *adjusted_mode) 497 struct drm_display_mode *adjusted_mode)
@@ -511,8 +518,8 @@ void gma_crtc_disable(struct drm_crtc *crtc)
511 518
512 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 519 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
513 520
514 if (crtc->fb) { 521 if (crtc->primary->fb) {
515 gt = to_psb_fb(crtc->fb)->gtt; 522 gt = to_psb_fb(crtc->primary->fb)->gtt;
516 psb_gtt_unpin(gt); 523 psb_gtt_unpin(gt);
517 } 524 }
518} 525}
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h
index 78b9f986a6e5..ed569d8a6af3 100644
--- a/drivers/gpu/drm/gma500/gma_display.h
+++ b/drivers/gpu/drm/gma500/gma_display.h
@@ -90,6 +90,9 @@ extern void gma_crtc_restore(struct drm_crtc *crtc);
90extern void gma_encoder_prepare(struct drm_encoder *encoder); 90extern void gma_encoder_prepare(struct drm_encoder *encoder);
91extern void gma_encoder_commit(struct drm_encoder *encoder); 91extern void gma_encoder_commit(struct drm_encoder *encoder);
92extern void gma_encoder_destroy(struct drm_encoder *encoder); 92extern void gma_encoder_destroy(struct drm_encoder *encoder);
93extern bool gma_encoder_mode_fixup(struct drm_encoder *encoder,
94 const struct drm_display_mode *mode,
95 struct drm_display_mode *adjusted_mode);
93 96
94/* Common clock related functions */ 97/* Common clock related functions */
95extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk); 98extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk);
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 2db731f00930..592d205a0089 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -22,6 +22,7 @@
22#include <drm/drmP.h> 22#include <drm/drmP.h>
23#include <linux/shmem_fs.h> 23#include <linux/shmem_fs.h>
24#include "psb_drv.h" 24#include "psb_drv.h"
25#include "blitter.h"
25 26
26 27
27/* 28/*
@@ -105,11 +106,13 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
105 106
106 /* Write our page entries into the GTT itself */ 107 /* Write our page entries into the GTT itself */
107 for (i = r->roll; i < r->npage; i++) { 108 for (i = r->roll; i < r->npage; i++) {
108 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); 109 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
110 PSB_MMU_CACHED_MEMORY);
109 iowrite32(pte, gtt_slot++); 111 iowrite32(pte, gtt_slot++);
110 } 112 }
111 for (i = 0; i < r->roll; i++) { 113 for (i = 0; i < r->roll; i++) {
112 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); 114 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
115 PSB_MMU_CACHED_MEMORY);
113 iowrite32(pte, gtt_slot++); 116 iowrite32(pte, gtt_slot++);
114 } 117 }
115 /* Make sure all the entries are set before we return */ 118 /* Make sure all the entries are set before we return */
@@ -127,7 +130,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
127 * page table entries with the dummy page. This is protected via the gtt 130 * page table entries with the dummy page. This is protected via the gtt
128 * mutex which the caller must hold. 131 * mutex which the caller must hold.
129 */ 132 */
130static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) 133void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
131{ 134{
132 struct drm_psb_private *dev_priv = dev->dev_private; 135 struct drm_psb_private *dev_priv = dev->dev_private;
133 u32 __iomem *gtt_slot; 136 u32 __iomem *gtt_slot;
@@ -137,7 +140,8 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
137 WARN_ON(r->stolen); 140 WARN_ON(r->stolen);
138 141
139 gtt_slot = psb_gtt_entry(dev, r); 142 gtt_slot = psb_gtt_entry(dev, r);
140 pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); 143 pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page),
144 PSB_MMU_CACHED_MEMORY);
141 145
142 for (i = 0; i < r->npage; i++) 146 for (i = 0; i < r->npage; i++)
143 iowrite32(pte, gtt_slot++); 147 iowrite32(pte, gtt_slot++);
@@ -176,11 +180,13 @@ void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
176 gtt_slot = psb_gtt_entry(dev, r); 180 gtt_slot = psb_gtt_entry(dev, r);
177 181
178 for (i = r->roll; i < r->npage; i++) { 182 for (i = r->roll; i < r->npage; i++) {
179 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); 183 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
184 PSB_MMU_CACHED_MEMORY);
180 iowrite32(pte, gtt_slot++); 185 iowrite32(pte, gtt_slot++);
181 } 186 }
182 for (i = 0; i < r->roll; i++) { 187 for (i = 0; i < r->roll; i++) {
183 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); 188 pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
189 PSB_MMU_CACHED_MEMORY);
184 iowrite32(pte, gtt_slot++); 190 iowrite32(pte, gtt_slot++);
185 } 191 }
186 ioread32(gtt_slot - 1); 192 ioread32(gtt_slot - 1);
@@ -240,6 +246,7 @@ int psb_gtt_pin(struct gtt_range *gt)
240 int ret = 0; 246 int ret = 0;
241 struct drm_device *dev = gt->gem.dev; 247 struct drm_device *dev = gt->gem.dev;
242 struct drm_psb_private *dev_priv = dev->dev_private; 248 struct drm_psb_private *dev_priv = dev->dev_private;
249 u32 gpu_base = dev_priv->gtt.gatt_start;
243 250
244 mutex_lock(&dev_priv->gtt_mutex); 251 mutex_lock(&dev_priv->gtt_mutex);
245 252
@@ -252,6 +259,9 @@ int psb_gtt_pin(struct gtt_range *gt)
252 psb_gtt_detach_pages(gt); 259 psb_gtt_detach_pages(gt);
253 goto out; 260 goto out;
254 } 261 }
262 psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu),
263 gt->pages, (gpu_base + gt->offset),
264 gt->npage, 0, 0, PSB_MMU_CACHED_MEMORY);
255 } 265 }
256 gt->in_gart++; 266 gt->in_gart++;
257out: 267out:
@@ -274,16 +284,30 @@ void psb_gtt_unpin(struct gtt_range *gt)
274{ 284{
275 struct drm_device *dev = gt->gem.dev; 285 struct drm_device *dev = gt->gem.dev;
276 struct drm_psb_private *dev_priv = dev->dev_private; 286 struct drm_psb_private *dev_priv = dev->dev_private;
287 u32 gpu_base = dev_priv->gtt.gatt_start;
288 int ret;
277 289
290 /* While holding the gtt_mutex no new blits can be initiated */
278 mutex_lock(&dev_priv->gtt_mutex); 291 mutex_lock(&dev_priv->gtt_mutex);
279 292
293 /* Wait for any possible usage of the memory to be finished */
294 ret = gma_blt_wait_idle(dev_priv);
295 if (ret) {
296 DRM_ERROR("Failed to idle the blitter, unpin failed!");
297 goto out;
298 }
299
280 WARN_ON(!gt->in_gart); 300 WARN_ON(!gt->in_gart);
281 301
282 gt->in_gart--; 302 gt->in_gart--;
283 if (gt->in_gart == 0 && gt->stolen == 0) { 303 if (gt->in_gart == 0 && gt->stolen == 0) {
304 psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu),
305 (gpu_base + gt->offset), gt->npage, 0, 0);
284 psb_gtt_remove(dev, gt); 306 psb_gtt_remove(dev, gt);
285 psb_gtt_detach_pages(gt); 307 psb_gtt_detach_pages(gt);
286 } 308 }
309
310out:
287 mutex_unlock(&dev_priv->gtt_mutex); 311 mutex_unlock(&dev_priv->gtt_mutex);
288} 312}
289 313
@@ -306,7 +330,7 @@ void psb_gtt_unpin(struct gtt_range *gt)
306 * as in use. 330 * as in use.
307 */ 331 */
308struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, 332struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
309 const char *name, int backed) 333 const char *name, int backed, u32 align)
310{ 334{
311 struct drm_psb_private *dev_priv = dev->dev_private; 335 struct drm_psb_private *dev_priv = dev->dev_private;
312 struct gtt_range *gt; 336 struct gtt_range *gt;
@@ -334,7 +358,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
334 /* Ensure this is set for non GEM objects */ 358 /* Ensure this is set for non GEM objects */
335 gt->gem.dev = dev; 359 gt->gem.dev = dev;
336 ret = allocate_resource(dev_priv->gtt_mem, &gt->resource, 360 ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
337 len, start, end, PAGE_SIZE, NULL, NULL); 361 len, start, end, align, NULL, NULL);
338 if (ret == 0) { 362 if (ret == 0) {
339 gt->offset = gt->resource.start - r->start; 363 gt->offset = gt->resource.start - r->start;
340 return gt; 364 return gt;
@@ -497,6 +521,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
497 if (!resume) 521 if (!resume)
498 dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, 522 dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
499 stolen_size); 523 stolen_size);
524
500 if (!dev_priv->vram_addr) { 525 if (!dev_priv->vram_addr) {
501 dev_err(dev->dev, "Failure to map stolen base.\n"); 526 dev_err(dev->dev, "Failure to map stolen base.\n");
502 ret = -ENOMEM; 527 ret = -ENOMEM;
@@ -512,7 +537,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
512 dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", 537 dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
513 num_pages, pfn_base << PAGE_SHIFT, 0); 538 num_pages, pfn_base << PAGE_SHIFT, 0);
514 for (i = 0; i < num_pages; ++i) { 539 for (i = 0; i < num_pages; ++i) {
515 pte = psb_gtt_mask_pte(pfn_base + i, 0); 540 pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY);
516 iowrite32(pte, dev_priv->gtt_map + i); 541 iowrite32(pte, dev_priv->gtt_map + i);
517 } 542 }
518 543
@@ -521,7 +546,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
521 */ 546 */
522 547
523 pfn_base = page_to_pfn(dev_priv->scratch_page); 548 pfn_base = page_to_pfn(dev_priv->scratch_page);
524 pte = psb_gtt_mask_pte(pfn_base, 0); 549 pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY);
525 for (; i < gtt_pages; ++i) 550 for (; i < gtt_pages; ++i)
526 iowrite32(pte, dev_priv->gtt_map + i); 551 iowrite32(pte, dev_priv->gtt_map + i);
527 552
diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h
index 6191d10acf33..f5860a739bd8 100644
--- a/drivers/gpu/drm/gma500/gtt.h
+++ b/drivers/gpu/drm/gma500/gtt.h
@@ -53,7 +53,8 @@ struct gtt_range {
53}; 53};
54 54
55extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, 55extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
56 const char *name, int backed); 56 const char *name, int backed,
57 u32 align);
57extern void psb_gtt_kref_put(struct gtt_range *gt); 58extern void psb_gtt_kref_put(struct gtt_range *gt);
58extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); 59extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
59extern int psb_gtt_pin(struct gtt_range *gt); 60extern int psb_gtt_pin(struct gtt_range *gt);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 860a4ee9baaf..6e91b20ce2e5 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -287,7 +287,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
287 &gma_crtc->saved_mode, 287 &gma_crtc->saved_mode,
288 encoder->crtc->x, 288 encoder->crtc->x,
289 encoder->crtc->y, 289 encoder->crtc->y,
290 encoder->crtc->fb)) 290 encoder->crtc->primary->fb))
291 goto set_prop_error; 291 goto set_prop_error;
292 } else { 292 } else {
293 struct drm_encoder_helper_funcs *funcs = 293 struct drm_encoder_helper_funcs *funcs =
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
index 321c00a944e9..8cc8a5abbc7b 100644
--- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
+++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
@@ -166,7 +166,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
166 struct drm_device *dev = crtc->dev; 166 struct drm_device *dev = crtc->dev;
167 struct drm_psb_private *dev_priv = dev->dev_private; 167 struct drm_psb_private *dev_priv = dev->dev_private;
168 struct gma_crtc *gma_crtc = to_gma_crtc(crtc); 168 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
169 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 169 struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
170 int pipe = gma_crtc->pipe; 170 int pipe = gma_crtc->pipe;
171 const struct psb_offset *map = &dev_priv->regmap[pipe]; 171 const struct psb_offset *map = &dev_priv->regmap[pipe];
172 unsigned long start, offset; 172 unsigned long start, offset;
@@ -178,12 +178,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
178 dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe); 178 dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
179 179
180 /* no fb bound */ 180 /* no fb bound */
181 if (!crtc->fb) { 181 if (!crtc->primary->fb) {
182 dev_dbg(dev->dev, "No FB bound\n"); 182 dev_dbg(dev->dev, "No FB bound\n");
183 return 0; 183 return 0;
184 } 184 }
185 185
186 ret = check_fb(crtc->fb); 186 ret = check_fb(crtc->primary->fb);
187 if (ret) 187 if (ret)
188 return ret; 188 return ret;
189 189
@@ -196,18 +196,18 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
196 return 0; 196 return 0;
197 197
198 start = psbfb->gtt->offset; 198 start = psbfb->gtt->offset;
199 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); 199 offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
200 200
201 REG_WRITE(map->stride, crtc->fb->pitches[0]); 201 REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
202 dspcntr = REG_READ(map->cntr); 202 dspcntr = REG_READ(map->cntr);
203 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 203 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
204 204
205 switch (crtc->fb->bits_per_pixel) { 205 switch (crtc->primary->fb->bits_per_pixel) {
206 case 8: 206 case 8:
207 dspcntr |= DISPPLANE_8BPP; 207 dspcntr |= DISPPLANE_8BPP;
208 break; 208 break;
209 case 16: 209 case 16:
210 if (crtc->fb->depth == 15) 210 if (crtc->primary->fb->depth == 15)
211 dspcntr |= DISPPLANE_15_16BPP; 211 dspcntr |= DISPPLANE_15_16BPP;
212 else 212 else
213 dspcntr |= DISPPLANE_16BPP; 213 dspcntr |= DISPPLANE_16BPP;
@@ -700,7 +700,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
700 } 700 }
701#endif 701#endif
702 702
703 ret = check_fb(crtc->fb); 703 ret = check_fb(crtc->primary->fb);
704 if (ret) 704 if (ret)
705 return ret; 705 return ret;
706 706
diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c
index 49bac41beefb..3e14a9b35252 100644
--- a/drivers/gpu/drm/gma500/mmu.c
+++ b/drivers/gpu/drm/gma500/mmu.c
@@ -18,6 +18,7 @@
18#include <drm/drmP.h> 18#include <drm/drmP.h>
19#include "psb_drv.h" 19#include "psb_drv.h"
20#include "psb_reg.h" 20#include "psb_reg.h"
21#include "mmu.h"
21 22
22/* 23/*
23 * Code for the SGX MMU: 24 * Code for the SGX MMU:
@@ -47,51 +48,6 @@
47 * but on average it should be fast. 48 * but on average it should be fast.
48 */ 49 */
49 50
50struct psb_mmu_driver {
51 /* protects driver- and pd structures. Always take in read mode
52 * before taking the page table spinlock.
53 */
54 struct rw_semaphore sem;
55
56 /* protects page tables, directory tables and pt tables.
57 * and pt structures.
58 */
59 spinlock_t lock;
60
61 atomic_t needs_tlbflush;
62
63 uint8_t __iomem *register_map;
64 struct psb_mmu_pd *default_pd;
65 /*uint32_t bif_ctrl;*/
66 int has_clflush;
67 int clflush_add;
68 unsigned long clflush_mask;
69
70 struct drm_psb_private *dev_priv;
71};
72
73struct psb_mmu_pd;
74
75struct psb_mmu_pt {
76 struct psb_mmu_pd *pd;
77 uint32_t index;
78 uint32_t count;
79 struct page *p;
80 uint32_t *v;
81};
82
83struct psb_mmu_pd {
84 struct psb_mmu_driver *driver;
85 int hw_context;
86 struct psb_mmu_pt **tables;
87 struct page *p;
88 struct page *dummy_pt;
89 struct page *dummy_page;
90 uint32_t pd_mask;
91 uint32_t invalid_pde;
92 uint32_t invalid_pte;
93};
94
95static inline uint32_t psb_mmu_pt_index(uint32_t offset) 51static inline uint32_t psb_mmu_pt_index(uint32_t offset)
96{ 52{
97 return (offset >> PSB_PTE_SHIFT) & 0x3FF; 53 return (offset >> PSB_PTE_SHIFT) & 0x3FF;
@@ -102,13 +58,13 @@ static inline uint32_t psb_mmu_pd_index(uint32_t offset)
102 return offset >> PSB_PDE_SHIFT; 58 return offset >> PSB_PDE_SHIFT;
103} 59}
104 60
61#if defined(CONFIG_X86)
105static inline void psb_clflush(void *addr) 62static inline void psb_clflush(void *addr)
106{ 63{
107 __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); 64 __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
108} 65}
109 66
110static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, 67static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr)
111 void *addr)
112{ 68{
113 if (!driver->has_clflush) 69 if (!driver->has_clflush)
114 return; 70 return;
@@ -117,62 +73,77 @@ static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
117 psb_clflush(addr); 73 psb_clflush(addr);
118 mb(); 74 mb();
119} 75}
76#else
120 77
121static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) 78static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr)
122{ 79{;
123 uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
124 uint32_t clflush_count = PAGE_SIZE / clflush_add;
125 int i;
126 uint8_t *clf;
127
128 clf = kmap_atomic(page);
129 mb();
130 for (i = 0; i < clflush_count; ++i) {
131 psb_clflush(clf);
132 clf += clflush_add;
133 }
134 mb();
135 kunmap_atomic(clf);
136} 80}
137 81
138static void psb_pages_clflush(struct psb_mmu_driver *driver, 82#endif
139 struct page *page[], unsigned long num_pages)
140{
141 int i;
142
143 if (!driver->has_clflush)
144 return ;
145 83
146 for (i = 0; i < num_pages; i++) 84static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, int force)
147 psb_page_clflush(driver, *page++);
148}
149
150static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
151 int force)
152{ 85{
86 struct drm_device *dev = driver->dev;
87 struct drm_psb_private *dev_priv = dev->dev_private;
88
89 if (atomic_read(&driver->needs_tlbflush) || force) {
90 uint32_t val = PSB_RSGX32(PSB_CR_BIF_CTRL);
91 PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
92
93 /* Make sure data cache is turned off before enabling it */
94 wmb();
95 PSB_WSGX32(val & ~_PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
96 (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
97 if (driver->msvdx_mmu_invaldc)
98 atomic_set(driver->msvdx_mmu_invaldc, 1);
99 }
153 atomic_set(&driver->needs_tlbflush, 0); 100 atomic_set(&driver->needs_tlbflush, 0);
154} 101}
155 102
103#if 0
156static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) 104static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
157{ 105{
158 down_write(&driver->sem); 106 down_write(&driver->sem);
159 psb_mmu_flush_pd_locked(driver, force); 107 psb_mmu_flush_pd_locked(driver, force);
160 up_write(&driver->sem); 108 up_write(&driver->sem);
161} 109}
110#endif
162 111
163void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) 112void psb_mmu_flush(struct psb_mmu_driver *driver)
164{ 113{
165 if (rc_prot) 114 struct drm_device *dev = driver->dev;
166 down_write(&driver->sem); 115 struct drm_psb_private *dev_priv = dev->dev_private;
167 if (rc_prot) 116 uint32_t val;
168 up_write(&driver->sem); 117
118 down_write(&driver->sem);
119 val = PSB_RSGX32(PSB_CR_BIF_CTRL);
120 if (atomic_read(&driver->needs_tlbflush))
121 PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
122 else
123 PSB_WSGX32(val | _PSB_CB_CTRL_FLUSH, PSB_CR_BIF_CTRL);
124
125 /* Make sure data cache is turned off and MMU is flushed before
126 restoring bank interface control register */
127 wmb();
128 PSB_WSGX32(val & ~(_PSB_CB_CTRL_FLUSH | _PSB_CB_CTRL_INVALDC),
129 PSB_CR_BIF_CTRL);
130 (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
131
132 atomic_set(&driver->needs_tlbflush, 0);
133 if (driver->msvdx_mmu_invaldc)
134 atomic_set(driver->msvdx_mmu_invaldc, 1);
135 up_write(&driver->sem);
169} 136}
170 137
171void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) 138void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
172{ 139{
173 /*ttm_tt_cache_flush(&pd->p, 1);*/ 140 struct drm_device *dev = pd->driver->dev;
174 psb_pages_clflush(pd->driver, &pd->p, 1); 141 struct drm_psb_private *dev_priv = dev->dev_private;
142 uint32_t offset = (hw_context == 0) ? PSB_CR_BIF_DIR_LIST_BASE0 :
143 PSB_CR_BIF_DIR_LIST_BASE1 + hw_context * 4;
144
175 down_write(&pd->driver->sem); 145 down_write(&pd->driver->sem);
146 PSB_WSGX32(page_to_pfn(pd->p) << PAGE_SHIFT, offset);
176 wmb(); 147 wmb();
177 psb_mmu_flush_pd_locked(pd->driver, 1); 148 psb_mmu_flush_pd_locked(pd->driver, 1);
178 pd->hw_context = hw_context; 149 pd->hw_context = hw_context;
@@ -183,7 +154,6 @@ void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
183static inline unsigned long psb_pd_addr_end(unsigned long addr, 154static inline unsigned long psb_pd_addr_end(unsigned long addr,
184 unsigned long end) 155 unsigned long end)
185{ 156{
186
187 addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; 157 addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
188 return (addr < end) ? addr : end; 158 return (addr < end) ? addr : end;
189} 159}
@@ -223,12 +193,10 @@ struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
223 goto out_err3; 193 goto out_err3;
224 194
225 if (!trap_pagefaults) { 195 if (!trap_pagefaults) {
226 pd->invalid_pde = 196 pd->invalid_pde = psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
227 psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), 197 invalid_type);
228 invalid_type); 198 pd->invalid_pte = psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
229 pd->invalid_pte = 199 invalid_type);
230 psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
231 invalid_type);
232 } else { 200 } else {
233 pd->invalid_pde = 0; 201 pd->invalid_pde = 0;
234 pd->invalid_pte = 0; 202 pd->invalid_pte = 0;
@@ -279,12 +247,16 @@ static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
279void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) 247void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
280{ 248{
281 struct psb_mmu_driver *driver = pd->driver; 249 struct psb_mmu_driver *driver = pd->driver;
250 struct drm_device *dev = driver->dev;
251 struct drm_psb_private *dev_priv = dev->dev_private;
282 struct psb_mmu_pt *pt; 252 struct psb_mmu_pt *pt;
283 int i; 253 int i;
284 254
285 down_write(&driver->sem); 255 down_write(&driver->sem);
286 if (pd->hw_context != -1) 256 if (pd->hw_context != -1) {
257 PSB_WSGX32(0, PSB_CR_BIF_DIR_LIST_BASE0 + pd->hw_context * 4);
287 psb_mmu_flush_pd_locked(driver, 1); 258 psb_mmu_flush_pd_locked(driver, 1);
259 }
288 260
289 /* Should take the spinlock here, but we don't need to do that 261 /* Should take the spinlock here, but we don't need to do that
290 since we have the semaphore in write mode. */ 262 since we have the semaphore in write mode. */
@@ -331,7 +303,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
331 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) 303 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
332 *ptes++ = pd->invalid_pte; 304 *ptes++ = pd->invalid_pte;
333 305
334 306#if defined(CONFIG_X86)
335 if (pd->driver->has_clflush && pd->hw_context != -1) { 307 if (pd->driver->has_clflush && pd->hw_context != -1) {
336 mb(); 308 mb();
337 for (i = 0; i < clflush_count; ++i) { 309 for (i = 0; i < clflush_count; ++i) {
@@ -340,7 +312,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
340 } 312 }
341 mb(); 313 mb();
342 } 314 }
343 315#endif
344 kunmap_atomic(v); 316 kunmap_atomic(v);
345 spin_unlock(lock); 317 spin_unlock(lock);
346 318
@@ -351,7 +323,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
351 return pt; 323 return pt;
352} 324}
353 325
354static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, 326struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
355 unsigned long addr) 327 unsigned long addr)
356{ 328{
357 uint32_t index = psb_mmu_pd_index(addr); 329 uint32_t index = psb_mmu_pd_index(addr);
@@ -383,7 +355,7 @@ static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
383 kunmap_atomic((void *) v); 355 kunmap_atomic((void *) v);
384 356
385 if (pd->hw_context != -1) { 357 if (pd->hw_context != -1) {
386 psb_mmu_clflush(pd->driver, (void *) &v[index]); 358 psb_mmu_clflush(pd->driver, (void *)&v[index]);
387 atomic_set(&pd->driver->needs_tlbflush, 1); 359 atomic_set(&pd->driver->needs_tlbflush, 1);
388 } 360 }
389 } 361 }
@@ -420,8 +392,7 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
420 pd->tables[pt->index] = NULL; 392 pd->tables[pt->index] = NULL;
421 393
422 if (pd->hw_context != -1) { 394 if (pd->hw_context != -1) {
423 psb_mmu_clflush(pd->driver, 395 psb_mmu_clflush(pd->driver, (void *)&v[pt->index]);
424 (void *) &v[pt->index]);
425 atomic_set(&pd->driver->needs_tlbflush, 1); 396 atomic_set(&pd->driver->needs_tlbflush, 1);
426 } 397 }
427 kunmap_atomic(pt->v); 398 kunmap_atomic(pt->v);
@@ -432,8 +403,8 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
432 spin_unlock(&pd->driver->lock); 403 spin_unlock(&pd->driver->lock);
433} 404}
434 405
435static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, 406static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, unsigned long addr,
436 unsigned long addr, uint32_t pte) 407 uint32_t pte)
437{ 408{
438 pt->v[psb_mmu_pt_index(addr)] = pte; 409 pt->v[psb_mmu_pt_index(addr)] = pte;
439} 410}
@@ -444,69 +415,50 @@ static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
444 pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; 415 pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
445} 416}
446 417
447 418struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
448void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
449 uint32_t mmu_offset, uint32_t gtt_start,
450 uint32_t gtt_pages)
451{ 419{
452 uint32_t *v; 420 struct psb_mmu_pd *pd;
453 uint32_t start = psb_mmu_pd_index(mmu_offset);
454 struct psb_mmu_driver *driver = pd->driver;
455 int num_pages = gtt_pages;
456 421
457 down_read(&driver->sem); 422 down_read(&driver->sem);
458 spin_lock(&driver->lock); 423 pd = driver->default_pd;
459 424 up_read(&driver->sem);
460 v = kmap_atomic(pd->p);
461 v += start;
462
463 while (gtt_pages--) {
464 *v++ = gtt_start | pd->pd_mask;
465 gtt_start += PAGE_SIZE;
466 }
467
468 /*ttm_tt_cache_flush(&pd->p, num_pages);*/
469 psb_pages_clflush(pd->driver, &pd->p, num_pages);
470 kunmap_atomic(v);
471 spin_unlock(&driver->lock);
472
473 if (pd->hw_context != -1)
474 atomic_set(&pd->driver->needs_tlbflush, 1);
475 425
476 up_read(&pd->driver->sem); 426 return pd;
477 psb_mmu_flush_pd(pd->driver, 0);
478} 427}
479 428
480struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) 429/* Returns the physical address of the PD shared by sgx/msvdx */
430uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
481{ 431{
482 struct psb_mmu_pd *pd; 432 struct psb_mmu_pd *pd;
483 433
484 /* down_read(&driver->sem); */ 434 pd = psb_mmu_get_default_pd(driver);
485 pd = driver->default_pd; 435 return page_to_pfn(pd->p) << PAGE_SHIFT;
486 /* up_read(&driver->sem); */
487
488 return pd;
489} 436}
490 437
491void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) 438void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
492{ 439{
440 struct drm_device *dev = driver->dev;
441 struct drm_psb_private *dev_priv = dev->dev_private;
442
443 PSB_WSGX32(driver->bif_ctrl, PSB_CR_BIF_CTRL);
493 psb_mmu_free_pagedir(driver->default_pd); 444 psb_mmu_free_pagedir(driver->default_pd);
494 kfree(driver); 445 kfree(driver);
495} 446}
496 447
497struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, 448struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
498 int trap_pagefaults, 449 int trap_pagefaults,
499 int invalid_type, 450 int invalid_type,
500 struct drm_psb_private *dev_priv) 451 atomic_t *msvdx_mmu_invaldc)
501{ 452{
502 struct psb_mmu_driver *driver; 453 struct psb_mmu_driver *driver;
454 struct drm_psb_private *dev_priv = dev->dev_private;
503 455
504 driver = kmalloc(sizeof(*driver), GFP_KERNEL); 456 driver = kmalloc(sizeof(*driver), GFP_KERNEL);
505 457
506 if (!driver) 458 if (!driver)
507 return NULL; 459 return NULL;
508 driver->dev_priv = dev_priv;
509 460
461 driver->dev = dev;
510 driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, 462 driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
511 invalid_type); 463 invalid_type);
512 if (!driver->default_pd) 464 if (!driver->default_pd)
@@ -515,17 +467,24 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
515 spin_lock_init(&driver->lock); 467 spin_lock_init(&driver->lock);
516 init_rwsem(&driver->sem); 468 init_rwsem(&driver->sem);
517 down_write(&driver->sem); 469 down_write(&driver->sem);
518 driver->register_map = registers;
519 atomic_set(&driver->needs_tlbflush, 1); 470 atomic_set(&driver->needs_tlbflush, 1);
471 driver->msvdx_mmu_invaldc = msvdx_mmu_invaldc;
472
473 driver->bif_ctrl = PSB_RSGX32(PSB_CR_BIF_CTRL);
474 PSB_WSGX32(driver->bif_ctrl | _PSB_CB_CTRL_CLEAR_FAULT,
475 PSB_CR_BIF_CTRL);
476 PSB_WSGX32(driver->bif_ctrl & ~_PSB_CB_CTRL_CLEAR_FAULT,
477 PSB_CR_BIF_CTRL);
520 478
521 driver->has_clflush = 0; 479 driver->has_clflush = 0;
522 480
481#if defined(CONFIG_X86)
523 if (boot_cpu_has(X86_FEATURE_CLFLSH)) { 482 if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
524 uint32_t tfms, misc, cap0, cap4, clflush_size; 483 uint32_t tfms, misc, cap0, cap4, clflush_size;
525 484
526 /* 485 /*
527 * clflush size is determined at kernel setup for x86_64 486 * clflush size is determined at kernel setup for x86_64 but not
528 * but not for i386. We have to do it here. 487 * for i386. We have to do it here.
529 */ 488 */
530 489
531 cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); 490 cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
@@ -536,6 +495,7 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
536 driver->clflush_mask = driver->clflush_add - 1; 495 driver->clflush_mask = driver->clflush_add - 1;
537 driver->clflush_mask = ~driver->clflush_mask; 496 driver->clflush_mask = ~driver->clflush_mask;
538 } 497 }
498#endif
539 499
540 up_write(&driver->sem); 500 up_write(&driver->sem);
541 return driver; 501 return driver;
@@ -545,9 +505,9 @@ out_err1:
545 return NULL; 505 return NULL;
546} 506}
547 507
548static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, 508#if defined(CONFIG_X86)
549 unsigned long address, uint32_t num_pages, 509static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address,
550 uint32_t desired_tile_stride, 510 uint32_t num_pages, uint32_t desired_tile_stride,
551 uint32_t hw_tile_stride) 511 uint32_t hw_tile_stride)
552{ 512{
553 struct psb_mmu_pt *pt; 513 struct psb_mmu_pt *pt;
@@ -561,11 +521,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
561 unsigned long clflush_add = pd->driver->clflush_add; 521 unsigned long clflush_add = pd->driver->clflush_add;
562 unsigned long clflush_mask = pd->driver->clflush_mask; 522 unsigned long clflush_mask = pd->driver->clflush_mask;
563 523
564 if (!pd->driver->has_clflush) { 524 if (!pd->driver->has_clflush)
565 /*ttm_tt_cache_flush(&pd->p, num_pages);*/
566 psb_pages_clflush(pd->driver, &pd->p, num_pages);
567 return; 525 return;
568 }
569 526
570 if (hw_tile_stride) 527 if (hw_tile_stride)
571 rows = num_pages / desired_tile_stride; 528 rows = num_pages / desired_tile_stride;
@@ -586,10 +543,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
586 if (!pt) 543 if (!pt)
587 continue; 544 continue;
588 do { 545 do {
589 psb_clflush(&pt->v 546 psb_clflush(&pt->v[psb_mmu_pt_index(addr)]);
590 [psb_mmu_pt_index(addr)]); 547 } while (addr += clflush_add,
591 } while (addr +=
592 clflush_add,
593 (addr & clflush_mask) < next); 548 (addr & clflush_mask) < next);
594 549
595 psb_mmu_pt_unmap_unlock(pt); 550 psb_mmu_pt_unmap_unlock(pt);
@@ -598,6 +553,14 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
598 } 553 }
599 mb(); 554 mb();
600} 555}
556#else
557static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address,
558 uint32_t num_pages, uint32_t desired_tile_stride,
559 uint32_t hw_tile_stride)
560{
561 drm_ttm_cache_flush();
562}
563#endif
601 564
602void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, 565void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
603 unsigned long address, uint32_t num_pages) 566 unsigned long address, uint32_t num_pages)
@@ -633,7 +596,7 @@ out:
633 up_read(&pd->driver->sem); 596 up_read(&pd->driver->sem);
634 597
635 if (pd->hw_context != -1) 598 if (pd->hw_context != -1)
636 psb_mmu_flush(pd->driver, 0); 599 psb_mmu_flush(pd->driver);
637 600
638 return; 601 return;
639} 602}
@@ -660,7 +623,7 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
660 add = desired_tile_stride << PAGE_SHIFT; 623 add = desired_tile_stride << PAGE_SHIFT;
661 row_add = hw_tile_stride << PAGE_SHIFT; 624 row_add = hw_tile_stride << PAGE_SHIFT;
662 625
663 /* down_read(&pd->driver->sem); */ 626 down_read(&pd->driver->sem);
664 627
665 /* Make sure we only need to flush this processor's cache */ 628 /* Make sure we only need to flush this processor's cache */
666 629
@@ -688,10 +651,10 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
688 psb_mmu_flush_ptes(pd, f_address, num_pages, 651 psb_mmu_flush_ptes(pd, f_address, num_pages,
689 desired_tile_stride, hw_tile_stride); 652 desired_tile_stride, hw_tile_stride);
690 653
691 /* up_read(&pd->driver->sem); */ 654 up_read(&pd->driver->sem);
692 655
693 if (pd->hw_context != -1) 656 if (pd->hw_context != -1)
694 psb_mmu_flush(pd->driver, 0); 657 psb_mmu_flush(pd->driver);
695} 658}
696 659
697int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, 660int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
@@ -704,7 +667,7 @@ int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
704 unsigned long end; 667 unsigned long end;
705 unsigned long next; 668 unsigned long next;
706 unsigned long f_address = address; 669 unsigned long f_address = address;
707 int ret = 0; 670 int ret = -ENOMEM;
708 671
709 down_read(&pd->driver->sem); 672 down_read(&pd->driver->sem);
710 673
@@ -726,6 +689,7 @@ int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
726 psb_mmu_pt_unmap_unlock(pt); 689 psb_mmu_pt_unmap_unlock(pt);
727 690
728 } while (addr = next, next != end); 691 } while (addr = next, next != end);
692 ret = 0;
729 693
730out: 694out:
731 if (pd->hw_context != -1) 695 if (pd->hw_context != -1)
@@ -734,15 +698,15 @@ out:
734 up_read(&pd->driver->sem); 698 up_read(&pd->driver->sem);
735 699
736 if (pd->hw_context != -1) 700 if (pd->hw_context != -1)
737 psb_mmu_flush(pd->driver, 1); 701 psb_mmu_flush(pd->driver);
738 702
739 return ret; 703 return 0;
740} 704}
741 705
742int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, 706int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
743 unsigned long address, uint32_t num_pages, 707 unsigned long address, uint32_t num_pages,
744 uint32_t desired_tile_stride, 708 uint32_t desired_tile_stride, uint32_t hw_tile_stride,
745 uint32_t hw_tile_stride, int type) 709 int type)
746{ 710{
747 struct psb_mmu_pt *pt; 711 struct psb_mmu_pt *pt;
748 uint32_t rows = 1; 712 uint32_t rows = 1;
@@ -754,7 +718,7 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
754 unsigned long add; 718 unsigned long add;
755 unsigned long row_add; 719 unsigned long row_add;
756 unsigned long f_address = address; 720 unsigned long f_address = address;
757 int ret = 0; 721 int ret = -ENOMEM;
758 722
759 if (hw_tile_stride) { 723 if (hw_tile_stride) {
760 if (num_pages % desired_tile_stride != 0) 724 if (num_pages % desired_tile_stride != 0)
@@ -777,14 +741,11 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
777 do { 741 do {
778 next = psb_pd_addr_end(addr, end); 742 next = psb_pd_addr_end(addr, end);
779 pt = psb_mmu_pt_alloc_map_lock(pd, addr); 743 pt = psb_mmu_pt_alloc_map_lock(pd, addr);
780 if (!pt) { 744 if (!pt)
781 ret = -ENOMEM;
782 goto out; 745 goto out;
783 }
784 do { 746 do {
785 pte = 747 pte = psb_mmu_mask_pte(page_to_pfn(*pages++),
786 psb_mmu_mask_pte(page_to_pfn(*pages++), 748 type);
787 type);
788 psb_mmu_set_pte(pt, addr, pte); 749 psb_mmu_set_pte(pt, addr, pte);
789 pt->count++; 750 pt->count++;
790 } while (addr += PAGE_SIZE, addr < next); 751 } while (addr += PAGE_SIZE, addr < next);
@@ -794,6 +755,8 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
794 755
795 address += row_add; 756 address += row_add;
796 } 757 }
758
759 ret = 0;
797out: 760out:
798 if (pd->hw_context != -1) 761 if (pd->hw_context != -1)
799 psb_mmu_flush_ptes(pd, f_address, num_pages, 762 psb_mmu_flush_ptes(pd, f_address, num_pages,
@@ -802,7 +765,7 @@ out:
802 up_read(&pd->driver->sem); 765 up_read(&pd->driver->sem);
803 766
804 if (pd->hw_context != -1) 767 if (pd->hw_context != -1)
805 psb_mmu_flush(pd->driver, 1); 768 psb_mmu_flush(pd->driver);
806 769
807 return ret; 770 return ret;
808} 771}
diff --git a/drivers/gpu/drm/gma500/mmu.h b/drivers/gpu/drm/gma500/mmu.h
new file mode 100644
index 000000000000..e89abec6209d
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mmu.h
@@ -0,0 +1,93 @@
1/**************************************************************************
2 * Copyright (c) 2007-2011, Intel Corporation.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 **************************************************************************/
14
15#ifndef __MMU_H
16#define __MMU_H
17
18struct psb_mmu_driver {
19 /* protects driver- and pd structures. Always take in read mode
20 * before taking the page table spinlock.
21 */
22 struct rw_semaphore sem;
23
24 /* protects page tables, directory tables and pt tables.
25 * and pt structures.
26 */
27 spinlock_t lock;
28
29 atomic_t needs_tlbflush;
30 atomic_t *msvdx_mmu_invaldc;
31 struct psb_mmu_pd *default_pd;
32 uint32_t bif_ctrl;
33 int has_clflush;
34 int clflush_add;
35 unsigned long clflush_mask;
36
37 struct drm_device *dev;
38};
39
40struct psb_mmu_pd;
41
42struct psb_mmu_pt {
43 struct psb_mmu_pd *pd;
44 uint32_t index;
45 uint32_t count;
46 struct page *p;
47 uint32_t *v;
48};
49
50struct psb_mmu_pd {
51 struct psb_mmu_driver *driver;
52 int hw_context;
53 struct psb_mmu_pt **tables;
54 struct page *p;
55 struct page *dummy_pt;
56 struct page *dummy_page;
57 uint32_t pd_mask;
58 uint32_t invalid_pde;
59 uint32_t invalid_pte;
60};
61
62extern struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
63 int trap_pagefaults,
64 int invalid_type,
65 atomic_t *msvdx_mmu_invaldc);
66extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
67extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
68 *driver);
69extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
70 int trap_pagefaults,
71 int invalid_type);
72extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
73extern void psb_mmu_flush(struct psb_mmu_driver *driver);
74extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
75 unsigned long address,
76 uint32_t num_pages);
77extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
78 uint32_t start_pfn,
79 unsigned long address,
80 uint32_t num_pages, int type);
81extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
82 unsigned long *pfn);
83extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
84extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
85 unsigned long address, uint32_t num_pages,
86 uint32_t desired_tile_stride,
87 uint32_t hw_tile_stride, int type);
88extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
89 unsigned long address, uint32_t num_pages,
90 uint32_t desired_tile_stride,
91 uint32_t hw_tile_stride);
92
93#endif
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
index 8195e8592107..2de216c2374f 100644
--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -599,7 +599,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
599 struct drm_device *dev = crtc->dev; 599 struct drm_device *dev = crtc->dev;
600 struct drm_psb_private *dev_priv = dev->dev_private; 600 struct drm_psb_private *dev_priv = dev->dev_private;
601 struct gma_crtc *gma_crtc = to_gma_crtc(crtc); 601 struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
602 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 602 struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
603 int pipe = gma_crtc->pipe; 603 int pipe = gma_crtc->pipe;
604 const struct psb_offset *map = &dev_priv->regmap[pipe]; 604 const struct psb_offset *map = &dev_priv->regmap[pipe];
605 unsigned long start, offset; 605 unsigned long start, offset;
@@ -608,7 +608,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
608 int ret = 0; 608 int ret = 0;
609 609
610 /* no fb bound */ 610 /* no fb bound */
611 if (!crtc->fb) { 611 if (!crtc->primary->fb) {
612 dev_dbg(dev->dev, "No FB bound\n"); 612 dev_dbg(dev->dev, "No FB bound\n");
613 return 0; 613 return 0;
614 } 614 }
@@ -617,19 +617,19 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
617 return 0; 617 return 0;
618 618
619 start = psbfb->gtt->offset; 619 start = psbfb->gtt->offset;
620 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); 620 offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
621 621
622 REG_WRITE(map->stride, crtc->fb->pitches[0]); 622 REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
623 623
624 dspcntr = REG_READ(map->cntr); 624 dspcntr = REG_READ(map->cntr);
625 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 625 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
626 626
627 switch (crtc->fb->bits_per_pixel) { 627 switch (crtc->primary->fb->bits_per_pixel) {
628 case 8: 628 case 8:
629 dspcntr |= DISPPLANE_8BPP; 629 dspcntr |= DISPPLANE_8BPP;
630 break; 630 break;
631 case 16: 631 case 16:
632 if (crtc->fb->depth == 15) 632 if (crtc->primary->fb->depth == 15)
633 dspcntr |= DISPPLANE_15_16BPP; 633 dspcntr |= DISPPLANE_15_16BPP;
634 else 634 else
635 dspcntr |= DISPPLANE_16BPP; 635 dspcntr |= DISPPLANE_16BPP;
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 38153143ed8c..cf018ddcc5a6 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -523,13 +523,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
523 return MODE_OK; 523 return MODE_OK;
524} 524}
525 525
526static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder,
527 const struct drm_display_mode *mode,
528 struct drm_display_mode *adjusted_mode)
529{
530 return true;
531}
532
533static enum drm_connector_status 526static enum drm_connector_status
534oaktrail_hdmi_detect(struct drm_connector *connector, bool force) 527oaktrail_hdmi_detect(struct drm_connector *connector, bool force)
535{ 528{
@@ -608,7 +601,7 @@ static void oaktrail_hdmi_destroy(struct drm_connector *connector)
608 601
609static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = { 602static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = {
610 .dpms = oaktrail_hdmi_dpms, 603 .dpms = oaktrail_hdmi_dpms,
611 .mode_fixup = oaktrail_hdmi_mode_fixup, 604 .mode_fixup = gma_encoder_mode_fixup,
612 .prepare = gma_encoder_prepare, 605 .prepare = gma_encoder_prepare,
613 .mode_set = oaktrail_hdmi_mode_set, 606 .mode_set = oaktrail_hdmi_mode_set,
614 .commit = gma_encoder_commit, 607 .commit = gma_encoder_commit,
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index 5e0697862736..9b099468a5db 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -359,6 +359,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
359 * if closed, act like it's not there for now 359 * if closed, act like it's not there for now
360 */ 360 */
361 361
362 mutex_lock(&dev->mode_config.mutex);
362 i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); 363 i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
363 if (i2c_adap == NULL) 364 if (i2c_adap == NULL)
364 dev_err(dev->dev, "No ddc adapter available!\n"); 365 dev_err(dev->dev, "No ddc adapter available!\n");
@@ -401,10 +402,14 @@ void oaktrail_lvds_init(struct drm_device *dev,
401 } 402 }
402 403
403out: 404out:
405 mutex_unlock(&dev->mode_config.mutex);
406
404 drm_sysfs_connector_add(connector); 407 drm_sysfs_connector_add(connector);
405 return; 408 return;
406 409
407failed_find: 410failed_find:
411 mutex_unlock(&dev->mode_config.mutex);
412
408 dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); 413 dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
409 if (gma_encoder->ddc_bus) 414 if (gma_encoder->ddc_bus)
410 psb_intel_i2c_destroy(gma_encoder->ddc_bus); 415 psb_intel_i2c_destroy(gma_encoder->ddc_bus);
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c
index 13ec6283bf59..ab696ca7eeec 100644
--- a/drivers/gpu/drm/gma500/opregion.c
+++ b/drivers/gpu/drm/gma500/opregion.c
@@ -173,10 +173,13 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
173 return 0; 173 return 0;
174} 174}
175 175
176void psb_intel_opregion_asle_intr(struct drm_device *dev) 176static void psb_intel_opregion_asle_work(struct work_struct *work)
177{ 177{
178 struct drm_psb_private *dev_priv = dev->dev_private; 178 struct psb_intel_opregion *opregion =
179 struct opregion_asle *asle = dev_priv->opregion.asle; 179 container_of(work, struct psb_intel_opregion, asle_work);
180 struct drm_psb_private *dev_priv =
181 container_of(opregion, struct drm_psb_private, opregion);
182 struct opregion_asle *asle = opregion->asle;
180 u32 asle_stat = 0; 183 u32 asle_stat = 0;
181 u32 asle_req; 184 u32 asle_req;
182 185
@@ -190,9 +193,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev)
190 } 193 }
191 194
192 if (asle_req & ASLE_SET_BACKLIGHT) 195 if (asle_req & ASLE_SET_BACKLIGHT)
193 asle_stat |= asle_set_backlight(dev, asle->bclp); 196 asle_stat |= asle_set_backlight(dev_priv->dev, asle->bclp);
194 197
195 asle->aslc = asle_stat; 198 asle->aslc = asle_stat;
199
200}
201
202void psb_intel_opregion_asle_intr(struct drm_device *dev)
203{
204 struct drm_psb_private *dev_priv = dev->dev_private;
205
206 if (dev_priv->opregion.asle)
207 schedule_work(&dev_priv->opregion.asle_work);
196} 208}
197 209
198#define ASLE_ALS_EN (1<<0) 210#define ASLE_ALS_EN (1<<0)
@@ -282,6 +294,8 @@ void psb_intel_opregion_fini(struct drm_device *dev)
282 unregister_acpi_notifier(&psb_intel_opregion_notifier); 294 unregister_acpi_notifier(&psb_intel_opregion_notifier);
283 } 295 }
284 296
297 cancel_work_sync(&opregion->asle_work);
298
285 /* just clear all opregion memory pointers now */ 299 /* just clear all opregion memory pointers now */
286 iounmap(opregion->header); 300 iounmap(opregion->header);
287 opregion->header = NULL; 301 opregion->header = NULL;
@@ -304,6 +318,9 @@ int psb_intel_opregion_setup(struct drm_device *dev)
304 DRM_DEBUG_DRIVER("ACPI Opregion not supported\n"); 318 DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
305 return -ENOTSUPP; 319 return -ENOTSUPP;
306 } 320 }
321
322 INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);
323
307 DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy); 324 DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
308 base = acpi_os_ioremap(opregion_phy, 8*1024); 325 base = acpi_os_ioremap(opregion_phy, 8*1024);
309 if (!base) 326 if (!base)
diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c
index 23fb33f1471b..07df7d4eea72 100644
--- a/drivers/gpu/drm/gma500/psb_device.c
+++ b/drivers/gpu/drm/gma500/psb_device.c
@@ -26,6 +26,7 @@
26#include "psb_intel_reg.h" 26#include "psb_intel_reg.h"
27#include "intel_bios.h" 27#include "intel_bios.h"
28#include "psb_device.h" 28#include "psb_device.h"
29#include "gma_device.h"
29 30
30static int psb_output_init(struct drm_device *dev) 31static int psb_output_init(struct drm_device *dev)
31{ 32{
@@ -257,45 +258,6 @@ static int psb_power_up(struct drm_device *dev)
257 return 0; 258 return 0;
258} 259}
259 260
260static void psb_get_core_freq(struct drm_device *dev)
261{
262 uint32_t clock;
263 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
264 struct drm_psb_private *dev_priv = dev->dev_private;
265
266 /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
267 /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
268
269 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
270 pci_read_config_dword(pci_root, 0xD4, &clock);
271 pci_dev_put(pci_root);
272
273 switch (clock & 0x07) {
274 case 0:
275 dev_priv->core_freq = 100;
276 break;
277 case 1:
278 dev_priv->core_freq = 133;
279 break;
280 case 2:
281 dev_priv->core_freq = 150;
282 break;
283 case 3:
284 dev_priv->core_freq = 178;
285 break;
286 case 4:
287 dev_priv->core_freq = 200;
288 break;
289 case 5:
290 case 6:
291 case 7:
292 dev_priv->core_freq = 266;
293 break;
294 default:
295 dev_priv->core_freq = 0;
296 }
297}
298
299/* Poulsbo */ 261/* Poulsbo */
300static const struct psb_offset psb_regmap[2] = { 262static const struct psb_offset psb_regmap[2] = {
301 { 263 {
@@ -352,7 +314,7 @@ static int psb_chip_setup(struct drm_device *dev)
352{ 314{
353 struct drm_psb_private *dev_priv = dev->dev_private; 315 struct drm_psb_private *dev_priv = dev->dev_private;
354 dev_priv->regmap = psb_regmap; 316 dev_priv->regmap = psb_regmap;
355 psb_get_core_freq(dev); 317 gma_get_core_freq(dev);
356 gma_intel_setup_gmbus(dev); 318 gma_intel_setup_gmbus(dev);
357 psb_intel_opregion_init(dev); 319 psb_intel_opregion_init(dev);
358 psb_intel_init_bios(dev); 320 psb_intel_init_bios(dev);
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 1199180667c9..b686e56646eb 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -21,7 +21,6 @@
21 21
22#include <drm/drmP.h> 22#include <drm/drmP.h>
23#include <drm/drm.h> 23#include <drm/drm.h>
24#include <drm/gma_drm.h>
25#include "psb_drv.h" 24#include "psb_drv.h"
26#include "framebuffer.h" 25#include "framebuffer.h"
27#include "psb_reg.h" 26#include "psb_reg.h"
@@ -37,56 +36,65 @@
37#include <acpi/video.h> 36#include <acpi/video.h>
38#include <linux/module.h> 37#include <linux/module.h>
39 38
40static int drm_psb_trap_pagefaults; 39static struct drm_driver driver;
41 40static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
42static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
43
44MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
45module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
46
47 41
42/*
43 * The table below contains a mapping of the PCI vendor ID and the PCI Device ID
44 * to the different groups of PowerVR 5-series chip designs
45 *
46 * 0x8086 = Intel Corporation
47 *
48 * PowerVR SGX535 - Poulsbo - Intel GMA 500, Intel Atom Z5xx
49 * PowerVR SGX535 - Moorestown - Intel GMA 600
50 * PowerVR SGX535 - Oaktrail - Intel GMA 600, Intel Atom Z6xx, E6xx
51 * PowerVR SGX540 - Medfield - Intel Atom Z2460
52 * PowerVR SGX544MP2 - Medfield -
53 * PowerVR SGX545 - Cedartrail - Intel GMA 3600, Intel Atom D2500, N2600
54 * PowerVR SGX545 - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700,
55 * N2800
56 */
48static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { 57static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
49 { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, 58 { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
50 { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, 59 { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
51#if defined(CONFIG_DRM_GMA600) 60#if defined(CONFIG_DRM_GMA600)
52 { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 61 { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
53 { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 62 { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
54 { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 63 { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
55 { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 64 { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
56 { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 65 { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
57 { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 66 { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
58 { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 67 { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
59 { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 68 { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
60 /* Atom E620 */ 69 { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
61 { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
62#endif 70#endif
63#if defined(CONFIG_DRM_MEDFIELD) 71#if defined(CONFIG_DRM_MEDFIELD)
64 {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 72 { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
65 {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 73 { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
66 {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 74 { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
67 {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 75 { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
68 {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 76 { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
69 {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 77 { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
70 {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 78 { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
71 {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, 79 { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
72#endif 80#endif
73#if defined(CONFIG_DRM_GMA3600) 81#if defined(CONFIG_DRM_GMA3600)
74 { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 82 { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
75 { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 83 { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
76 { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 84 { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
77 { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 85 { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
78 { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 86 { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
79 { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 87 { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
80 { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 88 { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
81 { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 89 { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
82 { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 90 { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
83 { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 91 { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
84 { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 92 { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
85 { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 93 { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
86 { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 94 { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
87 { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 95 { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
88 { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 96 { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
89 { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 97 { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
90#endif 98#endif
91 { 0, } 99 { 0, }
92}; 100};
@@ -95,59 +103,10 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
95/* 103/*
96 * Standard IOCTLs. 104 * Standard IOCTLs.
97 */ 105 */
98
99#define DRM_IOCTL_GMA_ADB \
100 DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
101#define DRM_IOCTL_GMA_MODE_OPERATION \
102 DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
103 struct drm_psb_mode_operation_arg)
104#define DRM_IOCTL_GMA_STOLEN_MEMORY \
105 DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
106 struct drm_psb_stolen_memory_arg)
107#define DRM_IOCTL_GMA_GAMMA \
108 DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
109 struct drm_psb_dpst_lut_arg)
110#define DRM_IOCTL_GMA_DPST_BL \
111 DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
112 uint32_t)
113#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID \
114 DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
115 struct drm_psb_get_pipe_from_crtc_id_arg)
116#define DRM_IOCTL_GMA_GEM_CREATE \
117 DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
118 struct drm_psb_gem_create)
119#define DRM_IOCTL_GMA_GEM_MMAP \
120 DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
121 struct drm_psb_gem_mmap)
122
123static int psb_adb_ioctl(struct drm_device *dev, void *data,
124 struct drm_file *file_priv);
125static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
126 struct drm_file *file_priv);
127static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
128 struct drm_file *file_priv);
129static int psb_gamma_ioctl(struct drm_device *dev, void *data,
130 struct drm_file *file_priv);
131static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
132 struct drm_file *file_priv);
133
134static const struct drm_ioctl_desc psb_ioctls[] = { 106static const struct drm_ioctl_desc psb_ioctls[] = {
135 DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
136 DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
137 DRM_AUTH),
138 DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl,
139 DRM_AUTH),
140 DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH),
141 DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
142 DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID,
143 psb_intel_get_pipe_from_crtc_id, 0),
144 DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl,
145 DRM_UNLOCKED | DRM_AUTH),
146 DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl,
147 DRM_UNLOCKED | DRM_AUTH),
148}; 107};
149 108
150static void psb_lastclose(struct drm_device *dev) 109static void psb_driver_lastclose(struct drm_device *dev)
151{ 110{
152 int ret; 111 int ret;
153 struct drm_psb_private *dev_priv = dev->dev_private; 112 struct drm_psb_private *dev_priv = dev->dev_private;
@@ -169,19 +128,14 @@ static int psb_do_init(struct drm_device *dev)
169 128
170 uint32_t stolen_gtt; 129 uint32_t stolen_gtt;
171 130
172 int ret = -ENOMEM;
173
174 if (pg->mmu_gatt_start & 0x0FFFFFFF) { 131 if (pg->mmu_gatt_start & 0x0FFFFFFF) {
175 dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); 132 dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
176 ret = -EINVAL; 133 return -EINVAL;
177 goto out_err;
178 } 134 }
179 135
180
181 stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; 136 stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
182 stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; 137 stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
183 stolen_gtt = 138 stolen_gtt = (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
184 (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
185 139
186 dev_priv->gatt_free_offset = pg->mmu_gatt_start + 140 dev_priv->gatt_free_offset = pg->mmu_gatt_start +
187 (stolen_gtt << PAGE_SHIFT) * 1024; 141 (stolen_gtt << PAGE_SHIFT) * 1024;
@@ -192,23 +146,26 @@ static int psb_do_init(struct drm_device *dev)
192 PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); 146 PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
193 PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); 147 PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
194 PSB_RSGX32(PSB_CR_BIF_BANK1); 148 PSB_RSGX32(PSB_CR_BIF_BANK1);
195 PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, 149
196 PSB_CR_BIF_CTRL); 150 /* Do not bypass any MMU access, let them pagefault instead */
151 PSB_WSGX32((PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_MMU_ER_MASK),
152 PSB_CR_BIF_CTRL);
153 PSB_RSGX32(PSB_CR_BIF_CTRL);
154
197 psb_spank(dev_priv); 155 psb_spank(dev_priv);
198 156
199 /* mmu_gatt ?? */ 157 /* mmu_gatt ?? */
200 PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); 158 PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
159 PSB_RSGX32(PSB_CR_BIF_TWOD_REQ_BASE); /* Post */
160
201 return 0; 161 return 0;
202out_err:
203 return ret;
204} 162}
205 163
206static int psb_driver_unload(struct drm_device *dev) 164static int psb_driver_unload(struct drm_device *dev)
207{ 165{
208 struct drm_psb_private *dev_priv = dev->dev_private; 166 struct drm_psb_private *dev_priv = dev->dev_private;
209 167
210 /* Kill vblank etc here */ 168 /* TODO: Kill vblank etc here */
211
212 169
213 if (dev_priv) { 170 if (dev_priv) {
214 if (dev_priv->backlight_device) 171 if (dev_priv->backlight_device)
@@ -268,8 +225,7 @@ static int psb_driver_unload(struct drm_device *dev)
268 return 0; 225 return 0;
269} 226}
270 227
271 228static int psb_driver_load(struct drm_device *dev, unsigned long flags)
272static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
273{ 229{
274 struct drm_psb_private *dev_priv; 230 struct drm_psb_private *dev_priv;
275 unsigned long resource_start, resource_len; 231 unsigned long resource_start, resource_len;
@@ -277,15 +233,19 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
277 int ret = -ENOMEM; 233 int ret = -ENOMEM;
278 struct drm_connector *connector; 234 struct drm_connector *connector;
279 struct gma_encoder *gma_encoder; 235 struct gma_encoder *gma_encoder;
236 struct psb_gtt *pg;
280 237
238 /* allocating and initializing driver private data */
281 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); 239 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
282 if (dev_priv == NULL) 240 if (dev_priv == NULL)
283 return -ENOMEM; 241 return -ENOMEM;
284 242
285 dev_priv->ops = (struct psb_ops *)chipset; 243 dev_priv->ops = (struct psb_ops *)flags;
286 dev_priv->dev = dev; 244 dev_priv->dev = dev;
287 dev->dev_private = (void *) dev_priv; 245 dev->dev_private = (void *) dev_priv;
288 246
247 pg = &dev_priv->gtt;
248
289 pci_set_master(dev->pdev); 249 pci_set_master(dev->pdev);
290 250
291 dev_priv->num_pipe = dev_priv->ops->pipes; 251 dev_priv->num_pipe = dev_priv->ops->pipes;
@@ -347,9 +307,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
347 if (ret) 307 if (ret)
348 goto out_err; 308 goto out_err;
349 309
350 dev_priv->mmu = psb_mmu_driver_init((void *)0, 310 dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0);
351 drm_psb_trap_pagefaults, 0,
352 dev_priv);
353 if (!dev_priv->mmu) 311 if (!dev_priv->mmu)
354 goto out_err; 312 goto out_err;
355 313
@@ -357,18 +315,27 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
357 if (!dev_priv->pf_pd) 315 if (!dev_priv->pf_pd)
358 goto out_err; 316 goto out_err;
359 317
360 psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
361 psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
362
363 ret = psb_do_init(dev); 318 ret = psb_do_init(dev);
364 if (ret) 319 if (ret)
365 return ret; 320 return ret;
366 321
322 /* Add stolen memory to SGX MMU */
323 down_read(&pg->sem);
324 ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd(dev_priv->mmu),
325 dev_priv->stolen_base >> PAGE_SHIFT,
326 pg->gatt_start,
327 pg->stolen_size >> PAGE_SHIFT, 0);
328 up_read(&pg->sem);
329
330 psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
331 psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
332
367 PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); 333 PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
368 PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); 334 PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
369 335
370 acpi_video_register(); 336 acpi_video_register();
371 337
338 /* Setup vertical blanking handling */
372 ret = drm_vblank_init(dev, dev_priv->num_pipe); 339 ret = drm_vblank_init(dev, dev_priv->num_pipe);
373 if (ret) 340 if (ret)
374 goto out_err; 341 goto out_err;
@@ -390,9 +357,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
390 drm_irq_install(dev); 357 drm_irq_install(dev);
391 358
392 dev->vblank_disable_allowed = true; 359 dev->vblank_disable_allowed = true;
393
394 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ 360 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
395
396 dev->driver->get_vblank_counter = psb_get_vblank_counter; 361 dev->driver->get_vblank_counter = psb_get_vblank_counter;
397 362
398 psb_modeset_init(dev); 363 psb_modeset_init(dev);
@@ -416,11 +381,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
416 return ret; 381 return ret;
417 psb_intel_opregion_enable_asle(dev); 382 psb_intel_opregion_enable_asle(dev);
418#if 0 383#if 0
419 /*enable runtime pm at last*/ 384 /* Enable runtime pm at last */
420 pm_runtime_enable(&dev->pdev->dev); 385 pm_runtime_enable(&dev->pdev->dev);
421 pm_runtime_set_active(&dev->pdev->dev); 386 pm_runtime_set_active(&dev->pdev->dev);
422#endif 387#endif
423 /*Intel drm driver load is done, continue doing pvr load*/ 388 /* Intel drm driver load is done, continue doing pvr load */
424 return 0; 389 return 0;
425out_err: 390out_err:
426 psb_driver_unload(dev); 391 psb_driver_unload(dev);
@@ -442,161 +407,6 @@ static inline void get_brightness(struct backlight_device *bd)
442#endif 407#endif
443} 408}
444 409
445static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
446 struct drm_file *file_priv)
447{
448 struct drm_psb_private *dev_priv = psb_priv(dev);
449 uint32_t *arg = data;
450
451 dev_priv->blc_adj2 = *arg;
452 get_brightness(dev_priv->backlight_device);
453 return 0;
454}
455
456static int psb_adb_ioctl(struct drm_device *dev, void *data,
457 struct drm_file *file_priv)
458{
459 struct drm_psb_private *dev_priv = psb_priv(dev);
460 uint32_t *arg = data;
461
462 dev_priv->blc_adj1 = *arg;
463 get_brightness(dev_priv->backlight_device);
464 return 0;
465}
466
467static int psb_gamma_ioctl(struct drm_device *dev, void *data,
468 struct drm_file *file_priv)
469{
470 struct drm_psb_dpst_lut_arg *lut_arg = data;
471 struct drm_mode_object *obj;
472 struct drm_crtc *crtc;
473 struct drm_connector *connector;
474 struct gma_crtc *gma_crtc;
475 int i = 0;
476 int32_t obj_id;
477
478 obj_id = lut_arg->output_id;
479 obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
480 if (!obj) {
481 dev_dbg(dev->dev, "Invalid Connector object.\n");
482 return -ENOENT;
483 }
484
485 connector = obj_to_connector(obj);
486 crtc = connector->encoder->crtc;
487 gma_crtc = to_gma_crtc(crtc);
488
489 for (i = 0; i < 256; i++)
490 gma_crtc->lut_adj[i] = lut_arg->lut[i];
491
492 gma_crtc_load_lut(crtc);
493
494 return 0;
495}
496
497static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
498 struct drm_file *file_priv)
499{
500 uint32_t obj_id;
501 uint16_t op;
502 struct drm_mode_modeinfo *umode;
503 struct drm_display_mode *mode = NULL;
504 struct drm_psb_mode_operation_arg *arg;
505 struct drm_mode_object *obj;
506 struct drm_connector *connector;
507 struct drm_connector_helper_funcs *connector_funcs;
508 int ret = 0;
509 int resp = MODE_OK;
510
511 arg = (struct drm_psb_mode_operation_arg *)data;
512 obj_id = arg->obj_id;
513 op = arg->operation;
514
515 switch (op) {
516 case PSB_MODE_OPERATION_MODE_VALID:
517 umode = &arg->mode;
518
519 drm_modeset_lock_all(dev);
520
521 obj = drm_mode_object_find(dev, obj_id,
522 DRM_MODE_OBJECT_CONNECTOR);
523 if (!obj) {
524 ret = -ENOENT;
525 goto mode_op_out;
526 }
527
528 connector = obj_to_connector(obj);
529
530 mode = drm_mode_create(dev);
531 if (!mode) {
532 ret = -ENOMEM;
533 goto mode_op_out;
534 }
535
536 /* drm_crtc_convert_umode(mode, umode); */
537 {
538 mode->clock = umode->clock;
539 mode->hdisplay = umode->hdisplay;
540 mode->hsync_start = umode->hsync_start;
541 mode->hsync_end = umode->hsync_end;
542 mode->htotal = umode->htotal;
543 mode->hskew = umode->hskew;
544 mode->vdisplay = umode->vdisplay;
545 mode->vsync_start = umode->vsync_start;
546 mode->vsync_end = umode->vsync_end;
547 mode->vtotal = umode->vtotal;
548 mode->vscan = umode->vscan;
549 mode->vrefresh = umode->vrefresh;
550 mode->flags = umode->flags;
551 mode->type = umode->type;
552 strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
553 mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
554 }
555
556 connector_funcs = (struct drm_connector_helper_funcs *)
557 connector->helper_private;
558
559 if (connector_funcs->mode_valid) {
560 resp = connector_funcs->mode_valid(connector, mode);
561 arg->data = resp;
562 }
563
564 /*do some clean up work*/
565 if (mode)
566 drm_mode_destroy(dev, mode);
567mode_op_out:
568 drm_modeset_unlock_all(dev);
569 return ret;
570
571 default:
572 dev_dbg(dev->dev, "Unsupported psb mode operation\n");
573 return -EOPNOTSUPP;
574 }
575
576 return 0;
577}
578
579static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
580 struct drm_file *file_priv)
581{
582 struct drm_psb_private *dev_priv = psb_priv(dev);
583 struct drm_psb_stolen_memory_arg *arg = data;
584
585 arg->base = dev_priv->stolen_base;
586 arg->size = dev_priv->vram_stolen_size;
587
588 return 0;
589}
590
591static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
592{
593 return 0;
594}
595
596static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
597{
598}
599
600static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, 410static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
601 unsigned long arg) 411 unsigned long arg)
602{ 412{
@@ -614,15 +424,21 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
614 /* FIXME: do we need to wrap the other side of this */ 424 /* FIXME: do we need to wrap the other side of this */
615} 425}
616 426
617 427/*
618/* When a client dies: 428 * When a client dies:
619 * - Check for and clean up flipped page state 429 * - Check for and clean up flipped page state
620 */ 430 */
621static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) 431static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
622{ 432{
623} 433}
624 434
625static void psb_remove(struct pci_dev *pdev) 435static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
436{
437 return drm_get_pci_dev(pdev, ent, &driver);
438}
439
440
441static void psb_pci_remove(struct pci_dev *pdev)
626{ 442{
627 struct drm_device *dev = pci_get_drvdata(pdev); 443 struct drm_device *dev = pci_get_drvdata(pdev);
628 drm_put_dev(dev); 444 drm_put_dev(dev);
@@ -657,11 +473,12 @@ static const struct file_operations psb_gem_fops = {
657 473
658static struct drm_driver driver = { 474static struct drm_driver driver = {
659 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ 475 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
660 DRIVER_MODESET | DRIVER_GEM , 476 DRIVER_MODESET | DRIVER_GEM,
661 .load = psb_driver_load, 477 .load = psb_driver_load,
662 .unload = psb_driver_unload, 478 .unload = psb_driver_unload,
479 .lastclose = psb_driver_lastclose,
480 .preclose = psb_driver_preclose,
663 481
664 .ioctls = psb_ioctls,
665 .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), 482 .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
666 .device_is_agp = psb_driver_device_is_agp, 483 .device_is_agp = psb_driver_device_is_agp,
667 .irq_preinstall = psb_irq_preinstall, 484 .irq_preinstall = psb_irq_preinstall,
@@ -671,40 +488,31 @@ static struct drm_driver driver = {
671 .enable_vblank = psb_enable_vblank, 488 .enable_vblank = psb_enable_vblank,
672 .disable_vblank = psb_disable_vblank, 489 .disable_vblank = psb_disable_vblank,
673 .get_vblank_counter = psb_get_vblank_counter, 490 .get_vblank_counter = psb_get_vblank_counter,
674 .lastclose = psb_lastclose,
675 .open = psb_driver_open,
676 .preclose = psb_driver_preclose,
677 .postclose = psb_driver_close,
678 491
679 .gem_free_object = psb_gem_free_object, 492 .gem_free_object = psb_gem_free_object,
680 .gem_vm_ops = &psb_gem_vm_ops, 493 .gem_vm_ops = &psb_gem_vm_ops,
494
681 .dumb_create = psb_gem_dumb_create, 495 .dumb_create = psb_gem_dumb_create,
682 .dumb_map_offset = psb_gem_dumb_map_gtt, 496 .dumb_map_offset = psb_gem_dumb_map_gtt,
683 .dumb_destroy = drm_gem_dumb_destroy, 497 .dumb_destroy = drm_gem_dumb_destroy,
498 .ioctls = psb_ioctls,
684 .fops = &psb_gem_fops, 499 .fops = &psb_gem_fops,
685 .name = DRIVER_NAME, 500 .name = DRIVER_NAME,
686 .desc = DRIVER_DESC, 501 .desc = DRIVER_DESC,
687 .date = PSB_DRM_DRIVER_DATE, 502 .date = DRIVER_DATE,
688 .major = PSB_DRM_DRIVER_MAJOR, 503 .major = DRIVER_MAJOR,
689 .minor = PSB_DRM_DRIVER_MINOR, 504 .minor = DRIVER_MINOR,
690 .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL 505 .patchlevel = DRIVER_PATCHLEVEL
691}; 506};
692 507
693static struct pci_driver psb_pci_driver = { 508static struct pci_driver psb_pci_driver = {
694 .name = DRIVER_NAME, 509 .name = DRIVER_NAME,
695 .id_table = pciidlist, 510 .id_table = pciidlist,
696 .probe = psb_probe, 511 .probe = psb_pci_probe,
697 .remove = psb_remove, 512 .remove = psb_pci_remove,
698 .driver = { 513 .driver.pm = &psb_pm_ops,
699 .pm = &psb_pm_ops,
700 }
701}; 514};
702 515
703static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
704{
705 return drm_get_pci_dev(pdev, ent, &driver);
706}
707
708static int __init psb_init(void) 516static int __init psb_init(void)
709{ 517{
710 return drm_pci_init(&driver, &psb_pci_driver); 518 return drm_pci_init(&driver, &psb_pci_driver);
@@ -718,6 +526,6 @@ static void __exit psb_exit(void)
718late_initcall(psb_init); 526late_initcall(psb_init);
719module_exit(psb_exit); 527module_exit(psb_exit);
720 528
721MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others"); 529MODULE_AUTHOR(DRIVER_AUTHOR);
722MODULE_DESCRIPTION(DRIVER_DESC); 530MODULE_DESCRIPTION(DRIVER_DESC);
723MODULE_LICENSE("GPL"); 531MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 5ad6a03e477e..55ebe2bd88dd 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -33,6 +33,18 @@
33#include "power.h" 33#include "power.h"
34#include "opregion.h" 34#include "opregion.h"
35#include "oaktrail.h" 35#include "oaktrail.h"
36#include "mmu.h"
37
38#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
39#define DRIVER_LICENSE "GPL"
40
41#define DRIVER_NAME "gma500"
42#define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650"
43#define DRIVER_DATE "20140314"
44
45#define DRIVER_MAJOR 1
46#define DRIVER_MINOR 0
47#define DRIVER_PATCHLEVEL 0
36 48
37/* Append new drm mode definition here, align with libdrm definition */ 49/* Append new drm mode definition here, align with libdrm definition */
38#define DRM_MODE_SCALE_NO_SCALE 2 50#define DRM_MODE_SCALE_NO_SCALE 2
@@ -49,21 +61,7 @@ enum {
49#define IS_MFLD(dev) (((dev)->pdev->device & 0xfff8) == 0x0130) 61#define IS_MFLD(dev) (((dev)->pdev->device & 0xfff8) == 0x0130)
50#define IS_CDV(dev) (((dev)->pdev->device & 0xfff0) == 0x0be0) 62#define IS_CDV(dev) (((dev)->pdev->device & 0xfff0) == 0x0be0)
51 63
52/* 64/* Hardware offsets */
53 * Driver definitions
54 */
55
56#define DRIVER_NAME "gma500"
57#define DRIVER_DESC "DRM driver for the Intel GMA500"
58
59#define PSB_DRM_DRIVER_DATE "2011-06-06"
60#define PSB_DRM_DRIVER_MAJOR 1
61#define PSB_DRM_DRIVER_MINOR 0
62#define PSB_DRM_DRIVER_PATCHLEVEL 0
63
64/*
65 * Hardware offsets
66 */
67#define PSB_VDC_OFFSET 0x00000000 65#define PSB_VDC_OFFSET 0x00000000
68#define PSB_VDC_SIZE 0x000080000 66#define PSB_VDC_SIZE 0x000080000
69#define MRST_MMIO_SIZE 0x0000C0000 67#define MRST_MMIO_SIZE 0x0000C0000
@@ -71,16 +69,14 @@ enum {
71#define PSB_SGX_SIZE 0x8000 69#define PSB_SGX_SIZE 0x8000
72#define PSB_SGX_OFFSET 0x00040000 70#define PSB_SGX_OFFSET 0x00040000
73#define MRST_SGX_OFFSET 0x00080000 71#define MRST_SGX_OFFSET 0x00080000
74/* 72
75 * PCI resource identifiers 73/* PCI resource identifiers */
76 */
77#define PSB_MMIO_RESOURCE 0 74#define PSB_MMIO_RESOURCE 0
78#define PSB_AUX_RESOURCE 0 75#define PSB_AUX_RESOURCE 0
79#define PSB_GATT_RESOURCE 2 76#define PSB_GATT_RESOURCE 2
80#define PSB_GTT_RESOURCE 3 77#define PSB_GTT_RESOURCE 3
81/* 78
82 * PCI configuration 79/* PCI configuration */
83 */
84#define PSB_GMCH_CTRL 0x52 80#define PSB_GMCH_CTRL 0x52
85#define PSB_BSM 0x5C 81#define PSB_BSM 0x5C
86#define _PSB_GMCH_ENABLED 0x4 82#define _PSB_GMCH_ENABLED 0x4
@@ -88,37 +84,29 @@ enum {
88#define _PSB_PGETBL_ENABLED 0x00000001 84#define _PSB_PGETBL_ENABLED 0x00000001
89#define PSB_SGX_2D_SLAVE_PORT 0x4000 85#define PSB_SGX_2D_SLAVE_PORT 0x4000
90 86
91/* To get rid of */ 87/* TODO: To get rid of */
92#define PSB_TT_PRIV0_LIMIT (256*1024*1024) 88#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
93#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) 89#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
94 90
95/* 91/* SGX side MMU definitions (these can probably go) */
96 * SGX side MMU definitions (these can probably go)
97 */
98 92
99/* 93/* Flags for external memory type field */
100 * Flags for external memory type field.
101 */
102#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ 94#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */
103#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ 95#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */
104#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ 96#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */
105/* 97
106 * PTE's and PDE's 98/* PTE's and PDE's */
107 */
108#define PSB_PDE_MASK 0x003FFFFF 99#define PSB_PDE_MASK 0x003FFFFF
109#define PSB_PDE_SHIFT 22 100#define PSB_PDE_SHIFT 22
110#define PSB_PTE_SHIFT 12 101#define PSB_PTE_SHIFT 12
111/* 102
112 * Cache control 103/* Cache control */
113 */
114#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */ 104#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */
115#define PSB_PTE_WO 0x0002 /* Write only */ 105#define PSB_PTE_WO 0x0002 /* Write only */
116#define PSB_PTE_RO 0x0004 /* Read only */ 106#define PSB_PTE_RO 0x0004 /* Read only */
117#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */ 107#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */
118 108
119/* 109/* VDC registers and bits */
120 * VDC registers and bits
121 */
122#define PSB_MSVDX_CLOCKGATING 0x2064 110#define PSB_MSVDX_CLOCKGATING 0x2064
123#define PSB_TOPAZ_CLOCKGATING 0x2068 111#define PSB_TOPAZ_CLOCKGATING 0x2068
124#define PSB_HWSTAM 0x2098 112#define PSB_HWSTAM 0x2098
@@ -265,6 +253,7 @@ struct psb_intel_opregion {
265 struct opregion_asle *asle; 253 struct opregion_asle *asle;
266 void *vbt; 254 void *vbt;
267 u32 __iomem *lid_state; 255 u32 __iomem *lid_state;
256 struct work_struct asle_work;
268}; 257};
269 258
270struct sdvo_device_mapping { 259struct sdvo_device_mapping {
@@ -283,10 +272,7 @@ struct intel_gmbus {
283 u32 reg0; 272 u32 reg0;
284}; 273};
285 274
286/* 275/* Register offset maps */
287 * Register offset maps
288 */
289
290struct psb_offset { 276struct psb_offset {
291 u32 fp0; 277 u32 fp0;
292 u32 fp1; 278 u32 fp1;
@@ -320,9 +306,7 @@ struct psb_offset {
320 * update the register cache instead. 306 * update the register cache instead.
321 */ 307 */
322 308
323/* 309/* Common status for pipes */
324 * Common status for pipes.
325 */
326struct psb_pipe { 310struct psb_pipe {
327 u32 fp0; 311 u32 fp0;
328 u32 fp1; 312 u32 fp1;
@@ -482,35 +466,24 @@ struct drm_psb_private {
482 struct psb_mmu_driver *mmu; 466 struct psb_mmu_driver *mmu;
483 struct psb_mmu_pd *pf_pd; 467 struct psb_mmu_pd *pf_pd;
484 468
485 /* 469 /* Register base */
486 * Register base
487 */
488
489 uint8_t __iomem *sgx_reg; 470 uint8_t __iomem *sgx_reg;
490 uint8_t __iomem *vdc_reg; 471 uint8_t __iomem *vdc_reg;
491 uint8_t __iomem *aux_reg; /* Auxillary vdc pipe regs */ 472 uint8_t __iomem *aux_reg; /* Auxillary vdc pipe regs */
492 uint32_t gatt_free_offset; 473 uint32_t gatt_free_offset;
493 474
494 /* 475 /* Fencing / irq */
495 * Fencing / irq.
496 */
497
498 uint32_t vdc_irq_mask; 476 uint32_t vdc_irq_mask;
499 uint32_t pipestat[PSB_NUM_PIPE]; 477 uint32_t pipestat[PSB_NUM_PIPE];
500 478
501 spinlock_t irqmask_lock; 479 spinlock_t irqmask_lock;
502 480
503 /* 481 /* Power */
504 * Power
505 */
506
507 bool suspended; 482 bool suspended;
508 bool display_power; 483 bool display_power;
509 int display_count; 484 int display_count;
510 485
511 /* 486 /* Modesetting */
512 * Modesetting
513 */
514 struct psb_intel_mode_device mode_dev; 487 struct psb_intel_mode_device mode_dev;
515 bool modeset; /* true if we have done the mode_device setup */ 488 bool modeset; /* true if we have done the mode_device setup */
516 489
@@ -518,15 +491,10 @@ struct drm_psb_private {
518 struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; 491 struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
519 uint32_t num_pipe; 492 uint32_t num_pipe;
520 493
521 /* 494 /* OSPM info (Power management base) (TODO: can go ?) */
522 * OSPM info (Power management base) (can go ?)
523 */
524 uint32_t ospm_base; 495 uint32_t ospm_base;
525 496
526 /* 497 /* Sizes info */
527 * Sizes info
528 */
529
530 u32 fuse_reg_value; 498 u32 fuse_reg_value;
531 u32 video_device_fuse; 499 u32 video_device_fuse;
532 500
@@ -546,9 +514,7 @@ struct drm_psb_private {
546 struct drm_property *broadcast_rgb_property; 514 struct drm_property *broadcast_rgb_property;
547 struct drm_property *force_audio_property; 515 struct drm_property *force_audio_property;
548 516
549 /* 517 /* LVDS info */
550 * LVDS info
551 */
552 int backlight_duty_cycle; /* restore backlight to this value */ 518 int backlight_duty_cycle; /* restore backlight to this value */
553 bool panel_wants_dither; 519 bool panel_wants_dither;
554 struct drm_display_mode *panel_fixed_mode; 520 struct drm_display_mode *panel_fixed_mode;
@@ -582,34 +548,23 @@ struct drm_psb_private {
582 /* Oaktrail HDMI state */ 548 /* Oaktrail HDMI state */
583 struct oaktrail_hdmi_dev *hdmi_priv; 549 struct oaktrail_hdmi_dev *hdmi_priv;
584 550
585 /* 551 /* Register state */
586 * Register state
587 */
588
589 struct psb_save_area regs; 552 struct psb_save_area regs;
590 553
591 /* MSI reg save */ 554 /* MSI reg save */
592 uint32_t msi_addr; 555 uint32_t msi_addr;
593 uint32_t msi_data; 556 uint32_t msi_data;
594 557
595 /* 558 /* Hotplug handling */
596 * Hotplug handling
597 */
598
599 struct work_struct hotplug_work; 559 struct work_struct hotplug_work;
600 560
601 /* 561 /* LID-Switch */
602 * LID-Switch
603 */
604 spinlock_t lid_lock; 562 spinlock_t lid_lock;
605 struct timer_list lid_timer; 563 struct timer_list lid_timer;
606 struct psb_intel_opregion opregion; 564 struct psb_intel_opregion opregion;
607 u32 lid_last_state; 565 u32 lid_last_state;
608 566
609 /* 567 /* Watchdog */
610 * Watchdog
611 */
612
613 uint32_t apm_reg; 568 uint32_t apm_reg;
614 uint16_t apm_base; 569 uint16_t apm_base;
615 570
@@ -629,9 +584,7 @@ struct drm_psb_private {
629 /* 2D acceleration */ 584 /* 2D acceleration */
630 spinlock_t lock_2d; 585 spinlock_t lock_2d;
631 586
632 /* 587 /* Panel brightness */
633 * Panel brightness
634 */
635 int brightness; 588 int brightness;
636 int brightness_adjusted; 589 int brightness_adjusted;
637 590
@@ -664,10 +617,7 @@ struct drm_psb_private {
664}; 617};
665 618
666 619
667/* 620/* Operations for each board type */
668 * Operations for each board type
669 */
670
671struct psb_ops { 621struct psb_ops {
672 const char *name; 622 const char *name;
673 unsigned int accel_2d:1; 623 unsigned int accel_2d:1;
@@ -713,8 +663,6 @@ struct psb_ops {
713 663
714 664
715 665
716struct psb_mmu_driver;
717
718extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); 666extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
719extern int drm_pick_crtcs(struct drm_device *dev); 667extern int drm_pick_crtcs(struct drm_device *dev);
720 668
@@ -723,52 +671,7 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
723 return (struct drm_psb_private *) dev->dev_private; 671 return (struct drm_psb_private *) dev->dev_private;
724} 672}
725 673
726/* 674/* psb_irq.c */
727 * MMU stuff.
728 */
729
730extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
731 int trap_pagefaults,
732 int invalid_type,
733 struct drm_psb_private *dev_priv);
734extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
735extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
736 *driver);
737extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
738 uint32_t gtt_start, uint32_t gtt_pages);
739extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
740 int trap_pagefaults,
741 int invalid_type);
742extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
743extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
744extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
745 unsigned long address,
746 uint32_t num_pages);
747extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
748 uint32_t start_pfn,
749 unsigned long address,
750 uint32_t num_pages, int type);
751extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
752 unsigned long *pfn);
753
754/*
755 * Enable / disable MMU for different requestors.
756 */
757
758
759extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
760extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
761 unsigned long address, uint32_t num_pages,
762 uint32_t desired_tile_stride,
763 uint32_t hw_tile_stride, int type);
764extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
765 unsigned long address, uint32_t num_pages,
766 uint32_t desired_tile_stride,
767 uint32_t hw_tile_stride);
768/*
769 *psb_irq.c
770 */
771
772extern irqreturn_t psb_irq_handler(int irq, void *arg); 675extern irqreturn_t psb_irq_handler(int irq, void *arg);
773extern int psb_irq_enable_dpst(struct drm_device *dev); 676extern int psb_irq_enable_dpst(struct drm_device *dev);
774extern int psb_irq_disable_dpst(struct drm_device *dev); 677extern int psb_irq_disable_dpst(struct drm_device *dev);
@@ -791,24 +694,17 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
791 694
792extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); 695extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
793 696
794/* 697/* framebuffer.c */
795 * framebuffer.c
796 */
797extern int psbfb_probed(struct drm_device *dev); 698extern int psbfb_probed(struct drm_device *dev);
798extern int psbfb_remove(struct drm_device *dev, 699extern int psbfb_remove(struct drm_device *dev,
799 struct drm_framebuffer *fb); 700 struct drm_framebuffer *fb);
800/* 701/* accel_2d.c */
801 * accel_2d.c
802 */
803extern void psbfb_copyarea(struct fb_info *info, 702extern void psbfb_copyarea(struct fb_info *info,
804 const struct fb_copyarea *region); 703 const struct fb_copyarea *region);
805extern int psbfb_sync(struct fb_info *info); 704extern int psbfb_sync(struct fb_info *info);
806extern void psb_spank(struct drm_psb_private *dev_priv); 705extern void psb_spank(struct drm_psb_private *dev_priv);
807 706
808/* 707/* psb_reset.c */
809 * psb_reset.c
810 */
811
812extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); 708extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
813extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); 709extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
814extern void psb_print_pagefault(struct drm_psb_private *dev_priv); 710extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
@@ -867,9 +763,7 @@ extern const struct psb_ops mdfld_chip_ops;
867/* cdv_device.c */ 763/* cdv_device.c */
868extern const struct psb_ops cdv_chip_ops; 764extern const struct psb_ops cdv_chip_ops;
869 765
870/* 766/* Debug print bits setting */
871 * Debug print bits setting
872 */
873#define PSB_D_GENERAL (1 << 0) 767#define PSB_D_GENERAL (1 << 0)
874#define PSB_D_INIT (1 << 1) 768#define PSB_D_INIT (1 << 1)
875#define PSB_D_IRQ (1 << 2) 769#define PSB_D_IRQ (1 << 2)
@@ -885,10 +779,7 @@ extern const struct psb_ops cdv_chip_ops;
885 779
886extern int drm_idle_check_interval; 780extern int drm_idle_check_interval;
887 781
888/* 782/* Utilities */
889 * Utilities
890 */
891
892static inline u32 MRST_MSG_READ32(uint port, uint offset) 783static inline u32 MRST_MSG_READ32(uint port, uint offset)
893{ 784{
894 int mcr = (0xD0<<24) | (port << 16) | (offset << 8); 785 int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index c8841ac6c8f1..87b50ba64ed4 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -120,7 +120,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
120 const struct gma_limit_t *limit; 120 const struct gma_limit_t *limit;
121 121
122 /* No scan out no play */ 122 /* No scan out no play */
123 if (crtc->fb == NULL) { 123 if (crtc->primary->fb == NULL) {
124 crtc_funcs->mode_set_base(crtc, x, y, old_fb); 124 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
125 return 0; 125 return 0;
126 } 126 }
@@ -469,7 +469,8 @@ static void psb_intel_cursor_init(struct drm_device *dev,
469 /* Allocate 4 pages of stolen mem for a hardware cursor. That 469 /* Allocate 4 pages of stolen mem for a hardware cursor. That
470 * is enough for the 64 x 64 ARGB cursors we support. 470 * is enough for the 64 x 64 ARGB cursors we support.
471 */ 471 */
472 cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1); 472 cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1,
473 PAGE_SIZE);
473 if (!cursor_gt) { 474 if (!cursor_gt) {
474 gma_crtc->cursor_gt = NULL; 475 gma_crtc->cursor_gt = NULL;
475 goto out; 476 goto out;
@@ -554,33 +555,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
554 gma_crtc->active = true; 555 gma_crtc->active = true;
555} 556}
556 557
557int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
558 struct drm_file *file_priv)
559{
560 struct drm_psb_private *dev_priv = dev->dev_private;
561 struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
562 struct drm_mode_object *drmmode_obj;
563 struct gma_crtc *crtc;
564
565 if (!dev_priv) {
566 dev_err(dev->dev, "called with no initialization\n");
567 return -EINVAL;
568 }
569
570 drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
571 DRM_MODE_OBJECT_CRTC);
572
573 if (!drmmode_obj) {
574 dev_err(dev->dev, "no such CRTC id\n");
575 return -ENOENT;
576 }
577
578 crtc = to_gma_crtc(obj_to_crtc(drmmode_obj));
579 pipe_from_crtc_id->pipe = crtc->pipe;
580
581 return 0;
582}
583
584struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) 558struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
585{ 559{
586 struct drm_crtc *crtc = NULL; 560 struct drm_crtc *crtc = NULL;
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index dc2c8eb030fa..336bd3aa1a06 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -238,8 +238,6 @@ static inline struct gma_encoder *gma_attached_encoder(
238 238
239extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, 239extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
240 struct drm_crtc *crtc); 240 struct drm_crtc *crtc);
241extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
242 struct drm_file *file_priv);
243extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, 241extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
244 int pipe); 242 int pipe);
245extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, 243extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 32342f6990d9..d7778d0472c1 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -614,7 +614,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
614 &crtc->saved_mode, 614 &crtc->saved_mode,
615 encoder->crtc->x, 615 encoder->crtc->x,
616 encoder->crtc->y, 616 encoder->crtc->y,
617 encoder->crtc->fb)) 617 encoder->crtc->primary->fb))
618 goto set_prop_error; 618 goto set_prop_error;
619 } 619 }
620 } else if (!strcmp(property->name, "backlight")) { 620 } else if (!strcmp(property->name, "backlight")) {
@@ -777,6 +777,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
777 * Attempt to get the fixed panel mode from DDC. Assume that the 777 * Attempt to get the fixed panel mode from DDC. Assume that the
778 * preferred mode is the right one. 778 * preferred mode is the right one.
779 */ 779 */
780 mutex_lock(&dev->mode_config.mutex);
780 psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter); 781 psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter);
781 list_for_each_entry(scan, &connector->probed_modes, head) { 782 list_for_each_entry(scan, &connector->probed_modes, head) {
782 if (scan->type & DRM_MODE_TYPE_PREFERRED) { 783 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
@@ -827,10 +828,12 @@ void psb_intel_lvds_init(struct drm_device *dev,
827 * actually having one. 828 * actually having one.
828 */ 829 */
829out: 830out:
831 mutex_unlock(&dev->mode_config.mutex);
830 drm_sysfs_connector_add(connector); 832 drm_sysfs_connector_add(connector);
831 return; 833 return;
832 834
833failed_find: 835failed_find:
836 mutex_unlock(&dev->mode_config.mutex);
834 if (lvds_priv->ddc_bus) 837 if (lvds_priv->ddc_bus)
835 psb_intel_i2c_destroy(lvds_priv->ddc_bus); 838 psb_intel_i2c_destroy(lvds_priv->ddc_bus);
836failed_ddc: 839failed_ddc:
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 07d3a9e6d79b..deeb0829b129 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -406,18 +406,18 @@ static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8
406 DRM_DEBUG_KMS("%s: W: %02X ", 406 DRM_DEBUG_KMS("%s: W: %02X ",
407 SDVO_NAME(psb_intel_sdvo), cmd); 407 SDVO_NAME(psb_intel_sdvo), cmd);
408 for (i = 0; i < args_len; i++) 408 for (i = 0; i < args_len; i++)
409 DRM_LOG_KMS("%02X ", ((u8 *)args)[i]); 409 DRM_DEBUG_KMS("%02X ", ((u8 *)args)[i]);
410 for (; i < 8; i++) 410 for (; i < 8; i++)
411 DRM_LOG_KMS(" "); 411 DRM_DEBUG_KMS(" ");
412 for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { 412 for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
413 if (cmd == sdvo_cmd_names[i].cmd) { 413 if (cmd == sdvo_cmd_names[i].cmd) {
414 DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name); 414 DRM_DEBUG_KMS("(%s)", sdvo_cmd_names[i].name);
415 break; 415 break;
416 } 416 }
417 } 417 }
418 if (i == ARRAY_SIZE(sdvo_cmd_names)) 418 if (i == ARRAY_SIZE(sdvo_cmd_names))
419 DRM_LOG_KMS("(%02X)", cmd); 419 DRM_DEBUG_KMS("(%02X)", cmd);
420 DRM_LOG_KMS("\n"); 420 DRM_DEBUG_KMS("\n");
421} 421}
422 422
423static const char *cmd_status_names[] = { 423static const char *cmd_status_names[] = {
@@ -512,9 +512,9 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
512 } 512 }
513 513
514 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) 514 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
515 DRM_LOG_KMS("(%s)", cmd_status_names[status]); 515 DRM_DEBUG_KMS("(%s)", cmd_status_names[status]);
516 else 516 else
517 DRM_LOG_KMS("(??? %d)", status); 517 DRM_DEBUG_KMS("(??? %d)", status);
518 518
519 if (status != SDVO_CMD_STATUS_SUCCESS) 519 if (status != SDVO_CMD_STATUS_SUCCESS)
520 goto log_fail; 520 goto log_fail;
@@ -525,13 +525,13 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
525 SDVO_I2C_RETURN_0 + i, 525 SDVO_I2C_RETURN_0 + i,
526 &((u8 *)response)[i])) 526 &((u8 *)response)[i]))
527 goto log_fail; 527 goto log_fail;
528 DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); 528 DRM_DEBUG_KMS(" %02X", ((u8 *)response)[i]);
529 } 529 }
530 DRM_LOG_KMS("\n"); 530 DRM_DEBUG_KMS("\n");
531 return true; 531 return true;
532 532
533log_fail: 533log_fail:
534 DRM_LOG_KMS("... failed\n"); 534 DRM_DEBUG_KMS("... failed\n");
535 return false; 535 return false;
536} 536}
537 537
@@ -1844,7 +1844,7 @@ done:
1844 if (psb_intel_sdvo->base.base.crtc) { 1844 if (psb_intel_sdvo->base.base.crtc) {
1845 struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc; 1845 struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
1846 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, 1846 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
1847 crtc->y, crtc->fb); 1847 crtc->y, crtc->primary->fb);
1848 } 1848 }
1849 1849
1850 return 0; 1850 return 0;
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index f883f9e4c524..624eb36511c5 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -200,11 +200,64 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
200 mid_pipe_event_handler(dev, 1); 200 mid_pipe_event_handler(dev, 1);
201} 201}
202 202
203/*
204 * SGX interrupt handler
205 */
206static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2)
207{
208 struct drm_psb_private *dev_priv = dev->dev_private;
209 u32 val, addr;
210 int error = false;
211
212 if (stat_1 & _PSB_CE_TWOD_COMPLETE)
213 val = PSB_RSGX32(PSB_CR_2D_BLIT_STATUS);
214
215 if (stat_2 & _PSB_CE2_BIF_REQUESTER_FAULT) {
216 val = PSB_RSGX32(PSB_CR_BIF_INT_STAT);
217 addr = PSB_RSGX32(PSB_CR_BIF_FAULT);
218 if (val) {
219 if (val & _PSB_CBI_STAT_PF_N_RW)
220 DRM_ERROR("SGX MMU page fault:");
221 else
222 DRM_ERROR("SGX MMU read / write protection fault:");
223
224 if (val & _PSB_CBI_STAT_FAULT_CACHE)
225 DRM_ERROR("\tCache requestor");
226 if (val & _PSB_CBI_STAT_FAULT_TA)
227 DRM_ERROR("\tTA requestor");
228 if (val & _PSB_CBI_STAT_FAULT_VDM)
229 DRM_ERROR("\tVDM requestor");
230 if (val & _PSB_CBI_STAT_FAULT_2D)
231 DRM_ERROR("\t2D requestor");
232 if (val & _PSB_CBI_STAT_FAULT_PBE)
233 DRM_ERROR("\tPBE requestor");
234 if (val & _PSB_CBI_STAT_FAULT_TSP)
235 DRM_ERROR("\tTSP requestor");
236 if (val & _PSB_CBI_STAT_FAULT_ISP)
237 DRM_ERROR("\tISP requestor");
238 if (val & _PSB_CBI_STAT_FAULT_USSEPDS)
239 DRM_ERROR("\tUSSEPDS requestor");
240 if (val & _PSB_CBI_STAT_FAULT_HOST)
241 DRM_ERROR("\tHost requestor");
242
243 DRM_ERROR("\tMMU failing address is 0x%08x.\n",
244 (unsigned int)addr);
245 error = true;
246 }
247 }
248
249 /* Clear bits */
250 PSB_WSGX32(stat_1, PSB_CR_EVENT_HOST_CLEAR);
251 PSB_WSGX32(stat_2, PSB_CR_EVENT_HOST_CLEAR2);
252 PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2);
253}
254
203irqreturn_t psb_irq_handler(int irq, void *arg) 255irqreturn_t psb_irq_handler(int irq, void *arg)
204{ 256{
205 struct drm_device *dev = arg; 257 struct drm_device *dev = arg;
206 struct drm_psb_private *dev_priv = dev->dev_private; 258 struct drm_psb_private *dev_priv = dev->dev_private;
207 uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; 259 uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0;
260 u32 sgx_stat_1, sgx_stat_2;
208 int handled = 0; 261 int handled = 0;
209 262
210 spin_lock(&dev_priv->irqmask_lock); 263 spin_lock(&dev_priv->irqmask_lock);
@@ -233,14 +286,9 @@ irqreturn_t psb_irq_handler(int irq, void *arg)
233 } 286 }
234 287
235 if (sgx_int) { 288 if (sgx_int) {
236 /* Not expected - we have it masked, shut it up */ 289 sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS);
237 u32 s, s2; 290 sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
238 s = PSB_RSGX32(PSB_CR_EVENT_STATUS); 291 psb_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2);
239 s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
240 PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
241 PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
242 /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
243 we may as well poll even if we add that ! */
244 handled = 1; 292 handled = 1;
245 } 293 }
246 294
@@ -269,8 +317,13 @@ void psb_irq_preinstall(struct drm_device *dev)
269 317
270 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 318 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
271 319
272 if (gma_power_is_on(dev)) 320 if (gma_power_is_on(dev)) {
273 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); 321 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
322 PSB_WVDC32(0x00000000, PSB_INT_MASK_R);
323 PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
324 PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
325 PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);
326 }
274 if (dev->vblank[0].enabled) 327 if (dev->vblank[0].enabled)
275 dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; 328 dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
276 if (dev->vblank[1].enabled) 329 if (dev->vblank[1].enabled)
@@ -286,7 +339,7 @@ void psb_irq_preinstall(struct drm_device *dev)
286 /* Revisit this area - want per device masks ? */ 339 /* Revisit this area - want per device masks ? */
287 if (dev_priv->ops->hotplug) 340 if (dev_priv->ops->hotplug)
288 dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; 341 dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC;
289 dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE; 342 dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE | _PSB_IRQ_SGX_FLAG;
290 343
291 /* This register is safe even if display island is off */ 344 /* This register is safe even if display island is off */
292 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); 345 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
@@ -295,12 +348,16 @@ void psb_irq_preinstall(struct drm_device *dev)
295 348
296int psb_irq_postinstall(struct drm_device *dev) 349int psb_irq_postinstall(struct drm_device *dev)
297{ 350{
298 struct drm_psb_private *dev_priv = 351 struct drm_psb_private *dev_priv = dev->dev_private;
299 (struct drm_psb_private *) dev->dev_private;
300 unsigned long irqflags; 352 unsigned long irqflags;
301 353
302 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 354 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
303 355
356 /* Enable 2D and MMU fault interrupts */
357 PSB_WSGX32(_PSB_CE2_BIF_REQUESTER_FAULT, PSB_CR_EVENT_HOST_ENABLE2);
358 PSB_WSGX32(_PSB_CE_TWOD_COMPLETE, PSB_CR_EVENT_HOST_ENABLE);
359 PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /* Post */
360
304 /* This register is safe even if display island is off */ 361 /* This register is safe even if display island is off */
305 PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); 362 PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
306 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); 363 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index af42e94f6846..a0f5bdd69491 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -340,9 +340,9 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
340 for (i = 0; i < CH7xxx_NUM_REGS; i++) { 340 for (i = 0; i < CH7xxx_NUM_REGS; i++) {
341 uint8_t val; 341 uint8_t val;
342 if ((i % 8) == 0) 342 if ((i % 8) == 0)
343 DRM_LOG_KMS("\n %02X: ", i); 343 DRM_DEBUG_KMS("\n %02X: ", i);
344 ch7xxx_readb(dvo, i, &val); 344 ch7xxx_readb(dvo, i, &val);
345 DRM_LOG_KMS("%02X ", val); 345 DRM_DEBUG_KMS("%02X ", val);
346 } 346 }
347} 347}
348 348
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index baaf65bf0bdd..0f1865d7d4d8 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -377,41 +377,41 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo)
377 uint16_t val; 377 uint16_t val;
378 378
379 ivch_read(dvo, VR00, &val); 379 ivch_read(dvo, VR00, &val);
380 DRM_LOG_KMS("VR00: 0x%04x\n", val); 380 DRM_DEBUG_KMS("VR00: 0x%04x\n", val);
381 ivch_read(dvo, VR01, &val); 381 ivch_read(dvo, VR01, &val);
382 DRM_LOG_KMS("VR01: 0x%04x\n", val); 382 DRM_DEBUG_KMS("VR01: 0x%04x\n", val);
383 ivch_read(dvo, VR30, &val); 383 ivch_read(dvo, VR30, &val);
384 DRM_LOG_KMS("VR30: 0x%04x\n", val); 384 DRM_DEBUG_KMS("VR30: 0x%04x\n", val);
385 ivch_read(dvo, VR40, &val); 385 ivch_read(dvo, VR40, &val);
386 DRM_LOG_KMS("VR40: 0x%04x\n", val); 386 DRM_DEBUG_KMS("VR40: 0x%04x\n", val);
387 387
388 /* GPIO registers */ 388 /* GPIO registers */
389 ivch_read(dvo, VR80, &val); 389 ivch_read(dvo, VR80, &val);
390 DRM_LOG_KMS("VR80: 0x%04x\n", val); 390 DRM_DEBUG_KMS("VR80: 0x%04x\n", val);
391 ivch_read(dvo, VR81, &val); 391 ivch_read(dvo, VR81, &val);
392 DRM_LOG_KMS("VR81: 0x%04x\n", val); 392 DRM_DEBUG_KMS("VR81: 0x%04x\n", val);
393 ivch_read(dvo, VR82, &val); 393 ivch_read(dvo, VR82, &val);
394 DRM_LOG_KMS("VR82: 0x%04x\n", val); 394 DRM_DEBUG_KMS("VR82: 0x%04x\n", val);
395 ivch_read(dvo, VR83, &val); 395 ivch_read(dvo, VR83, &val);
396 DRM_LOG_KMS("VR83: 0x%04x\n", val); 396 DRM_DEBUG_KMS("VR83: 0x%04x\n", val);
397 ivch_read(dvo, VR84, &val); 397 ivch_read(dvo, VR84, &val);
398 DRM_LOG_KMS("VR84: 0x%04x\n", val); 398 DRM_DEBUG_KMS("VR84: 0x%04x\n", val);
399 ivch_read(dvo, VR85, &val); 399 ivch_read(dvo, VR85, &val);
400 DRM_LOG_KMS("VR85: 0x%04x\n", val); 400 DRM_DEBUG_KMS("VR85: 0x%04x\n", val);
401 ivch_read(dvo, VR86, &val); 401 ivch_read(dvo, VR86, &val);
402 DRM_LOG_KMS("VR86: 0x%04x\n", val); 402 DRM_DEBUG_KMS("VR86: 0x%04x\n", val);
403 ivch_read(dvo, VR87, &val); 403 ivch_read(dvo, VR87, &val);
404 DRM_LOG_KMS("VR87: 0x%04x\n", val); 404 DRM_DEBUG_KMS("VR87: 0x%04x\n", val);
405 ivch_read(dvo, VR88, &val); 405 ivch_read(dvo, VR88, &val);
406 DRM_LOG_KMS("VR88: 0x%04x\n", val); 406 DRM_DEBUG_KMS("VR88: 0x%04x\n", val);
407 407
408 /* Scratch register 0 - AIM Panel type */ 408 /* Scratch register 0 - AIM Panel type */
409 ivch_read(dvo, VR8E, &val); 409 ivch_read(dvo, VR8E, &val);
410 DRM_LOG_KMS("VR8E: 0x%04x\n", val); 410 DRM_DEBUG_KMS("VR8E: 0x%04x\n", val);
411 411
412 /* Scratch register 1 - Status register */ 412 /* Scratch register 1 - Status register */
413 ivch_read(dvo, VR8F, &val); 413 ivch_read(dvo, VR8F, &val);
414 DRM_LOG_KMS("VR8F: 0x%04x\n", val); 414 DRM_DEBUG_KMS("VR8F: 0x%04x\n", val);
415} 415}
416 416
417static void ivch_destroy(struct intel_dvo_device *dvo) 417static void ivch_destroy(struct intel_dvo_device *dvo)
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
index 954acb2c7021..8155ded79079 100644
--- a/drivers/gpu/drm/i915/dvo_ns2501.c
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -490,15 +490,15 @@ static void ns2501_dump_regs(struct intel_dvo_device *dvo)
490 uint8_t val; 490 uint8_t val;
491 491
492 ns2501_readb(dvo, NS2501_FREQ_LO, &val); 492 ns2501_readb(dvo, NS2501_FREQ_LO, &val);
493 DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val); 493 DRM_DEBUG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
494 ns2501_readb(dvo, NS2501_FREQ_HI, &val); 494 ns2501_readb(dvo, NS2501_FREQ_HI, &val);
495 DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val); 495 DRM_DEBUG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
496 ns2501_readb(dvo, NS2501_REG8, &val); 496 ns2501_readb(dvo, NS2501_REG8, &val);
497 DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val); 497 DRM_DEBUG_KMS("NS2501_REG8: 0x%02x\n", val);
498 ns2501_readb(dvo, NS2501_REG9, &val); 498 ns2501_readb(dvo, NS2501_REG9, &val);
499 DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val); 499 DRM_DEBUG_KMS("NS2501_REG9: 0x%02x\n", val);
500 ns2501_readb(dvo, NS2501_REGC, &val); 500 ns2501_readb(dvo, NS2501_REGC, &val);
501 DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val); 501 DRM_DEBUG_KMS("NS2501_REGC: 0x%02x\n", val);
502} 502}
503 503
504static void ns2501_destroy(struct intel_dvo_device *dvo) 504static void ns2501_destroy(struct intel_dvo_device *dvo)
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index 4debd32e3e4c..7b3e9e936200 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -246,15 +246,15 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo)
246 uint8_t val; 246 uint8_t val;
247 247
248 sil164_readb(dvo, SIL164_FREQ_LO, &val); 248 sil164_readb(dvo, SIL164_FREQ_LO, &val);
249 DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val); 249 DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
250 sil164_readb(dvo, SIL164_FREQ_HI, &val); 250 sil164_readb(dvo, SIL164_FREQ_HI, &val);
251 DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val); 251 DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
252 sil164_readb(dvo, SIL164_REG8, &val); 252 sil164_readb(dvo, SIL164_REG8, &val);
253 DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val); 253 DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val);
254 sil164_readb(dvo, SIL164_REG9, &val); 254 sil164_readb(dvo, SIL164_REG9, &val);
255 DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val); 255 DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val);
256 sil164_readb(dvo, SIL164_REGC, &val); 256 sil164_readb(dvo, SIL164_REGC, &val);
257 DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val); 257 DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val);
258} 258}
259 259
260static void sil164_destroy(struct intel_dvo_device *dvo) 260static void sil164_destroy(struct intel_dvo_device *dvo)
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index e17f1b07e915..12ea4b164692 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -267,33 +267,33 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo)
267 uint8_t val, val2; 267 uint8_t val, val2;
268 268
269 tfp410_readb(dvo, TFP410_REV, &val); 269 tfp410_readb(dvo, TFP410_REV, &val);
270 DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val); 270 DRM_DEBUG_KMS("TFP410_REV: 0x%02X\n", val);
271 tfp410_readb(dvo, TFP410_CTL_1, &val); 271 tfp410_readb(dvo, TFP410_CTL_1, &val);
272 DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val); 272 DRM_DEBUG_KMS("TFP410_CTL1: 0x%02X\n", val);
273 tfp410_readb(dvo, TFP410_CTL_2, &val); 273 tfp410_readb(dvo, TFP410_CTL_2, &val);
274 DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val); 274 DRM_DEBUG_KMS("TFP410_CTL2: 0x%02X\n", val);
275 tfp410_readb(dvo, TFP410_CTL_3, &val); 275 tfp410_readb(dvo, TFP410_CTL_3, &val);
276 DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val); 276 DRM_DEBUG_KMS("TFP410_CTL3: 0x%02X\n", val);
277 tfp410_readb(dvo, TFP410_USERCFG, &val); 277 tfp410_readb(dvo, TFP410_USERCFG, &val);
278 DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val); 278 DRM_DEBUG_KMS("TFP410_USERCFG: 0x%02X\n", val);
279 tfp410_readb(dvo, TFP410_DE_DLY, &val); 279 tfp410_readb(dvo, TFP410_DE_DLY, &val);
280 DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val); 280 DRM_DEBUG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
281 tfp410_readb(dvo, TFP410_DE_CTL, &val); 281 tfp410_readb(dvo, TFP410_DE_CTL, &val);
282 DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val); 282 DRM_DEBUG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
283 tfp410_readb(dvo, TFP410_DE_TOP, &val); 283 tfp410_readb(dvo, TFP410_DE_TOP, &val);
284 DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val); 284 DRM_DEBUG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
285 tfp410_readb(dvo, TFP410_DE_CNT_LO, &val); 285 tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
286 tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2); 286 tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
287 DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); 287 DRM_DEBUG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
288 tfp410_readb(dvo, TFP410_DE_LIN_LO, &val); 288 tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
289 tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2); 289 tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
290 DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); 290 DRM_DEBUG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
291 tfp410_readb(dvo, TFP410_H_RES_LO, &val); 291 tfp410_readb(dvo, TFP410_H_RES_LO, &val);
292 tfp410_readb(dvo, TFP410_H_RES_HI, &val2); 292 tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
293 DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val); 293 DRM_DEBUG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
294 tfp410_readb(dvo, TFP410_V_RES_LO, &val); 294 tfp410_readb(dvo, TFP410_V_RES_LO, &val);
295 tfp410_readb(dvo, TFP410_V_RES_HI, &val2); 295 tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
296 DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val); 296 DRM_DEBUG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
297} 297}
298 298
299static void tfp410_destroy(struct intel_dvo_device *dvo) 299static void tfp410_destroy(struct intel_dvo_device *dvo)
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 0eaed44aee6d..4cf6d020d513 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -405,7 +405,7 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
405 DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n", 405 DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n",
406 *cmd, 406 *cmd,
407 length, 407 length,
408 batch_end - cmd); 408 (unsigned long)(batch_end - cmd));
409 ret = -EINVAL; 409 ret = -EINVAL;
410 break; 410 break;
411 } 411 }
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b27b7a5244b1..195fe5bc0aac 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2203,8 +2203,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
2203 struct intel_encoder *intel_encoder; 2203 struct intel_encoder *intel_encoder;
2204 2204
2205 seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", 2205 seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
2206 crtc->fb->base.id, crtc->x, crtc->y, 2206 crtc->primary->fb->base.id, crtc->x, crtc->y,
2207 crtc->fb->width, crtc->fb->height); 2207 crtc->primary->fb->width, crtc->primary->fb->height);
2208 for_each_encoder_on_crtc(dev, crtc, intel_encoder) 2208 for_each_encoder_on_crtc(dev, crtc, intel_encoder)
2209 intel_encoder_info(m, intel_crtc, intel_encoder); 2209 intel_encoder_info(m, intel_crtc, intel_encoder);
2210} 2210}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c70121dbce78..6370a761d137 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3264,7 +3264,8 @@ search_free:
3264 ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, 3264 ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
3265 size, alignment, 3265 size, alignment,
3266 obj->cache_level, 0, gtt_max, 3266 obj->cache_level, 0, gtt_max,
3267 DRM_MM_SEARCH_DEFAULT); 3267 DRM_MM_SEARCH_DEFAULT,
3268 DRM_MM_CREATE_DEFAULT);
3268 if (ret) { 3269 if (ret) {
3269 ret = i915_gem_evict_something(dev, vm, size, alignment, 3270 ret = i915_gem_evict_something(dev, vm, size, alignment,
3270 obj->cache_level, flags); 3271 obj->cache_level, flags);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 3b1f621f1009..ab5e93c30aa2 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1074,7 +1074,8 @@ alloc:
1074 &ppgtt->node, GEN6_PD_SIZE, 1074 &ppgtt->node, GEN6_PD_SIZE,
1075 GEN6_PD_ALIGN, 0, 1075 GEN6_PD_ALIGN, 0,
1076 0, dev_priv->gtt.base.total, 1076 0, dev_priv->gtt.base.total,
1077 DRM_MM_SEARCH_DEFAULT); 1077 DRM_MM_SEARCH_DEFAULT,
1078 DRM_MM_CREATE_DEFAULT);
1078 if (ret == -ENOSPC && !retried) { 1079 if (ret == -ENOSPC && !retried) {
1079 ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, 1080 ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
1080 GEN6_PD_SIZE, GEN6_PD_ALIGN, 1081 GEN6_PD_SIZE, GEN6_PD_ALIGN,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 26f217d63a3c..7753249b3a95 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2343,8 +2343,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
2343 } else { 2343 } else {
2344 int dspaddr = DSPADDR(intel_crtc->plane); 2344 int dspaddr = DSPADDR(intel_crtc->plane);
2345 stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) + 2345 stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
2346 crtc->y * crtc->fb->pitches[0] + 2346 crtc->y * crtc->primary->fb->pitches[0] +
2347 crtc->x * crtc->fb->bits_per_pixel/8); 2347 crtc->x * crtc->primary->fb->bits_per_pixel/8);
2348 } 2348 }
2349 2349
2350 spin_unlock_irqrestore(&dev->event_lock, flags); 2350 spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c31c6203c7ca..dae976f51d83 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -741,10 +741,10 @@ bool intel_crtc_active(struct drm_crtc *crtc)
741 * We can ditch the adjusted_mode.crtc_clock check as soon 741 * We can ditch the adjusted_mode.crtc_clock check as soon
742 * as Haswell has gained clock readout/fastboot support. 742 * as Haswell has gained clock readout/fastboot support.
743 * 743 *
744 * We can ditch the crtc->fb check as soon as we can 744 * We can ditch the crtc->primary->fb check as soon as we can
745 * properly reconstruct framebuffers. 745 * properly reconstruct framebuffers.
746 */ 746 */
747 return intel_crtc->active && crtc->fb && 747 return intel_crtc->active && crtc->primary->fb &&
748 intel_crtc->config.adjusted_mode.crtc_clock; 748 intel_crtc->config.adjusted_mode.crtc_clock;
749} 749}
750 750
@@ -2086,17 +2086,17 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
2086 2086
2087 if (plane_config->tiled) { 2087 if (plane_config->tiled) {
2088 obj->tiling_mode = I915_TILING_X; 2088 obj->tiling_mode = I915_TILING_X;
2089 obj->stride = crtc->base.fb->pitches[0]; 2089 obj->stride = crtc->base.primary->fb->pitches[0];
2090 } 2090 }
2091 2091
2092 mode_cmd.pixel_format = crtc->base.fb->pixel_format; 2092 mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
2093 mode_cmd.width = crtc->base.fb->width; 2093 mode_cmd.width = crtc->base.primary->fb->width;
2094 mode_cmd.height = crtc->base.fb->height; 2094 mode_cmd.height = crtc->base.primary->fb->height;
2095 mode_cmd.pitches[0] = crtc->base.fb->pitches[0]; 2095 mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
2096 2096
2097 mutex_lock(&dev->struct_mutex); 2097 mutex_lock(&dev->struct_mutex);
2098 2098
2099 if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb), 2099 if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.primary->fb),
2100 &mode_cmd, obj)) { 2100 &mode_cmd, obj)) {
2101 DRM_DEBUG_KMS("intel fb init failed\n"); 2101 DRM_DEBUG_KMS("intel fb init failed\n");
2102 goto out_unref_obj; 2102 goto out_unref_obj;
@@ -2121,14 +2121,14 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
2121 struct intel_crtc *i; 2121 struct intel_crtc *i;
2122 struct intel_framebuffer *fb; 2122 struct intel_framebuffer *fb;
2123 2123
2124 if (!intel_crtc->base.fb) 2124 if (!intel_crtc->base.primary->fb)
2125 return; 2125 return;
2126 2126
2127 if (intel_alloc_plane_obj(intel_crtc, plane_config)) 2127 if (intel_alloc_plane_obj(intel_crtc, plane_config))
2128 return; 2128 return;
2129 2129
2130 kfree(intel_crtc->base.fb); 2130 kfree(intel_crtc->base.primary->fb);
2131 intel_crtc->base.fb = NULL; 2131 intel_crtc->base.primary->fb = NULL;
2132 2132
2133 /* 2133 /*
2134 * Failed to alloc the obj, check to see if we should share 2134 * Failed to alloc the obj, check to see if we should share
@@ -2140,13 +2140,13 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
2140 if (c == &intel_crtc->base) 2140 if (c == &intel_crtc->base)
2141 continue; 2141 continue;
2142 2142
2143 if (!i->active || !c->fb) 2143 if (!i->active || !c->primary->fb)
2144 continue; 2144 continue;
2145 2145
2146 fb = to_intel_framebuffer(c->fb); 2146 fb = to_intel_framebuffer(c->primary->fb);
2147 if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) { 2147 if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
2148 drm_framebuffer_reference(c->fb); 2148 drm_framebuffer_reference(c->primary->fb);
2149 intel_crtc->base.fb = c->fb; 2149 intel_crtc->base.primary->fb = c->primary->fb;
2150 break; 2150 break;
2151 } 2151 }
2152 } 2152 }
@@ -2396,11 +2396,11 @@ void intel_display_handle_reset(struct drm_device *dev)
2396 /* 2396 /*
2397 * FIXME: Once we have proper support for primary planes (and 2397 * FIXME: Once we have proper support for primary planes (and
2398 * disabling them without disabling the entire crtc) allow again 2398 * disabling them without disabling the entire crtc) allow again
2399 * a NULL crtc->fb. 2399 * a NULL crtc->primary->fb.
2400 */ 2400 */
2401 if (intel_crtc->active && crtc->fb) 2401 if (intel_crtc->active && crtc->primary->fb)
2402 dev_priv->display.update_primary_plane(crtc, 2402 dev_priv->display.update_primary_plane(crtc,
2403 crtc->fb, 2403 crtc->primary->fb,
2404 crtc->x, 2404 crtc->x,
2405 crtc->y); 2405 crtc->y);
2406 mutex_unlock(&crtc->mutex); 2406 mutex_unlock(&crtc->mutex);
@@ -2527,8 +2527,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
2527 return ret; 2527 return ret;
2528 } 2528 }
2529 2529
2530 old_fb = crtc->fb; 2530 old_fb = crtc->primary->fb;
2531 crtc->fb = fb; 2531 crtc->primary->fb = fb;
2532 crtc->x = x; 2532 crtc->x = x;
2533 crtc->y = y; 2533 crtc->y = y;
2534 2534
@@ -3122,7 +3122,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
3122 struct drm_device *dev = crtc->dev; 3122 struct drm_device *dev = crtc->dev;
3123 struct drm_i915_private *dev_priv = dev->dev_private; 3123 struct drm_i915_private *dev_priv = dev->dev_private;
3124 3124
3125 if (crtc->fb == NULL) 3125 if (crtc->primary->fb == NULL)
3126 return; 3126 return;
3127 3127
3128 WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue)); 3128 WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
@@ -3131,7 +3131,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
3131 !intel_crtc_has_pending_flip(crtc)); 3131 !intel_crtc_has_pending_flip(crtc));
3132 3132
3133 mutex_lock(&dev->struct_mutex); 3133 mutex_lock(&dev->struct_mutex);
3134 intel_finish_fb(crtc->fb); 3134 intel_finish_fb(crtc->primary->fb);
3135 mutex_unlock(&dev->struct_mutex); 3135 mutex_unlock(&dev->struct_mutex);
3136} 3136}
3137 3137
@@ -3536,22 +3536,28 @@ static void intel_enable_planes(struct drm_crtc *crtc)
3536{ 3536{
3537 struct drm_device *dev = crtc->dev; 3537 struct drm_device *dev = crtc->dev;
3538 enum pipe pipe = to_intel_crtc(crtc)->pipe; 3538 enum pipe pipe = to_intel_crtc(crtc)->pipe;
3539 struct drm_plane *plane;
3539 struct intel_plane *intel_plane; 3540 struct intel_plane *intel_plane;
3540 3541
3541 list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) 3542 drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
3543 intel_plane = to_intel_plane(plane);
3542 if (intel_plane->pipe == pipe) 3544 if (intel_plane->pipe == pipe)
3543 intel_plane_restore(&intel_plane->base); 3545 intel_plane_restore(&intel_plane->base);
3546 }
3544} 3547}
3545 3548
3546static void intel_disable_planes(struct drm_crtc *crtc) 3549static void intel_disable_planes(struct drm_crtc *crtc)
3547{ 3550{
3548 struct drm_device *dev = crtc->dev; 3551 struct drm_device *dev = crtc->dev;
3549 enum pipe pipe = to_intel_crtc(crtc)->pipe; 3552 enum pipe pipe = to_intel_crtc(crtc)->pipe;
3553 struct drm_plane *plane;
3550 struct intel_plane *intel_plane; 3554 struct intel_plane *intel_plane;
3551 3555
3552 list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) 3556 drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
3557 intel_plane = to_intel_plane(plane);
3553 if (intel_plane->pipe == pipe) 3558 if (intel_plane->pipe == pipe)
3554 intel_plane_disable(&intel_plane->base); 3559 intel_plane_disable(&intel_plane->base);
3560 }
3555} 3561}
3556 3562
3557void hsw_enable_ips(struct intel_crtc *crtc) 3563void hsw_enable_ips(struct intel_crtc *crtc)
@@ -4573,11 +4579,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
4573 assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe); 4579 assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
4574 assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); 4580 assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
4575 4581
4576 if (crtc->fb) { 4582 if (crtc->primary->fb) {
4577 mutex_lock(&dev->struct_mutex); 4583 mutex_lock(&dev->struct_mutex);
4578 intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj); 4584 intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
4579 mutex_unlock(&dev->struct_mutex); 4585 mutex_unlock(&dev->struct_mutex);
4580 crtc->fb = NULL; 4586 crtc->primary->fb = NULL;
4581 } 4587 }
4582 4588
4583 /* Update computed state. */ 4589 /* Update computed state. */
@@ -5736,8 +5742,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5736 int fourcc, pixel_format; 5742 int fourcc, pixel_format;
5737 int aligned_height; 5743 int aligned_height;
5738 5744
5739 crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); 5745 crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
5740 if (!crtc->base.fb) { 5746 if (!crtc->base.primary->fb) {
5741 DRM_DEBUG_KMS("failed to alloc fb\n"); 5747 DRM_DEBUG_KMS("failed to alloc fb\n");
5742 return; 5748 return;
5743 } 5749 }
@@ -5750,8 +5756,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5750 5756
5751 pixel_format = val & DISPPLANE_PIXFORMAT_MASK; 5757 pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
5752 fourcc = intel_format_to_fourcc(pixel_format); 5758 fourcc = intel_format_to_fourcc(pixel_format);
5753 crtc->base.fb->pixel_format = fourcc; 5759 crtc->base.primary->fb->pixel_format = fourcc;
5754 crtc->base.fb->bits_per_pixel = 5760 crtc->base.primary->fb->bits_per_pixel =
5755 drm_format_plane_cpp(fourcc, 0) * 8; 5761 drm_format_plane_cpp(fourcc, 0) * 8;
5756 5762
5757 if (INTEL_INFO(dev)->gen >= 4) { 5763 if (INTEL_INFO(dev)->gen >= 4) {
@@ -5766,23 +5772,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5766 plane_config->base = base; 5772 plane_config->base = base;
5767 5773
5768 val = I915_READ(PIPESRC(pipe)); 5774 val = I915_READ(PIPESRC(pipe));
5769 crtc->base.fb->width = ((val >> 16) & 0xfff) + 1; 5775 crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
5770 crtc->base.fb->height = ((val >> 0) & 0xfff) + 1; 5776 crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
5771 5777
5772 val = I915_READ(DSPSTRIDE(pipe)); 5778 val = I915_READ(DSPSTRIDE(pipe));
5773 crtc->base.fb->pitches[0] = val & 0xffffff80; 5779 crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
5774 5780
5775 aligned_height = intel_align_height(dev, crtc->base.fb->height, 5781 aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
5776 plane_config->tiled); 5782 plane_config->tiled);
5777 5783
5778 plane_config->size = ALIGN(crtc->base.fb->pitches[0] * 5784 plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
5779 aligned_height, PAGE_SIZE); 5785 aligned_height, PAGE_SIZE);
5780 5786
5781 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 5787 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
5782 pipe, plane, crtc->base.fb->width, 5788 pipe, plane, crtc->base.primary->fb->width,
5783 crtc->base.fb->height, 5789 crtc->base.primary->fb->height,
5784 crtc->base.fb->bits_per_pixel, base, 5790 crtc->base.primary->fb->bits_per_pixel, base,
5785 crtc->base.fb->pitches[0], 5791 crtc->base.primary->fb->pitches[0],
5786 plane_config->size); 5792 plane_config->size);
5787 5793
5788} 5794}
@@ -6744,8 +6750,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6744 int fourcc, pixel_format; 6750 int fourcc, pixel_format;
6745 int aligned_height; 6751 int aligned_height;
6746 6752
6747 crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); 6753 crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
6748 if (!crtc->base.fb) { 6754 if (!crtc->base.primary->fb) {
6749 DRM_DEBUG_KMS("failed to alloc fb\n"); 6755 DRM_DEBUG_KMS("failed to alloc fb\n");
6750 return; 6756 return;
6751 } 6757 }
@@ -6758,8 +6764,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6758 6764
6759 pixel_format = val & DISPPLANE_PIXFORMAT_MASK; 6765 pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
6760 fourcc = intel_format_to_fourcc(pixel_format); 6766 fourcc = intel_format_to_fourcc(pixel_format);
6761 crtc->base.fb->pixel_format = fourcc; 6767 crtc->base.primary->fb->pixel_format = fourcc;
6762 crtc->base.fb->bits_per_pixel = 6768 crtc->base.primary->fb->bits_per_pixel =
6763 drm_format_plane_cpp(fourcc, 0) * 8; 6769 drm_format_plane_cpp(fourcc, 0) * 8;
6764 6770
6765 base = I915_READ(DSPSURF(plane)) & 0xfffff000; 6771 base = I915_READ(DSPSURF(plane)) & 0xfffff000;
@@ -6774,23 +6780,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6774 plane_config->base = base; 6780 plane_config->base = base;
6775 6781
6776 val = I915_READ(PIPESRC(pipe)); 6782 val = I915_READ(PIPESRC(pipe));
6777 crtc->base.fb->width = ((val >> 16) & 0xfff) + 1; 6783 crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
6778 crtc->base.fb->height = ((val >> 0) & 0xfff) + 1; 6784 crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
6779 6785
6780 val = I915_READ(DSPSTRIDE(pipe)); 6786 val = I915_READ(DSPSTRIDE(pipe));
6781 crtc->base.fb->pitches[0] = val & 0xffffff80; 6787 crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
6782 6788
6783 aligned_height = intel_align_height(dev, crtc->base.fb->height, 6789 aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
6784 plane_config->tiled); 6790 plane_config->tiled);
6785 6791
6786 plane_config->size = ALIGN(crtc->base.fb->pitches[0] * 6792 plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
6787 aligned_height, PAGE_SIZE); 6793 aligned_height, PAGE_SIZE);
6788 6794
6789 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 6795 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
6790 pipe, plane, crtc->base.fb->width, 6796 pipe, plane, crtc->base.primary->fb->width,
6791 crtc->base.fb->height, 6797 crtc->base.primary->fb->height,
6792 crtc->base.fb->bits_per_pixel, base, 6798 crtc->base.primary->fb->bits_per_pixel, base,
6793 crtc->base.fb->pitches[0], 6799 crtc->base.primary->fb->pitches[0],
6794 plane_config->size); 6800 plane_config->size);
6795} 6801}
6796 6802
@@ -8449,7 +8455,7 @@ void intel_mark_idle(struct drm_device *dev)
8449 goto out; 8455 goto out;
8450 8456
8451 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 8457 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
8452 if (!crtc->fb) 8458 if (!crtc->primary->fb)
8453 continue; 8459 continue;
8454 8460
8455 intel_decrease_pllclock(crtc); 8461 intel_decrease_pllclock(crtc);
@@ -8472,10 +8478,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
8472 return; 8478 return;
8473 8479
8474 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 8480 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
8475 if (!crtc->fb) 8481 if (!crtc->primary->fb)
8476 continue; 8482 continue;
8477 8483
8478 if (to_intel_framebuffer(crtc->fb)->obj != obj) 8484 if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
8479 continue; 8485 continue;
8480 8486
8481 intel_increase_pllclock(crtc); 8487 intel_increase_pllclock(crtc);
@@ -8903,7 +8909,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
8903{ 8909{
8904 struct drm_device *dev = crtc->dev; 8910 struct drm_device *dev = crtc->dev;
8905 struct drm_i915_private *dev_priv = dev->dev_private; 8911 struct drm_i915_private *dev_priv = dev->dev_private;
8906 struct drm_framebuffer *old_fb = crtc->fb; 8912 struct drm_framebuffer *old_fb = crtc->primary->fb;
8907 struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; 8913 struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
8908 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 8914 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
8909 struct intel_unpin_work *work; 8915 struct intel_unpin_work *work;
@@ -8911,7 +8917,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
8911 int ret; 8917 int ret;
8912 8918
8913 /* Can't change pixel format via MI display flips. */ 8919 /* Can't change pixel format via MI display flips. */
8914 if (fb->pixel_format != crtc->fb->pixel_format) 8920 if (fb->pixel_format != crtc->primary->fb->pixel_format)
8915 return -EINVAL; 8921 return -EINVAL;
8916 8922
8917 /* 8923 /*
@@ -8919,8 +8925,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
8919 * Note that pitch changes could also affect these register. 8925 * Note that pitch changes could also affect these register.
8920 */ 8926 */
8921 if (INTEL_INFO(dev)->gen > 3 && 8927 if (INTEL_INFO(dev)->gen > 3 &&
8922 (fb->offsets[0] != crtc->fb->offsets[0] || 8928 (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
8923 fb->pitches[0] != crtc->fb->pitches[0])) 8929 fb->pitches[0] != crtc->primary->fb->pitches[0]))
8924 return -EINVAL; 8930 return -EINVAL;
8925 8931
8926 if (i915_terminally_wedged(&dev_priv->gpu_error)) 8932 if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -8963,7 +8969,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
8963 drm_gem_object_reference(&work->old_fb_obj->base); 8969 drm_gem_object_reference(&work->old_fb_obj->base);
8964 drm_gem_object_reference(&obj->base); 8970 drm_gem_object_reference(&obj->base);
8965 8971
8966 crtc->fb = fb; 8972 crtc->primary->fb = fb;
8967 8973
8968 work->pending_flip_obj = obj; 8974 work->pending_flip_obj = obj;
8969 8975
@@ -8986,7 +8992,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
8986 8992
8987cleanup_pending: 8993cleanup_pending:
8988 atomic_dec(&intel_crtc->unpin_work_count); 8994 atomic_dec(&intel_crtc->unpin_work_count);
8989 crtc->fb = old_fb; 8995 crtc->primary->fb = old_fb;
8990 drm_gem_object_unreference(&work->old_fb_obj->base); 8996 drm_gem_object_unreference(&work->old_fb_obj->base);
8991 drm_gem_object_unreference(&obj->base); 8997 drm_gem_object_unreference(&obj->base);
8992 mutex_unlock(&dev->struct_mutex); 8998 mutex_unlock(&dev->struct_mutex);
@@ -10027,7 +10033,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
10027 10033
10028void intel_crtc_restore_mode(struct drm_crtc *crtc) 10034void intel_crtc_restore_mode(struct drm_crtc *crtc)
10029{ 10035{
10030 intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb); 10036 intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
10031} 10037}
10032 10038
10033#undef for_each_intel_crtc_masked 10039#undef for_each_intel_crtc_masked
@@ -10151,9 +10157,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
10151 * and then just flip_or_move it */ 10157 * and then just flip_or_move it */
10152 if (is_crtc_connector_off(set)) { 10158 if (is_crtc_connector_off(set)) {
10153 config->mode_changed = true; 10159 config->mode_changed = true;
10154 } else if (set->crtc->fb != set->fb) { 10160 } else if (set->crtc->primary->fb != set->fb) {
10155 /* If we have no fb then treat it as a full mode set */ 10161 /* If we have no fb then treat it as a full mode set */
10156 if (set->crtc->fb == NULL) { 10162 if (set->crtc->primary->fb == NULL) {
10157 struct intel_crtc *intel_crtc = 10163 struct intel_crtc *intel_crtc =
10158 to_intel_crtc(set->crtc); 10164 to_intel_crtc(set->crtc);
10159 10165
@@ -10167,7 +10173,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
10167 } else if (set->fb == NULL) { 10173 } else if (set->fb == NULL) {
10168 config->mode_changed = true; 10174 config->mode_changed = true;
10169 } else if (set->fb->pixel_format != 10175 } else if (set->fb->pixel_format !=
10170 set->crtc->fb->pixel_format) { 10176 set->crtc->primary->fb->pixel_format) {
10171 config->mode_changed = true; 10177 config->mode_changed = true;
10172 } else { 10178 } else {
10173 config->fb_changed = true; 10179 config->fb_changed = true;
@@ -10380,7 +10386,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
10380 save_set.mode = &set->crtc->mode; 10386 save_set.mode = &set->crtc->mode;
10381 save_set.x = set->crtc->x; 10387 save_set.x = set->crtc->x;
10382 save_set.y = set->crtc->y; 10388 save_set.y = set->crtc->y;
10383 save_set.fb = set->crtc->fb; 10389 save_set.fb = set->crtc->primary->fb;
10384 10390
10385 /* Compute whether we need a full modeset, only an fb base update or no 10391 /* Compute whether we need a full modeset, only an fb base update or no
10386 * change at all. In the future we might also check whether only the 10392 * change at all. In the future we might also check whether only the
@@ -11745,7 +11751,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
11745 dev_priv->pipe_to_crtc_mapping[pipe]; 11751 dev_priv->pipe_to_crtc_mapping[pipe];
11746 11752
11747 __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, 11753 __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
11748 crtc->fb); 11754 crtc->primary->fb);
11749 } 11755 }
11750 } else { 11756 } else {
11751 intel_modeset_update_staged_output_state(dev); 11757 intel_modeset_update_staged_output_state(dev);
@@ -11774,15 +11780,15 @@ void intel_modeset_gem_init(struct drm_device *dev)
11774 */ 11780 */
11775 mutex_lock(&dev->struct_mutex); 11781 mutex_lock(&dev->struct_mutex);
11776 list_for_each_entry(c, &dev->mode_config.crtc_list, head) { 11782 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
11777 if (!c->fb) 11783 if (!c->primary->fb)
11778 continue; 11784 continue;
11779 11785
11780 fb = to_intel_framebuffer(c->fb); 11786 fb = to_intel_framebuffer(c->primary->fb);
11781 if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) { 11787 if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
11782 DRM_ERROR("failed to pin boot fb on pipe %d\n", 11788 DRM_ERROR("failed to pin boot fb on pipe %d\n",
11783 to_intel_crtc(c)->pipe); 11789 to_intel_crtc(c)->pipe);
11784 drm_framebuffer_unreference(c->fb); 11790 drm_framebuffer_unreference(c->primary->fb);
11785 c->fb = NULL; 11791 c->primary->fb = NULL;
11786 } 11792 }
11787 } 11793 }
11788 mutex_unlock(&dev->struct_mutex); 11794 mutex_unlock(&dev->struct_mutex);
@@ -11821,7 +11827,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
11821 11827
11822 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 11828 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
11823 /* Skip inactive CRTCs */ 11829 /* Skip inactive CRTCs */
11824 if (!crtc->fb) 11830 if (!crtc->primary->fb)
11825 continue; 11831 continue;
11826 11832
11827 intel_increase_pllclock(crtc); 11833 intel_increase_pllclock(crtc);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 44471ccdc385..a0dad1a2f819 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1635,7 +1635,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
1635 struct drm_i915_private *dev_priv = dev->dev_private; 1635 struct drm_i915_private *dev_priv = dev->dev_private;
1636 struct drm_crtc *crtc = dig_port->base.base.crtc; 1636 struct drm_crtc *crtc = dig_port->base.base.crtc;
1637 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 1637 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1638 struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj; 1638 struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->primary->fb)->obj;
1639 struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; 1639 struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
1640 1640
1641 dev_priv->psr.source_ok = false; 1641 dev_priv->psr.source_ok = false;
@@ -1668,7 +1668,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
1668 return false; 1668 return false;
1669 } 1669 }
1670 1670
1671 obj = to_intel_framebuffer(crtc->fb)->obj; 1671 obj = to_intel_framebuffer(crtc->primary->fb)->obj;
1672 if (obj->tiling_mode != I915_TILING_X || 1672 if (obj->tiling_mode != I915_TILING_X ||
1673 obj->fence_reg == I915_FENCE_REG_NONE) { 1673 obj->fence_reg == I915_FENCE_REG_NONE) {
1674 DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n"); 1674 DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 86b012ca7217..b4d44e62f0c7 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
482 intel_crtc = to_intel_crtc(crtc); 482 intel_crtc = to_intel_crtc(crtc);
483 483
484 if (!intel_crtc->active || !crtc->fb) { 484 if (!intel_crtc->active || !crtc->primary->fb) {
485 DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", 485 DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
486 pipe_name(intel_crtc->pipe)); 486 pipe_name(intel_crtc->pipe));
487 continue; 487 continue;
@@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
491 DRM_DEBUG_KMS("found possible fb from plane %c\n", 491 DRM_DEBUG_KMS("found possible fb from plane %c\n",
492 pipe_name(intel_crtc->pipe)); 492 pipe_name(intel_crtc->pipe));
493 plane_config = &intel_crtc->plane_config; 493 plane_config = &intel_crtc->plane_config;
494 fb = to_intel_framebuffer(crtc->fb); 494 fb = to_intel_framebuffer(crtc->primary->fb);
495 max_size = plane_config->size; 495 max_size = plane_config->size;
496 } 496 }
497 } 497 }
@@ -573,7 +573,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
573 if (!intel_crtc->active) 573 if (!intel_crtc->active)
574 continue; 574 continue;
575 575
576 WARN(!crtc->fb, 576 WARN(!crtc->primary->fb,
577 "re-used BIOS config but lost an fb on crtc %d\n", 577 "re-used BIOS config but lost an fb on crtc %d\n",
578 crtc->base.id); 578 crtc->base.id);
579 } 579 }
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 778b8fbd6ccc..d8adc9104dca 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay,
606{ 606{
607 u32 key = overlay->color_key; 607 u32 key = overlay->color_key;
608 608
609 switch (overlay->crtc->base.fb->bits_per_pixel) { 609 switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
610 case 8: 610 case 8:
611 iowrite32(0, &regs->DCLRKV); 611 iowrite32(0, &regs->DCLRKV);
612 iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM); 612 iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
613 break; 613 break;
614 614
615 case 16: 615 case 16:
616 if (overlay->crtc->base.fb->depth == 15) { 616 if (overlay->crtc->base.primary->fb->depth == 15) {
617 iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV); 617 iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
618 iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE, 618 iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
619 &regs->DCLRKM); 619 &regs->DCLRKM);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f18dec071df7..5874716774a7 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
92{ 92{
93 struct drm_device *dev = crtc->dev; 93 struct drm_device *dev = crtc->dev;
94 struct drm_i915_private *dev_priv = dev->dev_private; 94 struct drm_i915_private *dev_priv = dev->dev_private;
95 struct drm_framebuffer *fb = crtc->fb; 95 struct drm_framebuffer *fb = crtc->primary->fb;
96 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 96 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
97 struct drm_i915_gem_object *obj = intel_fb->obj; 97 struct drm_i915_gem_object *obj = intel_fb->obj;
98 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 98 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
149{ 149{
150 struct drm_device *dev = crtc->dev; 150 struct drm_device *dev = crtc->dev;
151 struct drm_i915_private *dev_priv = dev->dev_private; 151 struct drm_i915_private *dev_priv = dev->dev_private;
152 struct drm_framebuffer *fb = crtc->fb; 152 struct drm_framebuffer *fb = crtc->primary->fb;
153 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 153 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
154 struct drm_i915_gem_object *obj = intel_fb->obj; 154 struct drm_i915_gem_object *obj = intel_fb->obj;
155 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 155 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
221{ 221{
222 struct drm_device *dev = crtc->dev; 222 struct drm_device *dev = crtc->dev;
223 struct drm_i915_private *dev_priv = dev->dev_private; 223 struct drm_i915_private *dev_priv = dev->dev_private;
224 struct drm_framebuffer *fb = crtc->fb; 224 struct drm_framebuffer *fb = crtc->primary->fb;
225 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 225 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
226 struct drm_i915_gem_object *obj = intel_fb->obj; 226 struct drm_i915_gem_object *obj = intel_fb->obj;
227 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 227 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
277{ 277{
278 struct drm_device *dev = crtc->dev; 278 struct drm_device *dev = crtc->dev;
279 struct drm_i915_private *dev_priv = dev->dev_private; 279 struct drm_i915_private *dev_priv = dev->dev_private;
280 struct drm_framebuffer *fb = crtc->fb; 280 struct drm_framebuffer *fb = crtc->primary->fb;
281 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 281 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
282 struct drm_i915_gem_object *obj = intel_fb->obj; 282 struct drm_i915_gem_object *obj = intel_fb->obj;
283 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 283 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -336,11 +336,11 @@ static void intel_fbc_work_fn(struct work_struct *__work)
336 /* Double check that we haven't switched fb without cancelling 336 /* Double check that we haven't switched fb without cancelling
337 * the prior work. 337 * the prior work.
338 */ 338 */
339 if (work->crtc->fb == work->fb) { 339 if (work->crtc->primary->fb == work->fb) {
340 dev_priv->display.enable_fbc(work->crtc); 340 dev_priv->display.enable_fbc(work->crtc);
341 341
342 dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; 342 dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
343 dev_priv->fbc.fb_id = work->crtc->fb->base.id; 343 dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
344 dev_priv->fbc.y = work->crtc->y; 344 dev_priv->fbc.y = work->crtc->y;
345 } 345 }
346 346
@@ -393,7 +393,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc)
393 } 393 }
394 394
395 work->crtc = crtc; 395 work->crtc = crtc;
396 work->fb = crtc->fb; 396 work->fb = crtc->primary->fb;
397 INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); 397 INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
398 398
399 dev_priv->fbc.fbc_work = work; 399 dev_priv->fbc.fbc_work = work;
@@ -499,14 +499,14 @@ void intel_update_fbc(struct drm_device *dev)
499 } 499 }
500 } 500 }
501 501
502 if (!crtc || crtc->fb == NULL) { 502 if (!crtc || crtc->primary->fb == NULL) {
503 if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT)) 503 if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
504 DRM_DEBUG_KMS("no output, disabling\n"); 504 DRM_DEBUG_KMS("no output, disabling\n");
505 goto out_disable; 505 goto out_disable;
506 } 506 }
507 507
508 intel_crtc = to_intel_crtc(crtc); 508 intel_crtc = to_intel_crtc(crtc);
509 fb = crtc->fb; 509 fb = crtc->primary->fb;
510 intel_fb = to_intel_framebuffer(fb); 510 intel_fb = to_intel_framebuffer(fb);
511 obj = intel_fb->obj; 511 obj = intel_fb->obj;
512 adjusted_mode = &intel_crtc->config.adjusted_mode; 512 adjusted_mode = &intel_crtc->config.adjusted_mode;
@@ -1041,7 +1041,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
1041 crtc = single_enabled_crtc(dev); 1041 crtc = single_enabled_crtc(dev);
1042 if (crtc) { 1042 if (crtc) {
1043 const struct drm_display_mode *adjusted_mode; 1043 const struct drm_display_mode *adjusted_mode;
1044 int pixel_size = crtc->fb->bits_per_pixel / 8; 1044 int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
1045 int clock; 1045 int clock;
1046 1046
1047 adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; 1047 adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
@@ -1121,7 +1121,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
1121 clock = adjusted_mode->crtc_clock; 1121 clock = adjusted_mode->crtc_clock;
1122 htotal = adjusted_mode->crtc_htotal; 1122 htotal = adjusted_mode->crtc_htotal;
1123 hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; 1123 hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
1124 pixel_size = crtc->fb->bits_per_pixel / 8; 1124 pixel_size = crtc->primary->fb->bits_per_pixel / 8;
1125 1125
1126 /* Use the small buffer method to calculate plane watermark */ 1126 /* Use the small buffer method to calculate plane watermark */
1127 entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; 1127 entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
@@ -1208,7 +1208,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
1208 clock = adjusted_mode->crtc_clock; 1208 clock = adjusted_mode->crtc_clock;
1209 htotal = adjusted_mode->crtc_htotal; 1209 htotal = adjusted_mode->crtc_htotal;
1210 hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; 1210 hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
1211 pixel_size = crtc->fb->bits_per_pixel / 8; 1211 pixel_size = crtc->primary->fb->bits_per_pixel / 8;
1212 1212
1213 line_time_us = max(htotal * 1000 / clock, 1); 1213 line_time_us = max(htotal * 1000 / clock, 1);
1214 line_count = (latency_ns / line_time_us + 1000) / 1000; 1214 line_count = (latency_ns / line_time_us + 1000) / 1000;
@@ -1247,7 +1247,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
1247 return false; 1247 return false;
1248 1248
1249 clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; 1249 clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
1250 pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ 1250 pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
1251 1251
1252 entries = (clock / 1000) * pixel_size; 1252 entries = (clock / 1000) * pixel_size;
1253 *plane_prec_mult = (entries > 256) ? 1253 *plane_prec_mult = (entries > 256) ?
@@ -1439,7 +1439,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
1439 int clock = adjusted_mode->crtc_clock; 1439 int clock = adjusted_mode->crtc_clock;
1440 int htotal = adjusted_mode->crtc_htotal; 1440 int htotal = adjusted_mode->crtc_htotal;
1441 int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; 1441 int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
1442 int pixel_size = crtc->fb->bits_per_pixel / 8; 1442 int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
1443 unsigned long line_time_us; 1443 unsigned long line_time_us;
1444 int entries; 1444 int entries;
1445 1445
@@ -1512,7 +1512,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
1512 crtc = intel_get_crtc_for_plane(dev, 0); 1512 crtc = intel_get_crtc_for_plane(dev, 0);
1513 if (intel_crtc_active(crtc)) { 1513 if (intel_crtc_active(crtc)) {
1514 const struct drm_display_mode *adjusted_mode; 1514 const struct drm_display_mode *adjusted_mode;
1515 int cpp = crtc->fb->bits_per_pixel / 8; 1515 int cpp = crtc->primary->fb->bits_per_pixel / 8;
1516 if (IS_GEN2(dev)) 1516 if (IS_GEN2(dev))
1517 cpp = 4; 1517 cpp = 4;
1518 1518
@@ -1528,7 +1528,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
1528 crtc = intel_get_crtc_for_plane(dev, 1); 1528 crtc = intel_get_crtc_for_plane(dev, 1);
1529 if (intel_crtc_active(crtc)) { 1529 if (intel_crtc_active(crtc)) {
1530 const struct drm_display_mode *adjusted_mode; 1530 const struct drm_display_mode *adjusted_mode;
1531 int cpp = crtc->fb->bits_per_pixel / 8; 1531 int cpp = crtc->primary->fb->bits_per_pixel / 8;
1532 if (IS_GEN2(dev)) 1532 if (IS_GEN2(dev))
1533 cpp = 4; 1533 cpp = 4;
1534 1534
@@ -1565,7 +1565,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
1565 int clock = adjusted_mode->crtc_clock; 1565 int clock = adjusted_mode->crtc_clock;
1566 int htotal = adjusted_mode->crtc_htotal; 1566 int htotal = adjusted_mode->crtc_htotal;
1567 int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w; 1567 int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
1568 int pixel_size = enabled->fb->bits_per_pixel / 8; 1568 int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
1569 unsigned long line_time_us; 1569 unsigned long line_time_us;
1570 int entries; 1570 int entries;
1571 1571
@@ -2117,7 +2117,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
2117 if (p->active) { 2117 if (p->active) {
2118 p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal; 2118 p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
2119 p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc); 2119 p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
2120 p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8; 2120 p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
2121 p->cur.bytes_per_pixel = 4; 2121 p->cur.bytes_per_pixel = 4;
2122 p->pri.horiz_pixels = intel_crtc->config.pipe_src_w; 2122 p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
2123 p->cur.horiz_pixels = intel_crtc->cursor_width; 2123 p->cur.horiz_pixels = intel_crtc->cursor_width;
@@ -2129,7 +2129,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
2129 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 2129 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
2130 config->num_pipes_active += intel_crtc_active(crtc); 2130 config->num_pipes_active += intel_crtc_active(crtc);
2131 2131
2132 list_for_each_entry(plane, &dev->mode_config.plane_list, head) { 2132 drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
2133 struct intel_plane *intel_plane = to_intel_plane(plane); 2133 struct intel_plane *intel_plane = to_intel_plane(plane);
2134 2134
2135 if (intel_plane->pipe == pipe) 2135 if (intel_plane->pipe == pipe)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 968374776db9..a034ed408252 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -29,7 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
29 struct mga_crtc *mga_crtc = to_mga_crtc(crtc); 29 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
30 struct drm_device *dev = crtc->dev; 30 struct drm_device *dev = crtc->dev;
31 struct mga_device *mdev = dev->dev_private; 31 struct mga_device *mdev = dev->dev_private;
32 struct drm_framebuffer *fb = crtc->fb; 32 struct drm_framebuffer *fb = crtc->primary->fb;
33 int i; 33 int i;
34 34
35 if (!crtc->enabled) 35 if (!crtc->enabled)
@@ -742,7 +742,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
742 mgag200_bo_unreserve(bo); 742 mgag200_bo_unreserve(bo);
743 } 743 }
744 744
745 mga_fb = to_mga_framebuffer(crtc->fb); 745 mga_fb = to_mga_framebuffer(crtc->primary->fb);
746 obj = mga_fb->obj; 746 obj = mga_fb->obj;
747 bo = gem_to_mga_bo(obj); 747 bo = gem_to_mga_bo(obj);
748 748
@@ -805,7 +805,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
805 /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 805 /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0
806 }; 806 };
807 807
808 bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1]; 808 bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
809 809
810 switch (mdev->type) { 810 switch (mdev->type) {
811 case G200_SE_A: 811 case G200_SE_A:
@@ -843,12 +843,12 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
843 break; 843 break;
844 } 844 }
845 845
846 switch (crtc->fb->bits_per_pixel) { 846 switch (crtc->primary->fb->bits_per_pixel) {
847 case 8: 847 case 8:
848 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits; 848 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
849 break; 849 break;
850 case 16: 850 case 16:
851 if (crtc->fb->depth == 15) 851 if (crtc->primary->fb->depth == 15)
852 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits; 852 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
853 else 853 else
854 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits; 854 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
@@ -896,8 +896,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
896 WREG_SEQ(3, 0); 896 WREG_SEQ(3, 0);
897 WREG_SEQ(4, 0xe); 897 WREG_SEQ(4, 0xe);
898 898
899 pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8); 899 pitch = crtc->primary->fb->pitches[0] / (crtc->primary->fb->bits_per_pixel / 8);
900 if (crtc->fb->bits_per_pixel == 24) 900 if (crtc->primary->fb->bits_per_pixel == 24)
901 pitch = (pitch * 3) >> (4 - bppshift); 901 pitch = (pitch * 3) >> (4 - bppshift);
902 else 902 else
903 pitch = pitch >> (4 - bppshift); 903 pitch = pitch >> (4 - bppshift);
@@ -974,7 +974,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
974 ((vdisplay & 0xc00) >> 7) | 974 ((vdisplay & 0xc00) >> 7) |
975 ((vsyncstart & 0xc00) >> 5) | 975 ((vsyncstart & 0xc00) >> 5) |
976 ((vdisplay & 0x400) >> 3); 976 ((vdisplay & 0x400) >> 3);
977 if (crtc->fb->bits_per_pixel == 24) 977 if (crtc->primary->fb->bits_per_pixel == 24)
978 ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80; 978 ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
979 else 979 else
980 ext_vga[3] = ((1 << bppshift) - 1) | 0x80; 980 ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
@@ -1034,9 +1034,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
1034 u32 bpp; 1034 u32 bpp;
1035 u32 mb; 1035 u32 mb;
1036 1036
1037 if (crtc->fb->bits_per_pixel > 16) 1037 if (crtc->primary->fb->bits_per_pixel > 16)
1038 bpp = 32; 1038 bpp = 32;
1039 else if (crtc->fb->bits_per_pixel > 8) 1039 else if (crtc->primary->fb->bits_per_pixel > 8)
1040 bpp = 16; 1040 bpp = 16;
1041 else 1041 else
1042 bpp = 8; 1042 bpp = 8;
@@ -1277,8 +1277,8 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
1277 int ret; 1277 int ret;
1278 DRM_DEBUG_KMS("\n"); 1278 DRM_DEBUG_KMS("\n");
1279 mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1279 mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1280 if (crtc->fb) { 1280 if (crtc->primary->fb) {
1281 struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb); 1281 struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);
1282 struct drm_gem_object *obj = mga_fb->obj; 1282 struct drm_gem_object *obj = mga_fb->obj;
1283 struct mgag200_bo *bo = gem_to_mga_bo(obj); 1283 struct mgag200_bo *bo = gem_to_mga_bo(obj);
1284 ret = mgag200_bo_reserve(bo, false); 1284 ret = mgag200_bo_reserve(bo, false);
@@ -1287,7 +1287,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
1287 mgag200_bo_push_sysram(bo); 1287 mgag200_bo_push_sysram(bo);
1288 mgag200_bo_unreserve(bo); 1288 mgag200_bo_unreserve(bo);
1289 } 1289 }
1290 crtc->fb = NULL; 1290 crtc->primary->fb = NULL;
1291} 1291}
1292 1292
1293/* These provide the minimum set of functions required to handle a CRTC */ 1293/* These provide the minimum set of functions required to handle a CRTC */
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 4f977a593bea..5e1e6b0cd8ac 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -7,6 +7,7 @@ msm-y := \
7 adreno/adreno_gpu.o \ 7 adreno/adreno_gpu.o \
8 adreno/a3xx_gpu.o \ 8 adreno/a3xx_gpu.o \
9 hdmi/hdmi.o \ 9 hdmi/hdmi.o \
10 hdmi/hdmi_audio.o \
10 hdmi/hdmi_bridge.o \ 11 hdmi/hdmi_bridge.o \
11 hdmi/hdmi_connector.o \ 12 hdmi/hdmi_connector.o \
12 hdmi/hdmi_i2c.o \ 13 hdmi/hdmi_i2c.o \
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 461df93e825e..f20fbde5dc49 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -35,7 +35,11 @@
35 A3XX_INT0_CP_AHB_ERROR_HALT | \ 35 A3XX_INT0_CP_AHB_ERROR_HALT | \
36 A3XX_INT0_UCHE_OOB_ACCESS) 36 A3XX_INT0_UCHE_OOB_ACCESS)
37 37
38static struct platform_device *a3xx_pdev; 38
39static bool hang_debug = false;
40MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
41module_param_named(hang_debug, hang_debug, bool, 0600);
42static void a3xx_dump(struct msm_gpu *gpu);
39 43
40static void a3xx_me_init(struct msm_gpu *gpu) 44static void a3xx_me_init(struct msm_gpu *gpu)
41{ 45{
@@ -291,6 +295,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
291 295
292static void a3xx_recover(struct msm_gpu *gpu) 296static void a3xx_recover(struct msm_gpu *gpu)
293{ 297{
298 /* dump registers before resetting gpu, if enabled: */
299 if (hang_debug)
300 a3xx_dump(gpu);
294 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 301 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
295 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 302 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
296 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); 303 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
@@ -311,27 +318,18 @@ static void a3xx_destroy(struct msm_gpu *gpu)
311 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); 318 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
312#endif 319#endif
313 320
314 put_device(&a3xx_gpu->pdev->dev);
315 kfree(a3xx_gpu); 321 kfree(a3xx_gpu);
316} 322}
317 323
318static void a3xx_idle(struct msm_gpu *gpu) 324static void a3xx_idle(struct msm_gpu *gpu)
319{ 325{
320 unsigned long t;
321
322 /* wait for ringbuffer to drain: */ 326 /* wait for ringbuffer to drain: */
323 adreno_idle(gpu); 327 adreno_idle(gpu);
324 328
325 t = jiffies + ADRENO_IDLE_TIMEOUT;
326
327 /* then wait for GPU to finish: */ 329 /* then wait for GPU to finish: */
328 do { 330 if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
329 uint32_t rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS); 331 A3XX_RBBM_STATUS_GPU_BUSY)))
330 if (!(rbbm_status & A3XX_RBBM_STATUS_GPU_BUSY)) 332 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
331 return;
332 } while(time_before(jiffies, t));
333
334 DRM_ERROR("timeout waiting for %s to idle!\n", gpu->name);
335 333
336 /* TODO maybe we need to reset GPU here to recover from hang? */ 334 /* TODO maybe we need to reset GPU here to recover from hang? */
337} 335}
@@ -352,7 +350,6 @@ static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
352 return IRQ_HANDLED; 350 return IRQ_HANDLED;
353} 351}
354 352
355#ifdef CONFIG_DEBUG_FS
356static const unsigned int a3xx_registers[] = { 353static const unsigned int a3xx_registers[] = {
357 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 354 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
358 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 355 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
@@ -392,11 +389,18 @@ static const unsigned int a3xx_registers[] = {
392 0x303c, 0x303c, 0x305e, 0x305f, 389 0x303c, 0x303c, 0x305e, 0x305f,
393}; 390};
394 391
392#ifdef CONFIG_DEBUG_FS
395static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 393static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
396{ 394{
395 struct drm_device *dev = gpu->dev;
397 int i; 396 int i;
398 397
399 adreno_show(gpu, m); 398 adreno_show(gpu, m);
399
400 mutex_lock(&dev->struct_mutex);
401
402 gpu->funcs->pm_resume(gpu);
403
400 seq_printf(m, "status: %08x\n", 404 seq_printf(m, "status: %08x\n",
401 gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 405 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
402 406
@@ -412,9 +416,36 @@ static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
412 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val); 416 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
413 } 417 }
414 } 418 }
419
420 gpu->funcs->pm_suspend(gpu);
421
422 mutex_unlock(&dev->struct_mutex);
415} 423}
416#endif 424#endif
417 425
426/* would be nice to not have to duplicate the _show() stuff with printk(): */
427static void a3xx_dump(struct msm_gpu *gpu)
428{
429 int i;
430
431 adreno_dump(gpu);
432 printk("status: %08x\n",
433 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
434
435 /* dump these out in a form that can be parsed by demsm: */
436 printk("IO:region %s 00000000 00020000\n", gpu->name);
437 for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
438 uint32_t start = a3xx_registers[i];
439 uint32_t end = a3xx_registers[i+1];
440 uint32_t addr;
441
442 for (addr = start; addr <= end; addr++) {
443 uint32_t val = gpu_read(gpu, addr);
444 printk("IO:R %08x %08x\n", addr<<2, val);
445 }
446 }
447}
448
418static const struct adreno_gpu_funcs funcs = { 449static const struct adreno_gpu_funcs funcs = {
419 .base = { 450 .base = {
420 .get_param = adreno_get_param, 451 .get_param = adreno_get_param,
@@ -439,7 +470,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
439 struct a3xx_gpu *a3xx_gpu = NULL; 470 struct a3xx_gpu *a3xx_gpu = NULL;
440 struct adreno_gpu *adreno_gpu; 471 struct adreno_gpu *adreno_gpu;
441 struct msm_gpu *gpu; 472 struct msm_gpu *gpu;
442 struct platform_device *pdev = a3xx_pdev; 473 struct msm_drm_private *priv = dev->dev_private;
474 struct platform_device *pdev = priv->gpu_pdev;
443 struct adreno_platform_config *config; 475 struct adreno_platform_config *config;
444 int ret; 476 int ret;
445 477
@@ -460,7 +492,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
460 adreno_gpu = &a3xx_gpu->base; 492 adreno_gpu = &a3xx_gpu->base;
461 gpu = &adreno_gpu->base; 493 gpu = &adreno_gpu->base;
462 494
463 get_device(&pdev->dev);
464 a3xx_gpu->pdev = pdev; 495 a3xx_gpu->pdev = pdev;
465 496
466 gpu->fast_rate = config->fast_rate; 497 gpu->fast_rate = config->fast_rate;
@@ -522,17 +553,24 @@ fail:
522# include <mach/kgsl.h> 553# include <mach/kgsl.h>
523#endif 554#endif
524 555
525static int a3xx_probe(struct platform_device *pdev) 556static void set_gpu_pdev(struct drm_device *dev,
557 struct platform_device *pdev)
558{
559 struct msm_drm_private *priv = dev->dev_private;
560 priv->gpu_pdev = pdev;
561}
562
563static int a3xx_bind(struct device *dev, struct device *master, void *data)
526{ 564{
527 static struct adreno_platform_config config = {}; 565 static struct adreno_platform_config config = {};
528#ifdef CONFIG_OF 566#ifdef CONFIG_OF
529 struct device_node *child, *node = pdev->dev.of_node; 567 struct device_node *child, *node = dev->of_node;
530 u32 val; 568 u32 val;
531 int ret; 569 int ret;
532 570
533 ret = of_property_read_u32(node, "qcom,chipid", &val); 571 ret = of_property_read_u32(node, "qcom,chipid", &val);
534 if (ret) { 572 if (ret) {
535 dev_err(&pdev->dev, "could not find chipid: %d\n", ret); 573 dev_err(dev, "could not find chipid: %d\n", ret);
536 return ret; 574 return ret;
537 } 575 }
538 576
@@ -548,7 +586,7 @@ static int a3xx_probe(struct platform_device *pdev)
548 for_each_child_of_node(child, pwrlvl) { 586 for_each_child_of_node(child, pwrlvl) {
549 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); 587 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
550 if (ret) { 588 if (ret) {
551 dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); 589 dev_err(dev, "could not find gpu-freq: %d\n", ret);
552 return ret; 590 return ret;
553 } 591 }
554 config.fast_rate = max(config.fast_rate, val); 592 config.fast_rate = max(config.fast_rate, val);
@@ -558,12 +596,12 @@ static int a3xx_probe(struct platform_device *pdev)
558 } 596 }
559 597
560 if (!config.fast_rate) { 598 if (!config.fast_rate) {
561 dev_err(&pdev->dev, "could not find clk rates\n"); 599 dev_err(dev, "could not find clk rates\n");
562 return -ENXIO; 600 return -ENXIO;
563 } 601 }
564 602
565#else 603#else
566 struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; 604 struct kgsl_device_platform_data *pdata = dev->platform_data;
567 uint32_t version = socinfo_get_version(); 605 uint32_t version = socinfo_get_version();
568 if (cpu_is_apq8064ab()) { 606 if (cpu_is_apq8064ab()) {
569 config.fast_rate = 450000000; 607 config.fast_rate = 450000000;
@@ -609,14 +647,30 @@ static int a3xx_probe(struct platform_device *pdev)
609 config.bus_scale_table = pdata->bus_scale_table; 647 config.bus_scale_table = pdata->bus_scale_table;
610# endif 648# endif
611#endif 649#endif
612 pdev->dev.platform_data = &config; 650 dev->platform_data = &config;
613 a3xx_pdev = pdev; 651 set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
614 return 0; 652 return 0;
615} 653}
616 654
655static void a3xx_unbind(struct device *dev, struct device *master,
656 void *data)
657{
658 set_gpu_pdev(dev_get_drvdata(master), NULL);
659}
660
661static const struct component_ops a3xx_ops = {
662 .bind = a3xx_bind,
663 .unbind = a3xx_unbind,
664};
665
666static int a3xx_probe(struct platform_device *pdev)
667{
668 return component_add(&pdev->dev, &a3xx_ops);
669}
670
617static int a3xx_remove(struct platform_device *pdev) 671static int a3xx_remove(struct platform_device *pdev)
618{ 672{
619 a3xx_pdev = NULL; 673 component_del(&pdev->dev, &a3xx_ops);
620 return 0; 674 return 0;
621} 675}
622 676
@@ -624,7 +678,6 @@ static const struct of_device_id dt_match[] = {
624 { .compatible = "qcom,kgsl-3d0" }, 678 { .compatible = "qcom,kgsl-3d0" },
625 {} 679 {}
626}; 680};
627MODULE_DEVICE_TABLE(of, dt_match);
628 681
629static struct platform_driver a3xx_driver = { 682static struct platform_driver a3xx_driver = {
630 .probe = a3xx_probe, 683 .probe = a3xx_probe,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index d321099abdd4..28ca8cd8b09e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -73,6 +73,12 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
73 case MSM_PARAM_GMEM_SIZE: 73 case MSM_PARAM_GMEM_SIZE:
74 *value = adreno_gpu->gmem; 74 *value = adreno_gpu->gmem;
75 return 0; 75 return 0;
76 case MSM_PARAM_CHIP_ID:
77 *value = adreno_gpu->rev.patchid |
78 (adreno_gpu->rev.minor << 8) |
79 (adreno_gpu->rev.major << 16) |
80 (adreno_gpu->rev.core << 24);
81 return 0;
76 default: 82 default:
77 DBG("%s: invalid param: %u", gpu->name, param); 83 DBG("%s: invalid param: %u", gpu->name, param);
78 return -EINVAL; 84 return -EINVAL;
@@ -225,19 +231,11 @@ void adreno_flush(struct msm_gpu *gpu)
225void adreno_idle(struct msm_gpu *gpu) 231void adreno_idle(struct msm_gpu *gpu)
226{ 232{
227 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 233 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
228 uint32_t rptr, wptr = get_wptr(gpu->rb); 234 uint32_t wptr = get_wptr(gpu->rb);
229 unsigned long t;
230
231 t = jiffies + ADRENO_IDLE_TIMEOUT;
232
233 /* then wait for CP to drain ringbuffer: */
234 do {
235 rptr = adreno_gpu->memptrs->rptr;
236 if (rptr == wptr)
237 return;
238 } while(time_before(jiffies, t));
239 235
240 DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); 236 /* wait for CP to drain ringbuffer: */
237 if (spin_until(adreno_gpu->memptrs->rptr == wptr))
238 DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
241 239
242 /* TODO maybe we need to reset GPU here to recover from hang? */ 240 /* TODO maybe we need to reset GPU here to recover from hang? */
243} 241}
@@ -260,22 +258,37 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
260} 258}
261#endif 259#endif
262 260
263void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) 261/* would be nice to not have to duplicate the _show() stuff with printk(): */
262void adreno_dump(struct msm_gpu *gpu)
264{ 263{
265 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 264 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
266 uint32_t freedwords; 265
267 unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT; 266 printk("revision: %d (%d.%d.%d.%d)\n",
268 do { 267 adreno_gpu->info->revn, adreno_gpu->rev.core,
269 uint32_t size = gpu->rb->size / 4; 268 adreno_gpu->rev.major, adreno_gpu->rev.minor,
270 uint32_t wptr = get_wptr(gpu->rb); 269 adreno_gpu->rev.patchid);
271 uint32_t rptr = adreno_gpu->memptrs->rptr; 270
272 freedwords = (rptr + (size - 1) - wptr) % size; 271 printk("fence: %d/%d\n", adreno_gpu->memptrs->fence,
273 272 gpu->submitted_fence);
274 if (time_after(jiffies, t)) { 273 printk("rptr: %d\n", adreno_gpu->memptrs->rptr);
275 DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); 274 printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
276 break; 275 printk("rb wptr: %d\n", get_wptr(gpu->rb));
277 } 276
278 } while(freedwords < ndwords); 277}
278
279static uint32_t ring_freewords(struct msm_gpu *gpu)
280{
281 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
282 uint32_t size = gpu->rb->size / 4;
283 uint32_t wptr = get_wptr(gpu->rb);
284 uint32_t rptr = adreno_gpu->memptrs->rptr;
285 return (rptr + (size - 1) - wptr) % size;
286}
287
288void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
289{
290 if (spin_until(ring_freewords(gpu) >= ndwords))
291 DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
279} 292}
280 293
281static const char *iommu_ports[] = { 294static const char *iommu_ports[] = {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index ca11ea4da165..63c36ce33020 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -76,7 +76,20 @@ struct adreno_platform_config {
76#endif 76#endif
77}; 77};
78 78
79#define ADRENO_IDLE_TIMEOUT (20 * 1000) 79#define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
80
81#define spin_until(X) ({ \
82 int __ret = -ETIMEDOUT; \
83 unsigned long __t = jiffies + ADRENO_IDLE_TIMEOUT; \
84 do { \
85 if (X) { \
86 __ret = 0; \
87 break; \
88 } \
89 } while (time_before(jiffies, __t)); \
90 __ret; \
91})
92
80 93
81static inline bool adreno_is_a3xx(struct adreno_gpu *gpu) 94static inline bool adreno_is_a3xx(struct adreno_gpu *gpu)
82{ 95{
@@ -114,6 +127,7 @@ void adreno_idle(struct msm_gpu *gpu);
114#ifdef CONFIG_DEBUG_FS 127#ifdef CONFIG_DEBUG_FS
115void adreno_show(struct msm_gpu *gpu, struct seq_file *m); 128void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
116#endif 129#endif
130void adreno_dump(struct msm_gpu *gpu);
117void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 131void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
118 132
119int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 133int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6f1588aa9071..ae750f6928c1 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -17,8 +17,6 @@
17 17
18#include "hdmi.h" 18#include "hdmi.h"
19 19
20static struct platform_device *hdmi_pdev;
21
22void hdmi_set_mode(struct hdmi *hdmi, bool power_on) 20void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
23{ 21{
24 uint32_t ctrl = 0; 22 uint32_t ctrl = 0;
@@ -67,7 +65,7 @@ void hdmi_destroy(struct kref *kref)
67 if (hdmi->i2c) 65 if (hdmi->i2c)
68 hdmi_i2c_destroy(hdmi->i2c); 66 hdmi_i2c_destroy(hdmi->i2c);
69 67
70 put_device(&hdmi->pdev->dev); 68 platform_set_drvdata(hdmi->pdev, NULL);
71} 69}
72 70
73/* initialize connector */ 71/* initialize connector */
@@ -75,7 +73,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
75{ 73{
76 struct hdmi *hdmi = NULL; 74 struct hdmi *hdmi = NULL;
77 struct msm_drm_private *priv = dev->dev_private; 75 struct msm_drm_private *priv = dev->dev_private;
78 struct platform_device *pdev = hdmi_pdev; 76 struct platform_device *pdev = priv->hdmi_pdev;
79 struct hdmi_platform_config *config; 77 struct hdmi_platform_config *config;
80 int i, ret; 78 int i, ret;
81 79
@@ -95,13 +93,13 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
95 93
96 kref_init(&hdmi->refcount); 94 kref_init(&hdmi->refcount);
97 95
98 get_device(&pdev->dev);
99
100 hdmi->dev = dev; 96 hdmi->dev = dev;
101 hdmi->pdev = pdev; 97 hdmi->pdev = pdev;
102 hdmi->config = config; 98 hdmi->config = config;
103 hdmi->encoder = encoder; 99 hdmi->encoder = encoder;
104 100
101 hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
102
105 /* not sure about which phy maps to which msm.. probably I miss some */ 103 /* not sure about which phy maps to which msm.. probably I miss some */
106 if (config->phy_init) 104 if (config->phy_init)
107 hdmi->phy = config->phy_init(hdmi); 105 hdmi->phy = config->phy_init(hdmi);
@@ -228,6 +226,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
228 priv->bridges[priv->num_bridges++] = hdmi->bridge; 226 priv->bridges[priv->num_bridges++] = hdmi->bridge;
229 priv->connectors[priv->num_connectors++] = hdmi->connector; 227 priv->connectors[priv->num_connectors++] = hdmi->connector;
230 228
229 platform_set_drvdata(pdev, hdmi);
230
231 return hdmi; 231 return hdmi;
232 232
233fail: 233fail:
@@ -249,17 +249,24 @@ fail:
249 249
250#include <linux/of_gpio.h> 250#include <linux/of_gpio.h>
251 251
252static int hdmi_dev_probe(struct platform_device *pdev) 252static void set_hdmi_pdev(struct drm_device *dev,
253 struct platform_device *pdev)
254{
255 struct msm_drm_private *priv = dev->dev_private;
256 priv->hdmi_pdev = pdev;
257}
258
259static int hdmi_bind(struct device *dev, struct device *master, void *data)
253{ 260{
254 static struct hdmi_platform_config config = {}; 261 static struct hdmi_platform_config config = {};
255#ifdef CONFIG_OF 262#ifdef CONFIG_OF
256 struct device_node *of_node = pdev->dev.of_node; 263 struct device_node *of_node = dev->of_node;
257 264
258 int get_gpio(const char *name) 265 int get_gpio(const char *name)
259 { 266 {
260 int gpio = of_get_named_gpio(of_node, name, 0); 267 int gpio = of_get_named_gpio(of_node, name, 0);
261 if (gpio < 0) { 268 if (gpio < 0) {
262 dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", 269 dev_err(dev, "failed to get gpio: %s (%d)\n",
263 name, gpio); 270 name, gpio);
264 gpio = -1; 271 gpio = -1;
265 } 272 }
@@ -305,7 +312,7 @@ static int hdmi_dev_probe(struct platform_device *pdev)
305 config.ddc_data_gpio = 71; 312 config.ddc_data_gpio = 71;
306 config.hpd_gpio = 72; 313 config.hpd_gpio = 72;
307 config.mux_en_gpio = -1; 314 config.mux_en_gpio = -1;
308 config.mux_sel_gpio = 13 + NR_GPIO_IRQS; 315 config.mux_sel_gpio = -1;
309 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) { 316 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
310 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"}; 317 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
311 config.phy_init = hdmi_phy_8960_init; 318 config.phy_init = hdmi_phy_8960_init;
@@ -336,14 +343,30 @@ static int hdmi_dev_probe(struct platform_device *pdev)
336 config.mux_sel_gpio = -1; 343 config.mux_sel_gpio = -1;
337 } 344 }
338#endif 345#endif
339 pdev->dev.platform_data = &config; 346 dev->platform_data = &config;
340 hdmi_pdev = pdev; 347 set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
341 return 0; 348 return 0;
342} 349}
343 350
351static void hdmi_unbind(struct device *dev, struct device *master,
352 void *data)
353{
354 set_hdmi_pdev(dev_get_drvdata(master), NULL);
355}
356
357static const struct component_ops hdmi_ops = {
358 .bind = hdmi_bind,
359 .unbind = hdmi_unbind,
360};
361
362static int hdmi_dev_probe(struct platform_device *pdev)
363{
364 return component_add(&pdev->dev, &hdmi_ops);
365}
366
344static int hdmi_dev_remove(struct platform_device *pdev) 367static int hdmi_dev_remove(struct platform_device *pdev)
345{ 368{
346 hdmi_pdev = NULL; 369 component_del(&pdev->dev, &hdmi_ops);
347 return 0; 370 return 0;
348} 371}
349 372
@@ -351,7 +374,6 @@ static const struct of_device_id dt_match[] = {
351 { .compatible = "qcom,hdmi-tx" }, 374 { .compatible = "qcom,hdmi-tx" },
352 {} 375 {}
353}; 376};
354MODULE_DEVICE_TABLE(of, dt_match);
355 377
356static struct platform_driver hdmi_driver = { 378static struct platform_driver hdmi_driver = {
357 .probe = hdmi_dev_probe, 379 .probe = hdmi_dev_probe,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 41b29add70b1..9fafee6a3e43 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -22,6 +22,7 @@
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
25#include <linux/hdmi.h>
25 26
26#include "msm_drv.h" 27#include "msm_drv.h"
27#include "hdmi.xml.h" 28#include "hdmi.xml.h"
@@ -30,6 +31,12 @@
30struct hdmi_phy; 31struct hdmi_phy;
31struct hdmi_platform_config; 32struct hdmi_platform_config;
32 33
34struct hdmi_audio {
35 bool enabled;
36 struct hdmi_audio_infoframe infoframe;
37 int rate;
38};
39
33struct hdmi { 40struct hdmi {
34 struct kref refcount; 41 struct kref refcount;
35 42
@@ -38,6 +45,13 @@ struct hdmi {
38 45
39 const struct hdmi_platform_config *config; 46 const struct hdmi_platform_config *config;
40 47
48 /* audio state: */
49 struct hdmi_audio audio;
50
51 /* video state: */
52 bool power_on;
53 unsigned long int pixclock;
54
41 void __iomem *mmio; 55 void __iomem *mmio;
42 56
43 struct regulator *hpd_regs[2]; 57 struct regulator *hpd_regs[2];
@@ -132,6 +146,17 @@ struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);
132struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi); 146struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi);
133 147
134/* 148/*
149 * audio:
150 */
151
152int hdmi_audio_update(struct hdmi *hdmi);
153int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
154 uint32_t num_of_channels, uint32_t channel_allocation,
155 uint32_t level_shift, bool down_mix);
156void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
157
158
159/*
135 * hdmi bridge: 160 * hdmi bridge:
136 */ 161 */
137 162
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
new file mode 100644
index 000000000000..872485f60134
--- /dev/null
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/hdmi.h>
19#include "hdmi.h"
20
21
22/* Supported HDMI Audio channels */
23#define MSM_HDMI_AUDIO_CHANNEL_2 0
24#define MSM_HDMI_AUDIO_CHANNEL_4 1
25#define MSM_HDMI_AUDIO_CHANNEL_6 2
26#define MSM_HDMI_AUDIO_CHANNEL_8 3
27
28/* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */
29static int nchannels[] = { 2, 4, 6, 8 };
30
31/* Supported HDMI Audio sample rates */
32#define MSM_HDMI_SAMPLE_RATE_32KHZ 0
33#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1
34#define MSM_HDMI_SAMPLE_RATE_48KHZ 2
35#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3
36#define MSM_HDMI_SAMPLE_RATE_96KHZ 4
37#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5
38#define MSM_HDMI_SAMPLE_RATE_192KHZ 6
39#define MSM_HDMI_SAMPLE_RATE_MAX 7
40
41
42struct hdmi_msm_audio_acr {
43 uint32_t n; /* N parameter for clock regeneration */
44 uint32_t cts; /* CTS parameter for clock regeneration */
45};
46
47struct hdmi_msm_audio_arcs {
48 unsigned long int pixclock;
49 struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX];
50};
51
52#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ }
53
54/* Audio constants lookup table for hdmi_msm_audio_acr_setup */
55/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
56static const struct hdmi_msm_audio_arcs acr_lut[] = {
57 /* 25.200MHz */
58 HDMI_MSM_AUDIO_ARCS(25200, {
59 {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
60 {12288, 25200}, {25088, 28000}, {24576, 25200} }),
61 /* 27.000MHz */
62 HDMI_MSM_AUDIO_ARCS(27000, {
63 {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
64 {12288, 27000}, {25088, 30000}, {24576, 27000} }),
65 /* 27.027MHz */
66 HDMI_MSM_AUDIO_ARCS(27030, {
67 {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
68 {12288, 27027}, {25088, 30030}, {24576, 27027} }),
69 /* 74.250MHz */
70 HDMI_MSM_AUDIO_ARCS(74250, {
71 {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
72 {12288, 74250}, {25088, 82500}, {24576, 74250} }),
73 /* 148.500MHz */
74 HDMI_MSM_AUDIO_ARCS(148500, {
75 {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
76 {12288, 148500}, {25088, 165000}, {24576, 148500} }),
77};
78
79static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock)
80{
81 int i;
82
83 for (i = 0; i < ARRAY_SIZE(acr_lut); i++) {
84 const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i];
85 if (arcs->pixclock == pixclock)
86 return arcs;
87 }
88
89 return NULL;
90}
91
92int hdmi_audio_update(struct hdmi *hdmi)
93{
94 struct hdmi_audio *audio = &hdmi->audio;
95 struct hdmi_audio_infoframe *info = &audio->infoframe;
96 const struct hdmi_msm_audio_arcs *arcs = NULL;
97 bool enabled = audio->enabled;
98 uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
99 uint32_t infofrm_ctrl, audio_config;
100
101 DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, "
102 "level_shift_value=%d, downmix_inhibit=%d, rate=%d",
103 audio->enabled, info->channels, info->channel_allocation,
104 info->level_shift_value, info->downmix_inhibit, audio->rate);
105 DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock);
106
107 if (enabled && !(hdmi->power_on && hdmi->pixclock)) {
108 DBG("disabling audio: no video");
109 enabled = false;
110 }
111
112 if (enabled) {
113 arcs = get_arcs(hdmi->pixclock);
114 if (!arcs) {
115 DBG("disabling audio: unsupported pixclock: %lu",
116 hdmi->pixclock);
117 enabled = false;
118 }
119 }
120
121 /* Read first before writing */
122 acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL);
123 vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL);
124 aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1);
125 infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
126 audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG);
127
128 /* Clear N/CTS selection bits */
129 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK;
130
131 if (enabled) {
132 uint32_t n, cts, multiplier;
133 enum hdmi_acr_cts select;
134 uint8_t buf[14];
135
136 n = arcs->lut[audio->rate].n;
137 cts = arcs->lut[audio->rate].cts;
138
139 if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) ||
140 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) {
141 multiplier = 4;
142 n >>= 2; /* divide N by 4 and use multiplier */
143 } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
144 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) {
145 multiplier = 2;
146 n >>= 1; /* divide N by 2 and use multiplier */
147 } else {
148 multiplier = 1;
149 }
150
151 DBG("n=%u, cts=%u, multiplier=%u", n, cts, multiplier);
152
153 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SOURCE;
154 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY;
155 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier);
156
157 if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) ||
158 (MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
159 (MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate))
160 select = ACR_48;
161 else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) ||
162 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) ||
163 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate))
164 select = ACR_44;
165 else /* default to 32k */
166 select = ACR_32;
167
168 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SELECT(select);
169
170 hdmi_write(hdmi, REG_HDMI_ACR_0(select - 1),
171 HDMI_ACR_0_CTS(cts));
172 hdmi_write(hdmi, REG_HDMI_ACR_1(select - 1),
173 HDMI_ACR_1_N(n));
174
175 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2,
176 COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) |
177 HDMI_AUDIO_PKT_CTRL2_OVERRIDE);
178
179 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT;
180 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND;
181
182 /* configure infoframe: */
183 hdmi_audio_infoframe_pack(info, buf, sizeof(buf));
184 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0,
185 (buf[3] << 0) || (buf[4] << 8) ||
186 (buf[5] << 16) || (buf[6] << 24));
187 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1,
188 (buf[7] << 0) || (buf[8] << 8));
189
190 hdmi_write(hdmi, REG_HDMI_GC, 0);
191
192 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE;
193 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
194
195 aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
196
197 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
198 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
199 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
200 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
201
202 audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK;
203 audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4);
204 audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE;
205 } else {
206 hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
207 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_CONT;
208 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SEND;
209 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE;
210 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
211 aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
212 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
213 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
214 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
215 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
216 audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE;
217 }
218
219 hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl);
220 hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl);
221 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl);
222 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl);
223
224 hdmi_write(hdmi, REG_HDMI_AUD_INT,
225 COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) |
226 COND(enabled, HDMI_AUD_INT_AUD_SAM_DROP_INT));
227
228 hdmi_write(hdmi, REG_HDMI_AUDIO_CFG, audio_config);
229
230
231 DBG("audio %sabled", enabled ? "en" : "dis");
232
233 return 0;
234}
235
236int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
237 uint32_t num_of_channels, uint32_t channel_allocation,
238 uint32_t level_shift, bool down_mix)
239{
240 struct hdmi_audio *audio;
241
242 if (!hdmi)
243 return -ENXIO;
244
245 audio = &hdmi->audio;
246
247 if (num_of_channels >= ARRAY_SIZE(nchannels))
248 return -EINVAL;
249
250 audio->enabled = enabled;
251 audio->infoframe.channels = nchannels[num_of_channels];
252 audio->infoframe.channel_allocation = channel_allocation;
253 audio->infoframe.level_shift_value = level_shift;
254 audio->infoframe.downmix_inhibit = down_mix;
255
256 return hdmi_audio_update(hdmi);
257}
258
259void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate)
260{
261 struct hdmi_audio *audio;
262
263 if (!hdmi)
264 return;
265
266 audio = &hdmi->audio;
267
268 if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX))
269 return;
270
271 audio->rate = rate;
272 hdmi_audio_update(hdmi);
273}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 7d10e55403c6..f6cf745c249e 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -19,11 +19,7 @@
19 19
20struct hdmi_bridge { 20struct hdmi_bridge {
21 struct drm_bridge base; 21 struct drm_bridge base;
22
23 struct hdmi *hdmi; 22 struct hdmi *hdmi;
24 bool power_on;
25
26 unsigned long int pixclock;
27}; 23};
28#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) 24#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
29 25
@@ -52,8 +48,8 @@ static void power_on(struct drm_bridge *bridge)
52 } 48 }
53 49
54 if (config->pwr_clk_cnt > 0) { 50 if (config->pwr_clk_cnt > 0) {
55 DBG("pixclock: %lu", hdmi_bridge->pixclock); 51 DBG("pixclock: %lu", hdmi->pixclock);
56 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi_bridge->pixclock); 52 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
57 if (ret) { 53 if (ret) {
58 dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n", 54 dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
59 config->pwr_clk_names[0], ret); 55 config->pwr_clk_names[0], ret);
@@ -102,12 +98,13 @@ static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
102 98
103 DBG("power up"); 99 DBG("power up");
104 100
105 if (!hdmi_bridge->power_on) { 101 if (!hdmi->power_on) {
106 power_on(bridge); 102 power_on(bridge);
107 hdmi_bridge->power_on = true; 103 hdmi->power_on = true;
104 hdmi_audio_update(hdmi);
108 } 105 }
109 106
110 phy->funcs->powerup(phy, hdmi_bridge->pixclock); 107 phy->funcs->powerup(phy, hdmi->pixclock);
111 hdmi_set_mode(hdmi, true); 108 hdmi_set_mode(hdmi, true);
112} 109}
113 110
@@ -129,9 +126,10 @@ static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
129 hdmi_set_mode(hdmi, false); 126 hdmi_set_mode(hdmi, false);
130 phy->funcs->powerdown(phy); 127 phy->funcs->powerdown(phy);
131 128
132 if (hdmi_bridge->power_on) { 129 if (hdmi->power_on) {
133 power_off(bridge); 130 power_off(bridge);
134 hdmi_bridge->power_on = false; 131 hdmi->power_on = false;
132 hdmi_audio_update(hdmi);
135 } 133 }
136} 134}
137 135
@@ -146,7 +144,7 @@ static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
146 144
147 mode = adjusted_mode; 145 mode = adjusted_mode;
148 146
149 hdmi_bridge->pixclock = mode->clock * 1000; 147 hdmi->pixclock = mode->clock * 1000;
150 148
151 hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1; 149 hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1;
152 150
@@ -194,9 +192,7 @@ static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
194 DBG("frame_ctrl=%08x", frame_ctrl); 192 DBG("frame_ctrl=%08x", frame_ctrl);
195 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); 193 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
196 194
197 // TODO until we have audio, this might be safest: 195 hdmi_audio_update(hdmi);
198 if (hdmi->hdmi_mode)
199 hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
200} 196}
201 197
202static const struct drm_bridge_funcs hdmi_bridge_funcs = { 198static const struct drm_bridge_funcs hdmi_bridge_funcs = {
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 84c5b13b33c9..3e6c0f3ed592 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -120,7 +120,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
120 120
121 /* grab reference to incoming scanout fb: */ 121 /* grab reference to incoming scanout fb: */
122 drm_framebuffer_reference(new_fb); 122 drm_framebuffer_reference(new_fb);
123 mdp4_crtc->base.fb = new_fb; 123 mdp4_crtc->base.primary->fb = new_fb;
124 mdp4_crtc->fb = new_fb; 124 mdp4_crtc->fb = new_fb;
125 125
126 if (old_fb) 126 if (old_fb)
@@ -182,7 +182,7 @@ static void pageflip_cb(struct msm_fence_cb *cb)
182 struct mdp4_crtc *mdp4_crtc = 182 struct mdp4_crtc *mdp4_crtc =
183 container_of(cb, struct mdp4_crtc, pageflip_cb); 183 container_of(cb, struct mdp4_crtc, pageflip_cb);
184 struct drm_crtc *crtc = &mdp4_crtc->base; 184 struct drm_crtc *crtc = &mdp4_crtc->base;
185 struct drm_framebuffer *fb = crtc->fb; 185 struct drm_framebuffer *fb = crtc->primary->fb;
186 186
187 if (!fb) 187 if (!fb)
188 return; 188 return;
@@ -348,14 +348,14 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
348 mode->type, mode->flags); 348 mode->type, mode->flags);
349 349
350 /* grab extra ref for update_scanout() */ 350 /* grab extra ref for update_scanout() */
351 drm_framebuffer_reference(crtc->fb); 351 drm_framebuffer_reference(crtc->primary->fb);
352 352
353 ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb, 353 ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
354 0, 0, mode->hdisplay, mode->vdisplay, 354 0, 0, mode->hdisplay, mode->vdisplay,
355 x << 16, y << 16, 355 x << 16, y << 16,
356 mode->hdisplay << 16, mode->vdisplay << 16); 356 mode->hdisplay << 16, mode->vdisplay << 16);
357 if (ret) { 357 if (ret) {
358 drm_framebuffer_unreference(crtc->fb); 358 drm_framebuffer_unreference(crtc->primary->fb);
359 dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n", 359 dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
360 mdp4_crtc->name, ret); 360 mdp4_crtc->name, ret);
361 return ret; 361 return ret;
@@ -368,7 +368,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
368 /* take data from pipe: */ 368 /* take data from pipe: */
369 mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0); 369 mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
370 mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma), 370 mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
371 crtc->fb->pitches[0]); 371 crtc->primary->fb->pitches[0]);
372 mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma), 372 mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
373 MDP4_DMA_DST_SIZE_WIDTH(0) | 373 MDP4_DMA_DST_SIZE_WIDTH(0) |
374 MDP4_DMA_DST_SIZE_HEIGHT(0)); 374 MDP4_DMA_DST_SIZE_HEIGHT(0));
@@ -378,7 +378,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
378 MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) | 378 MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
379 MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay)); 379 MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
380 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp), 380 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
381 crtc->fb->pitches[0]); 381 crtc->primary->fb->pitches[0]);
382 382
383 mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1); 383 mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
384 384
@@ -388,8 +388,8 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
388 mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000); 388 mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
389 } 389 }
390 390
391 update_fb(crtc, crtc->fb); 391 update_fb(crtc, crtc->primary->fb);
392 update_scanout(crtc, crtc->fb); 392 update_scanout(crtc, crtc->primary->fb);
393 393
394 return 0; 394 return 0;
395} 395}
@@ -420,19 +420,19 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
420 int ret; 420 int ret;
421 421
422 /* grab extra ref for update_scanout() */ 422 /* grab extra ref for update_scanout() */
423 drm_framebuffer_reference(crtc->fb); 423 drm_framebuffer_reference(crtc->primary->fb);
424 424
425 ret = mdp4_plane_mode_set(plane, crtc, crtc->fb, 425 ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
426 0, 0, mode->hdisplay, mode->vdisplay, 426 0, 0, mode->hdisplay, mode->vdisplay,
427 x << 16, y << 16, 427 x << 16, y << 16,
428 mode->hdisplay << 16, mode->vdisplay << 16); 428 mode->hdisplay << 16, mode->vdisplay << 16);
429 if (ret) { 429 if (ret) {
430 drm_framebuffer_unreference(crtc->fb); 430 drm_framebuffer_unreference(crtc->primary->fb);
431 return ret; 431 return ret;
432 } 432 }
433 433
434 update_fb(crtc, crtc->fb); 434 update_fb(crtc, crtc->primary->fb);
435 update_scanout(crtc, crtc->fb); 435 update_scanout(crtc, crtc->primary->fb);
436 436
437 return 0; 437 return 0;
438} 438}
@@ -740,6 +740,9 @@ void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
740 740
741void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane) 741void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
742{ 742{
743 /* don't actually detatch our primary plane: */
744 if (to_mdp4_crtc(crtc)->plane == plane)
745 return;
743 set_attach(crtc, mdp4_plane_pipe(plane), NULL); 746 set_attach(crtc, mdp4_plane_pipe(plane), NULL);
744} 747}
745 748
@@ -791,7 +794,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
791 794
792 INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb); 795 INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
793 796
794 drm_crtc_init(dev, crtc, &mdp4_crtc_funcs); 797 drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp4_crtc_funcs);
795 drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs); 798 drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
796 799
797 mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base); 800 mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 1e893dd13859..66f33dba1ebb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -222,6 +222,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
222 struct drm_plane *plane = NULL; 222 struct drm_plane *plane = NULL;
223 struct mdp4_plane *mdp4_plane; 223 struct mdp4_plane *mdp4_plane;
224 int ret; 224 int ret;
225 enum drm_plane_type type;
225 226
226 mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL); 227 mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
227 if (!mdp4_plane) { 228 if (!mdp4_plane) {
@@ -237,9 +238,10 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
237 mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, 238 mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats,
238 ARRAY_SIZE(mdp4_plane->formats)); 239 ARRAY_SIZE(mdp4_plane->formats));
239 240
240 drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, 241 type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
241 mdp4_plane->formats, mdp4_plane->nformats, 242 drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
242 private_plane); 243 mdp4_plane->formats, mdp4_plane->nformats,
244 type);
243 245
244 mdp4_plane_install_properties(plane, &plane->base); 246 mdp4_plane_install_properties(plane, &plane->base);
245 247
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index f2794021f086..6ea10bdb6e8f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -102,7 +102,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
102 102
103 /* grab reference to incoming scanout fb: */ 103 /* grab reference to incoming scanout fb: */
104 drm_framebuffer_reference(new_fb); 104 drm_framebuffer_reference(new_fb);
105 mdp5_crtc->base.fb = new_fb; 105 mdp5_crtc->base.primary->fb = new_fb;
106 mdp5_crtc->fb = new_fb; 106 mdp5_crtc->fb = new_fb;
107 107
108 if (old_fb) 108 if (old_fb)
@@ -289,14 +289,14 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
289 mode->type, mode->flags); 289 mode->type, mode->flags);
290 290
291 /* grab extra ref for update_scanout() */ 291 /* grab extra ref for update_scanout() */
292 drm_framebuffer_reference(crtc->fb); 292 drm_framebuffer_reference(crtc->primary->fb);
293 293
294 ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb, 294 ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
295 0, 0, mode->hdisplay, mode->vdisplay, 295 0, 0, mode->hdisplay, mode->vdisplay,
296 x << 16, y << 16, 296 x << 16, y << 16,
297 mode->hdisplay << 16, mode->vdisplay << 16); 297 mode->hdisplay << 16, mode->vdisplay << 16);
298 if (ret) { 298 if (ret) {
299 drm_framebuffer_unreference(crtc->fb); 299 drm_framebuffer_unreference(crtc->primary->fb);
300 dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n", 300 dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
301 mdp5_crtc->name, ret); 301 mdp5_crtc->name, ret);
302 return ret; 302 return ret;
@@ -306,8 +306,8 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
306 MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) | 306 MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
307 MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay)); 307 MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
308 308
309 update_fb(crtc, crtc->fb); 309 update_fb(crtc, crtc->primary->fb);
310 update_scanout(crtc, crtc->fb); 310 update_scanout(crtc, crtc->primary->fb);
311 311
312 return 0; 312 return 0;
313} 313}
@@ -338,19 +338,19 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
338 int ret; 338 int ret;
339 339
340 /* grab extra ref for update_scanout() */ 340 /* grab extra ref for update_scanout() */
341 drm_framebuffer_reference(crtc->fb); 341 drm_framebuffer_reference(crtc->primary->fb);
342 342
343 ret = mdp5_plane_mode_set(plane, crtc, crtc->fb, 343 ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
344 0, 0, mode->hdisplay, mode->vdisplay, 344 0, 0, mode->hdisplay, mode->vdisplay,
345 x << 16, y << 16, 345 x << 16, y << 16,
346 mode->hdisplay << 16, mode->vdisplay << 16); 346 mode->hdisplay << 16, mode->vdisplay << 16);
347 if (ret) { 347 if (ret) {
348 drm_framebuffer_unreference(crtc->fb); 348 drm_framebuffer_unreference(crtc->primary->fb);
349 return ret; 349 return ret;
350 } 350 }
351 351
352 update_fb(crtc, crtc->fb); 352 update_fb(crtc, crtc->primary->fb);
353 update_scanout(crtc, crtc->fb); 353 update_scanout(crtc, crtc->primary->fb);
354 354
355 return 0; 355 return 0;
356} 356}
@@ -524,6 +524,9 @@ void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
524 524
525void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane) 525void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
526{ 526{
527 /* don't actually detatch our primary plane: */
528 if (to_mdp5_crtc(crtc)->plane == plane)
529 return;
527 set_attach(crtc, mdp5_plane_pipe(plane), NULL); 530 set_attach(crtc, mdp5_plane_pipe(plane), NULL);
528} 531}
529 532
@@ -559,7 +562,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
559 562
560 INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb); 563 INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
561 564
562 drm_crtc_init(dev, crtc, &mdp5_crtc_funcs); 565 drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs);
563 drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs); 566 drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
564 567
565 mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base); 568 mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 0ac8bb5e7e85..47f7bbb9c15a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -358,6 +358,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
358 struct drm_plane *plane = NULL; 358 struct drm_plane *plane = NULL;
359 struct mdp5_plane *mdp5_plane; 359 struct mdp5_plane *mdp5_plane;
360 int ret; 360 int ret;
361 enum drm_plane_type type;
361 362
362 mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL); 363 mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
363 if (!mdp5_plane) { 364 if (!mdp5_plane) {
@@ -373,9 +374,10 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
373 mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats, 374 mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
374 ARRAY_SIZE(mdp5_plane->formats)); 375 ARRAY_SIZE(mdp5_plane->formats));
375 376
376 drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs, 377 type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
377 mdp5_plane->formats, mdp5_plane->nformats, 378 drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
378 private_plane); 379 mdp5_plane->formats, mdp5_plane->nformats,
380 type);
379 381
380 mdp5_plane_install_properties(plane, &plane->base); 382 mdp5_plane_install_properties(plane, &plane->base);
381 383
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c
index 3be48f7c36be..03455b64a245 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c
@@ -101,7 +101,8 @@ void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask)
101 .count = 1, 101 .count = 1,
102 }; 102 };
103 mdp_irq_register(mdp_kms, &wait.irq); 103 mdp_irq_register(mdp_kms, &wait.irq);
104 wait_event(wait_event, (wait.count <= 0)); 104 wait_event_timeout(wait_event, (wait.count <= 0),
105 msecs_to_jiffies(100));
105 mdp_irq_unregister(mdp_kms, &wait.irq); 106 mdp_irq_unregister(mdp_kms, &wait.irq);
106} 107}
107 108
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e6adafc7eff3..f9de156b9e65 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -56,6 +56,10 @@ static char *vram;
56MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); 56MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
57module_param(vram, charp, 0); 57module_param(vram, charp, 0);
58 58
59/*
60 * Util/helpers:
61 */
62
59void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, 63void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
60 const char *dbgname) 64 const char *dbgname)
61{ 65{
@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev)
143 priv->vram.paddr, &attrs); 147 priv->vram.paddr, &attrs);
144 } 148 }
145 149
150 component_unbind_all(dev->dev, dev);
151
146 dev->dev_private = NULL; 152 dev->dev_private = NULL;
147 153
148 kfree(priv); 154 kfree(priv);
@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
175 struct msm_kms *kms; 181 struct msm_kms *kms;
176 int ret; 182 int ret;
177 183
184
178 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 185 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
179 if (!priv) { 186 if (!priv) {
180 dev_err(dev->dev, "failed to allocate private data\n"); 187 dev_err(dev->dev, "failed to allocate private data\n");
@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
226 (uint32_t)(priv->vram.paddr + size)); 233 (uint32_t)(priv->vram.paddr + size));
227 } 234 }
228 235
236 platform_set_drvdata(pdev, dev);
237
238 /* Bind all our sub-components: */
239 ret = component_bind_all(dev->dev, dev);
240 if (ret)
241 return ret;
242
229 switch (get_mdp_ver(pdev)) { 243 switch (get_mdp_ver(pdev)) {
230 case 4: 244 case 4:
231 kms = mdp4_kms_init(dev); 245 kms = mdp4_kms_init(dev);
@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
281 goto fail; 295 goto fail;
282 } 296 }
283 297
284 platform_set_drvdata(pdev, dev);
285
286#ifdef CONFIG_DRM_MSM_FBDEV 298#ifdef CONFIG_DRM_MSM_FBDEV
287 priv->fbdev = msm_fbdev_init(dev); 299 priv->fbdev = msm_fbdev_init(dev);
288#endif 300#endif
@@ -311,7 +323,6 @@ static void load_gpu(struct drm_device *dev)
311 gpu = NULL; 323 gpu = NULL;
312 /* not fatal */ 324 /* not fatal */
313 } 325 }
314 mutex_unlock(&dev->struct_mutex);
315 326
316 if (gpu) { 327 if (gpu) {
317 int ret; 328 int ret;
@@ -321,10 +332,16 @@ static void load_gpu(struct drm_device *dev)
321 dev_err(dev->dev, "gpu hw init failed: %d\n", ret); 332 dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
322 gpu->funcs->destroy(gpu); 333 gpu->funcs->destroy(gpu);
323 gpu = NULL; 334 gpu = NULL;
335 } else {
336 /* give inactive pm a chance to kick in: */
337 msm_gpu_retire(gpu);
324 } 338 }
339
325 } 340 }
326 341
327 priv->gpu = gpu; 342 priv->gpu = gpu;
343
344 mutex_unlock(&dev->struct_mutex);
328} 345}
329 346
330static int msm_open(struct drm_device *dev, struct drm_file *file) 347static int msm_open(struct drm_device *dev, struct drm_file *file)
@@ -647,6 +664,12 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
647 struct drm_file *file) 664 struct drm_file *file)
648{ 665{
649 struct drm_msm_gem_new *args = data; 666 struct drm_msm_gem_new *args = data;
667
668 if (args->flags & ~MSM_BO_FLAGS) {
669 DRM_ERROR("invalid flags: %08x\n", args->flags);
670 return -EINVAL;
671 }
672
650 return msm_gem_new_handle(dev, file, args->size, 673 return msm_gem_new_handle(dev, file, args->size,
651 args->flags, &args->handle); 674 args->flags, &args->handle);
652} 675}
@@ -660,6 +683,11 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
660 struct drm_gem_object *obj; 683 struct drm_gem_object *obj;
661 int ret; 684 int ret;
662 685
686 if (args->op & ~MSM_PREP_FLAGS) {
687 DRM_ERROR("invalid op: %08x\n", args->op);
688 return -EINVAL;
689 }
690
663 obj = drm_gem_object_lookup(dev, file, args->handle); 691 obj = drm_gem_object_lookup(dev, file, args->handle);
664 if (!obj) 692 if (!obj)
665 return -ENOENT; 693 return -ENOENT;
@@ -714,7 +742,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
714 struct drm_file *file) 742 struct drm_file *file)
715{ 743{
716 struct drm_msm_wait_fence *args = data; 744 struct drm_msm_wait_fence *args = data;
717 return msm_wait_fence_interruptable(dev, args->fence, &TS(args->timeout)); 745
746 if (args->pad) {
747 DRM_ERROR("invalid pad: %08x\n", args->pad);
748 return -EINVAL;
749 }
750
751 return msm_wait_fence_interruptable(dev, args->fence,
752 &TS(args->timeout));
718} 753}
719 754
720static const struct drm_ioctl_desc msm_ioctls[] = { 755static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -819,18 +854,110 @@ static const struct dev_pm_ops msm_pm_ops = {
819}; 854};
820 855
821/* 856/*
857 * Componentized driver support:
858 */
859
860#ifdef CONFIG_OF
861/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx
862 * (or probably any other).. so probably some room for some helpers
863 */
864static int compare_of(struct device *dev, void *data)
865{
866 return dev->of_node == data;
867}
868
869static int msm_drm_add_components(struct device *master, struct master *m)
870{
871 struct device_node *np = master->of_node;
872 unsigned i;
873 int ret;
874
875 for (i = 0; ; i++) {
876 struct device_node *node;
877
878 node = of_parse_phandle(np, "connectors", i);
879 if (!node)
880 break;
881
882 ret = component_master_add_child(m, compare_of, node);
883 of_node_put(node);
884
885 if (ret)
886 return ret;
887 }
888 return 0;
889}
890#else
891static int compare_dev(struct device *dev, void *data)
892{
893 return dev == data;
894}
895
896static int msm_drm_add_components(struct device *master, struct master *m)
897{
898 /* For non-DT case, it kinda sucks. We don't actually have a way
899 * to know whether or not we are waiting for certain devices (or if
900 * they are simply not present). But for non-DT we only need to
901 * care about apq8064/apq8060/etc (all mdp4/a3xx):
902 */
903 static const char *devnames[] = {
904 "hdmi_msm.0", "kgsl-3d0.0",
905 };
906 int i;
907
908 DBG("Adding components..");
909
910 for (i = 0; i < ARRAY_SIZE(devnames); i++) {
911 struct device *dev;
912 int ret;
913
914 dev = bus_find_device_by_name(&platform_bus_type,
915 NULL, devnames[i]);
916 if (!dev) {
917 dev_info(master, "still waiting for %s\n", devnames[i]);
918 return -EPROBE_DEFER;
919 }
920
921 ret = component_master_add_child(m, compare_dev, dev);
922 if (ret) {
923 DBG("could not add child: %d", ret);
924 return ret;
925 }
926 }
927
928 return 0;
929}
930#endif
931
932static int msm_drm_bind(struct device *dev)
933{
934 return drm_platform_init(&msm_driver, to_platform_device(dev));
935}
936
937static void msm_drm_unbind(struct device *dev)
938{
939 drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
940}
941
942static const struct component_master_ops msm_drm_ops = {
943 .add_components = msm_drm_add_components,
944 .bind = msm_drm_bind,
945 .unbind = msm_drm_unbind,
946};
947
948/*
822 * Platform driver: 949 * Platform driver:
823 */ 950 */
824 951
825static int msm_pdev_probe(struct platform_device *pdev) 952static int msm_pdev_probe(struct platform_device *pdev)
826{ 953{
827 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 954 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
828 return drm_platform_init(&msm_driver, pdev); 955 return component_master_add(&pdev->dev, &msm_drm_ops);
829} 956}
830 957
831static int msm_pdev_remove(struct platform_device *pdev) 958static int msm_pdev_remove(struct platform_device *pdev)
832{ 959{
833 drm_put_dev(platform_get_drvdata(pdev)); 960 component_master_del(&pdev->dev, &msm_drm_ops);
834 961
835 return 0; 962 return 0;
836} 963}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3d63269c5b29..9d10ee0b5aac 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -22,6 +22,7 @@
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/component.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <linux/pm.h> 27#include <linux/pm.h>
27#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
@@ -69,6 +70,9 @@ struct msm_drm_private {
69 70
70 struct msm_kms *kms; 71 struct msm_kms *kms;
71 72
73 /* subordinate devices, if present: */
74 struct platform_device *hdmi_pdev, *gpu_pdev;
75
72 /* when we have more than one 'msm_gpu' these need to be an array: */ 76 /* when we have more than one 'msm_gpu' these need to be an array: */
73 struct msm_gpu *gpu; 77 struct msm_gpu *gpu;
74 struct msm_file_private *lastctx; 78 struct msm_file_private *lastctx;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 5423e914e491..1f1f4cffdaed 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -23,7 +23,6 @@
23 * Cmdstream submission: 23 * Cmdstream submission:
24 */ 24 */
25 25
26#define BO_INVALID_FLAGS ~(MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
27/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */ 26/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
28#define BO_VALID 0x8000 27#define BO_VALID 0x8000
29#define BO_LOCKED 0x4000 28#define BO_LOCKED 0x4000
@@ -77,7 +76,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
77 goto out_unlock; 76 goto out_unlock;
78 } 77 }
79 78
80 if (submit_bo.flags & BO_INVALID_FLAGS) { 79 if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
81 DRM_ERROR("invalid flags: %x\n", submit_bo.flags); 80 DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
82 ret = -EINVAL; 81 ret = -EINVAL;
83 goto out_unlock; 82 goto out_unlock;
@@ -369,6 +368,18 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
369 goto out; 368 goto out;
370 } 369 }
371 370
371 /* validate input from userspace: */
372 switch (submit_cmd.type) {
373 case MSM_SUBMIT_CMD_BUF:
374 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
375 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
376 break;
377 default:
378 DRM_ERROR("invalid type: %08x\n", submit_cmd.type);
379 ret = -EINVAL;
380 goto out;
381 }
382
372 ret = submit_bo(submit, submit_cmd.submit_idx, 383 ret = submit_bo(submit, submit_cmd.submit_idx,
373 &msm_obj, &iova, NULL); 384 &msm_obj, &iova, NULL);
374 if (ret) 385 if (ret)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0cfe3f426ee4..3e667ca1f2b9 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -154,9 +154,18 @@ static int disable_axi(struct msm_gpu *gpu)
154 154
155int msm_gpu_pm_resume(struct msm_gpu *gpu) 155int msm_gpu_pm_resume(struct msm_gpu *gpu)
156{ 156{
157 struct drm_device *dev = gpu->dev;
157 int ret; 158 int ret;
158 159
159 DBG("%s", gpu->name); 160 DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt);
161
162 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
163
164 if (gpu->active_cnt++ > 0)
165 return 0;
166
167 if (WARN_ON(gpu->active_cnt <= 0))
168 return -EINVAL;
160 169
161 ret = enable_pwrrail(gpu); 170 ret = enable_pwrrail(gpu);
162 if (ret) 171 if (ret)
@@ -175,9 +184,18 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
175 184
176int msm_gpu_pm_suspend(struct msm_gpu *gpu) 185int msm_gpu_pm_suspend(struct msm_gpu *gpu)
177{ 186{
187 struct drm_device *dev = gpu->dev;
178 int ret; 188 int ret;
179 189
180 DBG("%s", gpu->name); 190 DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt);
191
192 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
193
194 if (--gpu->active_cnt > 0)
195 return 0;
196
197 if (WARN_ON(gpu->active_cnt < 0))
198 return -EINVAL;
181 199
182 ret = disable_axi(gpu); 200 ret = disable_axi(gpu);
183 if (ret) 201 if (ret)
@@ -195,6 +213,55 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
195} 213}
196 214
197/* 215/*
216 * Inactivity detection (for suspend):
217 */
218
219static void inactive_worker(struct work_struct *work)
220{
221 struct msm_gpu *gpu = container_of(work, struct msm_gpu, inactive_work);
222 struct drm_device *dev = gpu->dev;
223
224 if (gpu->inactive)
225 return;
226
227 DBG("%s: inactive!\n", gpu->name);
228 mutex_lock(&dev->struct_mutex);
229 if (!(msm_gpu_active(gpu) || gpu->inactive)) {
230 disable_axi(gpu);
231 disable_clk(gpu);
232 gpu->inactive = true;
233 }
234 mutex_unlock(&dev->struct_mutex);
235}
236
237static void inactive_handler(unsigned long data)
238{
239 struct msm_gpu *gpu = (struct msm_gpu *)data;
240 struct msm_drm_private *priv = gpu->dev->dev_private;
241
242 queue_work(priv->wq, &gpu->inactive_work);
243}
244
245/* cancel inactive timer and make sure we are awake: */
246static void inactive_cancel(struct msm_gpu *gpu)
247{
248 DBG("%s", gpu->name);
249 del_timer(&gpu->inactive_timer);
250 if (gpu->inactive) {
251 enable_clk(gpu);
252 enable_axi(gpu);
253 gpu->inactive = false;
254 }
255}
256
257static void inactive_start(struct msm_gpu *gpu)
258{
259 DBG("%s", gpu->name);
260 mod_timer(&gpu->inactive_timer,
261 round_jiffies_up(jiffies + DRM_MSM_INACTIVE_JIFFIES));
262}
263
264/*
198 * Hangcheck detection for locked gpu: 265 * Hangcheck detection for locked gpu:
199 */ 266 */
200 267
@@ -206,7 +273,10 @@ static void recover_worker(struct work_struct *work)
206 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); 273 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
207 274
208 mutex_lock(&dev->struct_mutex); 275 mutex_lock(&dev->struct_mutex);
209 gpu->funcs->recover(gpu); 276 if (msm_gpu_active(gpu)) {
277 inactive_cancel(gpu);
278 gpu->funcs->recover(gpu);
279 }
210 mutex_unlock(&dev->struct_mutex); 280 mutex_unlock(&dev->struct_mutex);
211 281
212 msm_gpu_retire(gpu); 282 msm_gpu_retire(gpu);
@@ -281,6 +351,9 @@ static void retire_worker(struct work_struct *work)
281 } 351 }
282 352
283 mutex_unlock(&dev->struct_mutex); 353 mutex_unlock(&dev->struct_mutex);
354
355 if (!msm_gpu_active(gpu))
356 inactive_start(gpu);
284} 357}
285 358
286/* call from irq handler to schedule work to retire bo's */ 359/* call from irq handler to schedule work to retire bo's */
@@ -302,6 +375,8 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
302 375
303 gpu->submitted_fence = submit->fence; 376 gpu->submitted_fence = submit->fence;
304 377
378 inactive_cancel(gpu);
379
305 ret = gpu->funcs->submit(gpu, submit, ctx); 380 ret = gpu->funcs->submit(gpu, submit, ctx);
306 priv->lastctx = ctx; 381 priv->lastctx = ctx;
307 382
@@ -357,11 +432,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
357 gpu->dev = drm; 432 gpu->dev = drm;
358 gpu->funcs = funcs; 433 gpu->funcs = funcs;
359 gpu->name = name; 434 gpu->name = name;
435 gpu->inactive = true;
360 436
361 INIT_LIST_HEAD(&gpu->active_list); 437 INIT_LIST_HEAD(&gpu->active_list);
362 INIT_WORK(&gpu->retire_work, retire_worker); 438 INIT_WORK(&gpu->retire_work, retire_worker);
439 INIT_WORK(&gpu->inactive_work, inactive_worker);
363 INIT_WORK(&gpu->recover_work, recover_worker); 440 INIT_WORK(&gpu->recover_work, recover_worker);
364 441
442 setup_timer(&gpu->inactive_timer, inactive_handler,
443 (unsigned long)gpu);
365 setup_timer(&gpu->hangcheck_timer, hangcheck_handler, 444 setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
366 (unsigned long)gpu); 445 (unsigned long)gpu);
367 446
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 458db8c64c28..fad27008922f 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -72,6 +72,10 @@ struct msm_gpu {
72 72
73 uint32_t submitted_fence; 73 uint32_t submitted_fence;
74 74
75 /* is gpu powered/active? */
76 int active_cnt;
77 bool inactive;
78
75 /* worker for handling active-list retiring: */ 79 /* worker for handling active-list retiring: */
76 struct work_struct retire_work; 80 struct work_struct retire_work;
77 81
@@ -91,7 +95,12 @@ struct msm_gpu {
91 uint32_t bsc; 95 uint32_t bsc;
92#endif 96#endif
93 97
94 /* Hang Detction: */ 98 /* Hang and Inactivity Detection:
99 */
100#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
101#define DRM_MSM_INACTIVE_JIFFIES msecs_to_jiffies(DRM_MSM_INACTIVE_PERIOD)
102 struct timer_list inactive_timer;
103 struct work_struct inactive_work;
95#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */ 104#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
96#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD) 105#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD)
97 struct timer_list hangcheck_timer; 106 struct timer_list hangcheck_timer;
@@ -99,6 +108,11 @@ struct msm_gpu {
99 struct work_struct recover_work; 108 struct work_struct recover_work;
100}; 109};
101 110
111static inline bool msm_gpu_active(struct msm_gpu *gpu)
112{
113 return gpu->submitted_fence > gpu->funcs->last_fence(gpu);
114}
115
102static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data) 116static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data)
103{ 117{
104 msm_writel(data, gpu->mmio + (reg << 2)); 118 msm_writel(data, gpu->mmio + (reg << 2));
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index d310c195bdfe..b7d216264775 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -48,6 +48,7 @@ nouveau-y += core/subdev/bios/therm.o
48nouveau-y += core/subdev/bios/vmap.o 48nouveau-y += core/subdev/bios/vmap.o
49nouveau-y += core/subdev/bios/volt.o 49nouveau-y += core/subdev/bios/volt.o
50nouveau-y += core/subdev/bios/xpio.o 50nouveau-y += core/subdev/bios/xpio.o
51nouveau-y += core/subdev/bios/P0260.o
51nouveau-y += core/subdev/bus/hwsq.o 52nouveau-y += core/subdev/bus/hwsq.o
52nouveau-y += core/subdev/bus/nv04.o 53nouveau-y += core/subdev/bus/nv04.o
53nouveau-y += core/subdev/bus/nv31.o 54nouveau-y += core/subdev/bus/nv31.o
@@ -77,6 +78,7 @@ nouveau-y += core/subdev/devinit/nv98.o
77nouveau-y += core/subdev/devinit/nva3.o 78nouveau-y += core/subdev/devinit/nva3.o
78nouveau-y += core/subdev/devinit/nvaf.o 79nouveau-y += core/subdev/devinit/nvaf.o
79nouveau-y += core/subdev/devinit/nvc0.o 80nouveau-y += core/subdev/devinit/nvc0.o
81nouveau-y += core/subdev/devinit/gm107.o
80nouveau-y += core/subdev/fb/base.o 82nouveau-y += core/subdev/fb/base.o
81nouveau-y += core/subdev/fb/nv04.o 83nouveau-y += core/subdev/fb/nv04.o
82nouveau-y += core/subdev/fb/nv10.o 84nouveau-y += core/subdev/fb/nv10.o
@@ -100,6 +102,7 @@ nouveau-y += core/subdev/fb/nvaa.o
100nouveau-y += core/subdev/fb/nvaf.o 102nouveau-y += core/subdev/fb/nvaf.o
101nouveau-y += core/subdev/fb/nvc0.o 103nouveau-y += core/subdev/fb/nvc0.o
102nouveau-y += core/subdev/fb/nve0.o 104nouveau-y += core/subdev/fb/nve0.o
105nouveau-y += core/subdev/fb/gm107.o
103nouveau-y += core/subdev/fb/ramnv04.o 106nouveau-y += core/subdev/fb/ramnv04.o
104nouveau-y += core/subdev/fb/ramnv10.o 107nouveau-y += core/subdev/fb/ramnv10.o
105nouveau-y += core/subdev/fb/ramnv1a.o 108nouveau-y += core/subdev/fb/ramnv1a.o
@@ -114,6 +117,7 @@ nouveau-y += core/subdev/fb/ramnva3.o
114nouveau-y += core/subdev/fb/ramnvaa.o 117nouveau-y += core/subdev/fb/ramnvaa.o
115nouveau-y += core/subdev/fb/ramnvc0.o 118nouveau-y += core/subdev/fb/ramnvc0.o
116nouveau-y += core/subdev/fb/ramnve0.o 119nouveau-y += core/subdev/fb/ramnve0.o
120nouveau-y += core/subdev/fb/ramgm107.o
117nouveau-y += core/subdev/fb/sddr3.o 121nouveau-y += core/subdev/fb/sddr3.o
118nouveau-y += core/subdev/fb/gddr5.o 122nouveau-y += core/subdev/fb/gddr5.o
119nouveau-y += core/subdev/gpio/base.o 123nouveau-y += core/subdev/gpio/base.o
@@ -136,7 +140,8 @@ nouveau-y += core/subdev/instmem/base.o
136nouveau-y += core/subdev/instmem/nv04.o 140nouveau-y += core/subdev/instmem/nv04.o
137nouveau-y += core/subdev/instmem/nv40.o 141nouveau-y += core/subdev/instmem/nv40.o
138nouveau-y += core/subdev/instmem/nv50.o 142nouveau-y += core/subdev/instmem/nv50.o
139nouveau-y += core/subdev/ltcg/nvc0.o 143nouveau-y += core/subdev/ltcg/gf100.o
144nouveau-y += core/subdev/ltcg/gm107.o
140nouveau-y += core/subdev/mc/base.o 145nouveau-y += core/subdev/mc/base.o
141nouveau-y += core/subdev/mc/nv04.o 146nouveau-y += core/subdev/mc/nv04.o
142nouveau-y += core/subdev/mc/nv40.o 147nouveau-y += core/subdev/mc/nv40.o
@@ -170,6 +175,7 @@ nouveau-y += core/subdev/therm/nva3.o
170nouveau-y += core/subdev/therm/nvd0.o 175nouveau-y += core/subdev/therm/nvd0.o
171nouveau-y += core/subdev/timer/base.o 176nouveau-y += core/subdev/timer/base.o
172nouveau-y += core/subdev/timer/nv04.o 177nouveau-y += core/subdev/timer/nv04.o
178nouveau-y += core/subdev/timer/gk20a.o
173nouveau-y += core/subdev/vm/base.o 179nouveau-y += core/subdev/vm/base.o
174nouveau-y += core/subdev/vm/nv04.o 180nouveau-y += core/subdev/vm/nv04.o
175nouveau-y += core/subdev/vm/nv41.o 181nouveau-y += core/subdev/vm/nv41.o
@@ -206,6 +212,7 @@ nouveau-y += core/engine/device/nv40.o
206nouveau-y += core/engine/device/nv50.o 212nouveau-y += core/engine/device/nv50.o
207nouveau-y += core/engine/device/nvc0.o 213nouveau-y += core/engine/device/nvc0.o
208nouveau-y += core/engine/device/nve0.o 214nouveau-y += core/engine/device/nve0.o
215nouveau-y += core/engine/device/gm100.o
209nouveau-y += core/engine/disp/base.o 216nouveau-y += core/engine/disp/base.o
210nouveau-y += core/engine/disp/nv04.o 217nouveau-y += core/engine/disp/nv04.o
211nouveau-y += core/engine/disp/nv50.o 218nouveau-y += core/engine/disp/nv50.o
@@ -216,6 +223,7 @@ nouveau-y += core/engine/disp/nva3.o
216nouveau-y += core/engine/disp/nvd0.o 223nouveau-y += core/engine/disp/nvd0.o
217nouveau-y += core/engine/disp/nve0.o 224nouveau-y += core/engine/disp/nve0.o
218nouveau-y += core/engine/disp/nvf0.o 225nouveau-y += core/engine/disp/nvf0.o
226nouveau-y += core/engine/disp/gm107.o
219nouveau-y += core/engine/disp/dacnv50.o 227nouveau-y += core/engine/disp/dacnv50.o
220nouveau-y += core/engine/disp/dport.o 228nouveau-y += core/engine/disp/dport.o
221nouveau-y += core/engine/disp/hdanva3.o 229nouveau-y += core/engine/disp/hdanva3.o
@@ -242,13 +250,14 @@ nouveau-y += core/engine/graph/ctxnv40.o
242nouveau-y += core/engine/graph/ctxnv50.o 250nouveau-y += core/engine/graph/ctxnv50.o
243nouveau-y += core/engine/graph/ctxnvc0.o 251nouveau-y += core/engine/graph/ctxnvc0.o
244nouveau-y += core/engine/graph/ctxnvc1.o 252nouveau-y += core/engine/graph/ctxnvc1.o
245nouveau-y += core/engine/graph/ctxnvc3.o 253nouveau-y += core/engine/graph/ctxnvc4.o
246nouveau-y += core/engine/graph/ctxnvc8.o 254nouveau-y += core/engine/graph/ctxnvc8.o
247nouveau-y += core/engine/graph/ctxnvd7.o 255nouveau-y += core/engine/graph/ctxnvd7.o
248nouveau-y += core/engine/graph/ctxnvd9.o 256nouveau-y += core/engine/graph/ctxnvd9.o
249nouveau-y += core/engine/graph/ctxnve4.o 257nouveau-y += core/engine/graph/ctxnve4.o
250nouveau-y += core/engine/graph/ctxnvf0.o 258nouveau-y += core/engine/graph/ctxnvf0.o
251nouveau-y += core/engine/graph/ctxnv108.o 259nouveau-y += core/engine/graph/ctxnv108.o
260nouveau-y += core/engine/graph/ctxgm107.o
252nouveau-y += core/engine/graph/nv04.o 261nouveau-y += core/engine/graph/nv04.o
253nouveau-y += core/engine/graph/nv10.o 262nouveau-y += core/engine/graph/nv10.o
254nouveau-y += core/engine/graph/nv20.o 263nouveau-y += core/engine/graph/nv20.o
@@ -261,13 +270,14 @@ nouveau-y += core/engine/graph/nv40.o
261nouveau-y += core/engine/graph/nv50.o 270nouveau-y += core/engine/graph/nv50.o
262nouveau-y += core/engine/graph/nvc0.o 271nouveau-y += core/engine/graph/nvc0.o
263nouveau-y += core/engine/graph/nvc1.o 272nouveau-y += core/engine/graph/nvc1.o
264nouveau-y += core/engine/graph/nvc3.o 273nouveau-y += core/engine/graph/nvc4.o
265nouveau-y += core/engine/graph/nvc8.o 274nouveau-y += core/engine/graph/nvc8.o
266nouveau-y += core/engine/graph/nvd7.o 275nouveau-y += core/engine/graph/nvd7.o
267nouveau-y += core/engine/graph/nvd9.o 276nouveau-y += core/engine/graph/nvd9.o
268nouveau-y += core/engine/graph/nve4.o 277nouveau-y += core/engine/graph/nve4.o
269nouveau-y += core/engine/graph/nvf0.o 278nouveau-y += core/engine/graph/nvf0.o
270nouveau-y += core/engine/graph/nv108.o 279nouveau-y += core/engine/graph/nv108.o
280nouveau-y += core/engine/graph/gm107.o
271nouveau-y += core/engine/mpeg/nv31.o 281nouveau-y += core/engine/mpeg/nv31.o
272nouveau-y += core/engine/mpeg/nv40.o 282nouveau-y += core/engine/mpeg/nv40.o
273nouveau-y += core/engine/mpeg/nv44.o 283nouveau-y += core/engine/mpeg/nv44.o
diff --git a/drivers/gpu/drm/nouveau/core/core/namedb.c b/drivers/gpu/drm/nouveau/core/core/namedb.c
index 1ce95a8709df..0594a599f6fb 100644
--- a/drivers/gpu/drm/nouveau/core/core/namedb.c
+++ b/drivers/gpu/drm/nouveau/core/core/namedb.c
@@ -167,7 +167,7 @@ int
167nouveau_namedb_create_(struct nouveau_object *parent, 167nouveau_namedb_create_(struct nouveau_object *parent,
168 struct nouveau_object *engine, 168 struct nouveau_object *engine,
169 struct nouveau_oclass *oclass, u32 pclass, 169 struct nouveau_oclass *oclass, u32 pclass,
170 struct nouveau_oclass *sclass, u32 engcls, 170 struct nouveau_oclass *sclass, u64 engcls,
171 int length, void **pobject) 171 int length, void **pobject)
172{ 172{
173 struct nouveau_namedb *namedb; 173 struct nouveau_namedb *namedb;
diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c
index 313380ce632d..dee5d1235e9b 100644
--- a/drivers/gpu/drm/nouveau/core/core/parent.c
+++ b/drivers/gpu/drm/nouveau/core/core/parent.c
@@ -49,7 +49,7 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
49 49
50 mask = nv_parent(parent)->engine; 50 mask = nv_parent(parent)->engine;
51 while (mask) { 51 while (mask) {
52 int i = ffsll(mask) - 1; 52 int i = __ffs64(mask);
53 53
54 if (nv_iclass(parent, NV_CLIENT_CLASS)) 54 if (nv_iclass(parent, NV_CLIENT_CLASS))
55 engine = nv_engine(nv_client(parent)->device); 55 engine = nv_engine(nv_client(parent)->device);
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index dd01c6c435d6..18c8c7245b73 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
131 if (ret) 131 if (ret)
132 return ret; 132 return ret;
133 133
134 mmio_base = pci_resource_start(device->pdev, 0); 134 mmio_base = nv_device_resource_start(device, 0);
135 mmio_size = pci_resource_len(device->pdev, 0); 135 mmio_size = nv_device_resource_len(device, 0);
136 136
137 /* translate api disable mask into internal mapping */ 137 /* translate api disable mask into internal mapping */
138 disable = args->debug0; 138 disable = args->debug0;
@@ -185,6 +185,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
185 case 0x0e0: 185 case 0x0e0:
186 case 0x0f0: 186 case 0x0f0:
187 case 0x100: device->card_type = NV_E0; break; 187 case 0x100: device->card_type = NV_E0; break;
188 case 0x110: device->card_type = GM100; break;
188 default: 189 default:
189 break; 190 break;
190 } 191 }
@@ -208,6 +209,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
208 case NV_C0: 209 case NV_C0:
209 case NV_D0: ret = nvc0_identify(device); break; 210 case NV_D0: ret = nvc0_identify(device); break;
210 case NV_E0: ret = nve0_identify(device); break; 211 case NV_E0: ret = nve0_identify(device); break;
212 case GM100: ret = gm100_identify(device); break;
211 default: 213 default:
212 ret = -EINVAL; 214 ret = -EINVAL;
213 break; 215 break;
@@ -446,6 +448,72 @@ nouveau_device_dtor(struct nouveau_object *object)
446 nouveau_engine_destroy(&device->base); 448 nouveau_engine_destroy(&device->base);
447} 449}
448 450
451resource_size_t
452nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
453{
454 if (nv_device_is_pci(device)) {
455 return pci_resource_start(device->pdev, bar);
456 } else {
457 struct resource *res;
458 res = platform_get_resource(device->platformdev,
459 IORESOURCE_MEM, bar);
460 if (!res)
461 return 0;
462 return res->start;
463 }
464}
465
466resource_size_t
467nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
468{
469 if (nv_device_is_pci(device)) {
470 return pci_resource_len(device->pdev, bar);
471 } else {
472 struct resource *res;
473 res = platform_get_resource(device->platformdev,
474 IORESOURCE_MEM, bar);
475 if (!res)
476 return 0;
477 return resource_size(res);
478 }
479}
480
481dma_addr_t
482nv_device_map_page(struct nouveau_device *device, struct page *page)
483{
484 dma_addr_t ret;
485
486 if (nv_device_is_pci(device)) {
487 ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
488 PCI_DMA_BIDIRECTIONAL);
489 if (pci_dma_mapping_error(device->pdev, ret))
490 ret = 0;
491 } else {
492 ret = page_to_phys(page);
493 }
494
495 return ret;
496}
497
498void
499nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
500{
501 if (nv_device_is_pci(device))
502 pci_unmap_page(device->pdev, addr, PAGE_SIZE,
503 PCI_DMA_BIDIRECTIONAL);
504}
505
506int
507nv_device_get_irq(struct nouveau_device *device, bool stall)
508{
509 if (nv_device_is_pci(device)) {
510 return device->pdev->irq;
511 } else {
512 return platform_get_irq_byname(device->platformdev,
513 stall ? "stall" : "nonstall");
514 }
515}
516
449static struct nouveau_oclass 517static struct nouveau_oclass
450nouveau_device_oclass = { 518nouveau_device_oclass = {
451 .handle = NV_ENGINE(DEVICE, 0x00), 519 .handle = NV_ENGINE(DEVICE, 0x00),
@@ -457,8 +525,8 @@ nouveau_device_oclass = {
457}; 525};
458 526
459int 527int
460nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname, 528nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
461 const char *cfg, const char *dbg, 529 const char *sname, const char *cfg, const char *dbg,
462 int length, void **pobject) 530 int length, void **pobject)
463{ 531{
464 struct nouveau_device *device; 532 struct nouveau_device *device;
@@ -476,7 +544,14 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
476 if (ret) 544 if (ret)
477 goto done; 545 goto done;
478 546
479 device->pdev = pdev; 547 switch (type) {
548 case NOUVEAU_BUS_PCI:
549 device->pdev = dev;
550 break;
551 case NOUVEAU_BUS_PLATFORM:
552 device->platformdev = dev;
553 break;
554 }
480 device->handle = name; 555 device->handle = name;
481 device->cfgopt = cfg; 556 device->cfgopt = cfg;
482 device->dbgopt = dbg; 557 device->dbgopt = dbg;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
new file mode 100644
index 000000000000..d258c21c4a22
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bus.h>
27#include <subdev/gpio.h>
28#include <subdev/i2c.h>
29#include <subdev/clock.h>
30#include <subdev/therm.h>
31#include <subdev/mxm.h>
32#include <subdev/devinit.h>
33#include <subdev/mc.h>
34#include <subdev/timer.h>
35#include <subdev/fb.h>
36#include <subdev/ltcg.h>
37#include <subdev/ibus.h>
38#include <subdev/instmem.h>
39#include <subdev/vm.h>
40#include <subdev/bar.h>
41#include <subdev/pwr.h>
42#include <subdev/volt.h>
43
44#include <engine/device.h>
45#include <engine/dmaobj.h>
46#include <engine/fifo.h>
47#include <engine/software.h>
48#include <engine/graph.h>
49#include <engine/disp.h>
50#include <engine/copy.h>
51#include <engine/bsp.h>
52#include <engine/vp.h>
53#include <engine/ppp.h>
54#include <engine/perfmon.h>
55
56int
57gm100_identify(struct nouveau_device *device)
58{
59 switch (device->chipset) {
60 case 0x117:
61 device->cname = "GM107";
62 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
63 device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
64 device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
65 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass;
66#if 0
67 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
68#endif
69 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
70 device->oclass[NVDEV_SUBDEV_DEVINIT] = gm107_devinit_oclass;
71 device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
72 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
73 device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
74 device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass;
75 device->oclass[NVDEV_SUBDEV_LTCG ] = gm107_ltcg_oclass;
76 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
77 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
78 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
79 device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
80#if 0
81 device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
82 device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
83#endif
84 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
85 device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
86 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
87 device->oclass[NVDEV_ENGINE_GR ] = gm107_graph_oclass;
88 device->oclass[NVDEV_ENGINE_DISP ] = gm107_disp_oclass;
89 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
90#if 0
91 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
92#endif
93 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
94#if 0
95 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
96 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
97 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
98#endif
99 break;
100 default:
101 nv_fatal(device, "unknown Maxwell chipset\n");
102 return -EINVAL;
103 }
104
105 return 0;
106}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
index 32113b08c4d5..0a51ff4e9e00 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
@@ -60,7 +60,7 @@ nv04_identify(struct nouveau_device *device)
60 device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass; 60 device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
61 device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass; 61 device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
62 device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; 62 device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
63 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 63 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
64 break; 64 break;
65 case 0x05: 65 case 0x05:
66 device->cname = "NV05"; 66 device->cname = "NV05";
@@ -78,7 +78,7 @@ nv04_identify(struct nouveau_device *device)
78 device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass; 78 device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
79 device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass; 79 device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
80 device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; 80 device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
81 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 81 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
82 break; 82 break;
83 default: 83 default:
84 nv_fatal(device, "unknown RIVA chipset\n"); 84 nv_fatal(device, "unknown RIVA chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
index 744f15d7e131..e008de8b51b0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
@@ -60,7 +60,7 @@ nv10_identify(struct nouveau_device *device)
60 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 60 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
61 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 61 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
62 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 62 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
63 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 63 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
64 break; 64 break;
65 case 0x15: 65 case 0x15:
66 device->cname = "NV15"; 66 device->cname = "NV15";
@@ -79,7 +79,7 @@ nv10_identify(struct nouveau_device *device)
79 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; 79 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
80 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 80 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
81 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 81 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
82 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 82 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
83 break; 83 break;
84 case 0x16: 84 case 0x16:
85 device->cname = "NV16"; 85 device->cname = "NV16";
@@ -98,7 +98,7 @@ nv10_identify(struct nouveau_device *device)
98 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; 98 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
99 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 99 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
100 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 100 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
101 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 101 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
102 break; 102 break;
103 case 0x1a: 103 case 0x1a:
104 device->cname = "nForce"; 104 device->cname = "nForce";
@@ -117,7 +117,7 @@ nv10_identify(struct nouveau_device *device)
117 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; 117 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
118 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 118 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
119 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 119 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
120 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 120 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
121 break; 121 break;
122 case 0x11: 122 case 0x11:
123 device->cname = "NV11"; 123 device->cname = "NV11";
@@ -136,7 +136,7 @@ nv10_identify(struct nouveau_device *device)
136 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; 136 device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
137 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 137 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
138 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 138 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
139 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 139 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
140 break; 140 break;
141 case 0x17: 141 case 0x17:
142 device->cname = "NV17"; 142 device->cname = "NV17";
@@ -155,7 +155,7 @@ nv10_identify(struct nouveau_device *device)
155 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 155 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
156 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 156 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
157 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 157 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
158 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 158 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
159 break; 159 break;
160 case 0x1f: 160 case 0x1f:
161 device->cname = "nForce2"; 161 device->cname = "nForce2";
@@ -174,7 +174,7 @@ nv10_identify(struct nouveau_device *device)
174 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 174 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
175 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 175 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
176 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 176 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
177 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 177 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
178 break; 178 break;
179 case 0x18: 179 case 0x18:
180 device->cname = "NV18"; 180 device->cname = "NV18";
@@ -193,7 +193,7 @@ nv10_identify(struct nouveau_device *device)
193 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 193 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
194 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 194 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
195 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; 195 device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
196 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 196 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
197 break; 197 break;
198 default: 198 default:
199 nv_fatal(device, "unknown Celsius chipset\n"); 199 nv_fatal(device, "unknown Celsius chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
index 27ba61fb2710..7b629a3aed05 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
@@ -63,7 +63,7 @@ nv20_identify(struct nouveau_device *device)
63 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 63 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
64 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 64 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
65 device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass; 65 device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass;
66 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 66 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
67 break; 67 break;
68 case 0x25: 68 case 0x25:
69 device->cname = "NV25"; 69 device->cname = "NV25";
@@ -82,7 +82,7 @@ nv20_identify(struct nouveau_device *device)
82 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 82 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
83 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 83 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
84 device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; 84 device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
85 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 85 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
86 break; 86 break;
87 case 0x28: 87 case 0x28:
88 device->cname = "NV28"; 88 device->cname = "NV28";
@@ -101,7 +101,7 @@ nv20_identify(struct nouveau_device *device)
101 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 101 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
102 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 102 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
103 device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; 103 device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
104 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 104 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
105 break; 105 break;
106 case 0x2a: 106 case 0x2a:
107 device->cname = "NV2A"; 107 device->cname = "NV2A";
@@ -120,7 +120,7 @@ nv20_identify(struct nouveau_device *device)
120 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 120 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
121 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 121 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
122 device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass; 122 device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass;
123 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 123 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
124 break; 124 break;
125 default: 125 default:
126 nv_fatal(device, "unknown Kelvin chipset\n"); 126 nv_fatal(device, "unknown Kelvin chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
index fd47ace67543..7dfddd5a1908 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
@@ -63,7 +63,7 @@ nv30_identify(struct nouveau_device *device)
63 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 63 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
64 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 64 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
65 device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; 65 device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
66 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 66 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
67 break; 67 break;
68 case 0x35: 68 case 0x35:
69 device->cname = "NV35"; 69 device->cname = "NV35";
@@ -82,7 +82,7 @@ nv30_identify(struct nouveau_device *device)
82 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; 82 device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
83 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 83 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
84 device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; 84 device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
85 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 85 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
86 break; 86 break;
87 case 0x31: 87 case 0x31:
88 device->cname = "NV31"; 88 device->cname = "NV31";
@@ -102,7 +102,7 @@ nv30_identify(struct nouveau_device *device)
102 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 102 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
103 device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; 103 device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
104 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; 104 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
105 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 105 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
106 break; 106 break;
107 case 0x36: 107 case 0x36:
108 device->cname = "NV36"; 108 device->cname = "NV36";
@@ -122,7 +122,7 @@ nv30_identify(struct nouveau_device *device)
122 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 122 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
123 device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; 123 device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
124 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; 124 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
125 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 125 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
126 break; 126 break;
127 case 0x34: 127 case 0x34:
128 device->cname = "NV34"; 128 device->cname = "NV34";
@@ -142,7 +142,7 @@ nv30_identify(struct nouveau_device *device)
142 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 142 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
143 device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass; 143 device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass;
144 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; 144 device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
145 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 145 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
146 break; 146 break;
147 default: 147 default:
148 nv_fatal(device, "unknown Rankine chipset\n"); 148 nv_fatal(device, "unknown Rankine chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index 08b88591ed60..7c1ce6cf4f1f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -70,7 +70,7 @@ nv40_identify(struct nouveau_device *device)
70 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 70 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
71 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 71 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
72 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 72 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
73 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 73 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
74 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 74 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
75 break; 75 break;
76 case 0x41: 76 case 0x41:
@@ -93,7 +93,7 @@ nv40_identify(struct nouveau_device *device)
93 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 93 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
94 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 94 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
95 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 95 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
96 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 96 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
97 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 97 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
98 break; 98 break;
99 case 0x42: 99 case 0x42:
@@ -116,7 +116,7 @@ nv40_identify(struct nouveau_device *device)
116 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 116 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
117 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 117 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
118 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 118 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
119 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 119 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
120 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 120 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
121 break; 121 break;
122 case 0x43: 122 case 0x43:
@@ -139,7 +139,7 @@ nv40_identify(struct nouveau_device *device)
139 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 139 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
140 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 140 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
141 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 141 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
142 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 142 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
143 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 143 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
144 break; 144 break;
145 case 0x45: 145 case 0x45:
@@ -162,7 +162,7 @@ nv40_identify(struct nouveau_device *device)
162 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 162 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
163 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 163 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
164 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 164 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
165 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 165 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
166 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 166 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
167 break; 167 break;
168 case 0x47: 168 case 0x47:
@@ -185,7 +185,7 @@ nv40_identify(struct nouveau_device *device)
185 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 185 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
186 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 186 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
187 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 187 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
188 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 188 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
189 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 189 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
190 break; 190 break;
191 case 0x49: 191 case 0x49:
@@ -208,7 +208,7 @@ nv40_identify(struct nouveau_device *device)
208 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 208 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
209 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 209 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
210 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 210 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
211 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 211 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
212 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 212 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
213 break; 213 break;
214 case 0x4b: 214 case 0x4b:
@@ -231,7 +231,7 @@ nv40_identify(struct nouveau_device *device)
231 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 231 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
232 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 232 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
233 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 233 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
234 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 234 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
235 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 235 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
236 break; 236 break;
237 case 0x44: 237 case 0x44:
@@ -254,7 +254,7 @@ nv40_identify(struct nouveau_device *device)
254 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 254 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
255 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 255 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
256 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 256 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
257 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 257 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
258 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 258 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
259 break; 259 break;
260 case 0x46: 260 case 0x46:
@@ -277,7 +277,7 @@ nv40_identify(struct nouveau_device *device)
277 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 277 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
278 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 278 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
279 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 279 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
280 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 280 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
281 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 281 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
282 break; 282 break;
283 case 0x4a: 283 case 0x4a:
@@ -300,7 +300,7 @@ nv40_identify(struct nouveau_device *device)
300 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 300 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
301 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 301 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
302 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 302 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
303 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 303 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
304 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 304 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
305 break; 305 break;
306 case 0x4c: 306 case 0x4c:
@@ -323,7 +323,7 @@ nv40_identify(struct nouveau_device *device)
323 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 323 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
324 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 324 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
325 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 325 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
326 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 326 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
327 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 327 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
328 break; 328 break;
329 case 0x4e: 329 case 0x4e:
@@ -346,7 +346,7 @@ nv40_identify(struct nouveau_device *device)
346 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 346 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
347 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 347 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
348 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 348 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
349 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 349 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
350 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 350 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
351 break; 351 break;
352 case 0x63: 352 case 0x63:
@@ -369,7 +369,7 @@ nv40_identify(struct nouveau_device *device)
369 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 369 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
370 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 370 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
371 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 371 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
372 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 372 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
373 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 373 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
374 break; 374 break;
375 case 0x67: 375 case 0x67:
@@ -392,7 +392,7 @@ nv40_identify(struct nouveau_device *device)
392 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 392 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
393 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 393 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
394 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 394 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
395 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 395 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
396 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 396 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
397 break; 397 break;
398 case 0x68: 398 case 0x68:
@@ -415,7 +415,7 @@ nv40_identify(struct nouveau_device *device)
415 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass; 415 device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
416 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 416 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
417 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 417 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
418 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 418 device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
419 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass; 419 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
420 break; 420 break;
421 default: 421 default:
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
index 81d5c26643d5..66499fa0f758 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -79,7 +79,7 @@ nv50_identify(struct nouveau_device *device)
79 device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass; 79 device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
80 device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; 80 device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
81 device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass; 81 device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass;
82 device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; 82 device->oclass[NVDEV_ENGINE_DISP ] = nv50_disp_oclass;
83 device->oclass[NVDEV_ENGINE_PERFMON] = nv50_perfmon_oclass; 83 device->oclass[NVDEV_ENGINE_PERFMON] = nv50_perfmon_oclass;
84 break; 84 break;
85 case 0x84: 85 case 0x84:
@@ -107,7 +107,7 @@ nv50_identify(struct nouveau_device *device)
107 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 107 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
108 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 108 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
109 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 109 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
110 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 110 device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
111 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 111 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
112 break; 112 break;
113 case 0x86: 113 case 0x86:
@@ -135,7 +135,7 @@ nv50_identify(struct nouveau_device *device)
135 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 135 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
136 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 136 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
137 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 137 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
138 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 138 device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
139 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 139 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
140 break; 140 break;
141 case 0x92: 141 case 0x92:
@@ -163,7 +163,7 @@ nv50_identify(struct nouveau_device *device)
163 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 163 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
164 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 164 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
165 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 165 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
166 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 166 device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
167 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 167 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
168 break; 168 break;
169 case 0x94: 169 case 0x94:
@@ -191,7 +191,7 @@ nv50_identify(struct nouveau_device *device)
191 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 191 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
192 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 192 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
193 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 193 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
194 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 194 device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
195 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 195 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
196 break; 196 break;
197 case 0x96: 197 case 0x96:
@@ -219,7 +219,7 @@ nv50_identify(struct nouveau_device *device)
219 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 219 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
220 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 220 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
221 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 221 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
222 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 222 device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
223 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 223 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
224 break; 224 break;
225 case 0x98: 225 case 0x98:
@@ -247,7 +247,7 @@ nv50_identify(struct nouveau_device *device)
247 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; 247 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
248 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 248 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
249 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 249 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
250 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 250 device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
251 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 251 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
252 break; 252 break;
253 case 0xa0: 253 case 0xa0:
@@ -275,7 +275,7 @@ nv50_identify(struct nouveau_device *device)
275 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; 275 device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
276 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 276 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
277 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 277 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
278 device->oclass[NVDEV_ENGINE_DISP ] = &nva0_disp_oclass; 278 device->oclass[NVDEV_ENGINE_DISP ] = nva0_disp_oclass;
279 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 279 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
280 break; 280 break;
281 case 0xaa: 281 case 0xaa:
@@ -303,7 +303,7 @@ nv50_identify(struct nouveau_device *device)
303 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; 303 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
304 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 304 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
305 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 305 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
306 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 306 device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
307 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 307 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
308 break; 308 break;
309 case 0xac: 309 case 0xac:
@@ -331,7 +331,7 @@ nv50_identify(struct nouveau_device *device)
331 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; 331 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
332 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 332 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
333 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 333 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
334 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 334 device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
335 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass; 335 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
336 break; 336 break;
337 case 0xa3: 337 case 0xa3:
@@ -361,7 +361,7 @@ nv50_identify(struct nouveau_device *device)
361 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 361 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
362 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 362 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
363 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 363 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
364 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 364 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
365 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass; 365 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
366 break; 366 break;
367 case 0xa5: 367 case 0xa5:
@@ -390,7 +390,7 @@ nv50_identify(struct nouveau_device *device)
390 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 390 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
391 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 391 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
392 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 392 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
393 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 393 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
394 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass; 394 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
395 break; 395 break;
396 case 0xa8: 396 case 0xa8:
@@ -419,7 +419,7 @@ nv50_identify(struct nouveau_device *device)
419 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 419 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
420 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 420 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
421 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 421 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
422 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 422 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
423 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass; 423 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
424 break; 424 break;
425 case 0xaf: 425 case 0xaf:
@@ -448,7 +448,7 @@ nv50_identify(struct nouveau_device *device)
448 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 448 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
449 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 449 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
450 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 450 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
451 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 451 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
452 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass; 452 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
453 break; 453 break;
454 default: 454 default:
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index b7d66b59f43d..2075b3027052 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -70,7 +70,7 @@ nvc0_identify(struct nouveau_device *device)
70 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 70 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
72 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 72 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
73 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 73 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
74 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 74 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
75 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 75 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
76 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 76 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -86,7 +86,7 @@ nvc0_identify(struct nouveau_device *device)
86 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 86 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
87 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 87 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
88 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 88 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
89 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 89 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
90 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 90 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
91 break; 91 break;
92 case 0xc4: 92 case 0xc4:
@@ -102,7 +102,7 @@ nvc0_identify(struct nouveau_device *device)
102 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 102 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
103 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 103 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
104 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 104 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
105 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 105 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
106 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 106 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
107 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 107 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
108 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 108 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -112,13 +112,13 @@ nvc0_identify(struct nouveau_device *device)
112 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; 112 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
113 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass; 113 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
114 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 114 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
115 device->oclass[NVDEV_ENGINE_GR ] = nvc3_graph_oclass; 115 device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
116 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass; 116 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
117 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 117 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
118 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 118 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
119 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 119 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
120 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 120 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
121 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 121 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
122 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 122 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
123 break; 123 break;
124 case 0xc3: 124 case 0xc3:
@@ -134,7 +134,7 @@ nvc0_identify(struct nouveau_device *device)
134 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 134 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
135 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 135 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
136 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 136 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
137 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 137 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
138 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 138 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
139 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 139 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
140 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 140 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -144,12 +144,12 @@ nvc0_identify(struct nouveau_device *device)
144 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; 144 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
145 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass; 145 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
146 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 146 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
147 device->oclass[NVDEV_ENGINE_GR ] = nvc3_graph_oclass; 147 device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
148 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass; 148 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
149 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 149 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
150 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 150 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
151 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 151 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
152 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 152 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
153 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 153 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
154 break; 154 break;
155 case 0xce: 155 case 0xce:
@@ -165,7 +165,7 @@ nvc0_identify(struct nouveau_device *device)
165 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 165 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
166 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 166 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
167 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 167 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
168 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 168 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
169 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 169 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
170 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 170 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
171 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 171 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -175,13 +175,13 @@ nvc0_identify(struct nouveau_device *device)
175 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; 175 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
176 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass; 176 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
177 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 177 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
178 device->oclass[NVDEV_ENGINE_GR ] = nvc3_graph_oclass; 178 device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
179 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass; 179 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
180 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 180 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
181 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 181 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
182 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 182 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
183 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 183 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
184 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 184 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
185 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 185 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
186 break; 186 break;
187 case 0xcf: 187 case 0xcf:
@@ -197,7 +197,7 @@ nvc0_identify(struct nouveau_device *device)
197 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 197 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
198 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 198 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
199 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 199 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
200 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 200 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
201 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 201 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
202 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 202 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
203 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 203 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -207,13 +207,13 @@ nvc0_identify(struct nouveau_device *device)
207 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; 207 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
208 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass; 208 device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
209 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 209 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
210 device->oclass[NVDEV_ENGINE_GR ] = nvc3_graph_oclass; 210 device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
211 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass; 211 device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
212 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 212 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
213 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 213 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
214 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 214 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
215 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 215 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
216 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 216 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
217 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 217 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
218 break; 218 break;
219 case 0xc1: 219 case 0xc1:
@@ -229,7 +229,7 @@ nvc0_identify(struct nouveau_device *device)
229 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 229 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
230 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 230 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
231 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 231 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
232 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 232 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
233 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 233 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
234 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 234 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
235 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 235 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -244,7 +244,7 @@ nvc0_identify(struct nouveau_device *device)
244 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 244 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
245 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 245 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
246 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 246 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
247 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 247 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
248 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 248 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
249 break; 249 break;
250 case 0xc8: 250 case 0xc8:
@@ -260,7 +260,7 @@ nvc0_identify(struct nouveau_device *device)
260 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 260 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
261 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 261 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
262 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 262 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
263 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 263 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
264 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 264 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
265 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 265 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
266 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 266 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -276,7 +276,7 @@ nvc0_identify(struct nouveau_device *device)
276 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 276 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
277 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 277 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
278 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 278 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
279 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 279 device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
280 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 280 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
281 break; 281 break;
282 case 0xd9: 282 case 0xd9:
@@ -292,7 +292,7 @@ nvc0_identify(struct nouveau_device *device)
292 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 292 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
293 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 293 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
294 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 294 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
295 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 295 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
296 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 296 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
297 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 297 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
298 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 298 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -307,7 +307,7 @@ nvc0_identify(struct nouveau_device *device)
307 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 307 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
308 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 308 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
309 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 309 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
310 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; 310 device->oclass[NVDEV_ENGINE_DISP ] = nvd0_disp_oclass;
311 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 311 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
312 break; 312 break;
313 case 0xd7: 313 case 0xd7:
@@ -323,7 +323,7 @@ nvc0_identify(struct nouveau_device *device)
323 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 323 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
324 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 324 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
325 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; 325 device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
326 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 326 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
327 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; 327 device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
328 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 328 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
329 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 329 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -336,7 +336,7 @@ nvc0_identify(struct nouveau_device *device)
336 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 336 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
337 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 337 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
338 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 338 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
339 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; 339 device->oclass[NVDEV_ENGINE_DISP ] = nvd0_disp_oclass;
340 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; 340 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
341 break; 341 break;
342 default: 342 default:
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 987edbc30a09..9784cbf8a9d2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -70,7 +70,7 @@ nve0_identify(struct nouveau_device *device)
70 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 70 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
72 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; 72 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
73 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 73 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
74 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; 74 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
75 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 75 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
76 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 76 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -81,7 +81,7 @@ nve0_identify(struct nouveau_device *device)
81 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass; 81 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
82 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 82 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
83 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass; 83 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
84 device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass; 84 device->oclass[NVDEV_ENGINE_DISP ] = nve0_disp_oclass;
85 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; 85 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
86 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; 86 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
87 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; 87 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
@@ -103,7 +103,7 @@ nve0_identify(struct nouveau_device *device)
103 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 103 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
104 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 104 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
105 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; 105 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
106 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 106 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
107 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; 107 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
108 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 108 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
109 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 109 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -114,7 +114,7 @@ nve0_identify(struct nouveau_device *device)
114 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass; 114 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
115 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 115 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
116 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass; 116 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
117 device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass; 117 device->oclass[NVDEV_ENGINE_DISP ] = nve0_disp_oclass;
118 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; 118 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
119 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; 119 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
120 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; 120 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
@@ -136,7 +136,7 @@ nve0_identify(struct nouveau_device *device)
136 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 136 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
137 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 137 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
138 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; 138 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
139 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 139 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
140 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; 140 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
141 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 141 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
142 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 142 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -147,7 +147,7 @@ nve0_identify(struct nouveau_device *device)
147 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass; 147 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
148 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 148 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
149 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass; 149 device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
150 device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass; 150 device->oclass[NVDEV_ENGINE_DISP ] = nve0_disp_oclass;
151 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; 151 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
152 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; 152 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
153 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; 153 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
@@ -169,7 +169,7 @@ nve0_identify(struct nouveau_device *device)
169 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 169 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
170 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 170 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
171 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; 171 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
172 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 172 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
173 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; 173 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
174 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 174 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
175 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 175 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -180,7 +180,7 @@ nve0_identify(struct nouveau_device *device)
180 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass; 180 device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
181 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 181 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
182 device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass; 182 device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
183 device->oclass[NVDEV_ENGINE_DISP ] = &nvf0_disp_oclass; 183 device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass;
184 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; 184 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
185 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; 185 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
186 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; 186 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
@@ -204,7 +204,7 @@ nve0_identify(struct nouveau_device *device)
204 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; 204 device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
205 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 205 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
206 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; 206 device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
207 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 207 device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
208 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; 208 device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
209 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; 209 device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
210 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; 210 device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
@@ -215,7 +215,7 @@ nve0_identify(struct nouveau_device *device)
215 device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass; 215 device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
216 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; 216 device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
217 device->oclass[NVDEV_ENGINE_GR ] = nv108_graph_oclass; 217 device->oclass[NVDEV_ENGINE_GR ] = nv108_graph_oclass;
218 device->oclass[NVDEV_ENGINE_DISP ] = &nvf0_disp_oclass; 218 device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass;
219 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; 219 device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
220 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; 220 device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
221 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; 221 device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index 1bd4c63369c1..3ca2d25b7f5e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -273,7 +273,7 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
273 .outp = outp, 273 .outp = outp,
274 .head = head, 274 .head = head,
275 }, *dp = &_dp; 275 }, *dp = &_dp;
276 const u32 bw_list[] = { 270000, 162000, 0 }; 276 const u32 bw_list[] = { 540000, 270000, 162000, 0 };
277 const u32 *link_bw = bw_list; 277 const u32 *link_bw = bw_list;
278 u8 hdr, cnt, len; 278 u8 hdr, cnt, len;
279 u32 data; 279 u32 data;
@@ -312,6 +312,14 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
312 ERR("failed to read DPCD\n"); 312 ERR("failed to read DPCD\n");
313 } 313 }
314 314
315 /* bring capabilities within encoder limits */
316 if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
317 dp->dpcd[2] &= ~0x1f;
318 dp->dpcd[2] |= dp->outp->dpconf.link_nr;
319 }
320 if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
321 dp->dpcd[1] = dp->outp->dpconf.link_bw;
322
315 /* adjust required bandwidth for 8B/10B coding overhead */ 323 /* adjust required bandwidth for 8B/10B coding overhead */
316 datarate = (datarate / 8) * 10; 324 datarate = (datarate / 8) * 10;
317 325
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
new file mode 100644
index 000000000000..cf6f59677b74
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
@@ -0,0 +1,101 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <engine/software.h>
26#include <engine/disp.h>
27
28#include <core/class.h>
29
30#include "nv50.h"
31
32/*******************************************************************************
33 * Base display object
34 ******************************************************************************/
35
36static struct nouveau_oclass
37gm107_disp_sclass[] = {
38 { GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
39 { GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
40 { GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
41 { GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
42 { GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
43 {}
44};
45
46static struct nouveau_oclass
47gm107_disp_base_oclass[] = {
48 { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
49 {}
50};
51
52/*******************************************************************************
53 * Display engine implementation
54 ******************************************************************************/
55
56static int
57gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
58 struct nouveau_oclass *oclass, void *data, u32 size,
59 struct nouveau_object **pobject)
60{
61 struct nv50_disp_priv *priv;
62 int heads = nv_rd32(parent, 0x022448);
63 int ret;
64
65 ret = nouveau_disp_create(parent, engine, oclass, heads,
66 "PDISP", "display", &priv);
67 *pobject = nv_object(priv);
68 if (ret)
69 return ret;
70
71 nv_engine(priv)->sclass = gm107_disp_base_oclass;
72 nv_engine(priv)->cclass = &nv50_disp_cclass;
73 nv_subdev(priv)->intr = nvd0_disp_intr;
74 INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
75 priv->sclass = gm107_disp_sclass;
76 priv->head.nr = heads;
77 priv->dac.nr = 3;
78 priv->sor.nr = 4;
79 priv->dac.power = nv50_dac_power;
80 priv->dac.sense = nv50_dac_sense;
81 priv->sor.power = nv50_sor_power;
82 priv->sor.hda_eld = nvd0_hda_eld;
83 priv->sor.hdmi = nvd0_hdmi_ctrl;
84 priv->sor.dp = &nvd0_sor_dp_func;
85 return 0;
86}
87
88struct nouveau_oclass *
89gm107_disp_oclass = &(struct nv50_disp_impl) {
90 .base.base.handle = NV_ENGINE(DISP, 0x07),
91 .base.base.ofuncs = &(struct nouveau_ofuncs) {
92 .ctor = gm107_disp_ctor,
93 .dtor = _nouveau_disp_dtor,
94 .init = _nouveau_disp_init,
95 .fini = _nouveau_disp_fini,
96 },
97 .mthd.core = &nve0_disp_mast_mthd_chan,
98 .mthd.base = &nvd0_disp_sync_mthd_chan,
99 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
100 .mthd.prev = -0x020000,
101}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index 7cf8b1348632..6c89af792889 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -22,7 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <engine/disp.h> 25#include "priv.h"
26 26
27#include <core/event.h> 27#include <core/event.h>
28#include <core/class.h> 28#include <core/class.h>
@@ -138,13 +138,13 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
138 return 0; 138 return 0;
139} 139}
140 140
141struct nouveau_oclass 141struct nouveau_oclass *
142nv04_disp_oclass = { 142nv04_disp_oclass = &(struct nouveau_disp_impl) {
143 .handle = NV_ENGINE(DISP, 0x04), 143 .base.handle = NV_ENGINE(DISP, 0x04),
144 .ofuncs = &(struct nouveau_ofuncs) { 144 .base.ofuncs = &(struct nouveau_ofuncs) {
145 .ctor = nv04_disp_ctor, 145 .ctor = nv04_disp_ctor,
146 .dtor = _nouveau_disp_dtor, 146 .dtor = _nouveau_disp_dtor,
147 .init = _nouveau_disp_init, 147 .init = _nouveau_disp_init,
148 .fini = _nouveau_disp_fini, 148 .fini = _nouveau_disp_fini,
149 }, 149 },
150}; 150}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 9ad722e4e087..9a0cab9c3adb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -26,8 +26,7 @@
26#include <core/parent.h> 26#include <core/parent.h>
27#include <core/handle.h> 27#include <core/handle.h>
28#include <core/class.h> 28#include <core/class.h>
29 29#include <core/enum.h>
30#include <engine/disp.h>
31 30
32#include <subdev/bios.h> 31#include <subdev/bios.h>
33#include <subdev/bios/dcb.h> 32#include <subdev/bios/dcb.h>
@@ -227,6 +226,177 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)
227 * EVO master channel object 226 * EVO master channel object
228 ******************************************************************************/ 227 ******************************************************************************/
229 228
229static void
230nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c,
231 const struct nv50_disp_mthd_list *list, int inst)
232{
233 struct nouveau_object *disp = nv_object(priv);
234 int i;
235
236 for (i = 0; list->data[i].mthd; i++) {
237 if (list->data[i].addr) {
238 u32 next = nv_rd32(priv, list->data[i].addr + base + 0);
239 u32 prev = nv_rd32(priv, list->data[i].addr + base + c);
240 u32 mthd = list->data[i].mthd + (list->mthd * inst);
241 const char *name = list->data[i].name;
242 char mods[16];
243
244 if (prev != next)
245 snprintf(mods, sizeof(mods), "-> 0x%08x", next);
246 else
247 snprintf(mods, sizeof(mods), "%13c", ' ');
248
249 nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n",
250 mthd, prev, mods, name ? " // " : "",
251 name ? name : "");
252 }
253 }
254}
255
256void
257nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head,
258 const struct nv50_disp_mthd_chan *chan)
259{
260 struct nouveau_object *disp = nv_object(priv);
261 const struct nv50_disp_impl *impl = (void *)disp->oclass;
262 const struct nv50_disp_mthd_list *list;
263 int i, j;
264
265 if (debug > nv_subdev(priv)->debug)
266 return;
267
268 for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
269 u32 base = head * chan->addr;
270 for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
271 const char *cname = chan->name;
272 const char *sname = "";
273 char cname_[16], sname_[16];
274
275 if (chan->addr) {
276 snprintf(cname_, sizeof(cname_), "%s %d",
277 chan->name, head);
278 cname = cname_;
279 }
280
281 if (chan->data[i].nr > 1) {
282 snprintf(sname_, sizeof(sname_), " - %s %d",
283 chan->data[i].name, j);
284 sname = sname_;
285 }
286
287 nv_printk_(disp, debug, "%s%s:\n", cname, sname);
288 nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev,
289 list, j);
290 }
291 }
292}
293
294const struct nv50_disp_mthd_list
295nv50_disp_mast_mthd_base = {
296 .mthd = 0x0000,
297 .addr = 0x000000,
298 .data = {
299 { 0x0080, 0x000000 },
300 { 0x0084, 0x610bb8 },
301 { 0x0088, 0x610b9c },
302 { 0x008c, 0x000000 },
303 {}
304 }
305};
306
307static const struct nv50_disp_mthd_list
308nv50_disp_mast_mthd_dac = {
309 .mthd = 0x0080,
310 .addr = 0x000008,
311 .data = {
312 { 0x0400, 0x610b58 },
313 { 0x0404, 0x610bdc },
314 { 0x0420, 0x610828 },
315 {}
316 }
317};
318
319const struct nv50_disp_mthd_list
320nv50_disp_mast_mthd_sor = {
321 .mthd = 0x0040,
322 .addr = 0x000008,
323 .data = {
324 { 0x0600, 0x610b70 },
325 {}
326 }
327};
328
329const struct nv50_disp_mthd_list
330nv50_disp_mast_mthd_pior = {
331 .mthd = 0x0040,
332 .addr = 0x000008,
333 .data = {
334 { 0x0700, 0x610b80 },
335 {}
336 }
337};
338
339static const struct nv50_disp_mthd_list
340nv50_disp_mast_mthd_head = {
341 .mthd = 0x0400,
342 .addr = 0x000540,
343 .data = {
344 { 0x0800, 0x610ad8 },
345 { 0x0804, 0x610ad0 },
346 { 0x0808, 0x610a48 },
347 { 0x080c, 0x610a78 },
348 { 0x0810, 0x610ac0 },
349 { 0x0814, 0x610af8 },
350 { 0x0818, 0x610b00 },
351 { 0x081c, 0x610ae8 },
352 { 0x0820, 0x610af0 },
353 { 0x0824, 0x610b08 },
354 { 0x0828, 0x610b10 },
355 { 0x082c, 0x610a68 },
356 { 0x0830, 0x610a60 },
357 { 0x0834, 0x000000 },
358 { 0x0838, 0x610a40 },
359 { 0x0840, 0x610a24 },
360 { 0x0844, 0x610a2c },
361 { 0x0848, 0x610aa8 },
362 { 0x084c, 0x610ab0 },
363 { 0x0860, 0x610a84 },
364 { 0x0864, 0x610a90 },
365 { 0x0868, 0x610b18 },
366 { 0x086c, 0x610b20 },
367 { 0x0870, 0x610ac8 },
368 { 0x0874, 0x610a38 },
369 { 0x0880, 0x610a58 },
370 { 0x0884, 0x610a9c },
371 { 0x08a0, 0x610a70 },
372 { 0x08a4, 0x610a50 },
373 { 0x08a8, 0x610ae0 },
374 { 0x08c0, 0x610b28 },
375 { 0x08c4, 0x610b30 },
376 { 0x08c8, 0x610b40 },
377 { 0x08d4, 0x610b38 },
378 { 0x08d8, 0x610b48 },
379 { 0x08dc, 0x610b50 },
380 { 0x0900, 0x610a18 },
381 { 0x0904, 0x610ab8 },
382 {}
383 }
384};
385
386static const struct nv50_disp_mthd_chan
387nv50_disp_mast_mthd_chan = {
388 .name = "Core",
389 .addr = 0x000000,
390 .data = {
391 { "Global", 1, &nv50_disp_mast_mthd_base },
392 { "DAC", 3, &nv50_disp_mast_mthd_dac },
393 { "SOR", 2, &nv50_disp_mast_mthd_sor },
394 { "PIOR", 3, &nv50_disp_mast_mthd_pior },
395 { "HEAD", 2, &nv50_disp_mast_mthd_head },
396 {}
397 }
398};
399
230static int 400static int
231nv50_disp_mast_ctor(struct nouveau_object *parent, 401nv50_disp_mast_ctor(struct nouveau_object *parent,
232 struct nouveau_object *engine, 402 struct nouveau_object *engine,
@@ -323,6 +493,56 @@ nv50_disp_mast_ofuncs = {
323 * EVO sync channel objects 493 * EVO sync channel objects
324 ******************************************************************************/ 494 ******************************************************************************/
325 495
496static const struct nv50_disp_mthd_list
497nv50_disp_sync_mthd_base = {
498 .mthd = 0x0000,
499 .addr = 0x000000,
500 .data = {
501 { 0x0080, 0x000000 },
502 { 0x0084, 0x0008c4 },
503 { 0x0088, 0x0008d0 },
504 { 0x008c, 0x0008dc },
505 { 0x0090, 0x0008e4 },
506 { 0x0094, 0x610884 },
507 { 0x00a0, 0x6108a0 },
508 { 0x00a4, 0x610878 },
509 { 0x00c0, 0x61086c },
510 { 0x00e0, 0x610858 },
511 { 0x00e4, 0x610860 },
512 { 0x00e8, 0x6108ac },
513 { 0x00ec, 0x6108b4 },
514 { 0x0100, 0x610894 },
515 { 0x0110, 0x6108bc },
516 { 0x0114, 0x61088c },
517 {}
518 }
519};
520
521const struct nv50_disp_mthd_list
522nv50_disp_sync_mthd_image = {
523 .mthd = 0x0400,
524 .addr = 0x000000,
525 .data = {
526 { 0x0800, 0x6108f0 },
527 { 0x0804, 0x6108fc },
528 { 0x0808, 0x61090c },
529 { 0x080c, 0x610914 },
530 { 0x0810, 0x610904 },
531 {}
532 }
533};
534
535static const struct nv50_disp_mthd_chan
536nv50_disp_sync_mthd_chan = {
537 .name = "Base",
538 .addr = 0x000540,
539 .data = {
540 { "Global", 1, &nv50_disp_sync_mthd_base },
541 { "Image", 2, &nv50_disp_sync_mthd_image },
542 {}
543 }
544};
545
326static int 546static int
327nv50_disp_sync_ctor(struct nouveau_object *parent, 547nv50_disp_sync_ctor(struct nouveau_object *parent,
328 struct nouveau_object *engine, 548 struct nouveau_object *engine,
@@ -362,6 +582,44 @@ nv50_disp_sync_ofuncs = {
362 * EVO overlay channel objects 582 * EVO overlay channel objects
363 ******************************************************************************/ 583 ******************************************************************************/
364 584
585const struct nv50_disp_mthd_list
586nv50_disp_ovly_mthd_base = {
587 .mthd = 0x0000,
588 .addr = 0x000000,
589 .data = {
590 { 0x0080, 0x000000 },
591 { 0x0084, 0x0009a0 },
592 { 0x0088, 0x0009c0 },
593 { 0x008c, 0x0009c8 },
594 { 0x0090, 0x6109b4 },
595 { 0x0094, 0x610970 },
596 { 0x00a0, 0x610998 },
597 { 0x00a4, 0x610964 },
598 { 0x00c0, 0x610958 },
599 { 0x00e0, 0x6109a8 },
600 { 0x00e4, 0x6109d0 },
601 { 0x00e8, 0x6109d8 },
602 { 0x0100, 0x61094c },
603 { 0x0104, 0x610984 },
604 { 0x0108, 0x61098c },
605 { 0x0800, 0x6109f8 },
606 { 0x0808, 0x610a08 },
607 { 0x080c, 0x610a10 },
608 { 0x0810, 0x610a00 },
609 {}
610 }
611};
612
613static const struct nv50_disp_mthd_chan
614nv50_disp_ovly_mthd_chan = {
615 .name = "Overlay",
616 .addr = 0x000540,
617 .data = {
618 { "Global", 1, &nv50_disp_ovly_mthd_base },
619 {}
620 }
621};
622
365static int 623static int
366nv50_disp_ovly_ctor(struct nouveau_object *parent, 624nv50_disp_ovly_ctor(struct nouveau_object *parent,
367 struct nouveau_object *engine, 625 struct nouveau_object *engine,
@@ -782,25 +1040,78 @@ nv50_disp_cclass = {
782 * Display engine implementation 1040 * Display engine implementation
783 ******************************************************************************/ 1041 ******************************************************************************/
784 1042
785static void 1043static const struct nouveau_enum
786nv50_disp_intr_error(struct nv50_disp_priv *priv) 1044nv50_disp_intr_error_type[] = {
787{ 1045 { 3, "ILLEGAL_MTHD" },
788 u32 channels = (nv_rd32(priv, 0x610020) & 0x001f0000) >> 16; 1046 { 4, "INVALID_VALUE" },
789 u32 addr, data; 1047 { 5, "INVALID_STATE" },
790 int chid; 1048 { 7, "INVALID_HANDLE" },
791 1049 {}
792 for (chid = 0; chid < 5; chid++) { 1050};
793 if (!(channels & (1 << chid)))
794 continue;
795 1051
796 nv_wr32(priv, 0x610020, 0x00010000 << chid); 1052static const struct nouveau_enum
797 addr = nv_rd32(priv, 0x610080 + (chid * 0x08)); 1053nv50_disp_intr_error_code[] = {
798 data = nv_rd32(priv, 0x610084 + (chid * 0x08)); 1054 { 0x00, "" },
799 nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000); 1055 {}
1056};
800 1057
801 nv_error(priv, "chid %d mthd 0x%04x data 0x%08x 0x%08x\n", 1058static void
802 chid, addr & 0xffc, data, addr); 1059nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
1060{
1061 struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1062 u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
1063 u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
1064 u32 code = (addr & 0x00ff0000) >> 16;
1065 u32 type = (addr & 0x00007000) >> 12;
1066 u32 mthd = (addr & 0x00000ffc);
1067 const struct nouveau_enum *ec, *et;
1068 char ecunk[6], etunk[6];
1069
1070 et = nouveau_enum_find(nv50_disp_intr_error_type, type);
1071 if (!et)
1072 snprintf(etunk, sizeof(etunk), "UNK%02X", type);
1073
1074 ec = nouveau_enum_find(nv50_disp_intr_error_code, code);
1075 if (!ec)
1076 snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);
1077
1078 nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
1079 et ? et->name : etunk, ec ? ec->name : ecunk,
1080 chid, mthd, data);
1081
1082 if (chid == 0) {
1083 switch (mthd) {
1084 case 0x0080:
1085 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
1086 impl->mthd.core);
1087 break;
1088 default:
1089 break;
1090 }
1091 } else
1092 if (chid <= 2) {
1093 switch (mthd) {
1094 case 0x0080:
1095 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
1096 impl->mthd.base);
1097 break;
1098 default:
1099 break;
1100 }
1101 } else
1102 if (chid <= 4) {
1103 switch (mthd) {
1104 case 0x0080:
1105 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
1106 impl->mthd.ovly);
1107 break;
1108 default:
1109 break;
1110 }
803 } 1111 }
1112
1113 nv_wr32(priv, 0x610020, 0x00010000 << chid);
1114 nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
804} 1115}
805 1116
806static u16 1117static u16
@@ -1241,12 +1552,14 @@ nv50_disp_intr_supervisor(struct work_struct *work)
1241{ 1552{
1242 struct nv50_disp_priv *priv = 1553 struct nv50_disp_priv *priv =
1243 container_of(work, struct nv50_disp_priv, supervisor); 1554 container_of(work, struct nv50_disp_priv, supervisor);
1555 struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1244 u32 super = nv_rd32(priv, 0x610030); 1556 u32 super = nv_rd32(priv, 0x610030);
1245 int head; 1557 int head;
1246 1558
1247 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super); 1559 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
1248 1560
1249 if (priv->super & 0x00000010) { 1561 if (priv->super & 0x00000010) {
1562 nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
1250 for (head = 0; head < priv->head.nr; head++) { 1563 for (head = 0; head < priv->head.nr; head++) {
1251 if (!(super & (0x00000020 << head))) 1564 if (!(super & (0x00000020 << head)))
1252 continue; 1565 continue;
@@ -1290,9 +1603,10 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
1290 u32 intr0 = nv_rd32(priv, 0x610020); 1603 u32 intr0 = nv_rd32(priv, 0x610020);
1291 u32 intr1 = nv_rd32(priv, 0x610024); 1604 u32 intr1 = nv_rd32(priv, 0x610024);
1292 1605
1293 if (intr0 & 0x001f0000) { 1606 while (intr0 & 0x001f0000) {
1294 nv50_disp_intr_error(priv); 1607 u32 chid = __ffs(intr0 & 0x001f0000) - 16;
1295 intr0 &= ~0x001f0000; 1608 nv50_disp_intr_error(priv, chid);
1609 intr0 &= ~(0x00010000 << chid);
1296 } 1610 }
1297 1611
1298 if (intr1 & 0x00000004) { 1612 if (intr1 & 0x00000004) {
@@ -1346,13 +1660,17 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1346 return 0; 1660 return 0;
1347} 1661}
1348 1662
1349struct nouveau_oclass 1663struct nouveau_oclass *
1350nv50_disp_oclass = { 1664nv50_disp_oclass = &(struct nv50_disp_impl) {
1351 .handle = NV_ENGINE(DISP, 0x50), 1665 .base.base.handle = NV_ENGINE(DISP, 0x50),
1352 .ofuncs = &(struct nouveau_ofuncs) { 1666 .base.base.ofuncs = &(struct nouveau_ofuncs) {
1353 .ctor = nv50_disp_ctor, 1667 .ctor = nv50_disp_ctor,
1354 .dtor = _nouveau_disp_dtor, 1668 .dtor = _nouveau_disp_dtor,
1355 .init = _nouveau_disp_init, 1669 .init = _nouveau_disp_init,
1356 .fini = _nouveau_disp_fini, 1670 .fini = _nouveau_disp_fini,
1357 }, 1671 },
1358}; 1672 .mthd.core = &nv50_disp_mast_mthd_chan,
1673 .mthd.base = &nv50_disp_sync_mthd_chan,
1674 .mthd.ovly = &nv50_disp_ovly_mthd_chan,
1675 .mthd.prev = 0x000004,
1676}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index d31d426ea1f6..48d59db47f0d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -8,9 +8,19 @@
8#include <core/event.h> 8#include <core/event.h>
9 9
10#include <engine/dmaobj.h> 10#include <engine/dmaobj.h>
11#include <engine/disp.h>
12 11
13#include "dport.h" 12#include "dport.h"
13#include "priv.h"
14
15struct nv50_disp_impl {
16 struct nouveau_disp_impl base;
17 struct {
18 const struct nv50_disp_mthd_chan *core;
19 const struct nv50_disp_mthd_chan *base;
20 const struct nv50_disp_mthd_chan *ovly;
21 int prev;
22 } mthd;
23};
14 24
15struct nv50_disp_priv { 25struct nv50_disp_priv {
16 struct nouveau_disp base; 26 struct nouveau_disp base;
@@ -124,21 +134,60 @@ struct nv50_disp_pioc {
124 struct nv50_disp_chan base; 134 struct nv50_disp_chan base;
125}; 135};
126 136
137struct nv50_disp_mthd_list {
138 u32 mthd;
139 u32 addr;
140 struct {
141 u32 mthd;
142 u32 addr;
143 const char *name;
144 } data[];
145};
146
147struct nv50_disp_mthd_chan {
148 const char *name;
149 u32 addr;
150 struct {
151 const char *name;
152 int nr;
153 const struct nv50_disp_mthd_list *mthd;
154 } data[];
155};
156
127extern struct nouveau_ofuncs nv50_disp_mast_ofuncs; 157extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
158extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
159extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
160extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
128extern struct nouveau_ofuncs nv50_disp_sync_ofuncs; 161extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
162extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
129extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs; 163extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
164extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
130extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs; 165extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
131extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; 166extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
132extern struct nouveau_ofuncs nv50_disp_base_ofuncs; 167extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
133extern struct nouveau_oclass nv50_disp_cclass; 168extern struct nouveau_oclass nv50_disp_cclass;
169void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
170 const struct nv50_disp_mthd_chan *);
134void nv50_disp_intr_supervisor(struct work_struct *); 171void nv50_disp_intr_supervisor(struct work_struct *);
135void nv50_disp_intr(struct nouveau_subdev *); 172void nv50_disp_intr(struct nouveau_subdev *);
136 173
174extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
175extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
176extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
177extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
178extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
137extern struct nouveau_omthds nv84_disp_base_omthds[]; 179extern struct nouveau_omthds nv84_disp_base_omthds[];
138 180
181extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
182
139extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs; 183extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
184extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
185extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
186extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
187extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
140extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs; 188extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
141extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs; 189extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
190extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
142extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs; 191extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
143extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; 192extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
144extern struct nouveau_omthds nvd0_disp_base_omthds[]; 193extern struct nouveau_omthds nvd0_disp_base_omthds[];
@@ -147,4 +196,7 @@ extern struct nouveau_oclass nvd0_disp_cclass;
147void nvd0_disp_intr_supervisor(struct work_struct *); 196void nvd0_disp_intr_supervisor(struct work_struct *);
148void nvd0_disp_intr(struct nouveau_subdev *); 197void nvd0_disp_intr(struct nouveau_subdev *);
149 198
199extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
200extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;
201
150#endif 202#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index ef9ce300a496..98c5b19bc2b0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -29,6 +29,179 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * EVO master channel object
34 ******************************************************************************/
35
36const struct nv50_disp_mthd_list
37nv84_disp_mast_mthd_dac = {
38 .mthd = 0x0080,
39 .addr = 0x000008,
40 .data = {
41 { 0x0400, 0x610b58 },
42 { 0x0404, 0x610bdc },
43 { 0x0420, 0x610bc4 },
44 {}
45 }
46};
47
48const struct nv50_disp_mthd_list
49nv84_disp_mast_mthd_head = {
50 .mthd = 0x0400,
51 .addr = 0x000540,
52 .data = {
53 { 0x0800, 0x610ad8 },
54 { 0x0804, 0x610ad0 },
55 { 0x0808, 0x610a48 },
56 { 0x080c, 0x610a78 },
57 { 0x0810, 0x610ac0 },
58 { 0x0814, 0x610af8 },
59 { 0x0818, 0x610b00 },
60 { 0x081c, 0x610ae8 },
61 { 0x0820, 0x610af0 },
62 { 0x0824, 0x610b08 },
63 { 0x0828, 0x610b10 },
64 { 0x082c, 0x610a68 },
65 { 0x0830, 0x610a60 },
66 { 0x0834, 0x000000 },
67 { 0x0838, 0x610a40 },
68 { 0x0840, 0x610a24 },
69 { 0x0844, 0x610a2c },
70 { 0x0848, 0x610aa8 },
71 { 0x084c, 0x610ab0 },
72 { 0x085c, 0x610c5c },
73 { 0x0860, 0x610a84 },
74 { 0x0864, 0x610a90 },
75 { 0x0868, 0x610b18 },
76 { 0x086c, 0x610b20 },
77 { 0x0870, 0x610ac8 },
78 { 0x0874, 0x610a38 },
79 { 0x0878, 0x610c50 },
80 { 0x0880, 0x610a58 },
81 { 0x0884, 0x610a9c },
82 { 0x089c, 0x610c68 },
83 { 0x08a0, 0x610a70 },
84 { 0x08a4, 0x610a50 },
85 { 0x08a8, 0x610ae0 },
86 { 0x08c0, 0x610b28 },
87 { 0x08c4, 0x610b30 },
88 { 0x08c8, 0x610b40 },
89 { 0x08d4, 0x610b38 },
90 { 0x08d8, 0x610b48 },
91 { 0x08dc, 0x610b50 },
92 { 0x0900, 0x610a18 },
93 { 0x0904, 0x610ab8 },
94 { 0x0910, 0x610c70 },
95 { 0x0914, 0x610c78 },
96 {}
97 }
98};
99
100const struct nv50_disp_mthd_chan
101nv84_disp_mast_mthd_chan = {
102 .name = "Core",
103 .addr = 0x000000,
104 .data = {
105 { "Global", 1, &nv50_disp_mast_mthd_base },
106 { "DAC", 3, &nv84_disp_mast_mthd_dac },
107 { "SOR", 2, &nv50_disp_mast_mthd_sor },
108 { "PIOR", 3, &nv50_disp_mast_mthd_pior },
109 { "HEAD", 2, &nv84_disp_mast_mthd_head },
110 {}
111 }
112};
113
114/*******************************************************************************
115 * EVO sync channel objects
116 ******************************************************************************/
117
118static const struct nv50_disp_mthd_list
119nv84_disp_sync_mthd_base = {
120 .mthd = 0x0000,
121 .addr = 0x000000,
122 .data = {
123 { 0x0080, 0x000000 },
124 { 0x0084, 0x0008c4 },
125 { 0x0088, 0x0008d0 },
126 { 0x008c, 0x0008dc },
127 { 0x0090, 0x0008e4 },
128 { 0x0094, 0x610884 },
129 { 0x00a0, 0x6108a0 },
130 { 0x00a4, 0x610878 },
131 { 0x00c0, 0x61086c },
132 { 0x00c4, 0x610800 },
133 { 0x00c8, 0x61080c },
134 { 0x00cc, 0x610818 },
135 { 0x00e0, 0x610858 },
136 { 0x00e4, 0x610860 },
137 { 0x00e8, 0x6108ac },
138 { 0x00ec, 0x6108b4 },
139 { 0x00fc, 0x610824 },
140 { 0x0100, 0x610894 },
141 { 0x0104, 0x61082c },
142 { 0x0110, 0x6108bc },
143 { 0x0114, 0x61088c },
144 {}
145 }
146};
147
148const struct nv50_disp_mthd_chan
149nv84_disp_sync_mthd_chan = {
150 .name = "Base",
151 .addr = 0x000540,
152 .data = {
153 { "Global", 1, &nv84_disp_sync_mthd_base },
154 { "Image", 2, &nv50_disp_sync_mthd_image },
155 {}
156 }
157};
158
159/*******************************************************************************
160 * EVO overlay channel objects
161 ******************************************************************************/
162
163static const struct nv50_disp_mthd_list
164nv84_disp_ovly_mthd_base = {
165 .mthd = 0x0000,
166 .addr = 0x000000,
167 .data = {
168 { 0x0080, 0x000000 },
169 { 0x0084, 0x6109a0 },
170 { 0x0088, 0x6109c0 },
171 { 0x008c, 0x6109c8 },
172 { 0x0090, 0x6109b4 },
173 { 0x0094, 0x610970 },
174 { 0x00a0, 0x610998 },
175 { 0x00a4, 0x610964 },
176 { 0x00c0, 0x610958 },
177 { 0x00e0, 0x6109a8 },
178 { 0x00e4, 0x6109d0 },
179 { 0x00e8, 0x6109d8 },
180 { 0x0100, 0x61094c },
181 { 0x0104, 0x610984 },
182 { 0x0108, 0x61098c },
183 { 0x0800, 0x6109f8 },
184 { 0x0808, 0x610a08 },
185 { 0x080c, 0x610a10 },
186 { 0x0810, 0x610a00 },
187 {}
188 }
189};
190
191const struct nv50_disp_mthd_chan
192nv84_disp_ovly_mthd_chan = {
193 .name = "Overlay",
194 .addr = 0x000540,
195 .data = {
196 { "Global", 1, &nv84_disp_ovly_mthd_base },
197 {}
198 }
199};
200
201/*******************************************************************************
202 * Base display object
203 ******************************************************************************/
204
32static struct nouveau_oclass 205static struct nouveau_oclass
33nv84_disp_sclass[] = { 206nv84_disp_sclass[] = {
34 { NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, 207 { NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -59,6 +232,10 @@ nv84_disp_base_oclass[] = {
59 {} 232 {}
60}; 233};
61 234
235/*******************************************************************************
236 * Display engine implementation
237 ******************************************************************************/
238
62static int 239static int
63nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 240nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
64 struct nouveau_oclass *oclass, void *data, u32 size, 241 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -91,13 +268,17 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
91 return 0; 268 return 0;
92} 269}
93 270
94struct nouveau_oclass 271struct nouveau_oclass *
95nv84_disp_oclass = { 272nv84_disp_oclass = &(struct nv50_disp_impl) {
96 .handle = NV_ENGINE(DISP, 0x82), 273 .base.base.handle = NV_ENGINE(DISP, 0x82),
97 .ofuncs = &(struct nouveau_ofuncs) { 274 .base.base.ofuncs = &(struct nouveau_ofuncs) {
98 .ctor = nv84_disp_ctor, 275 .ctor = nv84_disp_ctor,
99 .dtor = _nouveau_disp_dtor, 276 .dtor = _nouveau_disp_dtor,
100 .init = _nouveau_disp_init, 277 .init = _nouveau_disp_init,
101 .fini = _nouveau_disp_fini, 278 .fini = _nouveau_disp_fini,
102 }, 279 },
103}; 280 .mthd.core = &nv84_disp_mast_mthd_chan,
281 .mthd.base = &nv84_disp_sync_mthd_chan,
282 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
283 .mthd.prev = 0x000004,
284}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index a518543c00ab..6844061c7e04 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -29,6 +29,38 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * EVO master channel object
34 ******************************************************************************/
35
36const struct nv50_disp_mthd_list
37nv94_disp_mast_mthd_sor = {
38 .mthd = 0x0040,
39 .addr = 0x000008,
40 .data = {
41 { 0x0600, 0x610794 },
42 {}
43 }
44};
45
46const struct nv50_disp_mthd_chan
47nv94_disp_mast_mthd_chan = {
48 .name = "Core",
49 .addr = 0x000000,
50 .data = {
51 { "Global", 1, &nv50_disp_mast_mthd_base },
52 { "DAC", 3, &nv84_disp_mast_mthd_dac },
53 { "SOR", 4, &nv94_disp_mast_mthd_sor },
54 { "PIOR", 3, &nv50_disp_mast_mthd_pior },
55 { "HEAD", 2, &nv84_disp_mast_mthd_head },
56 {}
57 }
58};
59
60/*******************************************************************************
61 * Base display object
62 ******************************************************************************/
63
32static struct nouveau_oclass 64static struct nouveau_oclass
33nv94_disp_sclass[] = { 65nv94_disp_sclass[] = {
34 { NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, 66 { NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -59,6 +91,10 @@ nv94_disp_base_oclass[] = {
59 {} 91 {}
60}; 92};
61 93
94/*******************************************************************************
95 * Display engine implementation
96 ******************************************************************************/
97
62static int 98static int
63nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 99nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
64 struct nouveau_oclass *oclass, void *data, u32 size, 100 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -92,13 +128,17 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
92 return 0; 128 return 0;
93} 129}
94 130
95struct nouveau_oclass 131struct nouveau_oclass *
96nv94_disp_oclass = { 132nv94_disp_oclass = &(struct nv50_disp_impl) {
97 .handle = NV_ENGINE(DISP, 0x88), 133 .base.base.handle = NV_ENGINE(DISP, 0x88),
98 .ofuncs = &(struct nouveau_ofuncs) { 134 .base.base.ofuncs = &(struct nouveau_ofuncs) {
99 .ctor = nv94_disp_ctor, 135 .ctor = nv94_disp_ctor,
100 .dtor = _nouveau_disp_dtor, 136 .dtor = _nouveau_disp_dtor,
101 .init = _nouveau_disp_init, 137 .init = _nouveau_disp_init,
102 .fini = _nouveau_disp_fini, 138 .fini = _nouveau_disp_fini,
103 }, 139 },
104}; 140 .mthd.core = &nv94_disp_mast_mthd_chan,
141 .mthd.base = &nv84_disp_sync_mthd_chan,
142 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
143 .mthd.prev = 0x000004,
144}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 6cf8eefac368..88c96241c02a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -29,6 +29,55 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * EVO overlay channel objects
34 ******************************************************************************/
35
36static const struct nv50_disp_mthd_list
37nva0_disp_ovly_mthd_base = {
38 .mthd = 0x0000,
39 .addr = 0x000000,
40 .data = {
41 { 0x0080, 0x000000 },
42 { 0x0084, 0x6109a0 },
43 { 0x0088, 0x6109c0 },
44 { 0x008c, 0x6109c8 },
45 { 0x0090, 0x6109b4 },
46 { 0x0094, 0x610970 },
47 { 0x00a0, 0x610998 },
48 { 0x00a4, 0x610964 },
49 { 0x00b0, 0x610c98 },
50 { 0x00b4, 0x610ca4 },
51 { 0x00b8, 0x610cac },
52 { 0x00c0, 0x610958 },
53 { 0x00e0, 0x6109a8 },
54 { 0x00e4, 0x6109d0 },
55 { 0x00e8, 0x6109d8 },
56 { 0x0100, 0x61094c },
57 { 0x0104, 0x610984 },
58 { 0x0108, 0x61098c },
59 { 0x0800, 0x6109f8 },
60 { 0x0808, 0x610a08 },
61 { 0x080c, 0x610a10 },
62 { 0x0810, 0x610a00 },
63 {}
64 }
65};
66
67static const struct nv50_disp_mthd_chan
68nva0_disp_ovly_mthd_chan = {
69 .name = "Overlay",
70 .addr = 0x000540,
71 .data = {
72 { "Global", 1, &nva0_disp_ovly_mthd_base },
73 {}
74 }
75};
76
77/*******************************************************************************
78 * Base display object
79 ******************************************************************************/
80
32static struct nouveau_oclass 81static struct nouveau_oclass
33nva0_disp_sclass[] = { 82nva0_disp_sclass[] = {
34 { NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, 83 { NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -45,6 +94,10 @@ nva0_disp_base_oclass[] = {
45 {} 94 {}
46}; 95};
47 96
97/*******************************************************************************
98 * Display engine implementation
99 ******************************************************************************/
100
48static int 101static int
49nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 102nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
50 struct nouveau_oclass *oclass, void *data, u32 size, 103 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +130,17 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
77 return 0; 130 return 0;
78} 131}
79 132
80struct nouveau_oclass 133struct nouveau_oclass *
81nva0_disp_oclass = { 134nva0_disp_oclass = &(struct nv50_disp_impl) {
82 .handle = NV_ENGINE(DISP, 0x83), 135 .base.base.handle = NV_ENGINE(DISP, 0x83),
83 .ofuncs = &(struct nouveau_ofuncs) { 136 .base.base.ofuncs = &(struct nouveau_ofuncs) {
84 .ctor = nva0_disp_ctor, 137 .ctor = nva0_disp_ctor,
85 .dtor = _nouveau_disp_dtor, 138 .dtor = _nouveau_disp_dtor,
86 .init = _nouveau_disp_init, 139 .init = _nouveau_disp_init,
87 .fini = _nouveau_disp_fini, 140 .fini = _nouveau_disp_fini,
88 }, 141 },
89}; 142 .mthd.core = &nv84_disp_mast_mthd_chan,
143 .mthd.base = &nv84_disp_sync_mthd_chan,
144 .mthd.ovly = &nva0_disp_ovly_mthd_chan,
145 .mthd.prev = 0x000004,
146}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index 6ad6dcece43b..46cb2ce0e82a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -29,6 +29,10 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * Base display object
34 ******************************************************************************/
35
32static struct nouveau_oclass 36static struct nouveau_oclass
33nva3_disp_sclass[] = { 37nva3_disp_sclass[] = {
34 { NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, 38 { NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -60,6 +64,10 @@ nva3_disp_base_oclass[] = {
60 {} 64 {}
61}; 65};
62 66
67/*******************************************************************************
68 * Display engine implementation
69 ******************************************************************************/
70
63static int 71static int
64nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 72nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
65 struct nouveau_oclass *oclass, void *data, u32 size, 73 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -94,13 +102,17 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
94 return 0; 102 return 0;
95} 103}
96 104
97struct nouveau_oclass 105struct nouveau_oclass *
98nva3_disp_oclass = { 106nva3_disp_oclass = &(struct nv50_disp_impl) {
99 .handle = NV_ENGINE(DISP, 0x85), 107 .base.base.handle = NV_ENGINE(DISP, 0x85),
100 .ofuncs = &(struct nouveau_ofuncs) { 108 .base.base.ofuncs = &(struct nouveau_ofuncs) {
101 .ctor = nva3_disp_ctor, 109 .ctor = nva3_disp_ctor,
102 .dtor = _nouveau_disp_dtor, 110 .dtor = _nouveau_disp_dtor,
103 .init = _nouveau_disp_init, 111 .init = _nouveau_disp_init,
104 .fini = _nouveau_disp_fini, 112 .fini = _nouveau_disp_fini,
105 }, 113 },
106}; 114 .mthd.core = &nv94_disp_mast_mthd_chan,
115 .mthd.base = &nv84_disp_sync_mthd_chan,
116 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
117 .mthd.prev = 0x000004,
118}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 1c5e4e8b2c82..7762665ad8fd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -124,6 +124,146 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
124 * EVO master channel object 124 * EVO master channel object
125 ******************************************************************************/ 125 ******************************************************************************/
126 126
127const struct nv50_disp_mthd_list
128nvd0_disp_mast_mthd_base = {
129 .mthd = 0x0000,
130 .addr = 0x000000,
131 .data = {
132 { 0x0080, 0x660080 },
133 { 0x0084, 0x660084 },
134 { 0x0088, 0x660088 },
135 { 0x008c, 0x000000 },
136 {}
137 }
138};
139
140const struct nv50_disp_mthd_list
141nvd0_disp_mast_mthd_dac = {
142 .mthd = 0x0020,
143 .addr = 0x000020,
144 .data = {
145 { 0x0180, 0x660180 },
146 { 0x0184, 0x660184 },
147 { 0x0188, 0x660188 },
148 { 0x0190, 0x660190 },
149 {}
150 }
151};
152
153const struct nv50_disp_mthd_list
154nvd0_disp_mast_mthd_sor = {
155 .mthd = 0x0020,
156 .addr = 0x000020,
157 .data = {
158 { 0x0200, 0x660200 },
159 { 0x0204, 0x660204 },
160 { 0x0208, 0x660208 },
161 { 0x0210, 0x660210 },
162 {}
163 }
164};
165
166const struct nv50_disp_mthd_list
167nvd0_disp_mast_mthd_pior = {
168 .mthd = 0x0020,
169 .addr = 0x000020,
170 .data = {
171 { 0x0300, 0x660300 },
172 { 0x0304, 0x660304 },
173 { 0x0308, 0x660308 },
174 { 0x0310, 0x660310 },
175 {}
176 }
177};
178
179static const struct nv50_disp_mthd_list
180nvd0_disp_mast_mthd_head = {
181 .mthd = 0x0300,
182 .addr = 0x000300,
183 .data = {
184 { 0x0400, 0x660400 },
185 { 0x0404, 0x660404 },
186 { 0x0408, 0x660408 },
187 { 0x040c, 0x66040c },
188 { 0x0410, 0x660410 },
189 { 0x0414, 0x660414 },
190 { 0x0418, 0x660418 },
191 { 0x041c, 0x66041c },
192 { 0x0420, 0x660420 },
193 { 0x0424, 0x660424 },
194 { 0x0428, 0x660428 },
195 { 0x042c, 0x66042c },
196 { 0x0430, 0x660430 },
197 { 0x0434, 0x660434 },
198 { 0x0438, 0x660438 },
199 { 0x0440, 0x660440 },
200 { 0x0444, 0x660444 },
201 { 0x0448, 0x660448 },
202 { 0x044c, 0x66044c },
203 { 0x0450, 0x660450 },
204 { 0x0454, 0x660454 },
205 { 0x0458, 0x660458 },
206 { 0x045c, 0x66045c },
207 { 0x0460, 0x660460 },
208 { 0x0468, 0x660468 },
209 { 0x046c, 0x66046c },
210 { 0x0470, 0x660470 },
211 { 0x0474, 0x660474 },
212 { 0x0480, 0x660480 },
213 { 0x0484, 0x660484 },
214 { 0x048c, 0x66048c },
215 { 0x0490, 0x660490 },
216 { 0x0494, 0x660494 },
217 { 0x0498, 0x660498 },
218 { 0x04b0, 0x6604b0 },
219 { 0x04b8, 0x6604b8 },
220 { 0x04bc, 0x6604bc },
221 { 0x04c0, 0x6604c0 },
222 { 0x04c4, 0x6604c4 },
223 { 0x04c8, 0x6604c8 },
224 { 0x04d0, 0x6604d0 },
225 { 0x04d4, 0x6604d4 },
226 { 0x04e0, 0x6604e0 },
227 { 0x04e4, 0x6604e4 },
228 { 0x04e8, 0x6604e8 },
229 { 0x04ec, 0x6604ec },
230 { 0x04f0, 0x6604f0 },
231 { 0x04f4, 0x6604f4 },
232 { 0x04f8, 0x6604f8 },
233 { 0x04fc, 0x6604fc },
234 { 0x0500, 0x660500 },
235 { 0x0504, 0x660504 },
236 { 0x0508, 0x660508 },
237 { 0x050c, 0x66050c },
238 { 0x0510, 0x660510 },
239 { 0x0514, 0x660514 },
240 { 0x0518, 0x660518 },
241 { 0x051c, 0x66051c },
242 { 0x052c, 0x66052c },
243 { 0x0530, 0x660530 },
244 { 0x054c, 0x66054c },
245 { 0x0550, 0x660550 },
246 { 0x0554, 0x660554 },
247 { 0x0558, 0x660558 },
248 { 0x055c, 0x66055c },
249 {}
250 }
251};
252
253static const struct nv50_disp_mthd_chan
254nvd0_disp_mast_mthd_chan = {
255 .name = "Core",
256 .addr = 0x000000,
257 .data = {
258 { "Global", 1, &nvd0_disp_mast_mthd_base },
259 { "DAC", 3, &nvd0_disp_mast_mthd_dac },
260 { "SOR", 8, &nvd0_disp_mast_mthd_sor },
261 { "PIOR", 4, &nvd0_disp_mast_mthd_pior },
262 { "HEAD", 4, &nvd0_disp_mast_mthd_head },
263 {}
264 }
265};
266
127static int 267static int
128nvd0_disp_mast_ctor(struct nouveau_object *parent, 268nvd0_disp_mast_ctor(struct nouveau_object *parent,
129 struct nouveau_object *engine, 269 struct nouveau_object *engine,
@@ -216,6 +356,81 @@ nvd0_disp_mast_ofuncs = {
216 * EVO sync channel objects 356 * EVO sync channel objects
217 ******************************************************************************/ 357 ******************************************************************************/
218 358
359static const struct nv50_disp_mthd_list
360nvd0_disp_sync_mthd_base = {
361 .mthd = 0x0000,
362 .addr = 0x000000,
363 .data = {
364 { 0x0080, 0x661080 },
365 { 0x0084, 0x661084 },
366 { 0x0088, 0x661088 },
367 { 0x008c, 0x66108c },
368 { 0x0090, 0x661090 },
369 { 0x0094, 0x661094 },
370 { 0x00a0, 0x6610a0 },
371 { 0x00a4, 0x6610a4 },
372 { 0x00c0, 0x6610c0 },
373 { 0x00c4, 0x6610c4 },
374 { 0x00c8, 0x6610c8 },
375 { 0x00cc, 0x6610cc },
376 { 0x00e0, 0x6610e0 },
377 { 0x00e4, 0x6610e4 },
378 { 0x00e8, 0x6610e8 },
379 { 0x00ec, 0x6610ec },
380 { 0x00fc, 0x6610fc },
381 { 0x0100, 0x661100 },
382 { 0x0104, 0x661104 },
383 { 0x0108, 0x661108 },
384 { 0x010c, 0x66110c },
385 { 0x0110, 0x661110 },
386 { 0x0114, 0x661114 },
387 { 0x0118, 0x661118 },
388 { 0x011c, 0x66111c },
389 { 0x0130, 0x661130 },
390 { 0x0134, 0x661134 },
391 { 0x0138, 0x661138 },
392 { 0x013c, 0x66113c },
393 { 0x0140, 0x661140 },
394 { 0x0144, 0x661144 },
395 { 0x0148, 0x661148 },
396 { 0x014c, 0x66114c },
397 { 0x0150, 0x661150 },
398 { 0x0154, 0x661154 },
399 { 0x0158, 0x661158 },
400 { 0x015c, 0x66115c },
401 { 0x0160, 0x661160 },
402 { 0x0164, 0x661164 },
403 { 0x0168, 0x661168 },
404 { 0x016c, 0x66116c },
405 {}
406 }
407};
408
409static const struct nv50_disp_mthd_list
410nvd0_disp_sync_mthd_image = {
411 .mthd = 0x0400,
412 .addr = 0x000400,
413 .data = {
414 { 0x0400, 0x661400 },
415 { 0x0404, 0x661404 },
416 { 0x0408, 0x661408 },
417 { 0x040c, 0x66140c },
418 { 0x0410, 0x661410 },
419 {}
420 }
421};
422
423const struct nv50_disp_mthd_chan
424nvd0_disp_sync_mthd_chan = {
425 .name = "Base",
426 .addr = 0x001000,
427 .data = {
428 { "Global", 1, &nvd0_disp_sync_mthd_base },
429 { "Image", 2, &nvd0_disp_sync_mthd_image },
430 {}
431 }
432};
433
219static int 434static int
220nvd0_disp_sync_ctor(struct nouveau_object *parent, 435nvd0_disp_sync_ctor(struct nouveau_object *parent,
221 struct nouveau_object *engine, 436 struct nouveau_object *engine,
@@ -256,6 +471,68 @@ nvd0_disp_sync_ofuncs = {
256 * EVO overlay channel objects 471 * EVO overlay channel objects
257 ******************************************************************************/ 472 ******************************************************************************/
258 473
474static const struct nv50_disp_mthd_list
475nvd0_disp_ovly_mthd_base = {
476 .mthd = 0x0000,
477 .data = {
478 { 0x0080, 0x665080 },
479 { 0x0084, 0x665084 },
480 { 0x0088, 0x665088 },
481 { 0x008c, 0x66508c },
482 { 0x0090, 0x665090 },
483 { 0x0094, 0x665094 },
484 { 0x00a0, 0x6650a0 },
485 { 0x00a4, 0x6650a4 },
486 { 0x00b0, 0x6650b0 },
487 { 0x00b4, 0x6650b4 },
488 { 0x00b8, 0x6650b8 },
489 { 0x00c0, 0x6650c0 },
490 { 0x00e0, 0x6650e0 },
491 { 0x00e4, 0x6650e4 },
492 { 0x00e8, 0x6650e8 },
493 { 0x0100, 0x665100 },
494 { 0x0104, 0x665104 },
495 { 0x0108, 0x665108 },
496 { 0x010c, 0x66510c },
497 { 0x0110, 0x665110 },
498 { 0x0118, 0x665118 },
499 { 0x011c, 0x66511c },
500 { 0x0120, 0x665120 },
501 { 0x0124, 0x665124 },
502 { 0x0130, 0x665130 },
503 { 0x0134, 0x665134 },
504 { 0x0138, 0x665138 },
505 { 0x013c, 0x66513c },
506 { 0x0140, 0x665140 },
507 { 0x0144, 0x665144 },
508 { 0x0148, 0x665148 },
509 { 0x014c, 0x66514c },
510 { 0x0150, 0x665150 },
511 { 0x0154, 0x665154 },
512 { 0x0158, 0x665158 },
513 { 0x015c, 0x66515c },
514 { 0x0160, 0x665160 },
515 { 0x0164, 0x665164 },
516 { 0x0168, 0x665168 },
517 { 0x016c, 0x66516c },
518 { 0x0400, 0x665400 },
519 { 0x0408, 0x665408 },
520 { 0x040c, 0x66540c },
521 { 0x0410, 0x665410 },
522 {}
523 }
524};
525
526static const struct nv50_disp_mthd_chan
527nvd0_disp_ovly_mthd_chan = {
528 .name = "Overlay",
529 .addr = 0x001000,
530 .data = {
531 { "Global", 1, &nvd0_disp_ovly_mthd_base },
532 {}
533 }
534};
535
259static int 536static int
260nvd0_disp_ovly_ctor(struct nouveau_object *parent, 537nvd0_disp_ovly_ctor(struct nouveau_object *parent,
261 struct nouveau_object *engine, 538 struct nouveau_object *engine,
@@ -897,19 +1174,22 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
897{ 1174{
898 struct nv50_disp_priv *priv = 1175 struct nv50_disp_priv *priv =
899 container_of(work, struct nv50_disp_priv, supervisor); 1176 container_of(work, struct nv50_disp_priv, supervisor);
1177 struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
900 u32 mask[4]; 1178 u32 mask[4];
901 int head; 1179 int head;
902 1180
903 nv_debug(priv, "supervisor %08x\n", priv->super); 1181 nv_debug(priv, "supervisor %d\n", ffs(priv->super));
904 for (head = 0; head < priv->head.nr; head++) { 1182 for (head = 0; head < priv->head.nr; head++) {
905 mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800)); 1183 mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800));
906 nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]); 1184 nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]);
907 } 1185 }
908 1186
909 if (priv->super & 0x00000001) { 1187 if (priv->super & 0x00000001) {
1188 nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
910 for (head = 0; head < priv->head.nr; head++) { 1189 for (head = 0; head < priv->head.nr; head++) {
911 if (!(mask[head] & 0x00001000)) 1190 if (!(mask[head] & 0x00001000))
912 continue; 1191 continue;
1192 nv_debug(priv, "supervisor 1.0 - head %d\n", head);
913 nvd0_disp_intr_unk1_0(priv, head); 1193 nvd0_disp_intr_unk1_0(priv, head);
914 } 1194 }
915 } else 1195 } else
@@ -917,16 +1197,19 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
917 for (head = 0; head < priv->head.nr; head++) { 1197 for (head = 0; head < priv->head.nr; head++) {
918 if (!(mask[head] & 0x00001000)) 1198 if (!(mask[head] & 0x00001000))
919 continue; 1199 continue;
1200 nv_debug(priv, "supervisor 2.0 - head %d\n", head);
920 nvd0_disp_intr_unk2_0(priv, head); 1201 nvd0_disp_intr_unk2_0(priv, head);
921 } 1202 }
922 for (head = 0; head < priv->head.nr; head++) { 1203 for (head = 0; head < priv->head.nr; head++) {
923 if (!(mask[head] & 0x00010000)) 1204 if (!(mask[head] & 0x00010000))
924 continue; 1205 continue;
1206 nv_debug(priv, "supervisor 2.1 - head %d\n", head);
925 nvd0_disp_intr_unk2_1(priv, head); 1207 nvd0_disp_intr_unk2_1(priv, head);
926 } 1208 }
927 for (head = 0; head < priv->head.nr; head++) { 1209 for (head = 0; head < priv->head.nr; head++) {
928 if (!(mask[head] & 0x00001000)) 1210 if (!(mask[head] & 0x00001000))
929 continue; 1211 continue;
1212 nv_debug(priv, "supervisor 2.2 - head %d\n", head);
930 nvd0_disp_intr_unk2_2(priv, head); 1213 nvd0_disp_intr_unk2_2(priv, head);
931 } 1214 }
932 } else 1215 } else
@@ -934,6 +1217,7 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
934 for (head = 0; head < priv->head.nr; head++) { 1217 for (head = 0; head < priv->head.nr; head++) {
935 if (!(mask[head] & 0x00001000)) 1218 if (!(mask[head] & 0x00001000))
936 continue; 1219 continue;
1220 nv_debug(priv, "supervisor 3.0 - head %d\n", head);
937 nvd0_disp_intr_unk4_0(priv, head); 1221 nvd0_disp_intr_unk4_0(priv, head);
938 } 1222 }
939 } 1223 }
@@ -943,6 +1227,53 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
943 nv_wr32(priv, 0x6101d0, 0x80000000); 1227 nv_wr32(priv, 0x6101d0, 0x80000000);
944} 1228}
945 1229
1230static void
1231nvd0_disp_intr_error(struct nv50_disp_priv *priv, int chid)
1232{
1233 const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1234 u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
1235 u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
1236 u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
1237
1238 nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
1239 "0x%08x 0x%08x\n",
1240 chid, (mthd & 0x0000ffc), data, mthd, unkn);
1241
1242 if (chid == 0) {
1243 switch (mthd) {
1244 case 0x0080:
1245 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
1246 impl->mthd.core);
1247 break;
1248 default:
1249 break;
1250 }
1251 } else
1252 if (chid <= 4) {
1253 switch (mthd) {
1254 case 0x0080:
1255 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
1256 impl->mthd.base);
1257 break;
1258 default:
1259 break;
1260 }
1261 } else
1262 if (chid <= 8) {
1263 switch (mthd) {
1264 case 0x0080:
1265 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5,
1266 impl->mthd.ovly);
1267 break;
1268 default:
1269 break;
1270 }
1271 }
1272
1273 nv_wr32(priv, 0x61009c, (1 << chid));
1274 nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
1275}
1276
946void 1277void
947nvd0_disp_intr(struct nouveau_subdev *subdev) 1278nvd0_disp_intr(struct nouveau_subdev *subdev)
948{ 1279{
@@ -959,18 +1290,8 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
959 if (intr & 0x00000002) { 1290 if (intr & 0x00000002) {
960 u32 stat = nv_rd32(priv, 0x61009c); 1291 u32 stat = nv_rd32(priv, 0x61009c);
961 int chid = ffs(stat) - 1; 1292 int chid = ffs(stat) - 1;
962 if (chid >= 0) { 1293 if (chid >= 0)
963 u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12)); 1294 nvd0_disp_intr_error(priv, chid);
964 u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
965 u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
966
967 nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
968 "0x%08x 0x%08x\n",
969 chid, (mthd & 0x0000ffc), data, mthd, unkn);
970 nv_wr32(priv, 0x61009c, (1 << chid));
971 nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
972 }
973
974 intr &= ~0x00000002; 1295 intr &= ~0x00000002;
975 } 1296 }
976 1297
@@ -1035,13 +1356,17 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1035 return 0; 1356 return 0;
1036} 1357}
1037 1358
1038struct nouveau_oclass 1359struct nouveau_oclass *
1039nvd0_disp_oclass = { 1360nvd0_disp_oclass = &(struct nv50_disp_impl) {
1040 .handle = NV_ENGINE(DISP, 0x90), 1361 .base.base.handle = NV_ENGINE(DISP, 0x90),
1041 .ofuncs = &(struct nouveau_ofuncs) { 1362 .base.base.ofuncs = &(struct nouveau_ofuncs) {
1042 .ctor = nvd0_disp_ctor, 1363 .ctor = nvd0_disp_ctor,
1043 .dtor = _nouveau_disp_dtor, 1364 .dtor = _nouveau_disp_dtor,
1044 .init = _nouveau_disp_init, 1365 .init = _nouveau_disp_init,
1045 .fini = _nouveau_disp_fini, 1366 .fini = _nouveau_disp_fini,
1046 }, 1367 },
1047}; 1368 .mthd.core = &nvd0_disp_mast_mthd_chan,
1369 .mthd.base = &nvd0_disp_sync_mthd_chan,
1370 .mthd.ovly = &nvd0_disp_ovly_mthd_chan,
1371 .mthd.prev = -0x020000,
1372}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index ab63f32c00b2..44e0b8f34c1a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -29,6 +29,175 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * EVO master channel object
34 ******************************************************************************/
35
36static const struct nv50_disp_mthd_list
37nve0_disp_mast_mthd_head = {
38 .mthd = 0x0300,
39 .addr = 0x000300,
40 .data = {
41 { 0x0400, 0x660400 },
42 { 0x0404, 0x660404 },
43 { 0x0408, 0x660408 },
44 { 0x040c, 0x66040c },
45 { 0x0410, 0x660410 },
46 { 0x0414, 0x660414 },
47 { 0x0418, 0x660418 },
48 { 0x041c, 0x66041c },
49 { 0x0420, 0x660420 },
50 { 0x0424, 0x660424 },
51 { 0x0428, 0x660428 },
52 { 0x042c, 0x66042c },
53 { 0x0430, 0x660430 },
54 { 0x0434, 0x660434 },
55 { 0x0438, 0x660438 },
56 { 0x0440, 0x660440 },
57 { 0x0444, 0x660444 },
58 { 0x0448, 0x660448 },
59 { 0x044c, 0x66044c },
60 { 0x0450, 0x660450 },
61 { 0x0454, 0x660454 },
62 { 0x0458, 0x660458 },
63 { 0x045c, 0x66045c },
64 { 0x0460, 0x660460 },
65 { 0x0468, 0x660468 },
66 { 0x046c, 0x66046c },
67 { 0x0470, 0x660470 },
68 { 0x0474, 0x660474 },
69 { 0x047c, 0x66047c },
70 { 0x0480, 0x660480 },
71 { 0x0484, 0x660484 },
72 { 0x0488, 0x660488 },
73 { 0x048c, 0x66048c },
74 { 0x0490, 0x660490 },
75 { 0x0494, 0x660494 },
76 { 0x0498, 0x660498 },
77 { 0x04a0, 0x6604a0 },
78 { 0x04b0, 0x6604b0 },
79 { 0x04b8, 0x6604b8 },
80 { 0x04bc, 0x6604bc },
81 { 0x04c0, 0x6604c0 },
82 { 0x04c4, 0x6604c4 },
83 { 0x04c8, 0x6604c8 },
84 { 0x04d0, 0x6604d0 },
85 { 0x04d4, 0x6604d4 },
86 { 0x04e0, 0x6604e0 },
87 { 0x04e4, 0x6604e4 },
88 { 0x04e8, 0x6604e8 },
89 { 0x04ec, 0x6604ec },
90 { 0x04f0, 0x6604f0 },
91 { 0x04f4, 0x6604f4 },
92 { 0x04f8, 0x6604f8 },
93 { 0x04fc, 0x6604fc },
94 { 0x0500, 0x660500 },
95 { 0x0504, 0x660504 },
96 { 0x0508, 0x660508 },
97 { 0x050c, 0x66050c },
98 { 0x0510, 0x660510 },
99 { 0x0514, 0x660514 },
100 { 0x0518, 0x660518 },
101 { 0x051c, 0x66051c },
102 { 0x0520, 0x660520 },
103 { 0x0524, 0x660524 },
104 { 0x052c, 0x66052c },
105 { 0x0530, 0x660530 },
106 { 0x054c, 0x66054c },
107 { 0x0550, 0x660550 },
108 { 0x0554, 0x660554 },
109 { 0x0558, 0x660558 },
110 { 0x055c, 0x66055c },
111 {}
112 }
113};
114
115const struct nv50_disp_mthd_chan
116nve0_disp_mast_mthd_chan = {
117 .name = "Core",
118 .addr = 0x000000,
119 .data = {
120 { "Global", 1, &nvd0_disp_mast_mthd_base },
121 { "DAC", 3, &nvd0_disp_mast_mthd_dac },
122 { "SOR", 8, &nvd0_disp_mast_mthd_sor },
123 { "PIOR", 4, &nvd0_disp_mast_mthd_pior },
124 { "HEAD", 4, &nve0_disp_mast_mthd_head },
125 {}
126 }
127};
128
129/*******************************************************************************
130 * EVO overlay channel objects
131 ******************************************************************************/
132
133static const struct nv50_disp_mthd_list
134nve0_disp_ovly_mthd_base = {
135 .mthd = 0x0000,
136 .data = {
137 { 0x0080, 0x665080 },
138 { 0x0084, 0x665084 },
139 { 0x0088, 0x665088 },
140 { 0x008c, 0x66508c },
141 { 0x0090, 0x665090 },
142 { 0x0094, 0x665094 },
143 { 0x00a0, 0x6650a0 },
144 { 0x00a4, 0x6650a4 },
145 { 0x00b0, 0x6650b0 },
146 { 0x00b4, 0x6650b4 },
147 { 0x00b8, 0x6650b8 },
148 { 0x00c0, 0x6650c0 },
149 { 0x00c4, 0x6650c4 },
150 { 0x00e0, 0x6650e0 },
151 { 0x00e4, 0x6650e4 },
152 { 0x00e8, 0x6650e8 },
153 { 0x0100, 0x665100 },
154 { 0x0104, 0x665104 },
155 { 0x0108, 0x665108 },
156 { 0x010c, 0x66510c },
157 { 0x0110, 0x665110 },
158 { 0x0118, 0x665118 },
159 { 0x011c, 0x66511c },
160 { 0x0120, 0x665120 },
161 { 0x0124, 0x665124 },
162 { 0x0130, 0x665130 },
163 { 0x0134, 0x665134 },
164 { 0x0138, 0x665138 },
165 { 0x013c, 0x66513c },
166 { 0x0140, 0x665140 },
167 { 0x0144, 0x665144 },
168 { 0x0148, 0x665148 },
169 { 0x014c, 0x66514c },
170 { 0x0150, 0x665150 },
171 { 0x0154, 0x665154 },
172 { 0x0158, 0x665158 },
173 { 0x015c, 0x66515c },
174 { 0x0160, 0x665160 },
175 { 0x0164, 0x665164 },
176 { 0x0168, 0x665168 },
177 { 0x016c, 0x66516c },
178 { 0x0400, 0x665400 },
179 { 0x0404, 0x665404 },
180 { 0x0408, 0x665408 },
181 { 0x040c, 0x66540c },
182 { 0x0410, 0x665410 },
183 {}
184 }
185};
186
187const struct nv50_disp_mthd_chan
188nve0_disp_ovly_mthd_chan = {
189 .name = "Overlay",
190 .addr = 0x001000,
191 .data = {
192 { "Global", 1, &nve0_disp_ovly_mthd_base },
193 {}
194 }
195};
196
197/*******************************************************************************
198 * Base display object
199 ******************************************************************************/
200
32static struct nouveau_oclass 201static struct nouveau_oclass
33nve0_disp_sclass[] = { 202nve0_disp_sclass[] = {
34 { NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs }, 203 { NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
@@ -45,6 +214,10 @@ nve0_disp_base_oclass[] = {
45 {} 214 {}
46}; 215};
47 216
217/*******************************************************************************
218 * Display engine implementation
219 ******************************************************************************/
220
48static int 221static int
49nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 222nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
50 struct nouveau_oclass *oclass, void *data, u32 size, 223 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +250,17 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
77 return 0; 250 return 0;
78} 251}
79 252
80struct nouveau_oclass 253struct nouveau_oclass *
81nve0_disp_oclass = { 254nve0_disp_oclass = &(struct nv50_disp_impl) {
82 .handle = NV_ENGINE(DISP, 0x91), 255 .base.base.handle = NV_ENGINE(DISP, 0x91),
83 .ofuncs = &(struct nouveau_ofuncs) { 256 .base.base.ofuncs = &(struct nouveau_ofuncs) {
84 .ctor = nve0_disp_ctor, 257 .ctor = nve0_disp_ctor,
85 .dtor = _nouveau_disp_dtor, 258 .dtor = _nouveau_disp_dtor,
86 .init = _nouveau_disp_init, 259 .init = _nouveau_disp_init,
87 .fini = _nouveau_disp_fini, 260 .fini = _nouveau_disp_fini,
88 }, 261 },
89}; 262 .mthd.core = &nve0_disp_mast_mthd_chan,
263 .mthd.base = &nvd0_disp_sync_mthd_chan,
264 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
265 .mthd.prev = -0x020000,
266}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index 05fee10e0c97..482585d375fa 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -29,6 +29,10 @@
29 29
30#include "nv50.h" 30#include "nv50.h"
31 31
32/*******************************************************************************
33 * Base display object
34 ******************************************************************************/
35
32static struct nouveau_oclass 36static struct nouveau_oclass
33nvf0_disp_sclass[] = { 37nvf0_disp_sclass[] = {
34 { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs }, 38 { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
@@ -45,6 +49,10 @@ nvf0_disp_base_oclass[] = {
45 {} 49 {}
46}; 50};
47 51
52/*******************************************************************************
53 * Display engine implementation
54 ******************************************************************************/
55
48static int 56static int
49nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 57nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
50 struct nouveau_oclass *oclass, void *data, u32 size, 58 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +85,17 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
77 return 0; 85 return 0;
78} 86}
79 87
80struct nouveau_oclass 88struct nouveau_oclass *
81nvf0_disp_oclass = { 89nvf0_disp_oclass = &(struct nv50_disp_impl) {
82 .handle = NV_ENGINE(DISP, 0x92), 90 .base.base.handle = NV_ENGINE(DISP, 0x92),
83 .ofuncs = &(struct nouveau_ofuncs) { 91 .base.base.ofuncs = &(struct nouveau_ofuncs) {
84 .ctor = nvf0_disp_ctor, 92 .ctor = nvf0_disp_ctor,
85 .dtor = _nouveau_disp_dtor, 93 .dtor = _nouveau_disp_dtor,
86 .init = _nouveau_disp_init, 94 .init = _nouveau_disp_init,
87 .fini = _nouveau_disp_fini, 95 .fini = _nouveau_disp_fini,
88 }, 96 },
89}; 97 .mthd.core = &nve0_disp_mast_mthd_chan,
98 .mthd.base = &nvd0_disp_sync_mthd_chan,
99 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
100 .mthd.prev = -0x020000,
101}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/priv.h b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
new file mode 100644
index 000000000000..cc3c7a4ca747
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
@@ -0,0 +1,10 @@
1#ifndef __NVKM_DISP_PRIV_H__
2#define __NVKM_DISP_PRIV_H__
3
4#include <engine/disp.h>
5
6struct nouveau_disp_impl {
7 struct nouveau_oclass base;
8};
9
10#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
index 944e73ac485c..1cfb3bb90131 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
@@ -53,6 +53,9 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
53 case NVF0_DISP_MAST_CLASS: 53 case NVF0_DISP_MAST_CLASS:
54 case NVF0_DISP_SYNC_CLASS: 54 case NVF0_DISP_SYNC_CLASS:
55 case NVF0_DISP_OVLY_CLASS: 55 case NVF0_DISP_OVLY_CLASS:
56 case GM107_DISP_MAST_CLASS:
57 case GM107_DISP_SYNC_CLASS:
58 case GM107_DISP_OVLY_CLASS:
56 break; 59 break;
57 default: 60 default:
58 return -EINVAL; 61 return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/engine/falcon.c b/drivers/gpu/drm/nouveau/core/engine/falcon.c
index 5e077e4ed7f6..2914646c8709 100644
--- a/drivers/gpu/drm/nouveau/core/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/core/engine/falcon.c
@@ -119,7 +119,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
119 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x", 119 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x",
120 device->chipset, falcon->addr >> 12); 120 device->chipset, falcon->addr >> 12);
121 121
122 ret = request_firmware(&fw, name, &device->pdev->dev); 122 ret = request_firmware(&fw, name, nv_device_base(device));
123 if (ret == 0) { 123 if (ret == 0) {
124 falcon->code.data = vmemdup(fw->data, fw->size); 124 falcon->code.data = vmemdup(fw->data, fw->size);
125 falcon->code.size = fw->size; 125 falcon->code.size = fw->size;
@@ -138,7 +138,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
138 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd", 138 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd",
139 device->chipset, falcon->addr >> 12); 139 device->chipset, falcon->addr >> 12);
140 140
141 ret = request_firmware(&fw, name, &device->pdev->dev); 141 ret = request_firmware(&fw, name, nv_device_base(device));
142 if (ret) { 142 if (ret) {
143 nv_error(falcon, "unable to load firmware data\n"); 143 nv_error(falcon, "unable to load firmware data\n");
144 return ret; 144 return ret;
@@ -153,7 +153,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
153 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc", 153 snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc",
154 device->chipset, falcon->addr >> 12); 154 device->chipset, falcon->addr >> 12);
155 155
156 ret = request_firmware(&fw, name, &device->pdev->dev); 156 ret = request_firmware(&fw, name, nv_device_base(device));
157 if (ret) { 157 if (ret) {
158 nv_error(falcon, "unable to load firmware code\n"); 158 nv_error(falcon, "unable to load firmware code\n");
159 return ret; 159 return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
index d3ec436d9cb5..6f9041ced9a2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
@@ -86,7 +86,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
86 } 86 }
87 87
88 /* map fifo control registers */ 88 /* map fifo control registers */
89 chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr + 89 chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
90 (chan->chid * size), size); 90 (chan->chid * size), size);
91 if (!chan->user) 91 if (!chan->user)
92 return -EFAULT; 92 return -EFAULT;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index b22a33f0702d..fa1e719872b7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -41,8 +41,16 @@
41 41
42struct nvc0_fifo_priv { 42struct nvc0_fifo_priv {
43 struct nouveau_fifo base; 43 struct nouveau_fifo base;
44 struct nouveau_gpuobj *playlist[2]; 44
45 int cur_playlist; 45 struct work_struct fault;
46 u64 mask;
47
48 struct {
49 struct nouveau_gpuobj *mem[2];
50 int active;
51 wait_queue_head_t wait;
52 } runlist;
53
46 struct { 54 struct {
47 struct nouveau_gpuobj *mem; 55 struct nouveau_gpuobj *mem;
48 struct nouveau_vma bar; 56 struct nouveau_vma bar;
@@ -58,6 +66,11 @@ struct nvc0_fifo_base {
58 66
59struct nvc0_fifo_chan { 67struct nvc0_fifo_chan {
60 struct nouveau_fifo_chan base; 68 struct nouveau_fifo_chan base;
69 enum {
70 STOPPED,
71 RUNNING,
72 KILLED
73 } state;
61}; 74};
62 75
63/******************************************************************************* 76/*******************************************************************************
@@ -65,29 +78,33 @@ struct nvc0_fifo_chan {
65 ******************************************************************************/ 78 ******************************************************************************/
66 79
67static void 80static void
68nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv) 81nvc0_fifo_runlist_update(struct nvc0_fifo_priv *priv)
69{ 82{
70 struct nouveau_bar *bar = nouveau_bar(priv); 83 struct nouveau_bar *bar = nouveau_bar(priv);
71 struct nouveau_gpuobj *cur; 84 struct nouveau_gpuobj *cur;
72 int i, p; 85 int i, p;
73 86
74 mutex_lock(&nv_subdev(priv)->mutex); 87 mutex_lock(&nv_subdev(priv)->mutex);
75 cur = priv->playlist[priv->cur_playlist]; 88 cur = priv->runlist.mem[priv->runlist.active];
76 priv->cur_playlist = !priv->cur_playlist; 89 priv->runlist.active = !priv->runlist.active;
77 90
78 for (i = 0, p = 0; i < 128; i++) { 91 for (i = 0, p = 0; i < 128; i++) {
79 if (!(nv_rd32(priv, 0x003004 + (i * 8)) & 1)) 92 struct nvc0_fifo_chan *chan = (void *)priv->base.channel[i];
80 continue; 93 if (chan && chan->state == RUNNING) {
81 nv_wo32(cur, p + 0, i); 94 nv_wo32(cur, p + 0, i);
82 nv_wo32(cur, p + 4, 0x00000004); 95 nv_wo32(cur, p + 4, 0x00000004);
83 p += 8; 96 p += 8;
97 }
84 } 98 }
85 bar->flush(bar); 99 bar->flush(bar);
86 100
87 nv_wr32(priv, 0x002270, cur->addr >> 12); 101 nv_wr32(priv, 0x002270, cur->addr >> 12);
88 nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); 102 nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3));
89 if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000)) 103
90 nv_error(priv, "playlist update failed\n"); 104 if (wait_event_timeout(priv->runlist.wait,
105 !(nv_rd32(priv, 0x00227c) & 0x00100000),
106 msecs_to_jiffies(2000)) == 0)
107 nv_error(priv, "runlist update timeout\n");
91 mutex_unlock(&nv_subdev(priv)->mutex); 108 mutex_unlock(&nv_subdev(priv)->mutex);
92} 109}
93 110
@@ -239,30 +256,32 @@ nvc0_fifo_chan_init(struct nouveau_object *object)
239 return ret; 256 return ret;
240 257
241 nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12); 258 nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12);
242 nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); 259
243 nvc0_fifo_playlist_update(priv); 260 if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
261 nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001);
262 nvc0_fifo_runlist_update(priv);
263 }
264
244 return 0; 265 return 0;
245} 266}
246 267
268static void nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv);
269
247static int 270static int
248nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend) 271nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
249{ 272{
250 struct nvc0_fifo_priv *priv = (void *)object->engine; 273 struct nvc0_fifo_priv *priv = (void *)object->engine;
251 struct nvc0_fifo_chan *chan = (void *)object; 274 struct nvc0_fifo_chan *chan = (void *)object;
252 u32 chid = chan->base.chid; 275 u32 chid = chan->base.chid;
253 u32 mask, engine;
254 276
255 nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); 277 if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
256 nvc0_fifo_playlist_update(priv); 278 nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
257 mask = nv_rd32(priv, 0x0025a4); 279 nvc0_fifo_runlist_update(priv);
258 for (engine = 0; mask && engine < 16; engine++) {
259 if (!(mask & (1 << engine)))
260 continue;
261 nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000);
262 mask &= ~(1 << engine);
263 } 280 }
264 nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
265 281
282 nvc0_fifo_intr_engine(priv);
283
284 nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
266 return nouveau_fifo_channel_fini(&chan->base, suspend); 285 return nouveau_fifo_channel_fini(&chan->base, suspend);
267} 286}
268 287
@@ -345,11 +364,177 @@ nvc0_fifo_cclass = {
345 * PFIFO engine 364 * PFIFO engine
346 ******************************************************************************/ 365 ******************************************************************************/
347 366
348static const struct nouveau_enum nvc0_fifo_fault_unit[] = { 367static inline int
368nvc0_fifo_engidx(struct nvc0_fifo_priv *priv, u32 engn)
369{
370 switch (engn) {
371 case NVDEV_ENGINE_GR : engn = 0; break;
372 case NVDEV_ENGINE_BSP : engn = 1; break;
373 case NVDEV_ENGINE_PPP : engn = 2; break;
374 case NVDEV_ENGINE_VP : engn = 3; break;
375 case NVDEV_ENGINE_COPY0: engn = 4; break;
376 case NVDEV_ENGINE_COPY1: engn = 5; break;
377 default:
378 return -1;
379 }
380
381 return engn;
382}
383
384static inline struct nouveau_engine *
385nvc0_fifo_engine(struct nvc0_fifo_priv *priv, u32 engn)
386{
387 switch (engn) {
388 case 0: engn = NVDEV_ENGINE_GR; break;
389 case 1: engn = NVDEV_ENGINE_BSP; break;
390 case 2: engn = NVDEV_ENGINE_PPP; break;
391 case 3: engn = NVDEV_ENGINE_VP; break;
392 case 4: engn = NVDEV_ENGINE_COPY0; break;
393 case 5: engn = NVDEV_ENGINE_COPY1; break;
394 default:
395 return NULL;
396 }
397
398 return nouveau_engine(priv, engn);
399}
400
401static void
402nvc0_fifo_recover_work(struct work_struct *work)
403{
404 struct nvc0_fifo_priv *priv = container_of(work, typeof(*priv), fault);
405 struct nouveau_object *engine;
406 unsigned long flags;
407 u32 engn, engm = 0;
408 u64 mask, todo;
409
410 spin_lock_irqsave(&priv->base.lock, flags);
411 mask = priv->mask;
412 priv->mask = 0ULL;
413 spin_unlock_irqrestore(&priv->base.lock, flags);
414
415 for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
416 engm |= 1 << nvc0_fifo_engidx(priv, engn);
417 nv_mask(priv, 0x002630, engm, engm);
418
419 for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
420 if ((engine = (void *)nouveau_engine(priv, engn))) {
421 nv_ofuncs(engine)->fini(engine, false);
422 WARN_ON(nv_ofuncs(engine)->init(engine));
423 }
424 }
425
426 nvc0_fifo_runlist_update(priv);
427 nv_wr32(priv, 0x00262c, engm);
428 nv_mask(priv, 0x002630, engm, 0x00000000);
429}
430
431static void
432nvc0_fifo_recover(struct nvc0_fifo_priv *priv, struct nouveau_engine *engine,
433 struct nvc0_fifo_chan *chan)
434{
435 struct nouveau_object *engobj = nv_object(engine);
436 u32 chid = chan->base.chid;
437 unsigned long flags;
438
439 nv_error(priv, "%s engine fault on channel %d, recovering...\n",
440 nv_subdev(engine)->name, chid);
441
442 nv_mask(priv, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
443 chan->state = KILLED;
444
445 spin_lock_irqsave(&priv->base.lock, flags);
446 priv->mask |= 1ULL << nv_engidx(engobj);
447 spin_unlock_irqrestore(&priv->base.lock, flags);
448 schedule_work(&priv->fault);
449}
450
451static int
452nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
453{
454 struct nvc0_fifo_chan *chan = NULL;
455 struct nouveau_handle *bind;
456 unsigned long flags;
457 int ret = -EINVAL;
458
459 spin_lock_irqsave(&priv->base.lock, flags);
460 if (likely(chid >= priv->base.min && chid <= priv->base.max))
461 chan = (void *)priv->base.channel[chid];
462 if (unlikely(!chan))
463 goto out;
464
465 bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
466 if (likely(bind)) {
467 if (!mthd || !nv_call(bind->object, mthd, data))
468 ret = 0;
469 nouveau_namedb_put(bind);
470 }
471
472out:
473 spin_unlock_irqrestore(&priv->base.lock, flags);
474 return ret;
475}
476
477static const struct nouveau_enum
478nvc0_fifo_sched_reason[] = {
479 { 0x0a, "CTXSW_TIMEOUT" },
480 {}
481};
482
483static void
484nvc0_fifo_intr_sched_ctxsw(struct nvc0_fifo_priv *priv)
485{
486 struct nouveau_engine *engine;
487 struct nvc0_fifo_chan *chan;
488 u32 engn;
489
490 for (engn = 0; engn < 6; engn++) {
491 u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04));
492 u32 busy = (stat & 0x80000000);
493 u32 save = (stat & 0x00100000); /* maybe? */
494 u32 unk0 = (stat & 0x00040000);
495 u32 unk1 = (stat & 0x00001000);
496 u32 chid = (stat & 0x0000007f);
497 (void)save;
498
499 if (busy && unk0 && unk1) {
500 if (!(chan = (void *)priv->base.channel[chid]))
501 continue;
502 if (!(engine = nvc0_fifo_engine(priv, engn)))
503 continue;
504 nvc0_fifo_recover(priv, engine, chan);
505 }
506 }
507}
508
509static void
510nvc0_fifo_intr_sched(struct nvc0_fifo_priv *priv)
511{
512 u32 intr = nv_rd32(priv, 0x00254c);
513 u32 code = intr & 0x000000ff;
514 const struct nouveau_enum *en;
515 char enunk[6] = "";
516
517 en = nouveau_enum_find(nvc0_fifo_sched_reason, code);
518 if (!en)
519 snprintf(enunk, sizeof(enunk), "UNK%02x", code);
520
521 nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk);
522
523 switch (code) {
524 case 0x0a:
525 nvc0_fifo_intr_sched_ctxsw(priv);
526 break;
527 default:
528 break;
529 }
530}
531
532static const struct nouveau_enum
533nvc0_fifo_fault_engine[] = {
349 { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR }, 534 { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR },
350 { 0x03, "PEEPHOLE" }, 535 { 0x03, "PEEPHOLE", NULL, NVDEV_ENGINE_IFB },
351 { 0x04, "BAR1" }, 536 { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
352 { 0x05, "BAR3" }, 537 { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
353 { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO }, 538 { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO },
354 { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP }, 539 { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP },
355 { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP }, 540 { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP },
@@ -361,7 +546,8 @@ static const struct nouveau_enum nvc0_fifo_fault_unit[] = {
361 {} 546 {}
362}; 547};
363 548
364static const struct nouveau_enum nvc0_fifo_fault_reason[] = { 549static const struct nouveau_enum
550nvc0_fifo_fault_reason[] = {
365 { 0x00, "PT_NOT_PRESENT" }, 551 { 0x00, "PT_NOT_PRESENT" },
366 { 0x01, "PT_TOO_SHORT" }, 552 { 0x01, "PT_TOO_SHORT" },
367 { 0x02, "PAGE_NOT_PRESENT" }, 553 { 0x02, "PAGE_NOT_PRESENT" },
@@ -374,7 +560,8 @@ static const struct nouveau_enum nvc0_fifo_fault_reason[] = {
374 {} 560 {}
375}; 561};
376 562
377static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = { 563static const struct nouveau_enum
564nvc0_fifo_fault_hubclient[] = {
378 { 0x01, "PCOPY0" }, 565 { 0x01, "PCOPY0" },
379 { 0x02, "PCOPY1" }, 566 { 0x02, "PCOPY1" },
380 { 0x04, "DISPATCH" }, 567 { 0x04, "DISPATCH" },
@@ -392,7 +579,8 @@ static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
392 {} 579 {}
393}; 580};
394 581
395static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { 582static const struct nouveau_enum
583nvc0_fifo_fault_gpcclient[] = {
396 { 0x01, "TEX" }, 584 { 0x01, "TEX" },
397 { 0x0c, "ESETUP" }, 585 { 0x0c, "ESETUP" },
398 { 0x0e, "CTXCTL" }, 586 { 0x0e, "CTXCTL" },
@@ -400,92 +588,92 @@ static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
400 {} 588 {}
401}; 589};
402 590
403static const struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = {
404/* { 0x00008000, "" } seen with null ib push */
405 { 0x00200000, "ILLEGAL_MTHD" },
406 { 0x00800000, "EMPTY_SUBC" },
407 {}
408};
409
410static void 591static void
411nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) 592nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)
412{ 593{
413 u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10)); 594 u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10));
414 u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10)); 595 u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10));
415 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); 596 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));
416 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); 597 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10));
598 u32 gpc = (stat & 0x1f000000) >> 24;
417 u32 client = (stat & 0x00001f00) >> 8; 599 u32 client = (stat & 0x00001f00) >> 8;
418 const struct nouveau_enum *en; 600 u32 write = (stat & 0x00000080);
419 struct nouveau_engine *engine; 601 u32 hub = (stat & 0x00000040);
420 struct nouveau_object *engctx = NULL; 602 u32 reason = (stat & 0x0000000f);
421 603 struct nouveau_object *engctx = NULL, *object;
422 switch (unit) { 604 struct nouveau_engine *engine = NULL;
423 case 3: /* PEEPHOLE */ 605 const struct nouveau_enum *er, *eu, *ec;
424 nv_mask(priv, 0x001718, 0x00000000, 0x00000000); 606 char erunk[6] = "";
425 break; 607 char euunk[6] = "";
426 case 4: /* BAR1 */ 608 char ecunk[6] = "";
427 nv_mask(priv, 0x001704, 0x00000000, 0x00000000); 609 char gpcid[3] = "";
428 break; 610
429 case 5: /* BAR3 */ 611 er = nouveau_enum_find(nvc0_fifo_fault_reason, reason);
430 nv_mask(priv, 0x001714, 0x00000000, 0x00000000); 612 if (!er)
431 break; 613 snprintf(erunk, sizeof(erunk), "UNK%02X", reason);
432 default: 614
433 break; 615 eu = nouveau_enum_find(nvc0_fifo_fault_engine, unit);
616 if (eu) {
617 switch (eu->data2) {
618 case NVDEV_SUBDEV_BAR:
619 nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
620 break;
621 case NVDEV_SUBDEV_INSTMEM:
622 nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
623 break;
624 case NVDEV_ENGINE_IFB:
625 nv_mask(priv, 0x001718, 0x00000000, 0x00000000);
626 break;
627 default:
628 engine = nouveau_engine(priv, eu->data2);
629 if (engine)
630 engctx = nouveau_engctx_get(engine, inst);
631 break;
632 }
633 } else {
634 snprintf(euunk, sizeof(euunk), "UNK%02x", unit);
434 } 635 }
435 636
436 nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? 637 if (hub) {
437 "write" : "read", (u64)vahi << 32 | valo); 638 ec = nouveau_enum_find(nvc0_fifo_fault_hubclient, client);
438 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
439 pr_cont("] from ");
440 en = nouveau_enum_print(nvc0_fifo_fault_unit, unit);
441 if (stat & 0x00000040) {
442 pr_cont("/");
443 nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
444 } else { 639 } else {
445 pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); 640 ec = nouveau_enum_find(nvc0_fifo_fault_gpcclient, client);
446 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); 641 snprintf(gpcid, sizeof(gpcid), "%d", gpc);
447 } 642 }
448 643
449 if (en && en->data2) { 644 if (!ec)
450 engine = nouveau_engine(priv, en->data2); 645 snprintf(ecunk, sizeof(ecunk), "UNK%02x", client);
451 if (engine) 646
452 engctx = nouveau_engctx_get(engine, inst); 647 nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on "
453 648 "channel 0x%010llx [%s]\n", write ? "write" : "read",
649 (u64)vahi << 32 | valo, er ? er->name : erunk,
650 eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/",
651 ec ? ec->name : ecunk, (u64)inst << 12,
652 nouveau_client_name(engctx));
653
654 object = engctx;
655 while (object) {
656 switch (nv_mclass(object)) {
657 case NVC0_CHANNEL_IND_CLASS:
658 nvc0_fifo_recover(priv, engine, (void *)object);
659 break;
660 }
661 object = object->parent;
454 } 662 }
455 pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
456 nouveau_client_name(engctx));
457 663
458 nouveau_engctx_put(engctx); 664 nouveau_engctx_put(engctx);
459} 665}
460 666
461static int 667static const struct nouveau_bitfield
462nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) 668nvc0_fifo_pbdma_intr[] = {
463{ 669/* { 0x00008000, "" } seen with null ib push */
464 struct nvc0_fifo_chan *chan = NULL; 670 { 0x00200000, "ILLEGAL_MTHD" },
465 struct nouveau_handle *bind; 671 { 0x00800000, "EMPTY_SUBC" },
466 unsigned long flags; 672 {}
467 int ret = -EINVAL; 673};
468
469 spin_lock_irqsave(&priv->base.lock, flags);
470 if (likely(chid >= priv->base.min && chid <= priv->base.max))
471 chan = (void *)priv->base.channel[chid];
472 if (unlikely(!chan))
473 goto out;
474
475 bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
476 if (likely(bind)) {
477 if (!mthd || !nv_call(bind->object, mthd, data))
478 ret = 0;
479 nouveau_namedb_put(bind);
480 }
481
482out:
483 spin_unlock_irqrestore(&priv->base.lock, flags);
484 return ret;
485}
486 674
487static void 675static void
488nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit) 676nvc0_fifo_intr_pbdma(struct nvc0_fifo_priv *priv, int unit)
489{ 677{
490 u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); 678 u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
491 u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); 679 u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -501,11 +689,11 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
501 } 689 }
502 690
503 if (show) { 691 if (show) {
504 nv_error(priv, "SUBFIFO%d:", unit); 692 nv_error(priv, "PBDMA%d:", unit);
505 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); 693 nouveau_bitfield_print(nvc0_fifo_pbdma_intr, show);
506 pr_cont("\n"); 694 pr_cont("\n");
507 nv_error(priv, 695 nv_error(priv,
508 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", 696 "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
509 unit, chid, 697 unit, chid,
510 nouveau_client_name_for_fifo_chid(&priv->base, chid), 698 nouveau_client_name_for_fifo_chid(&priv->base, chid),
511 subc, mthd, data); 699 subc, mthd, data);
@@ -516,6 +704,56 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
516} 704}
517 705
518static void 706static void
707nvc0_fifo_intr_runlist(struct nvc0_fifo_priv *priv)
708{
709 u32 intr = nv_rd32(priv, 0x002a00);
710
711 if (intr & 0x10000000) {
712 wake_up(&priv->runlist.wait);
713 nv_wr32(priv, 0x002a00, 0x10000000);
714 intr &= ~0x10000000;
715 }
716
717 if (intr) {
718 nv_error(priv, "RUNLIST 0x%08x\n", intr);
719 nv_wr32(priv, 0x002a00, intr);
720 }
721}
722
723static void
724nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
725{
726 u32 intr = nv_rd32(priv, 0x0025a8 + (engn * 0x04));
727 u32 inte = nv_rd32(priv, 0x002628);
728 u32 unkn;
729
730 for (unkn = 0; unkn < 8; unkn++) {
731 u32 ints = (intr >> (unkn * 0x04)) & inte;
732 if (ints & 0x1) {
733 nouveau_event_trigger(priv->base.uevent, 0);
734 ints &= ~1;
735 }
736 if (ints) {
737 nv_error(priv, "ENGINE %d %d %01x", engn, unkn, ints);
738 nv_mask(priv, 0x002628, ints, 0);
739 }
740 }
741
742 nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
743}
744
745static void
746nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv)
747{
748 u32 mask = nv_rd32(priv, 0x0025a4);
749 while (mask) {
750 u32 unit = __ffs(mask);
751 nvc0_fifo_intr_engine_unit(priv, unit);
752 mask &= ~(1 << unit);
753 }
754}
755
756static void
519nvc0_fifo_intr(struct nouveau_subdev *subdev) 757nvc0_fifo_intr(struct nouveau_subdev *subdev)
520{ 758{
521 struct nvc0_fifo_priv *priv = (void *)subdev; 759 struct nvc0_fifo_priv *priv = (void *)subdev;
@@ -530,8 +768,7 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
530 } 768 }
531 769
532 if (stat & 0x00000100) { 770 if (stat & 0x00000100) {
533 u32 intr = nv_rd32(priv, 0x00254c); 771 nvc0_fifo_intr_sched(priv);
534 nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr);
535 nv_wr32(priv, 0x002100, 0x00000100); 772 nv_wr32(priv, 0x002100, 0x00000100);
536 stat &= ~0x00000100; 773 stat &= ~0x00000100;
537 } 774 }
@@ -551,52 +788,41 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
551 } 788 }
552 789
553 if (stat & 0x10000000) { 790 if (stat & 0x10000000) {
554 u32 units = nv_rd32(priv, 0x00259c); 791 u32 mask = nv_rd32(priv, 0x00259c);
555 u32 u = units; 792 while (mask) {
556 793 u32 unit = __ffs(mask);
557 while (u) { 794 nvc0_fifo_intr_fault(priv, unit);
558 int i = ffs(u) - 1; 795 nv_wr32(priv, 0x00259c, (1 << unit));
559 nvc0_fifo_isr_vm_fault(priv, i); 796 mask &= ~(1 << unit);
560 u &= ~(1 << i);
561 } 797 }
562
563 nv_wr32(priv, 0x00259c, units);
564 stat &= ~0x10000000; 798 stat &= ~0x10000000;
565 } 799 }
566 800
567 if (stat & 0x20000000) { 801 if (stat & 0x20000000) {
568 u32 units = nv_rd32(priv, 0x0025a0); 802 u32 mask = nv_rd32(priv, 0x0025a0);
569 u32 u = units; 803 while (mask) {
570 804 u32 unit = __ffs(mask);
571 while (u) { 805 nvc0_fifo_intr_pbdma(priv, unit);
572 int i = ffs(u) - 1; 806 nv_wr32(priv, 0x0025a0, (1 << unit));
573 nvc0_fifo_isr_subfifo_intr(priv, i); 807 mask &= ~(1 << unit);
574 u &= ~(1 << i);
575 } 808 }
576
577 nv_wr32(priv, 0x0025a0, units);
578 stat &= ~0x20000000; 809 stat &= ~0x20000000;
579 } 810 }
580 811
581 if (stat & 0x40000000) { 812 if (stat & 0x40000000) {
582 u32 intr0 = nv_rd32(priv, 0x0025a4); 813 nvc0_fifo_intr_runlist(priv);
583 u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000);
584 nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n",
585 intr0, intr1);
586 stat &= ~0x40000000; 814 stat &= ~0x40000000;
587 } 815 }
588 816
589 if (stat & 0x80000000) { 817 if (stat & 0x80000000) {
590 u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000); 818 nvc0_fifo_intr_engine(priv);
591 nouveau_event_trigger(priv->base.uevent, 0);
592 nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr);
593 stat &= ~0x80000000; 819 stat &= ~0x80000000;
594 } 820 }
595 821
596 if (stat) { 822 if (stat) {
597 nv_fatal(priv, "unhandled status 0x%08x\n", stat); 823 nv_error(priv, "INTR 0x%08x\n", stat);
824 nv_mask(priv, 0x002140, stat, 0x00000000);
598 nv_wr32(priv, 0x002100, stat); 825 nv_wr32(priv, 0x002100, stat);
599 nv_wr32(priv, 0x002140, 0);
600 } 826 }
601} 827}
602 828
@@ -627,16 +853,20 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
627 if (ret) 853 if (ret)
628 return ret; 854 return ret;
629 855
856 INIT_WORK(&priv->fault, nvc0_fifo_recover_work);
857
630 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, 858 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
631 &priv->playlist[0]); 859 &priv->runlist.mem[0]);
632 if (ret) 860 if (ret)
633 return ret; 861 return ret;
634 862
635 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, 863 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
636 &priv->playlist[1]); 864 &priv->runlist.mem[1]);
637 if (ret) 865 if (ret)
638 return ret; 866 return ret;
639 867
868 init_waitqueue_head(&priv->runlist.wait);
869
640 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0, 870 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0,
641 &priv->user.mem); 871 &priv->user.mem);
642 if (ret) 872 if (ret)
@@ -665,8 +895,8 @@ nvc0_fifo_dtor(struct nouveau_object *object)
665 895
666 nouveau_gpuobj_unmap(&priv->user.bar); 896 nouveau_gpuobj_unmap(&priv->user.bar);
667 nouveau_gpuobj_ref(NULL, &priv->user.mem); 897 nouveau_gpuobj_ref(NULL, &priv->user.mem);
668 nouveau_gpuobj_ref(NULL, &priv->playlist[1]); 898 nouveau_gpuobj_ref(NULL, &priv->runlist.mem[0]);
669 nouveau_gpuobj_ref(NULL, &priv->playlist[0]); 899 nouveau_gpuobj_ref(NULL, &priv->runlist.mem[1]);
670 900
671 nouveau_fifo_destroy(&priv->base); 901 nouveau_fifo_destroy(&priv->base);
672} 902}
@@ -685,9 +915,9 @@ nvc0_fifo_init(struct nouveau_object *object)
685 nv_wr32(priv, 0x002204, 0xffffffff); 915 nv_wr32(priv, 0x002204, 0xffffffff);
686 916
687 priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204)); 917 priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204));
688 nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); 918 nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr);
689 919
690 /* assign engines to subfifos */ 920 /* assign engines to PBDMAs */
691 if (priv->spoon_nr >= 3) { 921 if (priv->spoon_nr >= 3) {
692 nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */ 922 nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */
693 nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */ 923 nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */
@@ -697,7 +927,7 @@ nvc0_fifo_init(struct nouveau_object *object)
697 nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */ 927 nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */
698 } 928 }
699 929
700 /* PSUBFIFO[n] */ 930 /* PBDMA[n] */
701 for (i = 0; i < priv->spoon_nr; i++) { 931 for (i = 0; i < priv->spoon_nr; i++) {
702 nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); 932 nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
703 nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ 933 nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
@@ -707,10 +937,9 @@ nvc0_fifo_init(struct nouveau_object *object)
707 nv_mask(priv, 0x002200, 0x00000001, 0x00000001); 937 nv_mask(priv, 0x002200, 0x00000001, 0x00000001);
708 nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); 938 nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
709 939
710 nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
711 nv_wr32(priv, 0x002100, 0xffffffff); 940 nv_wr32(priv, 0x002100, 0xffffffff);
712 nv_wr32(priv, 0x002140, 0x3fffffff); 941 nv_wr32(priv, 0x002140, 0x7fffffff);
713 nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */ 942 nv_wr32(priv, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
714 return 0; 943 return 0;
715} 944}
716 945
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 54c1b5b471cd..a9a1a9c9f9f2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -60,10 +60,15 @@ static const struct {
60struct nve0_fifo_engn { 60struct nve0_fifo_engn {
61 struct nouveau_gpuobj *runlist[2]; 61 struct nouveau_gpuobj *runlist[2];
62 int cur_runlist; 62 int cur_runlist;
63 wait_queue_head_t wait;
63}; 64};
64 65
65struct nve0_fifo_priv { 66struct nve0_fifo_priv {
66 struct nouveau_fifo base; 67 struct nouveau_fifo base;
68
69 struct work_struct fault;
70 u64 mask;
71
67 struct nve0_fifo_engn engine[FIFO_ENGINE_NR]; 72 struct nve0_fifo_engn engine[FIFO_ENGINE_NR];
68 struct { 73 struct {
69 struct nouveau_gpuobj *mem; 74 struct nouveau_gpuobj *mem;
@@ -81,6 +86,11 @@ struct nve0_fifo_base {
81struct nve0_fifo_chan { 86struct nve0_fifo_chan {
82 struct nouveau_fifo_chan base; 87 struct nouveau_fifo_chan base;
83 u32 engine; 88 u32 engine;
89 enum {
90 STOPPED,
91 RUNNING,
92 KILLED
93 } state;
84}; 94};
85 95
86/******************************************************************************* 96/*******************************************************************************
@@ -93,7 +103,6 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
93 struct nouveau_bar *bar = nouveau_bar(priv); 103 struct nouveau_bar *bar = nouveau_bar(priv);
94 struct nve0_fifo_engn *engn = &priv->engine[engine]; 104 struct nve0_fifo_engn *engn = &priv->engine[engine];
95 struct nouveau_gpuobj *cur; 105 struct nouveau_gpuobj *cur;
96 u32 match = (engine << 16) | 0x00000001;
97 int i, p; 106 int i, p;
98 107
99 mutex_lock(&nv_subdev(priv)->mutex); 108 mutex_lock(&nv_subdev(priv)->mutex);
@@ -101,18 +110,21 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
101 engn->cur_runlist = !engn->cur_runlist; 110 engn->cur_runlist = !engn->cur_runlist;
102 111
103 for (i = 0, p = 0; i < priv->base.max; i++) { 112 for (i = 0, p = 0; i < priv->base.max; i++) {
104 u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001; 113 struct nve0_fifo_chan *chan = (void *)priv->base.channel[i];
105 if (ctrl != match) 114 if (chan && chan->state == RUNNING && chan->engine == engine) {
106 continue; 115 nv_wo32(cur, p + 0, i);
107 nv_wo32(cur, p + 0, i); 116 nv_wo32(cur, p + 4, 0x00000000);
108 nv_wo32(cur, p + 4, 0x00000000); 117 p += 8;
109 p += 8; 118 }
110 } 119 }
111 bar->flush(bar); 120 bar->flush(bar);
112 121
113 nv_wr32(priv, 0x002270, cur->addr >> 12); 122 nv_wr32(priv, 0x002270, cur->addr >> 12);
114 nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); 123 nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
115 if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000)) 124
125 if (wait_event_timeout(engn->wait, !(nv_rd32(priv, 0x002284 +
126 (engine * 0x08)) & 0x00100000),
127 msecs_to_jiffies(2000)) == 0)
116 nv_error(priv, "runlist %d update timeout\n", engine); 128 nv_error(priv, "runlist %d update timeout\n", engine);
117 mutex_unlock(&nv_subdev(priv)->mutex); 129 mutex_unlock(&nv_subdev(priv)->mutex);
118} 130}
@@ -129,9 +141,11 @@ nve0_fifo_context_attach(struct nouveau_object *parent,
129 141
130 switch (nv_engidx(object->engine)) { 142 switch (nv_engidx(object->engine)) {
131 case NVDEV_ENGINE_SW : 143 case NVDEV_ENGINE_SW :
144 return 0;
132 case NVDEV_ENGINE_COPY0: 145 case NVDEV_ENGINE_COPY0:
133 case NVDEV_ENGINE_COPY1: 146 case NVDEV_ENGINE_COPY1:
134 case NVDEV_ENGINE_COPY2: 147 case NVDEV_ENGINE_COPY2:
148 nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
135 return 0; 149 return 0;
136 case NVDEV_ENGINE_GR : addr = 0x0210; break; 150 case NVDEV_ENGINE_GR : addr = 0x0210; break;
137 case NVDEV_ENGINE_BSP : addr = 0x0270; break; 151 case NVDEV_ENGINE_BSP : addr = 0x0270; break;
@@ -279,9 +293,13 @@ nve0_fifo_chan_init(struct nouveau_object *object)
279 293
280 nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16); 294 nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
281 nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); 295 nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
282 nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); 296
283 nve0_fifo_runlist_update(priv, chan->engine); 297 if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
284 nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); 298 nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
299 nve0_fifo_runlist_update(priv, chan->engine);
300 nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
301 }
302
285 return 0; 303 return 0;
286} 304}
287 305
@@ -292,10 +310,12 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
292 struct nve0_fifo_chan *chan = (void *)object; 310 struct nve0_fifo_chan *chan = (void *)object;
293 u32 chid = chan->base.chid; 311 u32 chid = chan->base.chid;
294 312
295 nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); 313 if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
296 nve0_fifo_runlist_update(priv, chan->engine); 314 nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
297 nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); 315 nve0_fifo_runlist_update(priv, chan->engine);
316 }
298 317
318 nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
299 return nouveau_fifo_channel_fini(&chan->base, suspend); 319 return nouveau_fifo_channel_fini(&chan->base, suspend);
300} 320}
301 321
@@ -377,14 +397,211 @@ nve0_fifo_cclass = {
377 * PFIFO engine 397 * PFIFO engine
378 ******************************************************************************/ 398 ******************************************************************************/
379 399
380static const struct nouveau_enum nve0_fifo_sched_reason[] = { 400static inline int
401nve0_fifo_engidx(struct nve0_fifo_priv *priv, u32 engn)
402{
403 switch (engn) {
404 case NVDEV_ENGINE_GR :
405 case NVDEV_ENGINE_COPY2: engn = 0; break;
406 case NVDEV_ENGINE_BSP : engn = 1; break;
407 case NVDEV_ENGINE_PPP : engn = 2; break;
408 case NVDEV_ENGINE_VP : engn = 3; break;
409 case NVDEV_ENGINE_COPY0: engn = 4; break;
410 case NVDEV_ENGINE_COPY1: engn = 5; break;
411 case NVDEV_ENGINE_VENC : engn = 6; break;
412 default:
413 return -1;
414 }
415
416 return engn;
417}
418
419static inline struct nouveau_engine *
420nve0_fifo_engine(struct nve0_fifo_priv *priv, u32 engn)
421{
422 if (engn >= ARRAY_SIZE(fifo_engine))
423 return NULL;
424 return nouveau_engine(priv, fifo_engine[engn].subdev);
425}
426
427static void
428nve0_fifo_recover_work(struct work_struct *work)
429{
430 struct nve0_fifo_priv *priv = container_of(work, typeof(*priv), fault);
431 struct nouveau_object *engine;
432 unsigned long flags;
433 u32 engn, engm = 0;
434 u64 mask, todo;
435
436 spin_lock_irqsave(&priv->base.lock, flags);
437 mask = priv->mask;
438 priv->mask = 0ULL;
439 spin_unlock_irqrestore(&priv->base.lock, flags);
440
441 for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
442 engm |= 1 << nve0_fifo_engidx(priv, engn);
443 nv_mask(priv, 0x002630, engm, engm);
444
445 for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
446 if ((engine = (void *)nouveau_engine(priv, engn))) {
447 nv_ofuncs(engine)->fini(engine, false);
448 WARN_ON(nv_ofuncs(engine)->init(engine));
449 }
450 nve0_fifo_runlist_update(priv, nve0_fifo_engidx(priv, engn));
451 }
452
453 nv_wr32(priv, 0x00262c, engm);
454 nv_mask(priv, 0x002630, engm, 0x00000000);
455}
456
457static void
458nve0_fifo_recover(struct nve0_fifo_priv *priv, struct nouveau_engine *engine,
459 struct nve0_fifo_chan *chan)
460{
461 struct nouveau_object *engobj = nv_object(engine);
462 u32 chid = chan->base.chid;
463 unsigned long flags;
464
465 nv_error(priv, "%s engine fault on channel %d, recovering...\n",
466 nv_subdev(engine)->name, chid);
467
468 nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800);
469 chan->state = KILLED;
470
471 spin_lock_irqsave(&priv->base.lock, flags);
472 priv->mask |= 1ULL << nv_engidx(engobj);
473 spin_unlock_irqrestore(&priv->base.lock, flags);
474 schedule_work(&priv->fault);
475}
476
477static int
478nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
479{
480 struct nve0_fifo_chan *chan = NULL;
481 struct nouveau_handle *bind;
482 unsigned long flags;
483 int ret = -EINVAL;
484
485 spin_lock_irqsave(&priv->base.lock, flags);
486 if (likely(chid >= priv->base.min && chid <= priv->base.max))
487 chan = (void *)priv->base.channel[chid];
488 if (unlikely(!chan))
489 goto out;
490
491 bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
492 if (likely(bind)) {
493 if (!mthd || !nv_call(bind->object, mthd, data))
494 ret = 0;
495 nouveau_namedb_put(bind);
496 }
497
498out:
499 spin_unlock_irqrestore(&priv->base.lock, flags);
500 return ret;
501}
502
503static const struct nouveau_enum
504nve0_fifo_bind_reason[] = {
505 { 0x01, "BIND_NOT_UNBOUND" },
506 { 0x02, "SNOOP_WITHOUT_BAR1" },
507 { 0x03, "UNBIND_WHILE_RUNNING" },
508 { 0x05, "INVALID_RUNLIST" },
509 { 0x06, "INVALID_CTX_TGT" },
510 { 0x0b, "UNBIND_WHILE_PARKED" },
511 {}
512};
513
514static void
515nve0_fifo_intr_bind(struct nve0_fifo_priv *priv)
516{
517 u32 intr = nv_rd32(priv, 0x00252c);
518 u32 code = intr & 0x000000ff;
519 const struct nouveau_enum *en;
520 char enunk[6] = "";
521
522 en = nouveau_enum_find(nve0_fifo_bind_reason, code);
523 if (!en)
524 snprintf(enunk, sizeof(enunk), "UNK%02x", code);
525
526 nv_error(priv, "BIND_ERROR [ %s ]\n", en ? en->name : enunk);
527}
528
529static const struct nouveau_enum
530nve0_fifo_sched_reason[] = {
381 { 0x0a, "CTXSW_TIMEOUT" }, 531 { 0x0a, "CTXSW_TIMEOUT" },
382 {} 532 {}
383}; 533};
384 534
385static const struct nouveau_enum nve0_fifo_fault_engine[] = { 535static void
536nve0_fifo_intr_sched_ctxsw(struct nve0_fifo_priv *priv)
537{
538 struct nouveau_engine *engine;
539 struct nve0_fifo_chan *chan;
540 u32 engn;
541
542 for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) {
543 u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04));
544 u32 busy = (stat & 0x80000000);
545 u32 next = (stat & 0x07ff0000) >> 16;
546 u32 chsw = (stat & 0x00008000);
547 u32 save = (stat & 0x00004000);
548 u32 load = (stat & 0x00002000);
549 u32 prev = (stat & 0x000007ff);
550 u32 chid = load ? next : prev;
551 (void)save;
552
553 if (busy && chsw) {
554 if (!(chan = (void *)priv->base.channel[chid]))
555 continue;
556 if (!(engine = nve0_fifo_engine(priv, engn)))
557 continue;
558 nve0_fifo_recover(priv, engine, chan);
559 }
560 }
561}
562
563static void
564nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
565{
566 u32 intr = nv_rd32(priv, 0x00254c);
567 u32 code = intr & 0x000000ff;
568 const struct nouveau_enum *en;
569 char enunk[6] = "";
570
571 en = nouveau_enum_find(nve0_fifo_sched_reason, code);
572 if (!en)
573 snprintf(enunk, sizeof(enunk), "UNK%02x", code);
574
575 nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk);
576
577 switch (code) {
578 case 0x0a:
579 nve0_fifo_intr_sched_ctxsw(priv);
580 break;
581 default:
582 break;
583 }
584}
585
586static void
587nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
588{
589 u32 stat = nv_rd32(priv, 0x00256c);
590 nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
591 nv_wr32(priv, 0x00256c, stat);
592}
593
594static void
595nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
596{
597 u32 stat = nv_rd32(priv, 0x00259c);
598 nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
599}
600
601static const struct nouveau_enum
602nve0_fifo_fault_engine[] = {
386 { 0x00, "GR", NULL, NVDEV_ENGINE_GR }, 603 { 0x00, "GR", NULL, NVDEV_ENGINE_GR },
387 { 0x03, "IFB" }, 604 { 0x03, "IFB", NULL, NVDEV_ENGINE_IFB },
388 { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR }, 605 { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
389 { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM }, 606 { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
390 { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO }, 607 { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
@@ -402,7 +619,8 @@ static const struct nouveau_enum nve0_fifo_fault_engine[] = {
402 {} 619 {}
403}; 620};
404 621
405static const struct nouveau_enum nve0_fifo_fault_reason[] = { 622static const struct nouveau_enum
623nve0_fifo_fault_reason[] = {
406 { 0x00, "PDE" }, 624 { 0x00, "PDE" },
407 { 0x01, "PDE_SIZE" }, 625 { 0x01, "PDE_SIZE" },
408 { 0x02, "PTE" }, 626 { 0x02, "PTE" },
@@ -422,7 +640,8 @@ static const struct nouveau_enum nve0_fifo_fault_reason[] = {
422 {} 640 {}
423}; 641};
424 642
425static const struct nouveau_enum nve0_fifo_fault_hubclient[] = { 643static const struct nouveau_enum
644nve0_fifo_fault_hubclient[] = {
426 { 0x00, "VIP" }, 645 { 0x00, "VIP" },
427 { 0x01, "CE0" }, 646 { 0x01, "CE0" },
428 { 0x02, "CE1" }, 647 { 0x02, "CE1" },
@@ -458,7 +677,8 @@ static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
458 {} 677 {}
459}; 678};
460 679
461static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = { 680static const struct nouveau_enum
681nve0_fifo_fault_gpcclient[] = {
462 { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, 682 { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
463 { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, 683 { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
464 { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, 684 { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
@@ -483,6 +703,82 @@ static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
483 {} 703 {}
484}; 704};
485 705
706static void
707nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
708{
709 u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10));
710 u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10));
711 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));
712 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10));
713 u32 gpc = (stat & 0x1f000000) >> 24;
714 u32 client = (stat & 0x00001f00) >> 8;
715 u32 write = (stat & 0x00000080);
716 u32 hub = (stat & 0x00000040);
717 u32 reason = (stat & 0x0000000f);
718 struct nouveau_object *engctx = NULL, *object;
719 struct nouveau_engine *engine = NULL;
720 const struct nouveau_enum *er, *eu, *ec;
721 char erunk[6] = "";
722 char euunk[6] = "";
723 char ecunk[6] = "";
724 char gpcid[3] = "";
725
726 er = nouveau_enum_find(nve0_fifo_fault_reason, reason);
727 if (!er)
728 snprintf(erunk, sizeof(erunk), "UNK%02X", reason);
729
730 eu = nouveau_enum_find(nve0_fifo_fault_engine, unit);
731 if (eu) {
732 switch (eu->data2) {
733 case NVDEV_SUBDEV_BAR:
734 nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
735 break;
736 case NVDEV_SUBDEV_INSTMEM:
737 nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
738 break;
739 case NVDEV_ENGINE_IFB:
740 nv_mask(priv, 0x001718, 0x00000000, 0x00000000);
741 break;
742 default:
743 engine = nouveau_engine(priv, eu->data2);
744 if (engine)
745 engctx = nouveau_engctx_get(engine, inst);
746 break;
747 }
748 } else {
749 snprintf(euunk, sizeof(euunk), "UNK%02x", unit);
750 }
751
752 if (hub) {
753 ec = nouveau_enum_find(nve0_fifo_fault_hubclient, client);
754 } else {
755 ec = nouveau_enum_find(nve0_fifo_fault_gpcclient, client);
756 snprintf(gpcid, sizeof(gpcid), "%d", gpc);
757 }
758
759 if (!ec)
760 snprintf(ecunk, sizeof(ecunk), "UNK%02x", client);
761
762 nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on "
763 "channel 0x%010llx [%s]\n", write ? "write" : "read",
764 (u64)vahi << 32 | valo, er ? er->name : erunk,
765 eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/",
766 ec ? ec->name : ecunk, (u64)inst << 12,
767 nouveau_client_name(engctx));
768
769 object = engctx;
770 while (object) {
771 switch (nv_mclass(object)) {
772 case NVE0_CHANNEL_IND_CLASS:
773 nve0_fifo_recover(priv, engine, (void *)object);
774 break;
775 }
776 object = object->parent;
777 }
778
779 nouveau_engctx_put(engctx);
780}
781
486static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = { 782static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
487 { 0x00000001, "MEMREQ" }, 783 { 0x00000001, "MEMREQ" },
488 { 0x00000002, "MEMACK_TIMEOUT" }, 784 { 0x00000002, "MEMACK_TIMEOUT" },
@@ -518,104 +814,6 @@ static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
518}; 814};
519 815
520static void 816static void
521nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
522{
523 u32 intr = nv_rd32(priv, 0x00254c);
524 u32 code = intr & 0x000000ff;
525 nv_error(priv, "SCHED_ERROR [");
526 nouveau_enum_print(nve0_fifo_sched_reason, code);
527 pr_cont("]\n");
528}
529
530static void
531nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
532{
533 u32 stat = nv_rd32(priv, 0x00256c);
534 nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
535 nv_wr32(priv, 0x00256c, stat);
536}
537
538static void
539nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
540{
541 u32 stat = nv_rd32(priv, 0x00259c);
542 nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
543}
544
545static void
546nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
547{
548 u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10));
549 u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10));
550 u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
551 u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
552 u32 client = (stat & 0x00001f00) >> 8;
553 struct nouveau_engine *engine = NULL;
554 struct nouveau_object *engctx = NULL;
555 const struct nouveau_enum *en;
556 const char *name = "unknown";
557
558 nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
559 "write" : "read", (u64)vahi << 32 | valo);
560 nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
561 pr_cont("] from ");
562 en = nouveau_enum_print(nve0_fifo_fault_engine, unit);
563 if (stat & 0x00000040) {
564 pr_cont("/");
565 nouveau_enum_print(nve0_fifo_fault_hubclient, client);
566 } else {
567 pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24);
568 nouveau_enum_print(nve0_fifo_fault_gpcclient, client);
569 }
570
571 if (en && en->data2) {
572 if (en->data2 == NVDEV_SUBDEV_BAR) {
573 nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
574 name = "BAR1";
575 } else
576 if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
577 nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
578 name = "BAR3";
579 } else {
580 engine = nouveau_engine(priv, en->data2);
581 if (engine) {
582 engctx = nouveau_engctx_get(engine, inst);
583 name = nouveau_client_name(engctx);
584 }
585 }
586 }
587 pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
588
589 nouveau_engctx_put(engctx);
590}
591
592static int
593nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
594{
595 struct nve0_fifo_chan *chan = NULL;
596 struct nouveau_handle *bind;
597 unsigned long flags;
598 int ret = -EINVAL;
599
600 spin_lock_irqsave(&priv->base.lock, flags);
601 if (likely(chid >= priv->base.min && chid <= priv->base.max))
602 chan = (void *)priv->base.channel[chid];
603 if (unlikely(!chan))
604 goto out;
605
606 bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
607 if (likely(bind)) {
608 if (!mthd || !nv_call(bind->object, mthd, data))
609 ret = 0;
610 nouveau_namedb_put(bind);
611 }
612
613out:
614 spin_unlock_irqrestore(&priv->base.lock, flags);
615 return ret;
616}
617
618static void
619nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit) 817nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
620{ 818{
621 u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); 819 u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
@@ -647,6 +845,24 @@ nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
647} 845}
648 846
649static void 847static void
848nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv)
849{
850 u32 mask = nv_rd32(priv, 0x002a00);
851 while (mask) {
852 u32 engn = __ffs(mask);
853 wake_up(&priv->engine[engn].wait);
854 nv_wr32(priv, 0x002a00, 1 << engn);
855 mask &= ~(1 << engn);
856 }
857}
858
859static void
860nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
861{
862 nouveau_event_trigger(priv->base.uevent, 0);
863}
864
865static void
650nve0_fifo_intr(struct nouveau_subdev *subdev) 866nve0_fifo_intr(struct nouveau_subdev *subdev)
651{ 867{
652 struct nve0_fifo_priv *priv = (void *)subdev; 868 struct nve0_fifo_priv *priv = (void *)subdev;
@@ -654,8 +870,7 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
654 u32 stat = nv_rd32(priv, 0x002100) & mask; 870 u32 stat = nv_rd32(priv, 0x002100) & mask;
655 871
656 if (stat & 0x00000001) { 872 if (stat & 0x00000001) {
657 u32 stat = nv_rd32(priv, 0x00252c); 873 nve0_fifo_intr_bind(priv);
658 nv_error(priv, "BIND_ERROR 0x%08x\n", stat);
659 nv_wr32(priv, 0x002100, 0x00000001); 874 nv_wr32(priv, 0x002100, 0x00000001);
660 stat &= ~0x00000001; 875 stat &= ~0x00000001;
661 } 876 }
@@ -697,55 +912,42 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
697 } 912 }
698 913
699 if (stat & 0x10000000) { 914 if (stat & 0x10000000) {
700 u32 units = nv_rd32(priv, 0x00259c); 915 u32 mask = nv_rd32(priv, 0x00259c);
701 u32 u = units; 916 while (mask) {
702 917 u32 unit = __ffs(mask);
703 while (u) { 918 nve0_fifo_intr_fault(priv, unit);
704 int i = ffs(u) - 1; 919 nv_wr32(priv, 0x00259c, (1 << unit));
705 nve0_fifo_intr_fault(priv, i); 920 mask &= ~(1 << unit);
706 u &= ~(1 << i);
707 } 921 }
708
709 nv_wr32(priv, 0x00259c, units);
710 stat &= ~0x10000000; 922 stat &= ~0x10000000;
711 } 923 }
712 924
713 if (stat & 0x20000000) { 925 if (stat & 0x20000000) {
714 u32 mask = nv_rd32(priv, 0x0025a0); 926 u32 mask = nv_rd32(priv, 0x0025a0);
715 u32 temp = mask; 927 while (mask) {
716 928 u32 unit = __ffs(mask);
717 while (temp) {
718 u32 unit = ffs(temp) - 1;
719 nve0_fifo_intr_pbdma(priv, unit); 929 nve0_fifo_intr_pbdma(priv, unit);
720 temp &= ~(1 << unit); 930 nv_wr32(priv, 0x0025a0, (1 << unit));
931 mask &= ~(1 << unit);
721 } 932 }
722
723 nv_wr32(priv, 0x0025a0, mask);
724 stat &= ~0x20000000; 933 stat &= ~0x20000000;
725 } 934 }
726 935
727 if (stat & 0x40000000) { 936 if (stat & 0x40000000) {
728 u32 mask = nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); 937 nve0_fifo_intr_runlist(priv);
729
730 while (mask) {
731 u32 engn = ffs(mask) - 1;
732 /* runlist event, not currently used */
733 mask &= ~(1 << engn);
734 }
735
736 stat &= ~0x40000000; 938 stat &= ~0x40000000;
737 } 939 }
738 940
739 if (stat & 0x80000000) { 941 if (stat & 0x80000000) {
740 nouveau_event_trigger(priv->base.uevent, 0); 942 nve0_fifo_intr_engine(priv);
741 nv_wr32(priv, 0x002100, 0x80000000); 943 nv_wr32(priv, 0x002100, 0x80000000);
742 stat &= ~0x80000000; 944 stat &= ~0x80000000;
743 } 945 }
744 946
745 if (stat) { 947 if (stat) {
746 nv_fatal(priv, "unhandled status 0x%08x\n", stat); 948 nv_error(priv, "INTR 0x%08x\n", stat);
949 nv_mask(priv, 0x002140, stat, 0x00000000);
747 nv_wr32(priv, 0x002100, stat); 950 nv_wr32(priv, 0x002100, stat);
748 nv_wr32(priv, 0x002140, 0);
749 } 951 }
750} 952}
751 953
@@ -802,9 +1004,8 @@ nve0_fifo_init(struct nouveau_object *object)
802 1004
803 nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); 1005 nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
804 1006
805 nv_wr32(priv, 0x002a00, 0xffffffff);
806 nv_wr32(priv, 0x002100, 0xffffffff); 1007 nv_wr32(priv, 0x002100, 0xffffffff);
807 nv_wr32(priv, 0x002140, 0x3fffffff); 1008 nv_wr32(priv, 0x002140, 0x7fffffff);
808 return 0; 1009 return 0;
809} 1010}
810 1011
@@ -840,6 +1041,8 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
840 if (ret) 1041 if (ret)
841 return ret; 1042 return ret;
842 1043
1044 INIT_WORK(&priv->fault, nve0_fifo_recover_work);
1045
843 for (i = 0; i < FIFO_ENGINE_NR; i++) { 1046 for (i = 0; i < FIFO_ENGINE_NR; i++) {
844 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, 1047 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
845 0, &priv->engine[i].runlist[0]); 1048 0, &priv->engine[i].runlist[0]);
@@ -850,10 +1053,12 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
850 0, &priv->engine[i].runlist[1]); 1053 0, &priv->engine[i].runlist[1]);
851 if (ret) 1054 if (ret)
852 return ret; 1055 return ret;
1056
1057 init_waitqueue_head(&priv->engine[i].wait);
853 } 1058 }
854 1059
855 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000, 1060 ret = nouveau_gpuobj_new(nv_object(priv), NULL, impl->channels * 0x200,
856 NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); 1061 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
857 if (ret) 1062 if (ret)
858 return ret; 1063 return ret;
859 1064
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
new file mode 100644
index 000000000000..1dc37b1ddbfa
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
@@ -0,0 +1,989 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#include "ctxnvc0.h"
26
27/*******************************************************************************
28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32gm107_grctx_init_icmd_0[] = {
33 { 0x001000, 1, 0x01, 0x00000004 },
34 { 0x000039, 3, 0x01, 0x00000000 },
35 { 0x0000a9, 1, 0x01, 0x0000ffff },
36 { 0x000038, 1, 0x01, 0x0fac6881 },
37 { 0x00003d, 1, 0x01, 0x00000001 },
38 { 0x0000e8, 8, 0x01, 0x00000400 },
39 { 0x000078, 8, 0x01, 0x00000300 },
40 { 0x000050, 1, 0x01, 0x00000011 },
41 { 0x000058, 8, 0x01, 0x00000008 },
42 { 0x000208, 8, 0x01, 0x00000001 },
43 { 0x000081, 1, 0x01, 0x00000001 },
44 { 0x000085, 1, 0x01, 0x00000004 },
45 { 0x000088, 1, 0x01, 0x00000400 },
46 { 0x000090, 1, 0x01, 0x00000300 },
47 { 0x000098, 1, 0x01, 0x00001001 },
48 { 0x0000e3, 1, 0x01, 0x00000001 },
49 { 0x0000da, 1, 0x01, 0x00000001 },
50 { 0x0000f8, 1, 0x01, 0x00000003 },
51 { 0x0000fa, 1, 0x01, 0x00000001 },
52 { 0x0000b1, 2, 0x01, 0x00000001 },
53 { 0x00009f, 4, 0x01, 0x0000ffff },
54 { 0x0000a8, 1, 0x01, 0x0000ffff },
55 { 0x0000ad, 1, 0x01, 0x0000013e },
56 { 0x0000e1, 1, 0x01, 0x00000010 },
57 { 0x000290, 16, 0x01, 0x00000000 },
58 { 0x0003b0, 16, 0x01, 0x00000000 },
59 { 0x0002a0, 16, 0x01, 0x00000000 },
60 { 0x000420, 16, 0x01, 0x00000000 },
61 { 0x0002b0, 16, 0x01, 0x00000000 },
62 { 0x000430, 16, 0x01, 0x00000000 },
63 { 0x0002c0, 16, 0x01, 0x00000000 },
64 { 0x0004d0, 16, 0x01, 0x00000000 },
65 { 0x000720, 16, 0x01, 0x00000000 },
66 { 0x0008c0, 16, 0x01, 0x00000000 },
67 { 0x000890, 16, 0x01, 0x00000000 },
68 { 0x0008e0, 16, 0x01, 0x00000000 },
69 { 0x0008a0, 16, 0x01, 0x00000000 },
70 { 0x0008f0, 16, 0x01, 0x00000000 },
71 { 0x00094c, 1, 0x01, 0x000000ff },
72 { 0x00094d, 1, 0x01, 0xffffffff },
73 { 0x00094e, 1, 0x01, 0x00000002 },
74 { 0x0002f2, 2, 0x01, 0x00000001 },
75 { 0x0002f5, 1, 0x01, 0x00000001 },
76 { 0x0002f7, 1, 0x01, 0x00000001 },
77 { 0x000303, 1, 0x01, 0x00000001 },
78 { 0x0002e6, 1, 0x01, 0x00000001 },
79 { 0x000466, 1, 0x01, 0x00000052 },
80 { 0x000301, 1, 0x01, 0x3f800000 },
81 { 0x000304, 1, 0x01, 0x30201000 },
82 { 0x000305, 1, 0x01, 0x70605040 },
83 { 0x000306, 1, 0x01, 0xb8a89888 },
84 { 0x000307, 1, 0x01, 0xf8e8d8c8 },
85 { 0x00030a, 1, 0x01, 0x00ffff00 },
86 { 0x0000de, 1, 0x01, 0x00000001 },
87 { 0x00030b, 1, 0x01, 0x0000001a },
88 { 0x00030c, 1, 0x01, 0x00000001 },
89 { 0x000318, 1, 0x01, 0x00000001 },
90 { 0x000340, 1, 0x01, 0x00000000 },
91 { 0x00037d, 1, 0x01, 0x00000006 },
92 { 0x0003a0, 1, 0x01, 0x00000002 },
93 { 0x0003aa, 1, 0x01, 0x00000001 },
94 { 0x0003a9, 1, 0x01, 0x00000001 },
95 { 0x000380, 1, 0x01, 0x00000001 },
96 { 0x000383, 1, 0x01, 0x00000011 },
97 { 0x000360, 1, 0x01, 0x00000040 },
98 { 0x000366, 2, 0x01, 0x00000000 },
99 { 0x000368, 1, 0x01, 0x00000fff },
100 { 0x000370, 2, 0x01, 0x00000000 },
101 { 0x000372, 1, 0x01, 0x000fffff },
102 { 0x00037a, 1, 0x01, 0x00000012 },
103 { 0x000619, 1, 0x01, 0x00000003 },
104 { 0x000811, 1, 0x01, 0x00000003 },
105 { 0x000812, 1, 0x01, 0x00000004 },
106 { 0x000813, 1, 0x01, 0x00000006 },
107 { 0x000814, 1, 0x01, 0x00000008 },
108 { 0x000815, 1, 0x01, 0x0000000b },
109 { 0x000800, 6, 0x01, 0x00000001 },
110 { 0x000632, 1, 0x01, 0x00000001 },
111 { 0x000633, 1, 0x01, 0x00000002 },
112 { 0x000634, 1, 0x01, 0x00000003 },
113 { 0x000635, 1, 0x01, 0x00000004 },
114 { 0x000654, 1, 0x01, 0x3f800000 },
115 { 0x000657, 1, 0x01, 0x3f800000 },
116 { 0x000655, 2, 0x01, 0x3f800000 },
117 { 0x0006cd, 1, 0x01, 0x3f800000 },
118 { 0x0007f5, 1, 0x01, 0x3f800000 },
119 { 0x0007dc, 1, 0x01, 0x39291909 },
120 { 0x0007dd, 1, 0x01, 0x79695949 },
121 { 0x0007de, 1, 0x01, 0xb9a99989 },
122 { 0x0007df, 1, 0x01, 0xf9e9d9c9 },
123 { 0x0007e8, 1, 0x01, 0x00003210 },
124 { 0x0007e9, 1, 0x01, 0x00007654 },
125 { 0x0007ea, 1, 0x01, 0x00000098 },
126 { 0x0007ec, 1, 0x01, 0x39291909 },
127 { 0x0007ed, 1, 0x01, 0x79695949 },
128 { 0x0007ee, 1, 0x01, 0xb9a99989 },
129 { 0x0007ef, 1, 0x01, 0xf9e9d9c9 },
130 { 0x0007f0, 1, 0x01, 0x00003210 },
131 { 0x0007f1, 1, 0x01, 0x00007654 },
132 { 0x0007f2, 1, 0x01, 0x00000098 },
133 { 0x0005a5, 1, 0x01, 0x00000001 },
134 { 0x0005d0, 1, 0x01, 0x20181008 },
135 { 0x0005d1, 1, 0x01, 0x40383028 },
136 { 0x0005d2, 1, 0x01, 0x60585048 },
137 { 0x0005d3, 1, 0x01, 0x80787068 },
138 { 0x000980, 128, 0x01, 0x00000000 },
139 { 0x000468, 1, 0x01, 0x00000004 },
140 { 0x00046c, 1, 0x01, 0x00000001 },
141 { 0x000470, 96, 0x01, 0x00000000 },
142 { 0x000510, 16, 0x01, 0x3f800000 },
143 { 0x000520, 1, 0x01, 0x000002b6 },
144 { 0x000529, 1, 0x01, 0x00000001 },
145 { 0x000530, 16, 0x01, 0xffff0000 },
146 { 0x000550, 32, 0x01, 0xffff0000 },
147 { 0x000585, 1, 0x01, 0x0000003f },
148 { 0x000576, 1, 0x01, 0x00000003 },
149 { 0x00057b, 1, 0x01, 0x00000059 },
150 { 0x000586, 1, 0x01, 0x00000040 },
151 { 0x000582, 2, 0x01, 0x00000080 },
152 { 0x000595, 1, 0x01, 0x00400040 },
153 { 0x000596, 1, 0x01, 0x00000492 },
154 { 0x000597, 1, 0x01, 0x08080203 },
155 { 0x0005ad, 1, 0x01, 0x00000008 },
156 { 0x000598, 1, 0x01, 0x00020001 },
157 { 0x0005c2, 1, 0x01, 0x00000001 },
158 { 0x000638, 2, 0x01, 0x00000001 },
159 { 0x00063a, 1, 0x01, 0x00000002 },
160 { 0x00063b, 2, 0x01, 0x00000001 },
161 { 0x00063d, 1, 0x01, 0x00000002 },
162 { 0x00063e, 1, 0x01, 0x00000001 },
163 { 0x0008b8, 8, 0x01, 0x00000001 },
164 { 0x000900, 8, 0x01, 0x00000001 },
165 { 0x000908, 8, 0x01, 0x00000002 },
166 { 0x000910, 16, 0x01, 0x00000001 },
167 { 0x000920, 8, 0x01, 0x00000002 },
168 { 0x000928, 8, 0x01, 0x00000001 },
169 { 0x000662, 1, 0x01, 0x00000001 },
170 { 0x000648, 9, 0x01, 0x00000001 },
171 { 0x000658, 1, 0x01, 0x0000000f },
172 { 0x0007ff, 1, 0x01, 0x0000000a },
173 { 0x00066a, 1, 0x01, 0x40000000 },
174 { 0x00066b, 1, 0x01, 0x10000000 },
175 { 0x00066c, 2, 0x01, 0xffff0000 },
176 { 0x0007af, 2, 0x01, 0x00000008 },
177 { 0x0007f6, 1, 0x01, 0x00000001 },
178 { 0x0006b2, 1, 0x01, 0x00000055 },
179 { 0x0007ad, 1, 0x01, 0x00000003 },
180 { 0x000971, 1, 0x01, 0x00000008 },
181 { 0x000972, 1, 0x01, 0x00000040 },
182 { 0x000973, 1, 0x01, 0x0000012c },
183 { 0x00097c, 1, 0x01, 0x00000040 },
184 { 0x000975, 1, 0x01, 0x00000020 },
185 { 0x000976, 1, 0x01, 0x00000001 },
186 { 0x000977, 1, 0x01, 0x00000020 },
187 { 0x000978, 1, 0x01, 0x00000001 },
188 { 0x000957, 1, 0x01, 0x00000003 },
189 { 0x00095e, 1, 0x01, 0x20164010 },
190 { 0x00095f, 1, 0x01, 0x00000020 },
191 { 0x000a0d, 1, 0x01, 0x00000006 },
192 { 0x00097d, 1, 0x01, 0x0000000c },
193 { 0x000683, 1, 0x01, 0x00000006 },
194 { 0x000687, 1, 0x01, 0x003fffff },
195 { 0x0006a0, 1, 0x01, 0x00000005 },
196 { 0x000840, 1, 0x01, 0x00400008 },
197 { 0x000841, 1, 0x01, 0x08000080 },
198 { 0x000842, 1, 0x01, 0x00400008 },
199 { 0x000843, 1, 0x01, 0x08000080 },
200 { 0x000818, 8, 0x01, 0x00000000 },
201 { 0x000848, 16, 0x01, 0x00000000 },
202 { 0x000738, 1, 0x01, 0x00000000 },
203 { 0x0006aa, 1, 0x01, 0x00000001 },
204 { 0x0006ab, 1, 0x01, 0x00000002 },
205 { 0x0006ac, 1, 0x01, 0x00000080 },
206 { 0x0006ad, 2, 0x01, 0x00000100 },
207 { 0x0006b1, 1, 0x01, 0x00000011 },
208 { 0x0006bb, 1, 0x01, 0x000000cf },
209 { 0x0006ce, 1, 0x01, 0x2a712488 },
210 { 0x000739, 1, 0x01, 0x4085c000 },
211 { 0x00073a, 1, 0x01, 0x00000080 },
212 { 0x000786, 1, 0x01, 0x80000100 },
213 { 0x00073c, 1, 0x01, 0x00010100 },
214 { 0x00073d, 1, 0x01, 0x02800000 },
215 { 0x000787, 1, 0x01, 0x000000cf },
216 { 0x00078c, 1, 0x01, 0x00000008 },
217 { 0x000792, 1, 0x01, 0x00000001 },
218 { 0x000794, 3, 0x01, 0x00000001 },
219 { 0x000797, 1, 0x01, 0x000000cf },
220 { 0x000836, 1, 0x01, 0x00000001 },
221 { 0x00079a, 1, 0x01, 0x00000002 },
222 { 0x000833, 1, 0x01, 0x04444480 },
223 { 0x0007a1, 1, 0x01, 0x00000001 },
224 { 0x0007a3, 3, 0x01, 0x00000001 },
225 { 0x000831, 1, 0x01, 0x00000004 },
226 { 0x000b07, 1, 0x01, 0x00000002 },
227 { 0x000b08, 2, 0x01, 0x00000100 },
228 { 0x000b0a, 1, 0x01, 0x00000001 },
229 { 0x000a04, 1, 0x01, 0x000000ff },
230 { 0x000a0b, 1, 0x01, 0x00000040 },
231 { 0x00097f, 1, 0x01, 0x00000100 },
232 { 0x000a02, 1, 0x01, 0x00000001 },
233 { 0x000809, 1, 0x01, 0x00000007 },
234 { 0x00c221, 1, 0x01, 0x00000040 },
235 { 0x00c1b0, 8, 0x01, 0x0000000f },
236 { 0x00c1b8, 1, 0x01, 0x0fac6881 },
237 { 0x00c1b9, 1, 0x01, 0x00fac688 },
238 { 0x00c401, 1, 0x01, 0x00000001 },
239 { 0x00c402, 1, 0x01, 0x00010001 },
240 { 0x00c403, 2, 0x01, 0x00000001 },
241 { 0x00c40e, 1, 0x01, 0x00000020 },
242 { 0x01e100, 1, 0x01, 0x00000001 },
243 { 0x001000, 1, 0x01, 0x00000002 },
244 { 0x0006aa, 1, 0x01, 0x00000001 },
245 { 0x0006ad, 2, 0x01, 0x00000100 },
246 { 0x0006b1, 1, 0x01, 0x00000011 },
247 { 0x00078c, 1, 0x01, 0x00000008 },
248 { 0x000792, 1, 0x01, 0x00000001 },
249 { 0x000794, 3, 0x01, 0x00000001 },
250 { 0x000797, 1, 0x01, 0x000000cf },
251 { 0x00079a, 1, 0x01, 0x00000002 },
252 { 0x0007a1, 1, 0x01, 0x00000001 },
253 { 0x0007a3, 3, 0x01, 0x00000001 },
254 { 0x000831, 1, 0x01, 0x00000004 },
255 { 0x01e100, 1, 0x01, 0x00000001 },
256 { 0x001000, 1, 0x01, 0x00000008 },
257 { 0x000039, 3, 0x01, 0x00000000 },
258 { 0x000380, 1, 0x01, 0x00000001 },
259 { 0x000366, 2, 0x01, 0x00000000 },
260 { 0x000368, 1, 0x01, 0x00000fff },
261 { 0x000370, 2, 0x01, 0x00000000 },
262 { 0x000372, 1, 0x01, 0x000fffff },
263 { 0x000813, 1, 0x01, 0x00000006 },
264 { 0x000814, 1, 0x01, 0x00000008 },
265 { 0x000818, 8, 0x01, 0x00000000 },
266 { 0x000848, 16, 0x01, 0x00000000 },
267 { 0x000738, 1, 0x01, 0x00000000 },
268 { 0x000b07, 1, 0x01, 0x00000002 },
269 { 0x000b08, 2, 0x01, 0x00000100 },
270 { 0x000b0a, 1, 0x01, 0x00000001 },
271 { 0x000a04, 1, 0x01, 0x000000ff },
272 { 0x000a0b, 1, 0x01, 0x00000040 },
273 { 0x00097f, 1, 0x01, 0x00000100 },
274 { 0x000a02, 1, 0x01, 0x00000001 },
275 { 0x000809, 1, 0x01, 0x00000007 },
276 { 0x00c221, 1, 0x01, 0x00000040 },
277 { 0x00c401, 1, 0x01, 0x00000001 },
278 { 0x00c402, 1, 0x01, 0x00010001 },
279 { 0x00c403, 2, 0x01, 0x00000001 },
280 { 0x00c40e, 1, 0x01, 0x00000020 },
281 { 0x01e100, 1, 0x01, 0x00000001 },
282 { 0x001000, 1, 0x01, 0x00000001 },
283 { 0x000b07, 1, 0x01, 0x00000002 },
284 { 0x000b08, 2, 0x01, 0x00000100 },
285 { 0x000b0a, 1, 0x01, 0x00000001 },
286 { 0x01e100, 1, 0x01, 0x00000001 },
287 {}
288};
289
290static const struct nvc0_graph_pack
291gm107_grctx_pack_icmd[] = {
292 { gm107_grctx_init_icmd_0 },
293 {}
294};
295
296static const struct nvc0_graph_init
297gm107_grctx_init_b097_0[] = {
298 { 0x000800, 8, 0x40, 0x00000000 },
299 { 0x000804, 8, 0x40, 0x00000000 },
300 { 0x000808, 8, 0x40, 0x00000400 },
301 { 0x00080c, 8, 0x40, 0x00000300 },
302 { 0x000810, 1, 0x04, 0x000000cf },
303 { 0x000850, 7, 0x40, 0x00000000 },
304 { 0x000814, 8, 0x40, 0x00000040 },
305 { 0x000818, 8, 0x40, 0x00000001 },
306 { 0x00081c, 8, 0x40, 0x00000000 },
307 { 0x000820, 8, 0x40, 0x00000000 },
308 { 0x001c00, 16, 0x10, 0x00000000 },
309 { 0x001c04, 16, 0x10, 0x00000000 },
310 { 0x001c08, 16, 0x10, 0x00000000 },
311 { 0x001c0c, 16, 0x10, 0x00000000 },
312 { 0x001d00, 16, 0x10, 0x00000000 },
313 { 0x001d04, 16, 0x10, 0x00000000 },
314 { 0x001d08, 16, 0x10, 0x00000000 },
315 { 0x001d0c, 16, 0x10, 0x00000000 },
316 { 0x001f00, 16, 0x08, 0x00000000 },
317 { 0x001f04, 16, 0x08, 0x00000000 },
318 { 0x001f80, 16, 0x08, 0x00000000 },
319 { 0x001f84, 16, 0x08, 0x00000000 },
320 { 0x002000, 1, 0x04, 0x00000000 },
321 { 0x002040, 1, 0x04, 0x00000011 },
322 { 0x002080, 1, 0x04, 0x00000020 },
323 { 0x0020c0, 1, 0x04, 0x00000030 },
324 { 0x002100, 1, 0x04, 0x00000040 },
325 { 0x002140, 1, 0x04, 0x00000051 },
326 { 0x00200c, 6, 0x40, 0x00000001 },
327 { 0x002010, 1, 0x04, 0x00000000 },
328 { 0x002050, 1, 0x04, 0x00000000 },
329 { 0x002090, 1, 0x04, 0x00000001 },
330 { 0x0020d0, 1, 0x04, 0x00000002 },
331 { 0x002110, 1, 0x04, 0x00000003 },
332 { 0x002150, 1, 0x04, 0x00000004 },
333 { 0x000380, 4, 0x20, 0x00000000 },
334 { 0x000384, 4, 0x20, 0x00000000 },
335 { 0x000388, 4, 0x20, 0x00000000 },
336 { 0x00038c, 4, 0x20, 0x00000000 },
337 { 0x000700, 4, 0x10, 0x00000000 },
338 { 0x000704, 4, 0x10, 0x00000000 },
339 { 0x000708, 4, 0x10, 0x00000000 },
340 { 0x002800, 128, 0x04, 0x00000000 },
341 { 0x000a00, 16, 0x20, 0x00000000 },
342 { 0x000a04, 16, 0x20, 0x00000000 },
343 { 0x000a08, 16, 0x20, 0x00000000 },
344 { 0x000a0c, 16, 0x20, 0x00000000 },
345 { 0x000a10, 16, 0x20, 0x00000000 },
346 { 0x000a14, 16, 0x20, 0x00000000 },
347 { 0x000c00, 16, 0x10, 0x00000000 },
348 { 0x000c04, 16, 0x10, 0x00000000 },
349 { 0x000c08, 16, 0x10, 0x00000000 },
350 { 0x000c0c, 16, 0x10, 0x3f800000 },
351 { 0x000d00, 8, 0x08, 0xffff0000 },
352 { 0x000d04, 8, 0x08, 0xffff0000 },
353 { 0x000e00, 16, 0x10, 0x00000000 },
354 { 0x000e04, 16, 0x10, 0xffff0000 },
355 { 0x000e08, 16, 0x10, 0xffff0000 },
356 { 0x000d40, 4, 0x08, 0x00000000 },
357 { 0x000d44, 4, 0x08, 0x00000000 },
358 { 0x001e00, 8, 0x20, 0x00000001 },
359 { 0x001e04, 8, 0x20, 0x00000001 },
360 { 0x001e08, 8, 0x20, 0x00000002 },
361 { 0x001e0c, 8, 0x20, 0x00000001 },
362 { 0x001e10, 8, 0x20, 0x00000001 },
363 { 0x001e14, 8, 0x20, 0x00000002 },
364 { 0x001e18, 8, 0x20, 0x00000001 },
365 { 0x001480, 8, 0x10, 0x00000000 },
366 { 0x001484, 8, 0x10, 0x00000000 },
367 { 0x001488, 8, 0x10, 0x00000000 },
368 { 0x003400, 128, 0x04, 0x00000000 },
369 { 0x00030c, 1, 0x04, 0x00000001 },
370 { 0x001944, 1, 0x04, 0x00000000 },
371 { 0x001514, 1, 0x04, 0x00000000 },
372 { 0x000d68, 1, 0x04, 0x0000ffff },
373 { 0x00121c, 1, 0x04, 0x0fac6881 },
374 { 0x000fac, 1, 0x04, 0x00000001 },
375 { 0x001538, 1, 0x04, 0x00000001 },
376 { 0x000fe0, 2, 0x04, 0x00000000 },
377 { 0x000fe8, 1, 0x04, 0x00000014 },
378 { 0x000fec, 1, 0x04, 0x00000040 },
379 { 0x000ff0, 1, 0x04, 0x00000000 },
380 { 0x00179c, 1, 0x04, 0x00000000 },
381 { 0x001228, 1, 0x04, 0x00000400 },
382 { 0x00122c, 1, 0x04, 0x00000300 },
383 { 0x001230, 1, 0x04, 0x00010001 },
384 { 0x0007f8, 1, 0x04, 0x00000000 },
385 { 0x0015b4, 1, 0x04, 0x00000001 },
386 { 0x0015cc, 1, 0x04, 0x00000000 },
387 { 0x001534, 1, 0x04, 0x00000000 },
388 { 0x000754, 1, 0x04, 0x00000001 },
389 { 0x000fb0, 1, 0x04, 0x00000000 },
390 { 0x0015d0, 1, 0x04, 0x00000000 },
391 { 0x00153c, 1, 0x04, 0x00000000 },
392 { 0x0016b4, 1, 0x04, 0x00000003 },
393 { 0x000fbc, 4, 0x04, 0x0000ffff },
394 { 0x000df8, 2, 0x04, 0x00000000 },
395 { 0x001948, 1, 0x04, 0x00000000 },
396 { 0x001970, 1, 0x04, 0x00000001 },
397 { 0x00161c, 1, 0x04, 0x000009f0 },
398 { 0x000dcc, 1, 0x04, 0x00000010 },
399 { 0x0015e4, 1, 0x04, 0x00000000 },
400 { 0x001160, 32, 0x04, 0x25e00040 },
401 { 0x001880, 32, 0x04, 0x00000000 },
402 { 0x000f84, 2, 0x04, 0x00000000 },
403 { 0x0017c8, 2, 0x04, 0x00000000 },
404 { 0x0017d0, 1, 0x04, 0x000000ff },
405 { 0x0017d4, 1, 0x04, 0xffffffff },
406 { 0x0017d8, 1, 0x04, 0x00000002 },
407 { 0x0017dc, 1, 0x04, 0x00000000 },
408 { 0x0015f4, 2, 0x04, 0x00000000 },
409 { 0x001434, 2, 0x04, 0x00000000 },
410 { 0x000d74, 1, 0x04, 0x00000000 },
411 { 0x0013a4, 1, 0x04, 0x00000000 },
412 { 0x001318, 1, 0x04, 0x00000001 },
413 { 0x001080, 2, 0x04, 0x00000000 },
414 { 0x001088, 2, 0x04, 0x00000001 },
415 { 0x001090, 1, 0x04, 0x00000000 },
416 { 0x001094, 1, 0x04, 0x00000001 },
417 { 0x001098, 1, 0x04, 0x00000000 },
418 { 0x00109c, 1, 0x04, 0x00000001 },
419 { 0x0010a0, 2, 0x04, 0x00000000 },
420 { 0x001644, 1, 0x04, 0x00000000 },
421 { 0x000748, 1, 0x04, 0x00000000 },
422 { 0x000de8, 1, 0x04, 0x00000000 },
423 { 0x001648, 1, 0x04, 0x00000000 },
424 { 0x0012a4, 1, 0x04, 0x00000000 },
425 { 0x001120, 4, 0x04, 0x00000000 },
426 { 0x001118, 1, 0x04, 0x00000000 },
427 { 0x00164c, 1, 0x04, 0x00000000 },
428 { 0x001658, 1, 0x04, 0x00000000 },
429 { 0x001910, 1, 0x04, 0x00000290 },
430 { 0x001518, 1, 0x04, 0x00000000 },
431 { 0x00165c, 1, 0x04, 0x00000001 },
432 { 0x001520, 1, 0x04, 0x00000000 },
433 { 0x001604, 1, 0x04, 0x00000000 },
434 { 0x001570, 1, 0x04, 0x00000000 },
435 { 0x0013b0, 2, 0x04, 0x3f800000 },
436 { 0x00020c, 1, 0x04, 0x00000000 },
437 { 0x001670, 1, 0x04, 0x30201000 },
438 { 0x001674, 1, 0x04, 0x70605040 },
439 { 0x001678, 1, 0x04, 0xb8a89888 },
440 { 0x00167c, 1, 0x04, 0xf8e8d8c8 },
441 { 0x00166c, 1, 0x04, 0x00000000 },
442 { 0x001680, 1, 0x04, 0x00ffff00 },
443 { 0x0012d0, 1, 0x04, 0x00000003 },
444 { 0x0012d4, 1, 0x04, 0x00000002 },
445 { 0x001684, 2, 0x04, 0x00000000 },
446 { 0x000dac, 2, 0x04, 0x00001b02 },
447 { 0x000db4, 1, 0x04, 0x00000000 },
448 { 0x00168c, 1, 0x04, 0x00000000 },
449 { 0x0015bc, 1, 0x04, 0x00000000 },
450 { 0x00156c, 1, 0x04, 0x00000000 },
451 { 0x00187c, 1, 0x04, 0x00000000 },
452 { 0x001110, 1, 0x04, 0x00000001 },
453 { 0x000dc0, 3, 0x04, 0x00000000 },
454 { 0x000f40, 5, 0x04, 0x00000000 },
455 { 0x001234, 1, 0x04, 0x00000000 },
456 { 0x001690, 1, 0x04, 0x00000000 },
457 { 0x000790, 5, 0x04, 0x00000000 },
458 { 0x00077c, 1, 0x04, 0x00000000 },
459 { 0x001000, 1, 0x04, 0x00000010 },
460 { 0x0010fc, 1, 0x04, 0x00000000 },
461 { 0x001290, 1, 0x04, 0x00000000 },
462 { 0x000218, 1, 0x04, 0x00000010 },
463 { 0x0012d8, 1, 0x04, 0x00000000 },
464 { 0x0012dc, 1, 0x04, 0x00000010 },
465 { 0x000d94, 1, 0x04, 0x00000001 },
466 { 0x00155c, 2, 0x04, 0x00000000 },
467 { 0x001564, 1, 0x04, 0x00000fff },
468 { 0x001574, 2, 0x04, 0x00000000 },
469 { 0x00157c, 1, 0x04, 0x000fffff },
470 { 0x001354, 1, 0x04, 0x00000000 },
471 { 0x001610, 1, 0x04, 0x00000012 },
472 { 0x001608, 2, 0x04, 0x00000000 },
473 { 0x00260c, 1, 0x04, 0x00000000 },
474 { 0x0007ac, 1, 0x04, 0x00000000 },
475 { 0x00162c, 1, 0x04, 0x00000003 },
476 { 0x000210, 1, 0x04, 0x00000000 },
477 { 0x000320, 1, 0x04, 0x00000000 },
478 { 0x000324, 6, 0x04, 0x3f800000 },
479 { 0x000750, 1, 0x04, 0x00000000 },
480 { 0x000760, 1, 0x04, 0x39291909 },
481 { 0x000764, 1, 0x04, 0x79695949 },
482 { 0x000768, 1, 0x04, 0xb9a99989 },
483 { 0x00076c, 1, 0x04, 0xf9e9d9c9 },
484 { 0x000770, 1, 0x04, 0x30201000 },
485 { 0x000774, 1, 0x04, 0x70605040 },
486 { 0x000778, 1, 0x04, 0x00009080 },
487 { 0x000780, 1, 0x04, 0x39291909 },
488 { 0x000784, 1, 0x04, 0x79695949 },
489 { 0x000788, 1, 0x04, 0xb9a99989 },
490 { 0x00078c, 1, 0x04, 0xf9e9d9c9 },
491 { 0x0007d0, 1, 0x04, 0x30201000 },
492 { 0x0007d4, 1, 0x04, 0x70605040 },
493 { 0x0007d8, 1, 0x04, 0x00009080 },
494 { 0x00037c, 1, 0x04, 0x00000001 },
495 { 0x000740, 2, 0x04, 0x00000000 },
496 { 0x002600, 1, 0x04, 0x00000000 },
497 { 0x001918, 1, 0x04, 0x00000000 },
498 { 0x00191c, 1, 0x04, 0x00000900 },
499 { 0x001920, 1, 0x04, 0x00000405 },
500 { 0x001308, 1, 0x04, 0x00000001 },
501 { 0x001924, 1, 0x04, 0x00000000 },
502 { 0x0013ac, 1, 0x04, 0x00000000 },
503 { 0x00192c, 1, 0x04, 0x00000001 },
504 { 0x00193c, 1, 0x04, 0x00002c1c },
505 { 0x000d7c, 1, 0x04, 0x00000000 },
506 { 0x000f8c, 1, 0x04, 0x00000000 },
507 { 0x0002c0, 1, 0x04, 0x00000001 },
508 { 0x001510, 1, 0x04, 0x00000000 },
509 { 0x001940, 1, 0x04, 0x00000000 },
510 { 0x000ff4, 2, 0x04, 0x00000000 },
511 { 0x00194c, 2, 0x04, 0x00000000 },
512 { 0x001968, 1, 0x04, 0x00000000 },
513 { 0x001590, 1, 0x04, 0x0000003f },
514 { 0x0007e8, 4, 0x04, 0x00000000 },
515 { 0x00196c, 1, 0x04, 0x00000011 },
516 { 0x0002e4, 1, 0x04, 0x0000b001 },
517 { 0x00036c, 2, 0x04, 0x00000000 },
518 { 0x00197c, 1, 0x04, 0x00000000 },
519 { 0x000fcc, 2, 0x04, 0x00000000 },
520 { 0x0002d8, 1, 0x04, 0x00000040 },
521 { 0x001980, 1, 0x04, 0x00000080 },
522 { 0x001504, 1, 0x04, 0x00000080 },
523 { 0x001984, 1, 0x04, 0x00000000 },
524 { 0x000f60, 1, 0x04, 0x00000000 },
525 { 0x000f64, 1, 0x04, 0x00400040 },
526 { 0x000f68, 1, 0x04, 0x00002212 },
527 { 0x000f6c, 1, 0x04, 0x08080203 },
528 { 0x001108, 1, 0x04, 0x00000008 },
529 { 0x000f70, 1, 0x04, 0x00080001 },
530 { 0x000ffc, 1, 0x04, 0x00000000 },
531 { 0x000300, 1, 0x04, 0x00000001 },
532 { 0x0013a8, 1, 0x04, 0x00000000 },
533 { 0x0012ec, 1, 0x04, 0x00000000 },
534 { 0x001310, 1, 0x04, 0x00000000 },
535 { 0x001314, 1, 0x04, 0x00000001 },
536 { 0x001380, 1, 0x04, 0x00000000 },
537 { 0x001384, 4, 0x04, 0x00000001 },
538 { 0x001394, 1, 0x04, 0x00000000 },
539 { 0x00139c, 1, 0x04, 0x00000000 },
540 { 0x001398, 1, 0x04, 0x00000000 },
541 { 0x001594, 1, 0x04, 0x00000000 },
542 { 0x001598, 4, 0x04, 0x00000001 },
543 { 0x000f54, 3, 0x04, 0x00000000 },
544 { 0x0019bc, 1, 0x04, 0x00000000 },
545 { 0x000f9c, 2, 0x04, 0x00000000 },
546 { 0x0012cc, 1, 0x04, 0x00000000 },
547 { 0x0012e8, 1, 0x04, 0x00000000 },
548 { 0x00130c, 1, 0x04, 0x00000001 },
549 { 0x001360, 8, 0x04, 0x00000000 },
550 { 0x00133c, 2, 0x04, 0x00000001 },
551 { 0x001344, 1, 0x04, 0x00000002 },
552 { 0x001348, 2, 0x04, 0x00000001 },
553 { 0x001350, 1, 0x04, 0x00000002 },
554 { 0x001358, 1, 0x04, 0x00000001 },
555 { 0x0012e4, 1, 0x04, 0x00000000 },
556 { 0x00131c, 4, 0x04, 0x00000000 },
557 { 0x0019c0, 1, 0x04, 0x00000000 },
558 { 0x001140, 1, 0x04, 0x00000000 },
559 { 0x000dd0, 1, 0x04, 0x00000000 },
560 { 0x000dd4, 1, 0x04, 0x00000001 },
561 { 0x0002f4, 1, 0x04, 0x00000000 },
562 { 0x0019c4, 1, 0x04, 0x00000000 },
563 { 0x0019c8, 1, 0x04, 0x00001500 },
564 { 0x00135c, 1, 0x04, 0x00000000 },
565 { 0x000f90, 1, 0x04, 0x00000000 },
566 { 0x0019e0, 8, 0x04, 0x00000001 },
567 { 0x0019cc, 1, 0x04, 0x00000001 },
568 { 0x0015b8, 1, 0x04, 0x00000000 },
569 { 0x001a00, 1, 0x04, 0x00001111 },
570 { 0x001a04, 7, 0x04, 0x00000000 },
571 { 0x000d6c, 2, 0x04, 0xffff0000 },
572 { 0x0010f8, 1, 0x04, 0x00001010 },
573 { 0x000d80, 5, 0x04, 0x00000000 },
574 { 0x000da0, 1, 0x04, 0x00000000 },
575 { 0x0007a4, 2, 0x04, 0x00000000 },
576 { 0x001508, 1, 0x04, 0x80000000 },
577 { 0x00150c, 1, 0x04, 0x40000000 },
578 { 0x001668, 1, 0x04, 0x00000000 },
579 { 0x000318, 2, 0x04, 0x00000008 },
580 { 0x000d9c, 1, 0x04, 0x00000001 },
581 { 0x000f14, 1, 0x04, 0x00000000 },
582 { 0x000374, 1, 0x04, 0x00000000 },
583 { 0x000378, 1, 0x04, 0x0000000c },
584 { 0x0007dc, 1, 0x04, 0x00000000 },
585 { 0x00074c, 1, 0x04, 0x00000055 },
586 { 0x001420, 1, 0x04, 0x00000003 },
587 { 0x001008, 1, 0x04, 0x00000008 },
588 { 0x00100c, 1, 0x04, 0x00000040 },
589 { 0x001010, 1, 0x04, 0x0000012c },
590 { 0x000d60, 1, 0x04, 0x00000040 },
591 { 0x001018, 1, 0x04, 0x00000020 },
592 { 0x00101c, 1, 0x04, 0x00000001 },
593 { 0x001020, 1, 0x04, 0x00000020 },
594 { 0x001024, 1, 0x04, 0x00000001 },
595 { 0x001444, 3, 0x04, 0x00000000 },
596 { 0x000360, 1, 0x04, 0x20164010 },
597 { 0x000364, 1, 0x04, 0x00000020 },
598 { 0x000368, 1, 0x04, 0x00000000 },
599 { 0x000da8, 1, 0x04, 0x00000030 },
600 { 0x000de4, 1, 0x04, 0x00000000 },
601 { 0x000204, 1, 0x04, 0x00000006 },
602 { 0x0002d0, 1, 0x04, 0x003fffff },
603 { 0x001220, 1, 0x04, 0x00000005 },
604 { 0x000fdc, 1, 0x04, 0x00000000 },
605 { 0x000f98, 1, 0x04, 0x00400008 },
606 { 0x001284, 1, 0x04, 0x08000080 },
607 { 0x001450, 1, 0x04, 0x00400008 },
608 { 0x001454, 1, 0x04, 0x08000080 },
609 { 0x000214, 1, 0x04, 0x00000000 },
610 {}
611};
612
613static const struct nvc0_graph_pack
614gm107_grctx_pack_mthd[] = {
615 { gm107_grctx_init_b097_0, 0xb097 },
616 { nvc0_grctx_init_902d_0, 0x902d },
617 {}
618};
619
620static const struct nvc0_graph_init
621gm107_grctx_init_fe_0[] = {
622 { 0x404004, 8, 0x04, 0x00000000 },
623 { 0x404024, 1, 0x04, 0x0000e000 },
624 { 0x404028, 8, 0x04, 0x00000000 },
625 { 0x4040a8, 8, 0x04, 0x00000000 },
626 { 0x4040c8, 1, 0x04, 0xf800008f },
627 { 0x4040d0, 6, 0x04, 0x00000000 },
628 { 0x4040f8, 1, 0x04, 0x00000000 },
629 { 0x404100, 10, 0x04, 0x00000000 },
630 { 0x404130, 2, 0x04, 0x00000000 },
631 { 0x404150, 1, 0x04, 0x0000002e },
632 { 0x404154, 1, 0x04, 0x00000400 },
633 { 0x404158, 1, 0x04, 0x00000200 },
634 { 0x404164, 1, 0x04, 0x00000045 },
635 { 0x40417c, 2, 0x04, 0x00000000 },
636 { 0x404194, 1, 0x04, 0x01000700 },
637 { 0x4041a0, 4, 0x04, 0x00000000 },
638 { 0x404200, 4, 0x04, 0x00000000 },
639 {}
640};
641
642static const struct nvc0_graph_init
643gm107_grctx_init_ds_0[] = {
644 { 0x405800, 1, 0x04, 0x0f8001bf },
645 { 0x405830, 1, 0x04, 0x0aa01000 },
646 { 0x405834, 1, 0x04, 0x08000000 },
647 { 0x405838, 1, 0x04, 0x00000000 },
648 { 0x405854, 1, 0x04, 0x00000000 },
649 { 0x405870, 4, 0x04, 0x00000001 },
650 { 0x405a00, 2, 0x04, 0x00000000 },
651 { 0x405a18, 1, 0x04, 0x00000000 },
652 { 0x405a1c, 1, 0x04, 0x000000ff },
653 {}
654};
655
656static const struct nvc0_graph_init
657gm107_grctx_init_pd_0[] = {
658 { 0x406020, 1, 0x04, 0x07410001 },
659 { 0x406028, 4, 0x04, 0x00000001 },
660 { 0x4064a8, 1, 0x04, 0x00000000 },
661 { 0x4064ac, 1, 0x04, 0x00003fff },
662 { 0x4064b0, 3, 0x04, 0x00000000 },
663 { 0x4064c0, 1, 0x04, 0x80400280 },
664 { 0x4064c4, 1, 0x04, 0x0400ffff },
665 { 0x4064c8, 1, 0x04, 0x018001ff },
666 { 0x4064cc, 9, 0x04, 0x00000000 },
667 { 0x4064fc, 1, 0x04, 0x0000022a },
668 { 0x406500, 1, 0x04, 0x00000000 },
669 {}
670};
671
672static const struct nvc0_graph_init
673gm107_grctx_init_be_0[] = {
674 { 0x408800, 1, 0x04, 0x32802a3c },
675 { 0x408804, 1, 0x04, 0x00000040 },
676 { 0x408808, 1, 0x04, 0x1003e005 },
677 { 0x408840, 1, 0x04, 0x0000000b },
678 { 0x408900, 1, 0x04, 0xb080b801 },
679 { 0x408904, 1, 0x04, 0x63038001 },
680 { 0x408908, 1, 0x04, 0x02c8102f },
681 { 0x408980, 1, 0x04, 0x0000011d },
682 {}
683};
684
685static const struct nvc0_graph_pack
686gm107_grctx_pack_hub[] = {
687 { nvc0_grctx_init_main_0 },
688 { gm107_grctx_init_fe_0 },
689 { nvf0_grctx_init_pri_0 },
690 { nve4_grctx_init_memfmt_0 },
691 { gm107_grctx_init_ds_0 },
692 { nvf0_grctx_init_cwd_0 },
693 { gm107_grctx_init_pd_0 },
694 { nv108_grctx_init_rstr2d_0 },
695 { nve4_grctx_init_scc_0 },
696 { gm107_grctx_init_be_0 },
697 {}
698};
699
700static const struct nvc0_graph_init
701gm107_grctx_init_gpc_unk_0[] = {
702 { 0x418380, 1, 0x04, 0x00000056 },
703 {}
704};
705
706static const struct nvc0_graph_init
707gm107_grctx_init_gpc_unk_1[] = {
708 { 0x418600, 1, 0x04, 0x0000007f },
709 { 0x418684, 1, 0x04, 0x0000001f },
710 { 0x418700, 1, 0x04, 0x00000002 },
711 { 0x418704, 1, 0x04, 0x00000080 },
712 { 0x418708, 1, 0x04, 0x40000000 },
713 { 0x41870c, 2, 0x04, 0x00000000 },
714 {}
715};
716
717static const struct nvc0_graph_init
718gm107_grctx_init_setup_0[] = {
719 { 0x418800, 1, 0x04, 0x7006863a },
720 { 0x418810, 1, 0x04, 0x00000000 },
721 { 0x418828, 1, 0x04, 0x00000044 },
722 { 0x418830, 1, 0x04, 0x10000001 },
723 { 0x4188d8, 1, 0x04, 0x00000008 },
724 { 0x4188e0, 1, 0x04, 0x01000000 },
725 { 0x4188e8, 5, 0x04, 0x00000000 },
726 { 0x4188fc, 1, 0x04, 0x20100058 },
727 {}
728};
729
730static const struct nvc0_graph_init
731gm107_grctx_init_gpc_unk_2[] = {
732 { 0x418d24, 1, 0x04, 0x00000000 },
733 { 0x418e00, 1, 0x04, 0x90000000 },
734 { 0x418e24, 1, 0x04, 0x00000000 },
735 { 0x418e28, 1, 0x04, 0x00000030 },
736 { 0x418e30, 1, 0x04, 0x00000000 },
737 { 0x418e34, 1, 0x04, 0x00010000 },
738 { 0x418e38, 1, 0x04, 0x00000000 },
739 { 0x418e40, 22, 0x04, 0x00000000 },
740 { 0x418ea0, 2, 0x04, 0x00000000 },
741 {}
742};
743
744static const struct nvc0_graph_pack
745gm107_grctx_pack_gpc[] = {
746 { gm107_grctx_init_gpc_unk_0 },
747 { nv108_grctx_init_prop_0 },
748 { gm107_grctx_init_gpc_unk_1 },
749 { gm107_grctx_init_setup_0 },
750 { nvc0_grctx_init_zcull_0 },
751 { nv108_grctx_init_crstr_0 },
752 { nve4_grctx_init_gpm_0 },
753 { gm107_grctx_init_gpc_unk_2 },
754 { nvc0_grctx_init_gcc_0 },
755 {}
756};
757
758static const struct nvc0_graph_init
759gm107_grctx_init_tex_0[] = {
760 { 0x419a00, 1, 0x04, 0x000300f0 },
761 { 0x419a04, 1, 0x04, 0x00000005 },
762 { 0x419a08, 1, 0x04, 0x00000421 },
763 { 0x419a0c, 1, 0x04, 0x00120000 },
764 { 0x419a10, 1, 0x04, 0x00000000 },
765 { 0x419a14, 1, 0x04, 0x00002200 },
766 { 0x419a1c, 1, 0x04, 0x0000c000 },
767 { 0x419a20, 1, 0x04, 0x20008a00 },
768 { 0x419a30, 1, 0x04, 0x00000001 },
769 { 0x419a3c, 1, 0x04, 0x00000002 },
770 { 0x419ac4, 1, 0x04, 0x00000000 },
771 {}
772};
773
774static const struct nvc0_graph_init
775gm107_grctx_init_mpc_0[] = {
776 { 0x419c00, 1, 0x04, 0x0000001a },
777 { 0x419c04, 1, 0x04, 0x80000006 },
778 { 0x419c08, 1, 0x04, 0x00000002 },
779 { 0x419c20, 1, 0x04, 0x00000000 },
780 { 0x419c24, 1, 0x04, 0x00084210 },
781 { 0x419c28, 1, 0x04, 0x3efbefbe },
782 { 0x419c2c, 1, 0x04, 0x00000000 },
783 { 0x419c34, 1, 0x04, 0x01ff1ff3 },
784 { 0x419c3c, 1, 0x04, 0x00001919 },
785 {}
786};
787
788static const struct nvc0_graph_init
789gm107_grctx_init_l1c_0[] = {
790 { 0x419c84, 1, 0x04, 0x00000020 },
791 {}
792};
793
794static const struct nvc0_graph_init
795gm107_grctx_init_sm_0[] = {
796 { 0x419e04, 3, 0x04, 0x00000000 },
797 { 0x419e10, 1, 0x04, 0x00001c02 },
798 { 0x419e44, 1, 0x04, 0x00d3eff2 },
799 { 0x419e48, 1, 0x04, 0x00000000 },
800 { 0x419e4c, 1, 0x04, 0x0000007f },
801 { 0x419e50, 1, 0x04, 0x00000000 },
802 { 0x419e60, 4, 0x04, 0x00000000 },
803 { 0x419e74, 10, 0x04, 0x00000000 },
804 { 0x419eac, 1, 0x04, 0x0001cf8b },
805 { 0x419eb0, 1, 0x04, 0x00030300 },
806 { 0x419eb8, 1, 0x04, 0x00000000 },
807 { 0x419ef0, 24, 0x04, 0x00000000 },
808 { 0x419f68, 2, 0x04, 0x00000000 },
809 { 0x419f70, 1, 0x04, 0x00000020 },
810 { 0x419f78, 1, 0x04, 0x000003eb },
811 { 0x419f7c, 1, 0x04, 0x00000000 },
812 {}
813};
814
815static const struct nvc0_graph_pack
816gm107_grctx_pack_tpc[] = {
817 { nvd7_grctx_init_pe_0 },
818 { gm107_grctx_init_tex_0 },
819 { gm107_grctx_init_mpc_0 },
820 { gm107_grctx_init_l1c_0 },
821 { gm107_grctx_init_sm_0 },
822 {}
823};
824
825static const struct nvc0_graph_init
826gm107_grctx_init_cbm_0[] = {
827 { 0x41bec0, 1, 0x04, 0x00000000 },
828 { 0x41bec4, 1, 0x04, 0x01050000 },
829 { 0x41bee4, 1, 0x04, 0x00000000 },
830 { 0x41bef0, 1, 0x04, 0x000003ff },
831 { 0x41bef4, 2, 0x04, 0x00000000 },
832 {}
833};
834
835static const struct nvc0_graph_init
836gm107_grctx_init_wwdx_0[] = {
837 { 0x41bf00, 1, 0x04, 0x0a418820 },
838 { 0x41bf04, 1, 0x04, 0x062080e6 },
839 { 0x41bf08, 1, 0x04, 0x020398a4 },
840 { 0x41bf0c, 1, 0x04, 0x0e629062 },
841 { 0x41bf10, 1, 0x04, 0x0a418820 },
842 { 0x41bf14, 1, 0x04, 0x000000e6 },
843 { 0x41bfd0, 1, 0x04, 0x00900103 },
844 { 0x41bfe0, 1, 0x04, 0x80000000 },
845 { 0x41bfe4, 1, 0x04, 0x00000000 },
846 {}
847};
848
849static const struct nvc0_graph_pack
850gm107_grctx_pack_ppc[] = {
851 { nve4_grctx_init_pes_0 },
852 { gm107_grctx_init_cbm_0 },
853 { gm107_grctx_init_wwdx_0 },
854 {}
855};
856
857/*******************************************************************************
858 * PGRAPH context implementation
859 ******************************************************************************/
860
861static void
862gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
863{
864 mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
865 mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
866 mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
867
868 mmio_list(0x40800c, 0x00000000, 8, 1);
869 mmio_list(0x408010, 0x80000000, 0, 0);
870 mmio_list(0x419004, 0x00000000, 8, 1);
871 mmio_list(0x419008, 0x00000000, 0, 0);
872 mmio_list(0x4064cc, 0x80000000, 0, 0);
873 mmio_list(0x418e30, 0x80000000, 0, 0);
874
875 mmio_list(0x408004, 0x00000000, 8, 0);
876 mmio_list(0x408008, 0x80000030, 0, 0);
877 mmio_list(0x418e24, 0x00000000, 8, 0);
878 mmio_list(0x418e28, 0x80000030, 0, 0);
879
880 mmio_list(0x418810, 0x80000000, 12, 2);
881 mmio_list(0x419848, 0x10000000, 12, 2);
882 mmio_list(0x419c2c, 0x10000000, 12, 2);
883
884 mmio_list(0x405830, 0x0aa01000, 0, 0);
885 mmio_list(0x4064c4, 0x0400ffff, 0, 0);
886
887 /*XXX*/
888 mmio_list(0x5030c0, 0x00001540, 0, 0);
889 mmio_list(0x5030f4, 0x00000000, 0, 0);
890 mmio_list(0x5030e4, 0x00002000, 0, 0);
891 mmio_list(0x5030f8, 0x00003fc0, 0, 0);
892 mmio_list(0x418ea0, 0x07151540, 0, 0);
893
894 mmio_list(0x5032c0, 0x00001540, 0, 0);
895 mmio_list(0x5032f4, 0x00001fe0, 0, 0);
896 mmio_list(0x5032e4, 0x00002000, 0, 0);
897 mmio_list(0x5032f8, 0x00006fc0, 0, 0);
898 mmio_list(0x418ea4, 0x07151540, 0, 0);
899}
900
901static void
902gm107_grctx_generate_tpcid(struct nvc0_graph_priv *priv)
903{
904 int gpc, tpc, id;
905
906 for (tpc = 0, id = 0; tpc < 4; tpc++) {
907 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
908 if (tpc < priv->tpc_nr[gpc]) {
909 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id);
910 nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id);
911 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id);
912 id++;
913 }
914
915 nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]);
916 nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]);
917 }
918 }
919}
920
921static void
922gm107_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
923{
924 struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
925 int i;
926
927 nvc0_graph_mmio(priv, oclass->hub);
928 nvc0_graph_mmio(priv, oclass->gpc);
929 nvc0_graph_mmio(priv, oclass->zcull);
930 nvc0_graph_mmio(priv, oclass->tpc);
931 nvc0_graph_mmio(priv, oclass->ppc);
932
933 nv_wr32(priv, 0x404154, 0x00000000);
934
935 oclass->mods(priv, info);
936 oclass->unkn(priv);
937
938 gm107_grctx_generate_tpcid(priv);
939 nvc0_grctx_generate_r406028(priv);
940 nve4_grctx_generate_r418bb8(priv);
941 nvc0_grctx_generate_r406800(priv);
942
943 nv_wr32(priv, 0x4064d0, 0x00000001);
944 for (i = 1; i < 8; i++)
945 nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000);
946 nv_wr32(priv, 0x406500, 0x00000001);
947
948 nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
949
950 if (priv->gpc_nr == 1) {
951 nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]);
952 nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]);
953 } else {
954 nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr);
955 nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr);
956 }
957
958 nvc0_graph_icmd(priv, oclass->icmd);
959 nv_wr32(priv, 0x404154, 0x00000400);
960 nvc0_graph_mthd(priv, oclass->mthd);
961
962 nv_mask(priv, 0x419e00, 0x00808080, 0x00808080);
963 nv_mask(priv, 0x419ccc, 0x80000000, 0x80000000);
964 nv_mask(priv, 0x419f80, 0x80000000, 0x80000000);
965 nv_mask(priv, 0x419f88, 0x80000000, 0x80000000);
966}
967
968struct nouveau_oclass *
969gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
970 .base.handle = NV_ENGCTX(GR, 0x08),
971 .base.ofuncs = &(struct nouveau_ofuncs) {
972 .ctor = nvc0_graph_context_ctor,
973 .dtor = nvc0_graph_context_dtor,
974 .init = _nouveau_graph_context_init,
975 .fini = _nouveau_graph_context_fini,
976 .rd32 = _nouveau_graph_context_rd32,
977 .wr32 = _nouveau_graph_context_wr32,
978 },
979 .main = gm107_grctx_generate_main,
980 .mods = gm107_grctx_generate_mods,
981 .unkn = nve4_grctx_generate_unkn,
982 .hub = gm107_grctx_pack_hub,
983 .gpc = gm107_grctx_pack_gpc,
984 .zcull = nvc0_grctx_pack_zcull,
985 .tpc = gm107_grctx_pack_tpc,
986 .ppc = gm107_grctx_pack_ppc,
987 .icmd = gm107_grctx_pack_icmd,
988 .mthd = gm107_grctx_pack_mthd,
989}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
index a86bd3352bf8..48351b4d6d6b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
@@ -22,10 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27static struct nvc0_graph_init 27/*******************************************************************************
28nv108_grctx_init_icmd[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nv108_grctx_init_icmd_0[] = {
29 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
30 { 0x000039, 3, 0x01, 0x00000000 }, 34 { 0x000039, 3, 0x01, 0x00000000 },
31 { 0x0000a9, 1, 0x01, 0x0000ffff }, 35 { 0x0000a9, 1, 0x01, 0x0000ffff },
@@ -274,839 +278,14 @@ nv108_grctx_init_icmd[] = {
274 {} 278 {}
275}; 279};
276 280
277static struct nvc0_graph_init 281static const struct nvc0_graph_pack
278nv108_grctx_init_a197[] = { 282nv108_grctx_pack_icmd[] = {
279 { 0x000800, 1, 0x04, 0x00000000 }, 283 { nv108_grctx_init_icmd_0 },
280 { 0x000840, 1, 0x04, 0x00000000 },
281 { 0x000880, 1, 0x04, 0x00000000 },
282 { 0x0008c0, 1, 0x04, 0x00000000 },
283 { 0x000900, 1, 0x04, 0x00000000 },
284 { 0x000940, 1, 0x04, 0x00000000 },
285 { 0x000980, 1, 0x04, 0x00000000 },
286 { 0x0009c0, 1, 0x04, 0x00000000 },
287 { 0x000804, 1, 0x04, 0x00000000 },
288 { 0x000844, 1, 0x04, 0x00000000 },
289 { 0x000884, 1, 0x04, 0x00000000 },
290 { 0x0008c4, 1, 0x04, 0x00000000 },
291 { 0x000904, 1, 0x04, 0x00000000 },
292 { 0x000944, 1, 0x04, 0x00000000 },
293 { 0x000984, 1, 0x04, 0x00000000 },
294 { 0x0009c4, 1, 0x04, 0x00000000 },
295 { 0x000808, 1, 0x04, 0x00000400 },
296 { 0x000848, 1, 0x04, 0x00000400 },
297 { 0x000888, 1, 0x04, 0x00000400 },
298 { 0x0008c8, 1, 0x04, 0x00000400 },
299 { 0x000908, 1, 0x04, 0x00000400 },
300 { 0x000948, 1, 0x04, 0x00000400 },
301 { 0x000988, 1, 0x04, 0x00000400 },
302 { 0x0009c8, 1, 0x04, 0x00000400 },
303 { 0x00080c, 1, 0x04, 0x00000300 },
304 { 0x00084c, 1, 0x04, 0x00000300 },
305 { 0x00088c, 1, 0x04, 0x00000300 },
306 { 0x0008cc, 1, 0x04, 0x00000300 },
307 { 0x00090c, 1, 0x04, 0x00000300 },
308 { 0x00094c, 1, 0x04, 0x00000300 },
309 { 0x00098c, 1, 0x04, 0x00000300 },
310 { 0x0009cc, 1, 0x04, 0x00000300 },
311 { 0x000810, 1, 0x04, 0x000000cf },
312 { 0x000850, 1, 0x04, 0x00000000 },
313 { 0x000890, 1, 0x04, 0x00000000 },
314 { 0x0008d0, 1, 0x04, 0x00000000 },
315 { 0x000910, 1, 0x04, 0x00000000 },
316 { 0x000950, 1, 0x04, 0x00000000 },
317 { 0x000990, 1, 0x04, 0x00000000 },
318 { 0x0009d0, 1, 0x04, 0x00000000 },
319 { 0x000814, 1, 0x04, 0x00000040 },
320 { 0x000854, 1, 0x04, 0x00000040 },
321 { 0x000894, 1, 0x04, 0x00000040 },
322 { 0x0008d4, 1, 0x04, 0x00000040 },
323 { 0x000914, 1, 0x04, 0x00000040 },
324 { 0x000954, 1, 0x04, 0x00000040 },
325 { 0x000994, 1, 0x04, 0x00000040 },
326 { 0x0009d4, 1, 0x04, 0x00000040 },
327 { 0x000818, 1, 0x04, 0x00000001 },
328 { 0x000858, 1, 0x04, 0x00000001 },
329 { 0x000898, 1, 0x04, 0x00000001 },
330 { 0x0008d8, 1, 0x04, 0x00000001 },
331 { 0x000918, 1, 0x04, 0x00000001 },
332 { 0x000958, 1, 0x04, 0x00000001 },
333 { 0x000998, 1, 0x04, 0x00000001 },
334 { 0x0009d8, 1, 0x04, 0x00000001 },
335 { 0x00081c, 1, 0x04, 0x00000000 },
336 { 0x00085c, 1, 0x04, 0x00000000 },
337 { 0x00089c, 1, 0x04, 0x00000000 },
338 { 0x0008dc, 1, 0x04, 0x00000000 },
339 { 0x00091c, 1, 0x04, 0x00000000 },
340 { 0x00095c, 1, 0x04, 0x00000000 },
341 { 0x00099c, 1, 0x04, 0x00000000 },
342 { 0x0009dc, 1, 0x04, 0x00000000 },
343 { 0x000820, 1, 0x04, 0x00000000 },
344 { 0x000860, 1, 0x04, 0x00000000 },
345 { 0x0008a0, 1, 0x04, 0x00000000 },
346 { 0x0008e0, 1, 0x04, 0x00000000 },
347 { 0x000920, 1, 0x04, 0x00000000 },
348 { 0x000960, 1, 0x04, 0x00000000 },
349 { 0x0009a0, 1, 0x04, 0x00000000 },
350 { 0x0009e0, 1, 0x04, 0x00000000 },
351 { 0x001c00, 1, 0x04, 0x00000000 },
352 { 0x001c10, 1, 0x04, 0x00000000 },
353 { 0x001c20, 1, 0x04, 0x00000000 },
354 { 0x001c30, 1, 0x04, 0x00000000 },
355 { 0x001c40, 1, 0x04, 0x00000000 },
356 { 0x001c50, 1, 0x04, 0x00000000 },
357 { 0x001c60, 1, 0x04, 0x00000000 },
358 { 0x001c70, 1, 0x04, 0x00000000 },
359 { 0x001c80, 1, 0x04, 0x00000000 },
360 { 0x001c90, 1, 0x04, 0x00000000 },
361 { 0x001ca0, 1, 0x04, 0x00000000 },
362 { 0x001cb0, 1, 0x04, 0x00000000 },
363 { 0x001cc0, 1, 0x04, 0x00000000 },
364 { 0x001cd0, 1, 0x04, 0x00000000 },
365 { 0x001ce0, 1, 0x04, 0x00000000 },
366 { 0x001cf0, 1, 0x04, 0x00000000 },
367 { 0x001c04, 1, 0x04, 0x00000000 },
368 { 0x001c14, 1, 0x04, 0x00000000 },
369 { 0x001c24, 1, 0x04, 0x00000000 },
370 { 0x001c34, 1, 0x04, 0x00000000 },
371 { 0x001c44, 1, 0x04, 0x00000000 },
372 { 0x001c54, 1, 0x04, 0x00000000 },
373 { 0x001c64, 1, 0x04, 0x00000000 },
374 { 0x001c74, 1, 0x04, 0x00000000 },
375 { 0x001c84, 1, 0x04, 0x00000000 },
376 { 0x001c94, 1, 0x04, 0x00000000 },
377 { 0x001ca4, 1, 0x04, 0x00000000 },
378 { 0x001cb4, 1, 0x04, 0x00000000 },
379 { 0x001cc4, 1, 0x04, 0x00000000 },
380 { 0x001cd4, 1, 0x04, 0x00000000 },
381 { 0x001ce4, 1, 0x04, 0x00000000 },
382 { 0x001cf4, 1, 0x04, 0x00000000 },
383 { 0x001c08, 1, 0x04, 0x00000000 },
384 { 0x001c18, 1, 0x04, 0x00000000 },
385 { 0x001c28, 1, 0x04, 0x00000000 },
386 { 0x001c38, 1, 0x04, 0x00000000 },
387 { 0x001c48, 1, 0x04, 0x00000000 },
388 { 0x001c58, 1, 0x04, 0x00000000 },
389 { 0x001c68, 1, 0x04, 0x00000000 },
390 { 0x001c78, 1, 0x04, 0x00000000 },
391 { 0x001c88, 1, 0x04, 0x00000000 },
392 { 0x001c98, 1, 0x04, 0x00000000 },
393 { 0x001ca8, 1, 0x04, 0x00000000 },
394 { 0x001cb8, 1, 0x04, 0x00000000 },
395 { 0x001cc8, 1, 0x04, 0x00000000 },
396 { 0x001cd8, 1, 0x04, 0x00000000 },
397 { 0x001ce8, 1, 0x04, 0x00000000 },
398 { 0x001cf8, 1, 0x04, 0x00000000 },
399 { 0x001c0c, 1, 0x04, 0x00000000 },
400 { 0x001c1c, 1, 0x04, 0x00000000 },
401 { 0x001c2c, 1, 0x04, 0x00000000 },
402 { 0x001c3c, 1, 0x04, 0x00000000 },
403 { 0x001c4c, 1, 0x04, 0x00000000 },
404 { 0x001c5c, 1, 0x04, 0x00000000 },
405 { 0x001c6c, 1, 0x04, 0x00000000 },
406 { 0x001c7c, 1, 0x04, 0x00000000 },
407 { 0x001c8c, 1, 0x04, 0x00000000 },
408 { 0x001c9c, 1, 0x04, 0x00000000 },
409 { 0x001cac, 1, 0x04, 0x00000000 },
410 { 0x001cbc, 1, 0x04, 0x00000000 },
411 { 0x001ccc, 1, 0x04, 0x00000000 },
412 { 0x001cdc, 1, 0x04, 0x00000000 },
413 { 0x001cec, 1, 0x04, 0x00000000 },
414 { 0x001cfc, 2, 0x04, 0x00000000 },
415 { 0x001d10, 1, 0x04, 0x00000000 },
416 { 0x001d20, 1, 0x04, 0x00000000 },
417 { 0x001d30, 1, 0x04, 0x00000000 },
418 { 0x001d40, 1, 0x04, 0x00000000 },
419 { 0x001d50, 1, 0x04, 0x00000000 },
420 { 0x001d60, 1, 0x04, 0x00000000 },
421 { 0x001d70, 1, 0x04, 0x00000000 },
422 { 0x001d80, 1, 0x04, 0x00000000 },
423 { 0x001d90, 1, 0x04, 0x00000000 },
424 { 0x001da0, 1, 0x04, 0x00000000 },
425 { 0x001db0, 1, 0x04, 0x00000000 },
426 { 0x001dc0, 1, 0x04, 0x00000000 },
427 { 0x001dd0, 1, 0x04, 0x00000000 },
428 { 0x001de0, 1, 0x04, 0x00000000 },
429 { 0x001df0, 1, 0x04, 0x00000000 },
430 { 0x001d04, 1, 0x04, 0x00000000 },
431 { 0x001d14, 1, 0x04, 0x00000000 },
432 { 0x001d24, 1, 0x04, 0x00000000 },
433 { 0x001d34, 1, 0x04, 0x00000000 },
434 { 0x001d44, 1, 0x04, 0x00000000 },
435 { 0x001d54, 1, 0x04, 0x00000000 },
436 { 0x001d64, 1, 0x04, 0x00000000 },
437 { 0x001d74, 1, 0x04, 0x00000000 },
438 { 0x001d84, 1, 0x04, 0x00000000 },
439 { 0x001d94, 1, 0x04, 0x00000000 },
440 { 0x001da4, 1, 0x04, 0x00000000 },
441 { 0x001db4, 1, 0x04, 0x00000000 },
442 { 0x001dc4, 1, 0x04, 0x00000000 },
443 { 0x001dd4, 1, 0x04, 0x00000000 },
444 { 0x001de4, 1, 0x04, 0x00000000 },
445 { 0x001df4, 1, 0x04, 0x00000000 },
446 { 0x001d08, 1, 0x04, 0x00000000 },
447 { 0x001d18, 1, 0x04, 0x00000000 },
448 { 0x001d28, 1, 0x04, 0x00000000 },
449 { 0x001d38, 1, 0x04, 0x00000000 },
450 { 0x001d48, 1, 0x04, 0x00000000 },
451 { 0x001d58, 1, 0x04, 0x00000000 },
452 { 0x001d68, 1, 0x04, 0x00000000 },
453 { 0x001d78, 1, 0x04, 0x00000000 },
454 { 0x001d88, 1, 0x04, 0x00000000 },
455 { 0x001d98, 1, 0x04, 0x00000000 },
456 { 0x001da8, 1, 0x04, 0x00000000 },
457 { 0x001db8, 1, 0x04, 0x00000000 },
458 { 0x001dc8, 1, 0x04, 0x00000000 },
459 { 0x001dd8, 1, 0x04, 0x00000000 },
460 { 0x001de8, 1, 0x04, 0x00000000 },
461 { 0x001df8, 1, 0x04, 0x00000000 },
462 { 0x001d0c, 1, 0x04, 0x00000000 },
463 { 0x001d1c, 1, 0x04, 0x00000000 },
464 { 0x001d2c, 1, 0x04, 0x00000000 },
465 { 0x001d3c, 1, 0x04, 0x00000000 },
466 { 0x001d4c, 1, 0x04, 0x00000000 },
467 { 0x001d5c, 1, 0x04, 0x00000000 },
468 { 0x001d6c, 1, 0x04, 0x00000000 },
469 { 0x001d7c, 1, 0x04, 0x00000000 },
470 { 0x001d8c, 1, 0x04, 0x00000000 },
471 { 0x001d9c, 1, 0x04, 0x00000000 },
472 { 0x001dac, 1, 0x04, 0x00000000 },
473 { 0x001dbc, 1, 0x04, 0x00000000 },
474 { 0x001dcc, 1, 0x04, 0x00000000 },
475 { 0x001ddc, 1, 0x04, 0x00000000 },
476 { 0x001dec, 1, 0x04, 0x00000000 },
477 { 0x001dfc, 1, 0x04, 0x00000000 },
478 { 0x001f00, 1, 0x04, 0x00000000 },
479 { 0x001f08, 1, 0x04, 0x00000000 },
480 { 0x001f10, 1, 0x04, 0x00000000 },
481 { 0x001f18, 1, 0x04, 0x00000000 },
482 { 0x001f20, 1, 0x04, 0x00000000 },
483 { 0x001f28, 1, 0x04, 0x00000000 },
484 { 0x001f30, 1, 0x04, 0x00000000 },
485 { 0x001f38, 1, 0x04, 0x00000000 },
486 { 0x001f40, 1, 0x04, 0x00000000 },
487 { 0x001f48, 1, 0x04, 0x00000000 },
488 { 0x001f50, 1, 0x04, 0x00000000 },
489 { 0x001f58, 1, 0x04, 0x00000000 },
490 { 0x001f60, 1, 0x04, 0x00000000 },
491 { 0x001f68, 1, 0x04, 0x00000000 },
492 { 0x001f70, 1, 0x04, 0x00000000 },
493 { 0x001f78, 1, 0x04, 0x00000000 },
494 { 0x001f04, 1, 0x04, 0x00000000 },
495 { 0x001f0c, 1, 0x04, 0x00000000 },
496 { 0x001f14, 1, 0x04, 0x00000000 },
497 { 0x001f1c, 1, 0x04, 0x00000000 },
498 { 0x001f24, 1, 0x04, 0x00000000 },
499 { 0x001f2c, 1, 0x04, 0x00000000 },
500 { 0x001f34, 1, 0x04, 0x00000000 },
501 { 0x001f3c, 1, 0x04, 0x00000000 },
502 { 0x001f44, 1, 0x04, 0x00000000 },
503 { 0x001f4c, 1, 0x04, 0x00000000 },
504 { 0x001f54, 1, 0x04, 0x00000000 },
505 { 0x001f5c, 1, 0x04, 0x00000000 },
506 { 0x001f64, 1, 0x04, 0x00000000 },
507 { 0x001f6c, 1, 0x04, 0x00000000 },
508 { 0x001f74, 1, 0x04, 0x00000000 },
509 { 0x001f7c, 2, 0x04, 0x00000000 },
510 { 0x001f88, 1, 0x04, 0x00000000 },
511 { 0x001f90, 1, 0x04, 0x00000000 },
512 { 0x001f98, 1, 0x04, 0x00000000 },
513 { 0x001fa0, 1, 0x04, 0x00000000 },
514 { 0x001fa8, 1, 0x04, 0x00000000 },
515 { 0x001fb0, 1, 0x04, 0x00000000 },
516 { 0x001fb8, 1, 0x04, 0x00000000 },
517 { 0x001fc0, 1, 0x04, 0x00000000 },
518 { 0x001fc8, 1, 0x04, 0x00000000 },
519 { 0x001fd0, 1, 0x04, 0x00000000 },
520 { 0x001fd8, 1, 0x04, 0x00000000 },
521 { 0x001fe0, 1, 0x04, 0x00000000 },
522 { 0x001fe8, 1, 0x04, 0x00000000 },
523 { 0x001ff0, 1, 0x04, 0x00000000 },
524 { 0x001ff8, 1, 0x04, 0x00000000 },
525 { 0x001f84, 1, 0x04, 0x00000000 },
526 { 0x001f8c, 1, 0x04, 0x00000000 },
527 { 0x001f94, 1, 0x04, 0x00000000 },
528 { 0x001f9c, 1, 0x04, 0x00000000 },
529 { 0x001fa4, 1, 0x04, 0x00000000 },
530 { 0x001fac, 1, 0x04, 0x00000000 },
531 { 0x001fb4, 1, 0x04, 0x00000000 },
532 { 0x001fbc, 1, 0x04, 0x00000000 },
533 { 0x001fc4, 1, 0x04, 0x00000000 },
534 { 0x001fcc, 1, 0x04, 0x00000000 },
535 { 0x001fd4, 1, 0x04, 0x00000000 },
536 { 0x001fdc, 1, 0x04, 0x00000000 },
537 { 0x001fe4, 1, 0x04, 0x00000000 },
538 { 0x001fec, 1, 0x04, 0x00000000 },
539 { 0x001ff4, 1, 0x04, 0x00000000 },
540 { 0x001ffc, 2, 0x04, 0x00000000 },
541 { 0x002040, 1, 0x04, 0x00000011 },
542 { 0x002080, 1, 0x04, 0x00000020 },
543 { 0x0020c0, 1, 0x04, 0x00000030 },
544 { 0x002100, 1, 0x04, 0x00000040 },
545 { 0x002140, 1, 0x04, 0x00000051 },
546 { 0x00200c, 1, 0x04, 0x00000001 },
547 { 0x00204c, 1, 0x04, 0x00000001 },
548 { 0x00208c, 1, 0x04, 0x00000001 },
549 { 0x0020cc, 1, 0x04, 0x00000001 },
550 { 0x00210c, 1, 0x04, 0x00000001 },
551 { 0x00214c, 1, 0x04, 0x00000001 },
552 { 0x002010, 1, 0x04, 0x00000000 },
553 { 0x002050, 1, 0x04, 0x00000000 },
554 { 0x002090, 1, 0x04, 0x00000001 },
555 { 0x0020d0, 1, 0x04, 0x00000002 },
556 { 0x002110, 1, 0x04, 0x00000003 },
557 { 0x002150, 1, 0x04, 0x00000004 },
558 { 0x000380, 1, 0x04, 0x00000000 },
559 { 0x0003a0, 1, 0x04, 0x00000000 },
560 { 0x0003c0, 1, 0x04, 0x00000000 },
561 { 0x0003e0, 1, 0x04, 0x00000000 },
562 { 0x000384, 1, 0x04, 0x00000000 },
563 { 0x0003a4, 1, 0x04, 0x00000000 },
564 { 0x0003c4, 1, 0x04, 0x00000000 },
565 { 0x0003e4, 1, 0x04, 0x00000000 },
566 { 0x000388, 1, 0x04, 0x00000000 },
567 { 0x0003a8, 1, 0x04, 0x00000000 },
568 { 0x0003c8, 1, 0x04, 0x00000000 },
569 { 0x0003e8, 1, 0x04, 0x00000000 },
570 { 0x00038c, 1, 0x04, 0x00000000 },
571 { 0x0003ac, 1, 0x04, 0x00000000 },
572 { 0x0003cc, 1, 0x04, 0x00000000 },
573 { 0x0003ec, 1, 0x04, 0x00000000 },
574 { 0x000700, 1, 0x04, 0x00000000 },
575 { 0x000710, 1, 0x04, 0x00000000 },
576 { 0x000720, 1, 0x04, 0x00000000 },
577 { 0x000730, 1, 0x04, 0x00000000 },
578 { 0x000704, 1, 0x04, 0x00000000 },
579 { 0x000714, 1, 0x04, 0x00000000 },
580 { 0x000724, 1, 0x04, 0x00000000 },
581 { 0x000734, 1, 0x04, 0x00000000 },
582 { 0x000708, 1, 0x04, 0x00000000 },
583 { 0x000718, 1, 0x04, 0x00000000 },
584 { 0x000728, 1, 0x04, 0x00000000 },
585 { 0x000738, 1, 0x04, 0x00000000 },
586 { 0x002800, 128, 0x04, 0x00000000 },
587 { 0x000a00, 1, 0x04, 0x00000000 },
588 { 0x000a20, 1, 0x04, 0x00000000 },
589 { 0x000a40, 1, 0x04, 0x00000000 },
590 { 0x000a60, 1, 0x04, 0x00000000 },
591 { 0x000a80, 1, 0x04, 0x00000000 },
592 { 0x000aa0, 1, 0x04, 0x00000000 },
593 { 0x000ac0, 1, 0x04, 0x00000000 },
594 { 0x000ae0, 1, 0x04, 0x00000000 },
595 { 0x000b00, 1, 0x04, 0x00000000 },
596 { 0x000b20, 1, 0x04, 0x00000000 },
597 { 0x000b40, 1, 0x04, 0x00000000 },
598 { 0x000b60, 1, 0x04, 0x00000000 },
599 { 0x000b80, 1, 0x04, 0x00000000 },
600 { 0x000ba0, 1, 0x04, 0x00000000 },
601 { 0x000bc0, 1, 0x04, 0x00000000 },
602 { 0x000be0, 1, 0x04, 0x00000000 },
603 { 0x000a04, 1, 0x04, 0x00000000 },
604 { 0x000a24, 1, 0x04, 0x00000000 },
605 { 0x000a44, 1, 0x04, 0x00000000 },
606 { 0x000a64, 1, 0x04, 0x00000000 },
607 { 0x000a84, 1, 0x04, 0x00000000 },
608 { 0x000aa4, 1, 0x04, 0x00000000 },
609 { 0x000ac4, 1, 0x04, 0x00000000 },
610 { 0x000ae4, 1, 0x04, 0x00000000 },
611 { 0x000b04, 1, 0x04, 0x00000000 },
612 { 0x000b24, 1, 0x04, 0x00000000 },
613 { 0x000b44, 1, 0x04, 0x00000000 },
614 { 0x000b64, 1, 0x04, 0x00000000 },
615 { 0x000b84, 1, 0x04, 0x00000000 },
616 { 0x000ba4, 1, 0x04, 0x00000000 },
617 { 0x000bc4, 1, 0x04, 0x00000000 },
618 { 0x000be4, 1, 0x04, 0x00000000 },
619 { 0x000a08, 1, 0x04, 0x00000000 },
620 { 0x000a28, 1, 0x04, 0x00000000 },
621 { 0x000a48, 1, 0x04, 0x00000000 },
622 { 0x000a68, 1, 0x04, 0x00000000 },
623 { 0x000a88, 1, 0x04, 0x00000000 },
624 { 0x000aa8, 1, 0x04, 0x00000000 },
625 { 0x000ac8, 1, 0x04, 0x00000000 },
626 { 0x000ae8, 1, 0x04, 0x00000000 },
627 { 0x000b08, 1, 0x04, 0x00000000 },
628 { 0x000b28, 1, 0x04, 0x00000000 },
629 { 0x000b48, 1, 0x04, 0x00000000 },
630 { 0x000b68, 1, 0x04, 0x00000000 },
631 { 0x000b88, 1, 0x04, 0x00000000 },
632 { 0x000ba8, 1, 0x04, 0x00000000 },
633 { 0x000bc8, 1, 0x04, 0x00000000 },
634 { 0x000be8, 1, 0x04, 0x00000000 },
635 { 0x000a0c, 1, 0x04, 0x00000000 },
636 { 0x000a2c, 1, 0x04, 0x00000000 },
637 { 0x000a4c, 1, 0x04, 0x00000000 },
638 { 0x000a6c, 1, 0x04, 0x00000000 },
639 { 0x000a8c, 1, 0x04, 0x00000000 },
640 { 0x000aac, 1, 0x04, 0x00000000 },
641 { 0x000acc, 1, 0x04, 0x00000000 },
642 { 0x000aec, 1, 0x04, 0x00000000 },
643 { 0x000b0c, 1, 0x04, 0x00000000 },
644 { 0x000b2c, 1, 0x04, 0x00000000 },
645 { 0x000b4c, 1, 0x04, 0x00000000 },
646 { 0x000b6c, 1, 0x04, 0x00000000 },
647 { 0x000b8c, 1, 0x04, 0x00000000 },
648 { 0x000bac, 1, 0x04, 0x00000000 },
649 { 0x000bcc, 1, 0x04, 0x00000000 },
650 { 0x000bec, 1, 0x04, 0x00000000 },
651 { 0x000a10, 1, 0x04, 0x00000000 },
652 { 0x000a30, 1, 0x04, 0x00000000 },
653 { 0x000a50, 1, 0x04, 0x00000000 },
654 { 0x000a70, 1, 0x04, 0x00000000 },
655 { 0x000a90, 1, 0x04, 0x00000000 },
656 { 0x000ab0, 1, 0x04, 0x00000000 },
657 { 0x000ad0, 1, 0x04, 0x00000000 },
658 { 0x000af0, 1, 0x04, 0x00000000 },
659 { 0x000b10, 1, 0x04, 0x00000000 },
660 { 0x000b30, 1, 0x04, 0x00000000 },
661 { 0x000b50, 1, 0x04, 0x00000000 },
662 { 0x000b70, 1, 0x04, 0x00000000 },
663 { 0x000b90, 1, 0x04, 0x00000000 },
664 { 0x000bb0, 1, 0x04, 0x00000000 },
665 { 0x000bd0, 1, 0x04, 0x00000000 },
666 { 0x000bf0, 1, 0x04, 0x00000000 },
667 { 0x000a14, 1, 0x04, 0x00000000 },
668 { 0x000a34, 1, 0x04, 0x00000000 },
669 { 0x000a54, 1, 0x04, 0x00000000 },
670 { 0x000a74, 1, 0x04, 0x00000000 },
671 { 0x000a94, 1, 0x04, 0x00000000 },
672 { 0x000ab4, 1, 0x04, 0x00000000 },
673 { 0x000ad4, 1, 0x04, 0x00000000 },
674 { 0x000af4, 1, 0x04, 0x00000000 },
675 { 0x000b14, 1, 0x04, 0x00000000 },
676 { 0x000b34, 1, 0x04, 0x00000000 },
677 { 0x000b54, 1, 0x04, 0x00000000 },
678 { 0x000b74, 1, 0x04, 0x00000000 },
679 { 0x000b94, 1, 0x04, 0x00000000 },
680 { 0x000bb4, 1, 0x04, 0x00000000 },
681 { 0x000bd4, 1, 0x04, 0x00000000 },
682 { 0x000bf4, 1, 0x04, 0x00000000 },
683 { 0x000c00, 1, 0x04, 0x00000000 },
684 { 0x000c10, 1, 0x04, 0x00000000 },
685 { 0x000c20, 1, 0x04, 0x00000000 },
686 { 0x000c30, 1, 0x04, 0x00000000 },
687 { 0x000c40, 1, 0x04, 0x00000000 },
688 { 0x000c50, 1, 0x04, 0x00000000 },
689 { 0x000c60, 1, 0x04, 0x00000000 },
690 { 0x000c70, 1, 0x04, 0x00000000 },
691 { 0x000c80, 1, 0x04, 0x00000000 },
692 { 0x000c90, 1, 0x04, 0x00000000 },
693 { 0x000ca0, 1, 0x04, 0x00000000 },
694 { 0x000cb0, 1, 0x04, 0x00000000 },
695 { 0x000cc0, 1, 0x04, 0x00000000 },
696 { 0x000cd0, 1, 0x04, 0x00000000 },
697 { 0x000ce0, 1, 0x04, 0x00000000 },
698 { 0x000cf0, 1, 0x04, 0x00000000 },
699 { 0x000c04, 1, 0x04, 0x00000000 },
700 { 0x000c14, 1, 0x04, 0x00000000 },
701 { 0x000c24, 1, 0x04, 0x00000000 },
702 { 0x000c34, 1, 0x04, 0x00000000 },
703 { 0x000c44, 1, 0x04, 0x00000000 },
704 { 0x000c54, 1, 0x04, 0x00000000 },
705 { 0x000c64, 1, 0x04, 0x00000000 },
706 { 0x000c74, 1, 0x04, 0x00000000 },
707 { 0x000c84, 1, 0x04, 0x00000000 },
708 { 0x000c94, 1, 0x04, 0x00000000 },
709 { 0x000ca4, 1, 0x04, 0x00000000 },
710 { 0x000cb4, 1, 0x04, 0x00000000 },
711 { 0x000cc4, 1, 0x04, 0x00000000 },
712 { 0x000cd4, 1, 0x04, 0x00000000 },
713 { 0x000ce4, 1, 0x04, 0x00000000 },
714 { 0x000cf4, 1, 0x04, 0x00000000 },
715 { 0x000c08, 1, 0x04, 0x00000000 },
716 { 0x000c18, 1, 0x04, 0x00000000 },
717 { 0x000c28, 1, 0x04, 0x00000000 },
718 { 0x000c38, 1, 0x04, 0x00000000 },
719 { 0x000c48, 1, 0x04, 0x00000000 },
720 { 0x000c58, 1, 0x04, 0x00000000 },
721 { 0x000c68, 1, 0x04, 0x00000000 },
722 { 0x000c78, 1, 0x04, 0x00000000 },
723 { 0x000c88, 1, 0x04, 0x00000000 },
724 { 0x000c98, 1, 0x04, 0x00000000 },
725 { 0x000ca8, 1, 0x04, 0x00000000 },
726 { 0x000cb8, 1, 0x04, 0x00000000 },
727 { 0x000cc8, 1, 0x04, 0x00000000 },
728 { 0x000cd8, 1, 0x04, 0x00000000 },
729 { 0x000ce8, 1, 0x04, 0x00000000 },
730 { 0x000cf8, 1, 0x04, 0x00000000 },
731 { 0x000c0c, 1, 0x04, 0x3f800000 },
732 { 0x000c1c, 1, 0x04, 0x3f800000 },
733 { 0x000c2c, 1, 0x04, 0x3f800000 },
734 { 0x000c3c, 1, 0x04, 0x3f800000 },
735 { 0x000c4c, 1, 0x04, 0x3f800000 },
736 { 0x000c5c, 1, 0x04, 0x3f800000 },
737 { 0x000c6c, 1, 0x04, 0x3f800000 },
738 { 0x000c7c, 1, 0x04, 0x3f800000 },
739 { 0x000c8c, 1, 0x04, 0x3f800000 },
740 { 0x000c9c, 1, 0x04, 0x3f800000 },
741 { 0x000cac, 1, 0x04, 0x3f800000 },
742 { 0x000cbc, 1, 0x04, 0x3f800000 },
743 { 0x000ccc, 1, 0x04, 0x3f800000 },
744 { 0x000cdc, 1, 0x04, 0x3f800000 },
745 { 0x000cec, 1, 0x04, 0x3f800000 },
746 { 0x000cfc, 1, 0x04, 0x3f800000 },
747 { 0x000d00, 1, 0x04, 0xffff0000 },
748 { 0x000d08, 1, 0x04, 0xffff0000 },
749 { 0x000d10, 1, 0x04, 0xffff0000 },
750 { 0x000d18, 1, 0x04, 0xffff0000 },
751 { 0x000d20, 1, 0x04, 0xffff0000 },
752 { 0x000d28, 1, 0x04, 0xffff0000 },
753 { 0x000d30, 1, 0x04, 0xffff0000 },
754 { 0x000d38, 1, 0x04, 0xffff0000 },
755 { 0x000d04, 1, 0x04, 0xffff0000 },
756 { 0x000d0c, 1, 0x04, 0xffff0000 },
757 { 0x000d14, 1, 0x04, 0xffff0000 },
758 { 0x000d1c, 1, 0x04, 0xffff0000 },
759 { 0x000d24, 1, 0x04, 0xffff0000 },
760 { 0x000d2c, 1, 0x04, 0xffff0000 },
761 { 0x000d34, 1, 0x04, 0xffff0000 },
762 { 0x000d3c, 1, 0x04, 0xffff0000 },
763 { 0x000e00, 1, 0x04, 0x00000000 },
764 { 0x000e10, 1, 0x04, 0x00000000 },
765 { 0x000e20, 1, 0x04, 0x00000000 },
766 { 0x000e30, 1, 0x04, 0x00000000 },
767 { 0x000e40, 1, 0x04, 0x00000000 },
768 { 0x000e50, 1, 0x04, 0x00000000 },
769 { 0x000e60, 1, 0x04, 0x00000000 },
770 { 0x000e70, 1, 0x04, 0x00000000 },
771 { 0x000e80, 1, 0x04, 0x00000000 },
772 { 0x000e90, 1, 0x04, 0x00000000 },
773 { 0x000ea0, 1, 0x04, 0x00000000 },
774 { 0x000eb0, 1, 0x04, 0x00000000 },
775 { 0x000ec0, 1, 0x04, 0x00000000 },
776 { 0x000ed0, 1, 0x04, 0x00000000 },
777 { 0x000ee0, 1, 0x04, 0x00000000 },
778 { 0x000ef0, 1, 0x04, 0x00000000 },
779 { 0x000e04, 1, 0x04, 0xffff0000 },
780 { 0x000e14, 1, 0x04, 0xffff0000 },
781 { 0x000e24, 1, 0x04, 0xffff0000 },
782 { 0x000e34, 1, 0x04, 0xffff0000 },
783 { 0x000e44, 1, 0x04, 0xffff0000 },
784 { 0x000e54, 1, 0x04, 0xffff0000 },
785 { 0x000e64, 1, 0x04, 0xffff0000 },
786 { 0x000e74, 1, 0x04, 0xffff0000 },
787 { 0x000e84, 1, 0x04, 0xffff0000 },
788 { 0x000e94, 1, 0x04, 0xffff0000 },
789 { 0x000ea4, 1, 0x04, 0xffff0000 },
790 { 0x000eb4, 1, 0x04, 0xffff0000 },
791 { 0x000ec4, 1, 0x04, 0xffff0000 },
792 { 0x000ed4, 1, 0x04, 0xffff0000 },
793 { 0x000ee4, 1, 0x04, 0xffff0000 },
794 { 0x000ef4, 1, 0x04, 0xffff0000 },
795 { 0x000e08, 1, 0x04, 0xffff0000 },
796 { 0x000e18, 1, 0x04, 0xffff0000 },
797 { 0x000e28, 1, 0x04, 0xffff0000 },
798 { 0x000e38, 1, 0x04, 0xffff0000 },
799 { 0x000e48, 1, 0x04, 0xffff0000 },
800 { 0x000e58, 1, 0x04, 0xffff0000 },
801 { 0x000e68, 1, 0x04, 0xffff0000 },
802 { 0x000e78, 1, 0x04, 0xffff0000 },
803 { 0x000e88, 1, 0x04, 0xffff0000 },
804 { 0x000e98, 1, 0x04, 0xffff0000 },
805 { 0x000ea8, 1, 0x04, 0xffff0000 },
806 { 0x000eb8, 1, 0x04, 0xffff0000 },
807 { 0x000ec8, 1, 0x04, 0xffff0000 },
808 { 0x000ed8, 1, 0x04, 0xffff0000 },
809 { 0x000ee8, 1, 0x04, 0xffff0000 },
810 { 0x000ef8, 1, 0x04, 0xffff0000 },
811 { 0x000d40, 1, 0x04, 0x00000000 },
812 { 0x000d48, 1, 0x04, 0x00000000 },
813 { 0x000d50, 1, 0x04, 0x00000000 },
814 { 0x000d58, 1, 0x04, 0x00000000 },
815 { 0x000d44, 1, 0x04, 0x00000000 },
816 { 0x000d4c, 1, 0x04, 0x00000000 },
817 { 0x000d54, 1, 0x04, 0x00000000 },
818 { 0x000d5c, 1, 0x04, 0x00000000 },
819 { 0x001e00, 1, 0x04, 0x00000001 },
820 { 0x001e20, 1, 0x04, 0x00000001 },
821 { 0x001e40, 1, 0x04, 0x00000001 },
822 { 0x001e60, 1, 0x04, 0x00000001 },
823 { 0x001e80, 1, 0x04, 0x00000001 },
824 { 0x001ea0, 1, 0x04, 0x00000001 },
825 { 0x001ec0, 1, 0x04, 0x00000001 },
826 { 0x001ee0, 1, 0x04, 0x00000001 },
827 { 0x001e04, 1, 0x04, 0x00000001 },
828 { 0x001e24, 1, 0x04, 0x00000001 },
829 { 0x001e44, 1, 0x04, 0x00000001 },
830 { 0x001e64, 1, 0x04, 0x00000001 },
831 { 0x001e84, 1, 0x04, 0x00000001 },
832 { 0x001ea4, 1, 0x04, 0x00000001 },
833 { 0x001ec4, 1, 0x04, 0x00000001 },
834 { 0x001ee4, 1, 0x04, 0x00000001 },
835 { 0x001e08, 1, 0x04, 0x00000002 },
836 { 0x001e28, 1, 0x04, 0x00000002 },
837 { 0x001e48, 1, 0x04, 0x00000002 },
838 { 0x001e68, 1, 0x04, 0x00000002 },
839 { 0x001e88, 1, 0x04, 0x00000002 },
840 { 0x001ea8, 1, 0x04, 0x00000002 },
841 { 0x001ec8, 1, 0x04, 0x00000002 },
842 { 0x001ee8, 1, 0x04, 0x00000002 },
843 { 0x001e0c, 1, 0x04, 0x00000001 },
844 { 0x001e2c, 1, 0x04, 0x00000001 },
845 { 0x001e4c, 1, 0x04, 0x00000001 },
846 { 0x001e6c, 1, 0x04, 0x00000001 },
847 { 0x001e8c, 1, 0x04, 0x00000001 },
848 { 0x001eac, 1, 0x04, 0x00000001 },
849 { 0x001ecc, 1, 0x04, 0x00000001 },
850 { 0x001eec, 1, 0x04, 0x00000001 },
851 { 0x001e10, 1, 0x04, 0x00000001 },
852 { 0x001e30, 1, 0x04, 0x00000001 },
853 { 0x001e50, 1, 0x04, 0x00000001 },
854 { 0x001e70, 1, 0x04, 0x00000001 },
855 { 0x001e90, 1, 0x04, 0x00000001 },
856 { 0x001eb0, 1, 0x04, 0x00000001 },
857 { 0x001ed0, 1, 0x04, 0x00000001 },
858 { 0x001ef0, 1, 0x04, 0x00000001 },
859 { 0x001e14, 1, 0x04, 0x00000002 },
860 { 0x001e34, 1, 0x04, 0x00000002 },
861 { 0x001e54, 1, 0x04, 0x00000002 },
862 { 0x001e74, 1, 0x04, 0x00000002 },
863 { 0x001e94, 1, 0x04, 0x00000002 },
864 { 0x001eb4, 1, 0x04, 0x00000002 },
865 { 0x001ed4, 1, 0x04, 0x00000002 },
866 { 0x001ef4, 1, 0x04, 0x00000002 },
867 { 0x001e18, 1, 0x04, 0x00000001 },
868 { 0x001e38, 1, 0x04, 0x00000001 },
869 { 0x001e58, 1, 0x04, 0x00000001 },
870 { 0x001e78, 1, 0x04, 0x00000001 },
871 { 0x001e98, 1, 0x04, 0x00000001 },
872 { 0x001eb8, 1, 0x04, 0x00000001 },
873 { 0x001ed8, 1, 0x04, 0x00000001 },
874 { 0x001ef8, 1, 0x04, 0x00000001 },
875 { 0x003400, 128, 0x04, 0x00000000 },
876 { 0x00030c, 1, 0x04, 0x00000001 },
877 { 0x001944, 1, 0x04, 0x00000000 },
878 { 0x001514, 1, 0x04, 0x00000000 },
879 { 0x000d68, 1, 0x04, 0x0000ffff },
880 { 0x00121c, 1, 0x04, 0x0fac6881 },
881 { 0x000fac, 1, 0x04, 0x00000001 },
882 { 0x001538, 1, 0x04, 0x00000001 },
883 { 0x000fe0, 2, 0x04, 0x00000000 },
884 { 0x000fe8, 1, 0x04, 0x00000014 },
885 { 0x000fec, 1, 0x04, 0x00000040 },
886 { 0x000ff0, 1, 0x04, 0x00000000 },
887 { 0x00179c, 1, 0x04, 0x00000000 },
888 { 0x001228, 1, 0x04, 0x00000400 },
889 { 0x00122c, 1, 0x04, 0x00000300 },
890 { 0x001230, 1, 0x04, 0x00010001 },
891 { 0x0007f8, 1, 0x04, 0x00000000 },
892 { 0x0015b4, 1, 0x04, 0x00000001 },
893 { 0x0015cc, 1, 0x04, 0x00000000 },
894 { 0x001534, 1, 0x04, 0x00000000 },
895 { 0x000fb0, 1, 0x04, 0x00000000 },
896 { 0x0015d0, 1, 0x04, 0x00000000 },
897 { 0x00153c, 1, 0x04, 0x00000000 },
898 { 0x0016b4, 1, 0x04, 0x00000003 },
899 { 0x000fbc, 4, 0x04, 0x0000ffff },
900 { 0x000df8, 2, 0x04, 0x00000000 },
901 { 0x001948, 1, 0x04, 0x00000000 },
902 { 0x001970, 1, 0x04, 0x00000001 },
903 { 0x00161c, 1, 0x04, 0x000009f0 },
904 { 0x000dcc, 1, 0x04, 0x00000010 },
905 { 0x00163c, 1, 0x04, 0x00000000 },
906 { 0x0015e4, 1, 0x04, 0x00000000 },
907 { 0x001160, 32, 0x04, 0x25e00040 },
908 { 0x001880, 32, 0x04, 0x00000000 },
909 { 0x000f84, 2, 0x04, 0x00000000 },
910 { 0x0017c8, 2, 0x04, 0x00000000 },
911 { 0x0017d0, 1, 0x04, 0x000000ff },
912 { 0x0017d4, 1, 0x04, 0xffffffff },
913 { 0x0017d8, 1, 0x04, 0x00000002 },
914 { 0x0017dc, 1, 0x04, 0x00000000 },
915 { 0x0015f4, 2, 0x04, 0x00000000 },
916 { 0x001434, 2, 0x04, 0x00000000 },
917 { 0x000d74, 1, 0x04, 0x00000000 },
918 { 0x000dec, 1, 0x04, 0x00000001 },
919 { 0x0013a4, 1, 0x04, 0x00000000 },
920 { 0x001318, 1, 0x04, 0x00000001 },
921 { 0x001644, 1, 0x04, 0x00000000 },
922 { 0x000748, 1, 0x04, 0x00000000 },
923 { 0x000de8, 1, 0x04, 0x00000000 },
924 { 0x001648, 1, 0x04, 0x00000000 },
925 { 0x0012a4, 1, 0x04, 0x00000000 },
926 { 0x001120, 4, 0x04, 0x00000000 },
927 { 0x001118, 1, 0x04, 0x00000000 },
928 { 0x00164c, 1, 0x04, 0x00000000 },
929 { 0x001658, 1, 0x04, 0x00000000 },
930 { 0x001910, 1, 0x04, 0x00000290 },
931 { 0x001518, 1, 0x04, 0x00000000 },
932 { 0x00165c, 1, 0x04, 0x00000001 },
933 { 0x001520, 1, 0x04, 0x00000000 },
934 { 0x001604, 1, 0x04, 0x00000000 },
935 { 0x001570, 1, 0x04, 0x00000000 },
936 { 0x0013b0, 2, 0x04, 0x3f800000 },
937 { 0x00020c, 1, 0x04, 0x00000000 },
938 { 0x001670, 1, 0x04, 0x30201000 },
939 { 0x001674, 1, 0x04, 0x70605040 },
940 { 0x001678, 1, 0x04, 0xb8a89888 },
941 { 0x00167c, 1, 0x04, 0xf8e8d8c8 },
942 { 0x00166c, 1, 0x04, 0x00000000 },
943 { 0x001680, 1, 0x04, 0x00ffff00 },
944 { 0x0012d0, 1, 0x04, 0x00000003 },
945 { 0x0012d4, 1, 0x04, 0x00000002 },
946 { 0x001684, 2, 0x04, 0x00000000 },
947 { 0x000dac, 2, 0x04, 0x00001b02 },
948 { 0x000db4, 1, 0x04, 0x00000000 },
949 { 0x00168c, 1, 0x04, 0x00000000 },
950 { 0x0015bc, 1, 0x04, 0x00000000 },
951 { 0x00156c, 1, 0x04, 0x00000000 },
952 { 0x00187c, 1, 0x04, 0x00000000 },
953 { 0x001110, 1, 0x04, 0x00000001 },
954 { 0x000dc0, 3, 0x04, 0x00000000 },
955 { 0x001234, 1, 0x04, 0x00000000 },
956 { 0x001690, 1, 0x04, 0x00000000 },
957 { 0x0012ac, 1, 0x04, 0x00000001 },
958 { 0x0002c4, 1, 0x04, 0x00000000 },
959 { 0x000790, 5, 0x04, 0x00000000 },
960 { 0x00077c, 1, 0x04, 0x00000000 },
961 { 0x001000, 1, 0x04, 0x00000010 },
962 { 0x0010fc, 1, 0x04, 0x00000000 },
963 { 0x001290, 1, 0x04, 0x00000000 },
964 { 0x000218, 1, 0x04, 0x00000010 },
965 { 0x0012d8, 1, 0x04, 0x00000000 },
966 { 0x0012dc, 1, 0x04, 0x00000010 },
967 { 0x000d94, 1, 0x04, 0x00000001 },
968 { 0x00155c, 2, 0x04, 0x00000000 },
969 { 0x001564, 1, 0x04, 0x00000fff },
970 { 0x001574, 2, 0x04, 0x00000000 },
971 { 0x00157c, 1, 0x04, 0x000fffff },
972 { 0x001354, 1, 0x04, 0x00000000 },
973 { 0x001610, 1, 0x04, 0x00000012 },
974 { 0x001608, 2, 0x04, 0x00000000 },
975 { 0x00260c, 1, 0x04, 0x00000000 },
976 { 0x0007ac, 1, 0x04, 0x00000000 },
977 { 0x00162c, 1, 0x04, 0x00000003 },
978 { 0x000210, 1, 0x04, 0x00000000 },
979 { 0x000320, 1, 0x04, 0x00000000 },
980 { 0x000324, 6, 0x04, 0x3f800000 },
981 { 0x000750, 1, 0x04, 0x00000000 },
982 { 0x000760, 1, 0x04, 0x39291909 },
983 { 0x000764, 1, 0x04, 0x79695949 },
984 { 0x000768, 1, 0x04, 0xb9a99989 },
985 { 0x00076c, 1, 0x04, 0xf9e9d9c9 },
986 { 0x000770, 1, 0x04, 0x30201000 },
987 { 0x000774, 1, 0x04, 0x70605040 },
988 { 0x000778, 1, 0x04, 0x00009080 },
989 { 0x000780, 1, 0x04, 0x39291909 },
990 { 0x000784, 1, 0x04, 0x79695949 },
991 { 0x000788, 1, 0x04, 0xb9a99989 },
992 { 0x00078c, 1, 0x04, 0xf9e9d9c9 },
993 { 0x0007d0, 1, 0x04, 0x30201000 },
994 { 0x0007d4, 1, 0x04, 0x70605040 },
995 { 0x0007d8, 1, 0x04, 0x00009080 },
996 { 0x00037c, 1, 0x04, 0x00000001 },
997 { 0x000740, 2, 0x04, 0x00000000 },
998 { 0x002600, 1, 0x04, 0x00000000 },
999 { 0x001918, 1, 0x04, 0x00000000 },
1000 { 0x00191c, 1, 0x04, 0x00000900 },
1001 { 0x001920, 1, 0x04, 0x00000405 },
1002 { 0x001308, 1, 0x04, 0x00000001 },
1003 { 0x001924, 1, 0x04, 0x00000000 },
1004 { 0x0013ac, 1, 0x04, 0x00000000 },
1005 { 0x00192c, 1, 0x04, 0x00000001 },
1006 { 0x00193c, 1, 0x04, 0x00002c1c },
1007 { 0x000d7c, 1, 0x04, 0x00000000 },
1008 { 0x000f8c, 1, 0x04, 0x00000000 },
1009 { 0x0002c0, 1, 0x04, 0x00000001 },
1010 { 0x001510, 1, 0x04, 0x00000000 },
1011 { 0x001940, 1, 0x04, 0x00000000 },
1012 { 0x000ff4, 2, 0x04, 0x00000000 },
1013 { 0x00194c, 2, 0x04, 0x00000000 },
1014 { 0x001968, 1, 0x04, 0x00000000 },
1015 { 0x001590, 1, 0x04, 0x0000003f },
1016 { 0x0007e8, 4, 0x04, 0x00000000 },
1017 { 0x00196c, 1, 0x04, 0x00000011 },
1018 { 0x0002e4, 1, 0x04, 0x0000b001 },
1019 { 0x00036c, 2, 0x04, 0x00000000 },
1020 { 0x00197c, 1, 0x04, 0x00000000 },
1021 { 0x000fcc, 2, 0x04, 0x00000000 },
1022 { 0x0002d8, 1, 0x04, 0x00000040 },
1023 { 0x001980, 1, 0x04, 0x00000080 },
1024 { 0x001504, 1, 0x04, 0x00000080 },
1025 { 0x001984, 1, 0x04, 0x00000000 },
1026 { 0x000300, 1, 0x04, 0x00000001 },
1027 { 0x0013a8, 1, 0x04, 0x00000000 },
1028 { 0x0012ec, 1, 0x04, 0x00000000 },
1029 { 0x001310, 1, 0x04, 0x00000000 },
1030 { 0x001314, 1, 0x04, 0x00000001 },
1031 { 0x001380, 1, 0x04, 0x00000000 },
1032 { 0x001384, 4, 0x04, 0x00000001 },
1033 { 0x001394, 1, 0x04, 0x00000000 },
1034 { 0x00139c, 1, 0x04, 0x00000000 },
1035 { 0x001398, 1, 0x04, 0x00000000 },
1036 { 0x001594, 1, 0x04, 0x00000000 },
1037 { 0x001598, 4, 0x04, 0x00000001 },
1038 { 0x000f54, 3, 0x04, 0x00000000 },
1039 { 0x0019bc, 1, 0x04, 0x00000000 },
1040 { 0x000f9c, 2, 0x04, 0x00000000 },
1041 { 0x0012cc, 1, 0x04, 0x00000000 },
1042 { 0x0012e8, 1, 0x04, 0x00000000 },
1043 { 0x00130c, 1, 0x04, 0x00000001 },
1044 { 0x001360, 8, 0x04, 0x00000000 },
1045 { 0x00133c, 2, 0x04, 0x00000001 },
1046 { 0x001344, 1, 0x04, 0x00000002 },
1047 { 0x001348, 2, 0x04, 0x00000001 },
1048 { 0x001350, 1, 0x04, 0x00000002 },
1049 { 0x001358, 1, 0x04, 0x00000001 },
1050 { 0x0012e4, 1, 0x04, 0x00000000 },
1051 { 0x00131c, 4, 0x04, 0x00000000 },
1052 { 0x0019c0, 1, 0x04, 0x00000000 },
1053 { 0x001140, 1, 0x04, 0x00000000 },
1054 { 0x0019c4, 1, 0x04, 0x00000000 },
1055 { 0x0019c8, 1, 0x04, 0x00001500 },
1056 { 0x00135c, 1, 0x04, 0x00000000 },
1057 { 0x000f90, 1, 0x04, 0x00000000 },
1058 { 0x0019e0, 8, 0x04, 0x00000001 },
1059 { 0x0019cc, 1, 0x04, 0x00000001 },
1060 { 0x0015b8, 1, 0x04, 0x00000000 },
1061 { 0x001a00, 1, 0x04, 0x00001111 },
1062 { 0x001a04, 7, 0x04, 0x00000000 },
1063 { 0x000d6c, 2, 0x04, 0xffff0000 },
1064 { 0x0010f8, 1, 0x04, 0x00001010 },
1065 { 0x000d80, 5, 0x04, 0x00000000 },
1066 { 0x000da0, 1, 0x04, 0x00000000 },
1067 { 0x0007a4, 2, 0x04, 0x00000000 },
1068 { 0x001508, 1, 0x04, 0x80000000 },
1069 { 0x00150c, 1, 0x04, 0x40000000 },
1070 { 0x001668, 1, 0x04, 0x00000000 },
1071 { 0x000318, 2, 0x04, 0x00000008 },
1072 { 0x000d9c, 1, 0x04, 0x00000001 },
1073 { 0x000ddc, 1, 0x04, 0x00000002 },
1074 { 0x000374, 1, 0x04, 0x00000000 },
1075 { 0x000378, 1, 0x04, 0x00000020 },
1076 { 0x0007dc, 1, 0x04, 0x00000000 },
1077 { 0x00074c, 1, 0x04, 0x00000055 },
1078 { 0x001420, 1, 0x04, 0x00000003 },
1079 { 0x0017bc, 2, 0x04, 0x00000000 },
1080 { 0x0017c4, 1, 0x04, 0x00000001 },
1081 { 0x001008, 1, 0x04, 0x00000008 },
1082 { 0x00100c, 1, 0x04, 0x00000040 },
1083 { 0x001010, 1, 0x04, 0x0000012c },
1084 { 0x000d60, 1, 0x04, 0x00000040 },
1085 { 0x00075c, 1, 0x04, 0x00000003 },
1086 { 0x001018, 1, 0x04, 0x00000020 },
1087 { 0x00101c, 1, 0x04, 0x00000001 },
1088 { 0x001020, 1, 0x04, 0x00000020 },
1089 { 0x001024, 1, 0x04, 0x00000001 },
1090 { 0x001444, 3, 0x04, 0x00000000 },
1091 { 0x000360, 1, 0x04, 0x20164010 },
1092 { 0x000364, 1, 0x04, 0x00000020 },
1093 { 0x000368, 1, 0x04, 0x00000000 },
1094 { 0x000de4, 1, 0x04, 0x00000000 },
1095 { 0x000204, 1, 0x04, 0x00000006 },
1096 { 0x000208, 1, 0x04, 0x00000000 },
1097 { 0x0002cc, 2, 0x04, 0x003fffff },
1098 { 0x001220, 1, 0x04, 0x00000005 },
1099 { 0x000fdc, 1, 0x04, 0x00000000 },
1100 { 0x000f98, 1, 0x04, 0x00400008 },
1101 { 0x001284, 1, 0x04, 0x08000080 },
1102 { 0x001450, 1, 0x04, 0x00400008 },
1103 { 0x001454, 1, 0x04, 0x08000080 },
1104 { 0x000214, 1, 0x04, 0x00000000 },
1105 {} 284 {}
1106}; 285};
1107 286
1108static struct nvc0_graph_init 287static const struct nvc0_graph_init
1109nv108_grctx_init_unk40xx[] = { 288nv108_grctx_init_fe_0[] = {
1110 { 0x404004, 8, 0x04, 0x00000000 }, 289 { 0x404004, 8, 0x04, 0x00000000 },
1111 { 0x404024, 1, 0x04, 0x0000e000 }, 290 { 0x404024, 1, 0x04, 0x0000e000 },
1112 { 0x404028, 8, 0x04, 0x00000000 }, 291 { 0x404028, 8, 0x04, 0x00000000 },
@@ -1132,8 +311,8 @@ nv108_grctx_init_unk40xx[] = {
1132 {} 311 {}
1133}; 312};
1134 313
1135static struct nvc0_graph_init 314static const struct nvc0_graph_init
1136nv108_grctx_init_unk58xx[] = { 315nv108_grctx_init_ds_0[] = {
1137 { 0x405800, 1, 0x04, 0x0f8000bf }, 316 { 0x405800, 1, 0x04, 0x0f8000bf },
1138 { 0x405830, 1, 0x04, 0x02180648 }, 317 { 0x405830, 1, 0x04, 0x02180648 },
1139 { 0x405834, 1, 0x04, 0x08000000 }, 318 { 0x405834, 1, 0x04, 0x08000000 },
@@ -1146,8 +325,10 @@ nv108_grctx_init_unk58xx[] = {
1146 {} 325 {}
1147}; 326};
1148 327
1149static struct nvc0_graph_init 328static const struct nvc0_graph_init
1150nv108_grctx_init_unk64xx[] = { 329nv108_grctx_init_pd_0[] = {
330 { 0x406020, 1, 0x04, 0x034103c1 },
331 { 0x406028, 4, 0x04, 0x00000001 },
1151 { 0x4064a8, 1, 0x04, 0x00000000 }, 332 { 0x4064a8, 1, 0x04, 0x00000000 },
1152 { 0x4064ac, 1, 0x04, 0x00003fff }, 333 { 0x4064ac, 1, 0x04, 0x00003fff },
1153 { 0x4064b0, 3, 0x04, 0x00000000 }, 334 { 0x4064b0, 3, 0x04, 0x00000000 },
@@ -1159,8 +340,8 @@ nv108_grctx_init_unk64xx[] = {
1159 {} 340 {}
1160}; 341};
1161 342
1162static struct nvc0_graph_init 343const struct nvc0_graph_init
1163nv108_grctx_init_unk78xx[] = { 344nv108_grctx_init_rstr2d_0[] = {
1164 { 0x407804, 1, 0x04, 0x00000063 }, 345 { 0x407804, 1, 0x04, 0x00000063 },
1165 { 0x40780c, 1, 0x04, 0x0a418820 }, 346 { 0x40780c, 1, 0x04, 0x0a418820 },
1166 { 0x407810, 1, 0x04, 0x062080e6 }, 347 { 0x407810, 1, 0x04, 0x062080e6 },
@@ -1172,8 +353,8 @@ nv108_grctx_init_unk78xx[] = {
1172 {} 353 {}
1173}; 354};
1174 355
1175static struct nvc0_graph_init 356static const struct nvc0_graph_init
1176nv108_grctx_init_unk88xx[] = { 357nv108_grctx_init_be_0[] = {
1177 { 0x408800, 1, 0x04, 0x32802a3c }, 358 { 0x408800, 1, 0x04, 0x32802a3c },
1178 { 0x408804, 1, 0x04, 0x00000040 }, 359 { 0x408804, 1, 0x04, 0x00000040 },
1179 { 0x408808, 1, 0x04, 0x1003e005 }, 360 { 0x408808, 1, 0x04, 0x1003e005 },
@@ -1185,9 +366,23 @@ nv108_grctx_init_unk88xx[] = {
1185 {} 366 {}
1186}; 367};
1187 368
1188static struct nvc0_graph_init 369static const struct nvc0_graph_pack
1189nv108_grctx_init_gpc_0[] = { 370nv108_grctx_pack_hub[] = {
1190 { 0x418380, 1, 0x04, 0x00000016 }, 371 { nvc0_grctx_init_main_0 },
372 { nv108_grctx_init_fe_0 },
373 { nvf0_grctx_init_pri_0 },
374 { nve4_grctx_init_memfmt_0 },
375 { nv108_grctx_init_ds_0 },
376 { nvf0_grctx_init_cwd_0 },
377 { nv108_grctx_init_pd_0 },
378 { nv108_grctx_init_rstr2d_0 },
379 { nve4_grctx_init_scc_0 },
380 { nv108_grctx_init_be_0 },
381 {}
382};
383
384const struct nvc0_graph_init
385nv108_grctx_init_prop_0[] = {
1191 { 0x418400, 1, 0x04, 0x38005e00 }, 386 { 0x418400, 1, 0x04, 0x38005e00 },
1192 { 0x418404, 1, 0x04, 0x71e0ffff }, 387 { 0x418404, 1, 0x04, 0x71e0ffff },
1193 { 0x41840c, 1, 0x04, 0x00001008 }, 388 { 0x41840c, 1, 0x04, 0x00001008 },
@@ -1196,11 +391,21 @@ nv108_grctx_init_gpc_0[] = {
1196 { 0x418450, 6, 0x04, 0x00000000 }, 391 { 0x418450, 6, 0x04, 0x00000000 },
1197 { 0x418468, 1, 0x04, 0x00000001 }, 392 { 0x418468, 1, 0x04, 0x00000001 },
1198 { 0x41846c, 2, 0x04, 0x00000000 }, 393 { 0x41846c, 2, 0x04, 0x00000000 },
394 {}
395};
396
397static const struct nvc0_graph_init
398nv108_grctx_init_gpc_unk_1[] = {
1199 { 0x418600, 1, 0x04, 0x0000007f }, 399 { 0x418600, 1, 0x04, 0x0000007f },
1200 { 0x418684, 1, 0x04, 0x0000001f }, 400 { 0x418684, 1, 0x04, 0x0000001f },
1201 { 0x418700, 1, 0x04, 0x00000002 }, 401 { 0x418700, 1, 0x04, 0x00000002 },
1202 { 0x418704, 2, 0x04, 0x00000080 }, 402 { 0x418704, 2, 0x04, 0x00000080 },
1203 { 0x41870c, 2, 0x04, 0x00000000 }, 403 { 0x41870c, 2, 0x04, 0x00000000 },
404 {}
405};
406
407static const struct nvc0_graph_init
408nv108_grctx_init_setup_0[] = {
1204 { 0x418800, 1, 0x04, 0x7006863a }, 409 { 0x418800, 1, 0x04, 0x7006863a },
1205 { 0x418808, 1, 0x04, 0x00000000 }, 410 { 0x418808, 1, 0x04, 0x00000000 },
1206 { 0x41880c, 1, 0x04, 0x00000030 }, 411 { 0x41880c, 1, 0x04, 0x00000030 },
@@ -1211,10 +416,11 @@ nv108_grctx_init_gpc_0[] = {
1211 { 0x4188e0, 1, 0x04, 0x01000000 }, 416 { 0x4188e0, 1, 0x04, 0x01000000 },
1212 { 0x4188e8, 5, 0x04, 0x00000000 }, 417 { 0x4188e8, 5, 0x04, 0x00000000 },
1213 { 0x4188fc, 1, 0x04, 0x20100058 }, 418 { 0x4188fc, 1, 0x04, 0x20100058 },
1214 { 0x41891c, 1, 0x04, 0x00ff00ff }, 419 {}
1215 { 0x418924, 1, 0x04, 0x00000000 }, 420};
1216 { 0x418928, 1, 0x04, 0x00ffff00 }, 421
1217 { 0x41892c, 1, 0x04, 0x0000ff00 }, 422const struct nvc0_graph_init
423nv108_grctx_init_crstr_0[] = {
1218 { 0x418b00, 1, 0x04, 0x0000001e }, 424 { 0x418b00, 1, 0x04, 0x0000001e },
1219 { 0x418b08, 1, 0x04, 0x0a418820 }, 425 { 0x418b08, 1, 0x04, 0x0a418820 },
1220 { 0x418b0c, 1, 0x04, 0x062080e6 }, 426 { 0x418b0c, 1, 0x04, 0x062080e6 },
@@ -1223,24 +429,36 @@ nv108_grctx_init_gpc_0[] = {
1223 { 0x418b18, 1, 0x04, 0x0a418820 }, 429 { 0x418b18, 1, 0x04, 0x0a418820 },
1224 { 0x418b1c, 1, 0x04, 0x000000e6 }, 430 { 0x418b1c, 1, 0x04, 0x000000e6 },
1225 { 0x418bb8, 1, 0x04, 0x00000103 }, 431 { 0x418bb8, 1, 0x04, 0x00000103 },
432 {}
433};
434
435static const struct nvc0_graph_init
436nv108_grctx_init_gpm_0[] = {
1226 { 0x418c08, 1, 0x04, 0x00000001 }, 437 { 0x418c08, 1, 0x04, 0x00000001 },
1227 { 0x418c10, 8, 0x04, 0x00000000 }, 438 { 0x418c10, 8, 0x04, 0x00000000 },
1228 { 0x418c40, 1, 0x04, 0xffffffff }, 439 { 0x418c40, 1, 0x04, 0xffffffff },
1229 { 0x418c6c, 1, 0x04, 0x00000001 }, 440 { 0x418c6c, 1, 0x04, 0x00000001 },
1230 { 0x418c80, 1, 0x04, 0x2020000c }, 441 { 0x418c80, 1, 0x04, 0x2020000c },
1231 { 0x418c8c, 1, 0x04, 0x00000001 }, 442 { 0x418c8c, 1, 0x04, 0x00000001 },
1232 { 0x418d24, 1, 0x04, 0x00000000 },
1233 { 0x419000, 1, 0x04, 0x00000780 },
1234 { 0x419004, 2, 0x04, 0x00000000 },
1235 { 0x419014, 1, 0x04, 0x00000004 },
1236 {} 443 {}
1237}; 444};
1238 445
1239static struct nvc0_graph_init 446static const struct nvc0_graph_pack
1240nv108_grctx_init_tpc[] = { 447nv108_grctx_pack_gpc[] = {
1241 { 0x419848, 1, 0x04, 0x00000000 }, 448 { nvc0_grctx_init_gpc_unk_0 },
1242 { 0x419864, 1, 0x04, 0x00000129 }, 449 { nv108_grctx_init_prop_0 },
1243 { 0x419888, 1, 0x04, 0x00000000 }, 450 { nv108_grctx_init_gpc_unk_1 },
451 { nv108_grctx_init_setup_0 },
452 { nvc0_grctx_init_zcull_0 },
453 { nv108_grctx_init_crstr_0 },
454 { nv108_grctx_init_gpm_0 },
455 { nvf0_grctx_init_gpc_unk_2 },
456 { nvc0_grctx_init_gcc_0 },
457 {}
458};
459
460static const struct nvc0_graph_init
461nv108_grctx_init_tex_0[] = {
1244 { 0x419a00, 1, 0x04, 0x000100f0 }, 462 { 0x419a00, 1, 0x04, 0x000100f0 },
1245 { 0x419a04, 1, 0x04, 0x00000001 }, 463 { 0x419a04, 1, 0x04, 0x00000001 },
1246 { 0x419a08, 1, 0x04, 0x00000421 }, 464 { 0x419a08, 1, 0x04, 0x00000421 },
@@ -1251,14 +469,11 @@ nv108_grctx_init_tpc[] = {
1251 { 0x419a20, 1, 0x04, 0x00000800 }, 469 { 0x419a20, 1, 0x04, 0x00000800 },
1252 { 0x419a30, 1, 0x04, 0x00000001 }, 470 { 0x419a30, 1, 0x04, 0x00000001 },
1253 { 0x419ac4, 1, 0x04, 0x0037f440 }, 471 { 0x419ac4, 1, 0x04, 0x0037f440 },
1254 { 0x419c00, 1, 0x04, 0x0000001a }, 472 {}
1255 { 0x419c04, 1, 0x04, 0x80000006 }, 473};
1256 { 0x419c08, 1, 0x04, 0x00000002 }, 474
1257 { 0x419c20, 1, 0x04, 0x00000000 }, 475static const struct nvc0_graph_init
1258 { 0x419c24, 1, 0x04, 0x00084210 }, 476nv108_grctx_init_sm_0[] = {
1259 { 0x419c28, 1, 0x04, 0x3efbefbe },
1260 { 0x419ce8, 1, 0x04, 0x00000000 },
1261 { 0x419cf4, 1, 0x04, 0x00000203 },
1262 { 0x419e04, 1, 0x04, 0x00000000 }, 477 { 0x419e04, 1, 0x04, 0x00000000 },
1263 { 0x419e08, 1, 0x04, 0x0000001d }, 478 { 0x419e08, 1, 0x04, 0x0000001d },
1264 { 0x419e0c, 1, 0x04, 0x00000000 }, 479 { 0x419e0c, 1, 0x04, 0x00000000 },
@@ -1272,7 +487,7 @@ nv108_grctx_init_tpc[] = {
1272 { 0x419e68, 1, 0x04, 0x00000002 }, 487 { 0x419e68, 1, 0x04, 0x00000002 },
1273 { 0x419e6c, 12, 0x04, 0x00000000 }, 488 { 0x419e6c, 12, 0x04, 0x00000000 },
1274 { 0x419eac, 1, 0x04, 0x00001f8f }, 489 { 0x419eac, 1, 0x04, 0x00001f8f },
1275 { 0x419eb0, 1, 0x04, 0x0db00da0 }, 490 { 0x419eb0, 1, 0x04, 0x0db00d2f },
1276 { 0x419eb8, 1, 0x04, 0x00000000 }, 491 { 0x419eb8, 1, 0x04, 0x00000000 },
1277 { 0x419ec8, 1, 0x04, 0x0001304f }, 492 { 0x419ec8, 1, 0x04, 0x0001304f },
1278 { 0x419f30, 4, 0x04, 0x00000000 }, 493 { 0x419f30, 4, 0x04, 0x00000000 },
@@ -1285,25 +500,37 @@ nv108_grctx_init_tpc[] = {
1285 {} 500 {}
1286}; 501};
1287 502
1288static struct nvc0_graph_init 503static const struct nvc0_graph_pack
1289nv108_grctx_init_unk[] = { 504nv108_grctx_pack_tpc[] = {
1290 { 0x41be24, 1, 0x04, 0x00000006 }, 505 { nvd7_grctx_init_pe_0 },
506 { nv108_grctx_init_tex_0 },
507 { nvf0_grctx_init_mpc_0 },
508 { nvf0_grctx_init_l1c_0 },
509 { nv108_grctx_init_sm_0 },
510 {}
511};
512
513static const struct nvc0_graph_init
514nv108_grctx_init_cbm_0[] = {
1291 { 0x41bec0, 1, 0x04, 0x10000000 }, 515 { 0x41bec0, 1, 0x04, 0x10000000 },
1292 { 0x41bec4, 1, 0x04, 0x00037f7f }, 516 { 0x41bec4, 1, 0x04, 0x00037f7f },
1293 { 0x41bee4, 1, 0x04, 0x00000000 }, 517 { 0x41bee4, 1, 0x04, 0x00000000 },
1294 { 0x41bef0, 1, 0x04, 0x000003ff }, 518 { 0x41bef0, 1, 0x04, 0x000003ff },
1295 { 0x41bf00, 1, 0x04, 0x0a418820 },
1296 { 0x41bf04, 1, 0x04, 0x062080e6 },
1297 { 0x41bf08, 1, 0x04, 0x020398a4 },
1298 { 0x41bf0c, 1, 0x04, 0x0e629062 },
1299 { 0x41bf10, 1, 0x04, 0x0a418820 },
1300 { 0x41bf14, 1, 0x04, 0x000000e6 },
1301 { 0x41bfd0, 1, 0x04, 0x00900103 },
1302 { 0x41bfe0, 1, 0x04, 0x00400001 },
1303 { 0x41bfe4, 1, 0x04, 0x00000000 },
1304 {} 519 {}
1305}; 520};
1306 521
522static const struct nvc0_graph_pack
523nv108_grctx_pack_ppc[] = {
524 { nve4_grctx_init_pes_0 },
525 { nv108_grctx_init_cbm_0 },
526 { nvd7_grctx_init_wwdx_0 },
527 {}
528};
529
530/*******************************************************************************
531 * PGRAPH context implementation
532 ******************************************************************************/
533
1307static void 534static void
1308nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 535nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
1309{ 536{
@@ -1346,47 +573,6 @@ nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
1346 mmio_list(0x17e920, 0x00090d08, 0, 0); 573 mmio_list(0x17e920, 0x00090d08, 0, 0);
1347} 574}
1348 575
1349static struct nvc0_graph_init *
1350nv108_grctx_init_hub[] = {
1351 nvc0_grctx_init_base,
1352 nv108_grctx_init_unk40xx,
1353 nvf0_grctx_init_unk44xx,
1354 nve4_grctx_init_unk46xx,
1355 nve4_grctx_init_unk47xx,
1356 nv108_grctx_init_unk58xx,
1357 nvf0_grctx_init_unk5bxx,
1358 nvf0_grctx_init_unk60xx,
1359 nv108_grctx_init_unk64xx,
1360 nv108_grctx_init_unk78xx,
1361 nve4_grctx_init_unk80xx,
1362 nv108_grctx_init_unk88xx,
1363 NULL
1364};
1365
1366struct nvc0_graph_init *
1367nv108_grctx_init_gpc[] = {
1368 nv108_grctx_init_gpc_0,
1369 nvc0_grctx_init_gpc_1,
1370 nv108_grctx_init_tpc,
1371 nv108_grctx_init_unk,
1372 NULL
1373};
1374
1375struct nvc0_graph_init
1376nv108_grctx_init_mthd_magic[] = {
1377 { 0x3410, 1, 0x04, 0x8e0e2006 },
1378 { 0x3414, 1, 0x04, 0x00000038 },
1379 {}
1380};
1381
1382static struct nvc0_graph_mthd
1383nv108_grctx_init_mthd[] = {
1384 { 0xa197, nv108_grctx_init_a197, },
1385 { 0x902d, nvc0_grctx_init_902d, },
1386 { 0x902d, nv108_grctx_init_mthd_magic, },
1387 {}
1388};
1389
1390struct nouveau_oclass * 576struct nouveau_oclass *
1391nv108_grctx_oclass = &(struct nvc0_grctx_oclass) { 577nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
1392 .base.handle = NV_ENGCTX(GR, 0x08), 578 .base.handle = NV_ENGCTX(GR, 0x08),
@@ -1398,11 +584,14 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
1398 .rd32 = _nouveau_graph_context_rd32, 584 .rd32 = _nouveau_graph_context_rd32,
1399 .wr32 = _nouveau_graph_context_wr32, 585 .wr32 = _nouveau_graph_context_wr32,
1400 }, 586 },
1401 .main = nve4_grctx_generate_main, 587 .main = nve4_grctx_generate_main,
1402 .mods = nv108_grctx_generate_mods, 588 .mods = nv108_grctx_generate_mods,
1403 .unkn = nve4_grctx_generate_unkn, 589 .unkn = nve4_grctx_generate_unkn,
1404 .hub = nv108_grctx_init_hub, 590 .hub = nv108_grctx_pack_hub,
1405 .gpc = nv108_grctx_init_gpc, 591 .gpc = nv108_grctx_pack_gpc,
1406 .icmd = nv108_grctx_init_icmd, 592 .zcull = nvc0_grctx_pack_zcull,
1407 .mthd = nv108_grctx_init_mthd, 593 .tpc = nv108_grctx_pack_tpc,
594 .ppc = nv108_grctx_pack_ppc,
595 .icmd = nv108_grctx_pack_icmd,
596 .mthd = nvf0_grctx_pack_mthd,
1408}.base; 597}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
index fe67415c3e17..833a96508c4e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
@@ -22,10 +22,14 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27struct nvc0_graph_init 27/*******************************************************************************
28nvc0_grctx_init_icmd[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nvc0_grctx_init_icmd_0[] = {
29 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
30 { 0x0000a9, 1, 0x01, 0x0000ffff }, 34 { 0x0000a9, 1, 0x01, 0x0000ffff },
31 { 0x000038, 1, 0x01, 0x0fac6881 }, 35 { 0x000038, 1, 0x01, 0x0fac6881 },
@@ -140,8 +144,7 @@ nvc0_grctx_init_icmd[] = {
140 { 0x000586, 1, 0x01, 0x00000040 }, 144 { 0x000586, 1, 0x01, 0x00000040 },
141 { 0x000582, 2, 0x01, 0x00000080 }, 145 { 0x000582, 2, 0x01, 0x00000080 },
142 { 0x0005c2, 1, 0x01, 0x00000001 }, 146 { 0x0005c2, 1, 0x01, 0x00000001 },
143 { 0x000638, 1, 0x01, 0x00000001 }, 147 { 0x000638, 2, 0x01, 0x00000001 },
144 { 0x000639, 1, 0x01, 0x00000001 },
145 { 0x00063a, 1, 0x01, 0x00000002 }, 148 { 0x00063a, 1, 0x01, 0x00000002 },
146 { 0x00063b, 2, 0x01, 0x00000001 }, 149 { 0x00063b, 2, 0x01, 0x00000001 },
147 { 0x00063d, 1, 0x01, 0x00000002 }, 150 { 0x00063d, 1, 0x01, 0x00000002 },
@@ -201,15 +204,13 @@ nvc0_grctx_init_icmd[] = {
201 { 0x000787, 1, 0x01, 0x000000cf }, 204 { 0x000787, 1, 0x01, 0x000000cf },
202 { 0x00078c, 1, 0x01, 0x00000008 }, 205 { 0x00078c, 1, 0x01, 0x00000008 },
203 { 0x000792, 1, 0x01, 0x00000001 }, 206 { 0x000792, 1, 0x01, 0x00000001 },
204 { 0x000794, 1, 0x01, 0x00000001 }, 207 { 0x000794, 3, 0x01, 0x00000001 },
205 { 0x000795, 2, 0x01, 0x00000001 },
206 { 0x000797, 1, 0x01, 0x000000cf }, 208 { 0x000797, 1, 0x01, 0x000000cf },
207 { 0x000836, 1, 0x01, 0x00000001 }, 209 { 0x000836, 1, 0x01, 0x00000001 },
208 { 0x00079a, 1, 0x01, 0x00000002 }, 210 { 0x00079a, 1, 0x01, 0x00000002 },
209 { 0x000833, 1, 0x01, 0x04444480 }, 211 { 0x000833, 1, 0x01, 0x04444480 },
210 { 0x0007a1, 1, 0x01, 0x00000001 }, 212 { 0x0007a1, 1, 0x01, 0x00000001 },
211 { 0x0007a3, 1, 0x01, 0x00000001 }, 213 { 0x0007a3, 3, 0x01, 0x00000001 },
212 { 0x0007a4, 2, 0x01, 0x00000001 },
213 { 0x000831, 1, 0x01, 0x00000004 }, 214 { 0x000831, 1, 0x01, 0x00000004 },
214 { 0x00080c, 1, 0x01, 0x00000002 }, 215 { 0x00080c, 1, 0x01, 0x00000002 },
215 { 0x00080d, 2, 0x01, 0x00000100 }, 216 { 0x00080d, 2, 0x01, 0x00000100 },
@@ -235,14 +236,12 @@ nvc0_grctx_init_icmd[] = {
235 { 0x0006b1, 1, 0x01, 0x00000011 }, 236 { 0x0006b1, 1, 0x01, 0x00000011 },
236 { 0x00078c, 1, 0x01, 0x00000008 }, 237 { 0x00078c, 1, 0x01, 0x00000008 },
237 { 0x000792, 1, 0x01, 0x00000001 }, 238 { 0x000792, 1, 0x01, 0x00000001 },
238 { 0x000794, 1, 0x01, 0x00000001 }, 239 { 0x000794, 3, 0x01, 0x00000001 },
239 { 0x000795, 2, 0x01, 0x00000001 },
240 { 0x000797, 1, 0x01, 0x000000cf }, 240 { 0x000797, 1, 0x01, 0x000000cf },
241 { 0x00079a, 1, 0x01, 0x00000002 }, 241 { 0x00079a, 1, 0x01, 0x00000002 },
242 { 0x000833, 1, 0x01, 0x04444480 }, 242 { 0x000833, 1, 0x01, 0x04444480 },
243 { 0x0007a1, 1, 0x01, 0x00000001 }, 243 { 0x0007a1, 1, 0x01, 0x00000001 },
244 { 0x0007a3, 1, 0x01, 0x00000001 }, 244 { 0x0007a3, 3, 0x01, 0x00000001 },
245 { 0x0007a4, 2, 0x01, 0x00000001 },
246 { 0x000831, 1, 0x01, 0x00000004 }, 245 { 0x000831, 1, 0x01, 0x00000004 },
247 { 0x01e100, 1, 0x01, 0x00000001 }, 246 { 0x01e100, 1, 0x01, 0x00000001 },
248 { 0x001000, 1, 0x01, 0x00000014 }, 247 { 0x001000, 1, 0x01, 0x00000014 },
@@ -267,8 +266,14 @@ nvc0_grctx_init_icmd[] = {
267 {} 266 {}
268}; 267};
269 268
270struct nvc0_graph_init 269const struct nvc0_graph_pack
271nvc0_grctx_init_9097[] = { 270nvc0_grctx_pack_icmd[] = {
271 { nvc0_grctx_init_icmd_0 },
272 {}
273};
274
275static const struct nvc0_graph_init
276nvc0_grctx_init_9097_0[] = {
272 { 0x000800, 8, 0x40, 0x00000000 }, 277 { 0x000800, 8, 0x40, 0x00000000 },
273 { 0x000804, 8, 0x40, 0x00000000 }, 278 { 0x000804, 8, 0x40, 0x00000000 },
274 { 0x000808, 8, 0x40, 0x00000400 }, 279 { 0x000808, 8, 0x40, 0x00000400 },
@@ -516,8 +521,7 @@ nvc0_grctx_init_9097[] = {
516 { 0x001350, 1, 0x04, 0x00000002 }, 521 { 0x001350, 1, 0x04, 0x00000002 },
517 { 0x001358, 1, 0x04, 0x00000001 }, 522 { 0x001358, 1, 0x04, 0x00000001 },
518 { 0x0012e4, 1, 0x04, 0x00000000 }, 523 { 0x0012e4, 1, 0x04, 0x00000000 },
519 { 0x00131c, 1, 0x04, 0x00000000 }, 524 { 0x00131c, 4, 0x04, 0x00000000 },
520 { 0x001320, 3, 0x04, 0x00000000 },
521 { 0x0019c0, 1, 0x04, 0x00000000 }, 525 { 0x0019c0, 1, 0x04, 0x00000000 },
522 { 0x001140, 1, 0x04, 0x00000000 }, 526 { 0x001140, 1, 0x04, 0x00000000 },
523 { 0x0019c4, 1, 0x04, 0x00000000 }, 527 { 0x0019c4, 1, 0x04, 0x00000000 },
@@ -571,8 +575,8 @@ nvc0_grctx_init_9097[] = {
571 {} 575 {}
572}; 576};
573 577
574struct nvc0_graph_init 578const struct nvc0_graph_init
575nvc0_grctx_init_902d[] = { 579nvc0_grctx_init_902d_0[] = {
576 { 0x000200, 1, 0x04, 0x000000cf }, 580 { 0x000200, 1, 0x04, 0x000000cf },
577 { 0x000204, 1, 0x04, 0x00000001 }, 581 { 0x000204, 1, 0x04, 0x00000001 },
578 { 0x000208, 1, 0x04, 0x00000020 }, 582 { 0x000208, 1, 0x04, 0x00000020 },
@@ -590,8 +594,8 @@ nvc0_grctx_init_902d[] = {
590 {} 594 {}
591}; 595};
592 596
593struct nvc0_graph_init 597const struct nvc0_graph_init
594nvc0_grctx_init_9039[] = { 598nvc0_grctx_init_9039_0[] = {
595 { 0x00030c, 3, 0x04, 0x00000000 }, 599 { 0x00030c, 3, 0x04, 0x00000000 },
596 { 0x000320, 1, 0x04, 0x00000000 }, 600 { 0x000320, 1, 0x04, 0x00000000 },
597 { 0x000238, 2, 0x04, 0x00000000 }, 601 { 0x000238, 2, 0x04, 0x00000000 },
@@ -599,8 +603,8 @@ nvc0_grctx_init_9039[] = {
599 {} 603 {}
600}; 604};
601 605
602struct nvc0_graph_init 606const struct nvc0_graph_init
603nvc0_grctx_init_90c0[] = { 607nvc0_grctx_init_90c0_0[] = {
604 { 0x00270c, 8, 0x20, 0x00000000 }, 608 { 0x00270c, 8, 0x20, 0x00000000 },
605 { 0x00030c, 1, 0x04, 0x00000001 }, 609 { 0x00030c, 1, 0x04, 0x00000001 },
606 { 0x001944, 1, 0x04, 0x00000000 }, 610 { 0x001944, 1, 0x04, 0x00000000 },
@@ -617,38 +621,44 @@ nvc0_grctx_init_90c0[] = {
617 {} 621 {}
618}; 622};
619 623
620struct nvc0_graph_init 624const struct nvc0_graph_pack
621nvc0_grctx_init_base[] = { 625nvc0_grctx_pack_mthd[] = {
626 { nvc0_grctx_init_9097_0, 0x9097 },
627 { nvc0_grctx_init_902d_0, 0x902d },
628 { nvc0_grctx_init_9039_0, 0x9039 },
629 { nvc0_grctx_init_90c0_0, 0x90c0 },
630 {}
631};
632
633const struct nvc0_graph_init
634nvc0_grctx_init_main_0[] = {
622 { 0x400204, 2, 0x04, 0x00000000 }, 635 { 0x400204, 2, 0x04, 0x00000000 },
623 {} 636 {}
624}; 637};
625 638
626struct nvc0_graph_init 639const struct nvc0_graph_init
627nvc0_grctx_init_unk40xx[] = { 640nvc0_grctx_init_fe_0[] = {
628 { 0x404004, 10, 0x04, 0x00000000 }, 641 { 0x404004, 11, 0x04, 0x00000000 },
629 { 0x404044, 1, 0x04, 0x00000000 }, 642 { 0x404044, 1, 0x04, 0x00000000 },
630 { 0x404094, 1, 0x04, 0x00000000 }, 643 { 0x404094, 13, 0x04, 0x00000000 },
631 { 0x404098, 12, 0x04, 0x00000000 },
632 { 0x4040c8, 1, 0x04, 0xf0000087 }, 644 { 0x4040c8, 1, 0x04, 0xf0000087 },
633 { 0x4040d0, 6, 0x04, 0x00000000 }, 645 { 0x4040d0, 6, 0x04, 0x00000000 },
634 { 0x4040e8, 1, 0x04, 0x00001000 }, 646 { 0x4040e8, 1, 0x04, 0x00001000 },
635 { 0x4040f8, 1, 0x04, 0x00000000 }, 647 { 0x4040f8, 1, 0x04, 0x00000000 },
636 { 0x404130, 1, 0x04, 0x00000000 }, 648 { 0x404130, 2, 0x04, 0x00000000 },
637 { 0x404134, 1, 0x04, 0x00000000 },
638 { 0x404138, 1, 0x04, 0x20000040 }, 649 { 0x404138, 1, 0x04, 0x20000040 },
639 { 0x404150, 1, 0x04, 0x0000002e }, 650 { 0x404150, 1, 0x04, 0x0000002e },
640 { 0x404154, 1, 0x04, 0x00000400 }, 651 { 0x404154, 1, 0x04, 0x00000400 },
641 { 0x404158, 1, 0x04, 0x00000200 }, 652 { 0x404158, 1, 0x04, 0x00000200 },
642 { 0x404164, 1, 0x04, 0x00000055 }, 653 { 0x404164, 1, 0x04, 0x00000055 },
643 { 0x404168, 1, 0x04, 0x00000000 }, 654 { 0x404168, 1, 0x04, 0x00000000 },
644 { 0x404174, 1, 0x04, 0x00000000 }, 655 { 0x404174, 3, 0x04, 0x00000000 },
645 { 0x404178, 2, 0x04, 0x00000000 },
646 { 0x404200, 8, 0x04, 0x00000000 }, 656 { 0x404200, 8, 0x04, 0x00000000 },
647 {} 657 {}
648}; 658};
649 659
650struct nvc0_graph_init 660const struct nvc0_graph_init
651nvc0_grctx_init_unk44xx[] = { 661nvc0_grctx_init_pri_0[] = {
652 { 0x404404, 14, 0x04, 0x00000000 }, 662 { 0x404404, 14, 0x04, 0x00000000 },
653 { 0x404460, 2, 0x04, 0x00000000 }, 663 { 0x404460, 2, 0x04, 0x00000000 },
654 { 0x404468, 1, 0x04, 0x00ffffff }, 664 { 0x404468, 1, 0x04, 0x00ffffff },
@@ -658,8 +668,8 @@ nvc0_grctx_init_unk44xx[] = {
658 {} 668 {}
659}; 669};
660 670
661struct nvc0_graph_init 671const struct nvc0_graph_init
662nvc0_grctx_init_unk46xx[] = { 672nvc0_grctx_init_memfmt_0[] = {
663 { 0x404604, 1, 0x04, 0x00000015 }, 673 { 0x404604, 1, 0x04, 0x00000015 },
664 { 0x404608, 1, 0x04, 0x00000000 }, 674 { 0x404608, 1, 0x04, 0x00000000 },
665 { 0x40460c, 1, 0x04, 0x00002e00 }, 675 { 0x40460c, 1, 0x04, 0x00002e00 },
@@ -674,19 +684,14 @@ nvc0_grctx_init_unk46xx[] = {
674 { 0x4046a0, 1, 0x04, 0x007f0080 }, 684 { 0x4046a0, 1, 0x04, 0x007f0080 },
675 { 0x4046a4, 18, 0x04, 0x00000000 }, 685 { 0x4046a4, 18, 0x04, 0x00000000 },
676 { 0x4046f0, 2, 0x04, 0x00000000 }, 686 { 0x4046f0, 2, 0x04, 0x00000000 },
677 {}
678};
679
680struct nvc0_graph_init
681nvc0_grctx_init_unk47xx[] = {
682 { 0x404700, 13, 0x04, 0x00000000 }, 687 { 0x404700, 13, 0x04, 0x00000000 },
683 { 0x404734, 1, 0x04, 0x00000100 }, 688 { 0x404734, 1, 0x04, 0x00000100 },
684 { 0x404738, 8, 0x04, 0x00000000 }, 689 { 0x404738, 8, 0x04, 0x00000000 },
685 {} 690 {}
686}; 691};
687 692
688struct nvc0_graph_init 693static const struct nvc0_graph_init
689nvc0_grctx_init_unk58xx[] = { 694nvc0_grctx_init_ds_0[] = {
690 { 0x405800, 1, 0x04, 0x078000bf }, 695 { 0x405800, 1, 0x04, 0x078000bf },
691 { 0x405830, 1, 0x04, 0x02180000 }, 696 { 0x405830, 1, 0x04, 0x02180000 },
692 { 0x405834, 2, 0x04, 0x00000000 }, 697 { 0x405834, 2, 0x04, 0x00000000 },
@@ -697,23 +702,18 @@ nvc0_grctx_init_unk58xx[] = {
697 {} 702 {}
698}; 703};
699 704
700struct nvc0_graph_init 705static const struct nvc0_graph_init
701nvc0_grctx_init_unk60xx[] = { 706nvc0_grctx_init_pd_0[] = {
702 { 0x406020, 1, 0x04, 0x000103c1 }, 707 { 0x406020, 1, 0x04, 0x000103c1 },
703 { 0x406028, 4, 0x04, 0x00000001 }, 708 { 0x406028, 4, 0x04, 0x00000001 },
704 {}
705};
706
707struct nvc0_graph_init
708nvc0_grctx_init_unk64xx[] = {
709 { 0x4064a8, 1, 0x04, 0x00000000 }, 709 { 0x4064a8, 1, 0x04, 0x00000000 },
710 { 0x4064ac, 1, 0x04, 0x00003fff }, 710 { 0x4064ac, 1, 0x04, 0x00003fff },
711 { 0x4064b4, 2, 0x04, 0x00000000 }, 711 { 0x4064b4, 2, 0x04, 0x00000000 },
712 {} 712 {}
713}; 713};
714 714
715struct nvc0_graph_init 715const struct nvc0_graph_init
716nvc0_grctx_init_unk78xx[] = { 716nvc0_grctx_init_rstr2d_0[] = {
717 { 0x407804, 1, 0x04, 0x00000023 }, 717 { 0x407804, 1, 0x04, 0x00000023 },
718 { 0x40780c, 1, 0x04, 0x0a418820 }, 718 { 0x40780c, 1, 0x04, 0x0a418820 },
719 { 0x407810, 1, 0x04, 0x062080e6 }, 719 { 0x407810, 1, 0x04, 0x062080e6 },
@@ -725,8 +725,8 @@ nvc0_grctx_init_unk78xx[] = {
725 {} 725 {}
726}; 726};
727 727
728struct nvc0_graph_init 728const struct nvc0_graph_init
729nvc0_grctx_init_unk80xx[] = { 729nvc0_grctx_init_scc_0[] = {
730 { 0x408000, 2, 0x04, 0x00000000 }, 730 { 0x408000, 2, 0x04, 0x00000000 },
731 { 0x408008, 1, 0x04, 0x00000018 }, 731 { 0x408008, 1, 0x04, 0x00000018 },
732 { 0x40800c, 2, 0x04, 0x00000000 }, 732 { 0x40800c, 2, 0x04, 0x00000000 },
@@ -736,8 +736,8 @@ nvc0_grctx_init_unk80xx[] = {
736 {} 736 {}
737}; 737};
738 738
739struct nvc0_graph_init 739static const struct nvc0_graph_init
740nvc0_grctx_init_rop[] = { 740nvc0_grctx_init_be_0[] = {
741 { 0x408800, 1, 0x04, 0x02802a3c }, 741 { 0x408800, 1, 0x04, 0x02802a3c },
742 { 0x408804, 1, 0x04, 0x00000040 }, 742 { 0x408804, 1, 0x04, 0x00000040 },
743 { 0x408808, 1, 0x04, 0x0003e00d }, 743 { 0x408808, 1, 0x04, 0x0003e00d },
@@ -748,9 +748,28 @@ nvc0_grctx_init_rop[] = {
748 {} 748 {}
749}; 749};
750 750
751struct nvc0_graph_init 751const struct nvc0_graph_pack
752nvc0_grctx_init_gpc_0[] = { 752nvc0_grctx_pack_hub[] = {
753 { nvc0_grctx_init_main_0 },
754 { nvc0_grctx_init_fe_0 },
755 { nvc0_grctx_init_pri_0 },
756 { nvc0_grctx_init_memfmt_0 },
757 { nvc0_grctx_init_ds_0 },
758 { nvc0_grctx_init_pd_0 },
759 { nvc0_grctx_init_rstr2d_0 },
760 { nvc0_grctx_init_scc_0 },
761 { nvc0_grctx_init_be_0 },
762 {}
763};
764
765const struct nvc0_graph_init
766nvc0_grctx_init_gpc_unk_0[] = {
753 { 0x418380, 1, 0x04, 0x00000016 }, 767 { 0x418380, 1, 0x04, 0x00000016 },
768 {}
769};
770
771const struct nvc0_graph_init
772nvc0_grctx_init_prop_0[] = {
754 { 0x418400, 1, 0x04, 0x38004e00 }, 773 { 0x418400, 1, 0x04, 0x38004e00 },
755 { 0x418404, 1, 0x04, 0x71e0ffff }, 774 { 0x418404, 1, 0x04, 0x71e0ffff },
756 { 0x418408, 1, 0x04, 0x00000000 }, 775 { 0x418408, 1, 0x04, 0x00000000 },
@@ -760,6 +779,11 @@ nvc0_grctx_init_gpc_0[] = {
760 { 0x418450, 6, 0x04, 0x00000000 }, 779 { 0x418450, 6, 0x04, 0x00000000 },
761 { 0x418468, 1, 0x04, 0x00000001 }, 780 { 0x418468, 1, 0x04, 0x00000001 },
762 { 0x41846c, 2, 0x04, 0x00000000 }, 781 { 0x41846c, 2, 0x04, 0x00000000 },
782 {}
783};
784
785const struct nvc0_graph_init
786nvc0_grctx_init_gpc_unk_1[] = {
763 { 0x418600, 1, 0x04, 0x0000001f }, 787 { 0x418600, 1, 0x04, 0x0000001f },
764 { 0x418684, 1, 0x04, 0x0000000f }, 788 { 0x418684, 1, 0x04, 0x0000000f },
765 { 0x418700, 1, 0x04, 0x00000002 }, 789 { 0x418700, 1, 0x04, 0x00000002 },
@@ -767,6 +791,11 @@ nvc0_grctx_init_gpc_0[] = {
767 { 0x418708, 1, 0x04, 0x00000000 }, 791 { 0x418708, 1, 0x04, 0x00000000 },
768 { 0x41870c, 1, 0x04, 0x07c80000 }, 792 { 0x41870c, 1, 0x04, 0x07c80000 },
769 { 0x418710, 1, 0x04, 0x00000000 }, 793 { 0x418710, 1, 0x04, 0x00000000 },
794 {}
795};
796
797static const struct nvc0_graph_init
798nvc0_grctx_init_setup_0[] = {
770 { 0x418800, 1, 0x04, 0x0006860a }, 799 { 0x418800, 1, 0x04, 0x0006860a },
771 { 0x418808, 3, 0x04, 0x00000000 }, 800 { 0x418808, 3, 0x04, 0x00000000 },
772 { 0x418828, 1, 0x04, 0x00008442 }, 801 { 0x418828, 1, 0x04, 0x00008442 },
@@ -775,10 +804,20 @@ nvc0_grctx_init_gpc_0[] = {
775 { 0x4188e0, 1, 0x04, 0x01000000 }, 804 { 0x4188e0, 1, 0x04, 0x01000000 },
776 { 0x4188e8, 5, 0x04, 0x00000000 }, 805 { 0x4188e8, 5, 0x04, 0x00000000 },
777 { 0x4188fc, 1, 0x04, 0x00100000 }, 806 { 0x4188fc, 1, 0x04, 0x00100000 },
807 {}
808};
809
810const struct nvc0_graph_init
811nvc0_grctx_init_zcull_0[] = {
778 { 0x41891c, 1, 0x04, 0x00ff00ff }, 812 { 0x41891c, 1, 0x04, 0x00ff00ff },
779 { 0x418924, 1, 0x04, 0x00000000 }, 813 { 0x418924, 1, 0x04, 0x00000000 },
780 { 0x418928, 1, 0x04, 0x00ffff00 }, 814 { 0x418928, 1, 0x04, 0x00ffff00 },
781 { 0x41892c, 1, 0x04, 0x0000ff00 }, 815 { 0x41892c, 1, 0x04, 0x0000ff00 },
816 {}
817};
818
819const struct nvc0_graph_init
820nvc0_grctx_init_crstr_0[] = {
782 { 0x418b00, 1, 0x04, 0x00000000 }, 821 { 0x418b00, 1, 0x04, 0x00000000 },
783 { 0x418b08, 1, 0x04, 0x0a418820 }, 822 { 0x418b08, 1, 0x04, 0x0a418820 },
784 { 0x418b0c, 1, 0x04, 0x062080e6 }, 823 { 0x418b0c, 1, 0x04, 0x062080e6 },
@@ -787,18 +826,41 @@ nvc0_grctx_init_gpc_0[] = {
787 { 0x418b18, 1, 0x04, 0x0a418820 }, 826 { 0x418b18, 1, 0x04, 0x0a418820 },
788 { 0x418b1c, 1, 0x04, 0x000000e6 }, 827 { 0x418b1c, 1, 0x04, 0x000000e6 },
789 { 0x418bb8, 1, 0x04, 0x00000103 }, 828 { 0x418bb8, 1, 0x04, 0x00000103 },
829 {}
830};
831
832const struct nvc0_graph_init
833nvc0_grctx_init_gpm_0[] = {
790 { 0x418c08, 1, 0x04, 0x00000001 }, 834 { 0x418c08, 1, 0x04, 0x00000001 },
791 { 0x418c10, 8, 0x04, 0x00000000 }, 835 { 0x418c10, 8, 0x04, 0x00000000 },
792 { 0x418c80, 1, 0x04, 0x20200004 }, 836 { 0x418c80, 1, 0x04, 0x20200004 },
793 { 0x418c8c, 1, 0x04, 0x00000001 }, 837 { 0x418c8c, 1, 0x04, 0x00000001 },
838 {}
839};
840
841const struct nvc0_graph_init
842nvc0_grctx_init_gcc_0[] = {
794 { 0x419000, 1, 0x04, 0x00000780 }, 843 { 0x419000, 1, 0x04, 0x00000780 },
795 { 0x419004, 2, 0x04, 0x00000000 }, 844 { 0x419004, 2, 0x04, 0x00000000 },
796 { 0x419014, 1, 0x04, 0x00000004 }, 845 { 0x419014, 1, 0x04, 0x00000004 },
797 {} 846 {}
798}; 847};
799 848
800struct nvc0_graph_init 849const struct nvc0_graph_pack
801nvc0_grctx_init_gpc_1[] = { 850nvc0_grctx_pack_gpc[] = {
851 { nvc0_grctx_init_gpc_unk_0 },
852 { nvc0_grctx_init_prop_0 },
853 { nvc0_grctx_init_gpc_unk_1 },
854 { nvc0_grctx_init_setup_0 },
855 { nvc0_grctx_init_zcull_0 },
856 { nvc0_grctx_init_crstr_0 },
857 { nvc0_grctx_init_gpm_0 },
858 { nvc0_grctx_init_gcc_0 },
859 {}
860};
861
862static const struct nvc0_graph_init
863nvc0_grctx_init_zcullr_0[] = {
802 { 0x418a00, 3, 0x04, 0x00000000 }, 864 { 0x418a00, 3, 0x04, 0x00000000 },
803 { 0x418a0c, 1, 0x04, 0x00010000 }, 865 { 0x418a0c, 1, 0x04, 0x00010000 },
804 { 0x418a10, 3, 0x04, 0x00000000 }, 866 { 0x418a10, 3, 0x04, 0x00000000 },
@@ -826,19 +888,35 @@ nvc0_grctx_init_gpc_1[] = {
826 {} 888 {}
827}; 889};
828 890
829struct nvc0_graph_init 891const struct nvc0_graph_pack
830nvc0_grctx_init_tpc[] = { 892nvc0_grctx_pack_zcull[] = {
893 { nvc0_grctx_init_zcullr_0 },
894 {}
895};
896
897const struct nvc0_graph_init
898nvc0_grctx_init_pe_0[] = {
831 { 0x419818, 1, 0x04, 0x00000000 }, 899 { 0x419818, 1, 0x04, 0x00000000 },
832 { 0x41983c, 1, 0x04, 0x00038bc7 }, 900 { 0x41983c, 1, 0x04, 0x00038bc7 },
833 { 0x419848, 1, 0x04, 0x00000000 }, 901 { 0x419848, 1, 0x04, 0x00000000 },
834 { 0x419864, 1, 0x04, 0x0000012a }, 902 { 0x419864, 1, 0x04, 0x0000012a },
835 { 0x419888, 1, 0x04, 0x00000000 }, 903 { 0x419888, 1, 0x04, 0x00000000 },
904 {}
905};
906
907static const struct nvc0_graph_init
908nvc0_grctx_init_tex_0[] = {
836 { 0x419a00, 1, 0x04, 0x000001f0 }, 909 { 0x419a00, 1, 0x04, 0x000001f0 },
837 { 0x419a04, 1, 0x04, 0x00000001 }, 910 { 0x419a04, 1, 0x04, 0x00000001 },
838 { 0x419a08, 1, 0x04, 0x00000023 }, 911 { 0x419a08, 1, 0x04, 0x00000023 },
839 { 0x419a0c, 1, 0x04, 0x00020000 }, 912 { 0x419a0c, 1, 0x04, 0x00020000 },
840 { 0x419a10, 1, 0x04, 0x00000000 }, 913 { 0x419a10, 1, 0x04, 0x00000000 },
841 { 0x419a14, 1, 0x04, 0x00000200 }, 914 { 0x419a14, 1, 0x04, 0x00000200 },
915 {}
916};
917
918const struct nvc0_graph_init
919nvc0_grctx_init_wwdx_0[] = {
842 { 0x419b00, 1, 0x04, 0x0a418820 }, 920 { 0x419b00, 1, 0x04, 0x0a418820 },
843 { 0x419b04, 1, 0x04, 0x062080e6 }, 921 { 0x419b04, 1, 0x04, 0x062080e6 },
844 { 0x419b08, 1, 0x04, 0x020398a4 }, 922 { 0x419b08, 1, 0x04, 0x020398a4 },
@@ -848,15 +926,35 @@ nvc0_grctx_init_tpc[] = {
848 { 0x419bd0, 1, 0x04, 0x00900103 }, 926 { 0x419bd0, 1, 0x04, 0x00900103 },
849 { 0x419be0, 1, 0x04, 0x00000001 }, 927 { 0x419be0, 1, 0x04, 0x00000001 },
850 { 0x419be4, 1, 0x04, 0x00000000 }, 928 { 0x419be4, 1, 0x04, 0x00000000 },
929 {}
930};
931
932const struct nvc0_graph_init
933nvc0_grctx_init_mpc_0[] = {
851 { 0x419c00, 1, 0x04, 0x00000002 }, 934 { 0x419c00, 1, 0x04, 0x00000002 },
852 { 0x419c04, 1, 0x04, 0x00000006 }, 935 { 0x419c04, 1, 0x04, 0x00000006 },
853 { 0x419c08, 1, 0x04, 0x00000002 }, 936 { 0x419c08, 1, 0x04, 0x00000002 },
854 { 0x419c20, 1, 0x04, 0x00000000 }, 937 { 0x419c20, 1, 0x04, 0x00000000 },
938 {}
939};
940
941static const struct nvc0_graph_init
942nvc0_grctx_init_l1c_0[] = {
855 { 0x419cb0, 1, 0x04, 0x00060048 }, 943 { 0x419cb0, 1, 0x04, 0x00060048 },
856 { 0x419ce8, 1, 0x04, 0x00000000 }, 944 { 0x419ce8, 1, 0x04, 0x00000000 },
857 { 0x419cf4, 1, 0x04, 0x00000183 }, 945 { 0x419cf4, 1, 0x04, 0x00000183 },
946 {}
947};
948
949const struct nvc0_graph_init
950nvc0_grctx_init_tpccs_0[] = {
858 { 0x419d20, 1, 0x04, 0x02180000 }, 951 { 0x419d20, 1, 0x04, 0x02180000 },
859 { 0x419d24, 1, 0x04, 0x00001fff }, 952 { 0x419d24, 1, 0x04, 0x00001fff },
953 {}
954};
955
956static const struct nvc0_graph_init
957nvc0_grctx_init_sm_0[] = {
860 { 0x419e04, 3, 0x04, 0x00000000 }, 958 { 0x419e04, 3, 0x04, 0x00000000 },
861 { 0x419e10, 1, 0x04, 0x00000002 }, 959 { 0x419e10, 1, 0x04, 0x00000002 },
862 { 0x419e44, 1, 0x04, 0x001beff2 }, 960 { 0x419e44, 1, 0x04, 0x001beff2 },
@@ -868,6 +966,22 @@ nvc0_grctx_init_tpc[] = {
868 {} 966 {}
869}; 967};
870 968
969const struct nvc0_graph_pack
970nvc0_grctx_pack_tpc[] = {
971 { nvc0_grctx_init_pe_0 },
972 { nvc0_grctx_init_tex_0 },
973 { nvc0_grctx_init_wwdx_0 },
974 { nvc0_grctx_init_mpc_0 },
975 { nvc0_grctx_init_l1c_0 },
976 { nvc0_grctx_init_tpccs_0 },
977 { nvc0_grctx_init_sm_0 },
978 {}
979};
980
981/*******************************************************************************
982 * PGRAPH context implementation
983 ******************************************************************************/
984
871void 985void
872nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 986nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
873{ 987{
@@ -1055,14 +1169,14 @@ void
1055nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 1169nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
1056{ 1170{
1057 struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; 1171 struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
1058 int i;
1059 1172
1060 nv_mask(priv, 0x000260, 0x00000001, 0x00000000); 1173 nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
1061 1174
1062 for (i = 0; oclass->hub[i]; i++) 1175 nvc0_graph_mmio(priv, oclass->hub);
1063 nvc0_graph_mmio(priv, oclass->hub[i]); 1176 nvc0_graph_mmio(priv, oclass->gpc);
1064 for (i = 0; oclass->gpc[i]; i++) 1177 nvc0_graph_mmio(priv, oclass->zcull);
1065 nvc0_graph_mmio(priv, oclass->gpc[i]); 1178 nvc0_graph_mmio(priv, oclass->tpc);
1179 nvc0_graph_mmio(priv, oclass->ppc);
1066 1180
1067 nv_wr32(priv, 0x404154, 0x00000000); 1181 nv_wr32(priv, 0x404154, 0x00000000);
1068 1182
@@ -1182,46 +1296,6 @@ done:
1182 return ret; 1296 return ret;
1183} 1297}
1184 1298
1185struct nvc0_graph_init *
1186nvc0_grctx_init_hub[] = {
1187 nvc0_grctx_init_base,
1188 nvc0_grctx_init_unk40xx,
1189 nvc0_grctx_init_unk44xx,
1190 nvc0_grctx_init_unk46xx,
1191 nvc0_grctx_init_unk47xx,
1192 nvc0_grctx_init_unk58xx,
1193 nvc0_grctx_init_unk60xx,
1194 nvc0_grctx_init_unk64xx,
1195 nvc0_grctx_init_unk78xx,
1196 nvc0_grctx_init_unk80xx,
1197 nvc0_grctx_init_rop,
1198 NULL
1199};
1200
1201static struct nvc0_graph_init *
1202nvc0_grctx_init_gpc[] = {
1203 nvc0_grctx_init_gpc_0,
1204 nvc0_grctx_init_gpc_1,
1205 nvc0_grctx_init_tpc,
1206 NULL
1207};
1208
1209struct nvc0_graph_init
1210nvc0_grctx_init_mthd_magic[] = {
1211 { 0x3410, 1, 0x04, 0x00000000 },
1212 {}
1213};
1214
1215struct nvc0_graph_mthd
1216nvc0_grctx_init_mthd[] = {
1217 { 0x9097, nvc0_grctx_init_9097, },
1218 { 0x902d, nvc0_grctx_init_902d, },
1219 { 0x9039, nvc0_grctx_init_9039, },
1220 { 0x90c0, nvc0_grctx_init_90c0, },
1221 { 0x902d, nvc0_grctx_init_mthd_magic, },
1222 {}
1223};
1224
1225struct nouveau_oclass * 1299struct nouveau_oclass *
1226nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) { 1300nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
1227 .base.handle = NV_ENGCTX(GR, 0xc0), 1301 .base.handle = NV_ENGCTX(GR, 0xc0),
@@ -1233,11 +1307,13 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
1233 .rd32 = _nouveau_graph_context_rd32, 1307 .rd32 = _nouveau_graph_context_rd32,
1234 .wr32 = _nouveau_graph_context_wr32, 1308 .wr32 = _nouveau_graph_context_wr32,
1235 }, 1309 },
1236 .main = nvc0_grctx_generate_main, 1310 .main = nvc0_grctx_generate_main,
1237 .mods = nvc0_grctx_generate_mods, 1311 .mods = nvc0_grctx_generate_mods,
1238 .unkn = nvc0_grctx_generate_unkn, 1312 .unkn = nvc0_grctx_generate_unkn,
1239 .hub = nvc0_grctx_init_hub, 1313 .hub = nvc0_grctx_pack_hub,
1240 .gpc = nvc0_grctx_init_gpc, 1314 .gpc = nvc0_grctx_pack_gpc,
1241 .icmd = nvc0_grctx_init_icmd, 1315 .zcull = nvc0_grctx_pack_zcull,
1242 .mthd = nvc0_grctx_init_mthd, 1316 .tpc = nvc0_grctx_pack_tpc,
1317 .icmd = nvc0_grctx_pack_icmd,
1318 .mthd = nvc0_grctx_pack_mthd,
1243}.base; 1319}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
new file mode 100644
index 000000000000..9c815d1f99ef
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
@@ -0,0 +1,170 @@
1#ifndef __NVKM_GRCTX_NVC0_H__
2#define __NVKM_GRCTX_NVC0_H__
3
4#include "nvc0.h"
5
6struct nvc0_grctx {
7 struct nvc0_graph_priv *priv;
8 struct nvc0_graph_data *data;
9 struct nvc0_graph_mmio *mmio;
10 int buffer_nr;
11 u64 buffer[4];
12 u64 addr;
13};
14
15struct nvc0_grctx_oclass {
16 struct nouveau_oclass base;
17 /* main context generation function */
18 void (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
19 /* context-specific modify-on-first-load list generation function */
20 void (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
21 void (*unkn)(struct nvc0_graph_priv *);
22 /* mmio context data */
23 const struct nvc0_graph_pack *hub;
24 const struct nvc0_graph_pack *gpc;
25 const struct nvc0_graph_pack *zcull;
26 const struct nvc0_graph_pack *tpc;
27 const struct nvc0_graph_pack *ppc;
28 /* indirect context data, generated with icmds/mthds */
29 const struct nvc0_graph_pack *icmd;
30 const struct nvc0_graph_pack *mthd;
31};
32
33#define mmio_data(s,a,p) do { \
34 info->buffer[info->buffer_nr] = round_up(info->addr, (a)); \
35 info->addr = info->buffer[info->buffer_nr++] + (s); \
36 info->data->size = (s); \
37 info->data->align = (a); \
38 info->data->access = (p); \
39 info->data++; \
40} while(0)
41
42#define mmio_list(r,d,s,b) do { \
43 info->mmio->addr = (r); \
44 info->mmio->data = (d); \
45 info->mmio->shift = (s); \
46 info->mmio->buffer = (b); \
47 info->mmio++; \
48 nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0)); \
49} while(0)
50
51extern struct nouveau_oclass *nvc0_grctx_oclass;
52int nvc0_grctx_generate(struct nvc0_graph_priv *);
53void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
54void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
55void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
56void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
57void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
58void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *);
59void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *);
60void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
61
62extern struct nouveau_oclass *nvc1_grctx_oclass;
63void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
64void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
65
66extern struct nouveau_oclass *nvc4_grctx_oclass;
67extern struct nouveau_oclass *nvc8_grctx_oclass;
68extern struct nouveau_oclass *nvd7_grctx_oclass;
69extern struct nouveau_oclass *nvd9_grctx_oclass;
70
71extern struct nouveau_oclass *nve4_grctx_oclass;
72void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
73void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
74void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
75
76extern struct nouveau_oclass *nvf0_grctx_oclass;
77extern struct nouveau_oclass *nv108_grctx_oclass;
78extern struct nouveau_oclass *gm107_grctx_oclass;
79
80/* context init value lists */
81
82extern const struct nvc0_graph_pack nvc0_grctx_pack_icmd[];
83
84extern const struct nvc0_graph_pack nvc0_grctx_pack_mthd[];
85extern const struct nvc0_graph_init nvc0_grctx_init_902d_0[];
86extern const struct nvc0_graph_init nvc0_grctx_init_9039_0[];
87extern const struct nvc0_graph_init nvc0_grctx_init_90c0_0[];
88
89extern const struct nvc0_graph_pack nvc0_grctx_pack_hub[];
90extern const struct nvc0_graph_init nvc0_grctx_init_main_0[];
91extern const struct nvc0_graph_init nvc0_grctx_init_fe_0[];
92extern const struct nvc0_graph_init nvc0_grctx_init_pri_0[];
93extern const struct nvc0_graph_init nvc0_grctx_init_memfmt_0[];
94extern const struct nvc0_graph_init nvc0_grctx_init_rstr2d_0[];
95extern const struct nvc0_graph_init nvc0_grctx_init_scc_0[];
96
97extern const struct nvc0_graph_pack nvc0_grctx_pack_gpc[];
98extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_0[];
99extern const struct nvc0_graph_init nvc0_grctx_init_prop_0[];
100extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_1[];
101extern const struct nvc0_graph_init nvc0_grctx_init_zcull_0[];
102extern const struct nvc0_graph_init nvc0_grctx_init_crstr_0[];
103extern const struct nvc0_graph_init nvc0_grctx_init_gpm_0[];
104extern const struct nvc0_graph_init nvc0_grctx_init_gcc_0[];
105
106extern const struct nvc0_graph_pack nvc0_grctx_pack_zcull[];
107
108extern const struct nvc0_graph_pack nvc0_grctx_pack_tpc[];
109extern const struct nvc0_graph_init nvc0_grctx_init_pe_0[];
110extern const struct nvc0_graph_init nvc0_grctx_init_wwdx_0[];
111extern const struct nvc0_graph_init nvc0_grctx_init_mpc_0[];
112extern const struct nvc0_graph_init nvc0_grctx_init_tpccs_0[];
113
114extern const struct nvc0_graph_init nvc4_grctx_init_tex_0[];
115extern const struct nvc0_graph_init nvc4_grctx_init_l1c_0[];
116extern const struct nvc0_graph_init nvc4_grctx_init_sm_0[];
117
118extern const struct nvc0_graph_init nvc1_grctx_init_9097_0[];
119
120extern const struct nvc0_graph_init nvc1_grctx_init_gpm_0[];
121
122extern const struct nvc0_graph_init nvc1_grctx_init_pe_0[];
123extern const struct nvc0_graph_init nvc1_grctx_init_wwdx_0[];
124extern const struct nvc0_graph_init nvc1_grctx_init_tpccs_0[];
125
126extern const struct nvc0_graph_init nvc8_grctx_init_9197_0[];
127extern const struct nvc0_graph_init nvc8_grctx_init_9297_0[];
128
129extern const struct nvc0_graph_pack nvd9_grctx_pack_icmd[];
130
131extern const struct nvc0_graph_pack nvd9_grctx_pack_mthd[];
132
133extern const struct nvc0_graph_init nvd9_grctx_init_fe_0[];
134extern const struct nvc0_graph_init nvd9_grctx_init_be_0[];
135
136extern const struct nvc0_graph_init nvd9_grctx_init_prop_0[];
137extern const struct nvc0_graph_init nvd9_grctx_init_gpc_unk_1[];
138extern const struct nvc0_graph_init nvd9_grctx_init_crstr_0[];
139
140extern const struct nvc0_graph_init nvd9_grctx_init_sm_0[];
141
142extern const struct nvc0_graph_init nvd7_grctx_init_pe_0[];
143
144extern const struct nvc0_graph_init nvd7_grctx_init_wwdx_0[];
145
146extern const struct nvc0_graph_init nve4_grctx_init_memfmt_0[];
147extern const struct nvc0_graph_init nve4_grctx_init_ds_0[];
148extern const struct nvc0_graph_init nve4_grctx_init_scc_0[];
149
150extern const struct nvc0_graph_init nve4_grctx_init_gpm_0[];
151
152extern const struct nvc0_graph_init nve4_grctx_init_pes_0[];
153
154extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
155
156extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
157extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[];
158
159extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[];
160
161extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[];
162extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[];
163
164extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[];
165
166extern const struct nvc0_graph_init nv108_grctx_init_prop_0[];
167extern const struct nvc0_graph_init nv108_grctx_init_crstr_0[];
168
169
170#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
index 71b4283f7fad..24a92c569c0a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
@@ -22,10 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27static struct nvc0_graph_init 27/*******************************************************************************
28nvc1_grctx_init_icmd[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nvc1_grctx_init_icmd_0[] = {
29 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
30 { 0x0000a9, 1, 0x01, 0x0000ffff }, 34 { 0x0000a9, 1, 0x01, 0x0000ffff },
31 { 0x000038, 1, 0x01, 0x0fac6881 }, 35 { 0x000038, 1, 0x01, 0x0fac6881 },
@@ -141,8 +145,7 @@ nvc1_grctx_init_icmd[] = {
141 { 0x000586, 1, 0x01, 0x00000040 }, 145 { 0x000586, 1, 0x01, 0x00000040 },
142 { 0x000582, 2, 0x01, 0x00000080 }, 146 { 0x000582, 2, 0x01, 0x00000080 },
143 { 0x0005c2, 1, 0x01, 0x00000001 }, 147 { 0x0005c2, 1, 0x01, 0x00000001 },
144 { 0x000638, 1, 0x01, 0x00000001 }, 148 { 0x000638, 2, 0x01, 0x00000001 },
145 { 0x000639, 1, 0x01, 0x00000001 },
146 { 0x00063a, 1, 0x01, 0x00000002 }, 149 { 0x00063a, 1, 0x01, 0x00000002 },
147 { 0x00063b, 2, 0x01, 0x00000001 }, 150 { 0x00063b, 2, 0x01, 0x00000001 },
148 { 0x00063d, 1, 0x01, 0x00000002 }, 151 { 0x00063d, 1, 0x01, 0x00000002 },
@@ -202,15 +205,13 @@ nvc1_grctx_init_icmd[] = {
202 { 0x000787, 1, 0x01, 0x000000cf }, 205 { 0x000787, 1, 0x01, 0x000000cf },
203 { 0x00078c, 1, 0x01, 0x00000008 }, 206 { 0x00078c, 1, 0x01, 0x00000008 },
204 { 0x000792, 1, 0x01, 0x00000001 }, 207 { 0x000792, 1, 0x01, 0x00000001 },
205 { 0x000794, 1, 0x01, 0x00000001 }, 208 { 0x000794, 3, 0x01, 0x00000001 },
206 { 0x000795, 2, 0x01, 0x00000001 },
207 { 0x000797, 1, 0x01, 0x000000cf }, 209 { 0x000797, 1, 0x01, 0x000000cf },
208 { 0x000836, 1, 0x01, 0x00000001 }, 210 { 0x000836, 1, 0x01, 0x00000001 },
209 { 0x00079a, 1, 0x01, 0x00000002 }, 211 { 0x00079a, 1, 0x01, 0x00000002 },
210 { 0x000833, 1, 0x01, 0x04444480 }, 212 { 0x000833, 1, 0x01, 0x04444480 },
211 { 0x0007a1, 1, 0x01, 0x00000001 }, 213 { 0x0007a1, 1, 0x01, 0x00000001 },
212 { 0x0007a3, 1, 0x01, 0x00000001 }, 214 { 0x0007a3, 3, 0x01, 0x00000001 },
213 { 0x0007a4, 2, 0x01, 0x00000001 },
214 { 0x000831, 1, 0x01, 0x00000004 }, 215 { 0x000831, 1, 0x01, 0x00000004 },
215 { 0x00080c, 1, 0x01, 0x00000002 }, 216 { 0x00080c, 1, 0x01, 0x00000002 },
216 { 0x00080d, 2, 0x01, 0x00000100 }, 217 { 0x00080d, 2, 0x01, 0x00000100 },
@@ -236,14 +237,12 @@ nvc1_grctx_init_icmd[] = {
236 { 0x0006b1, 1, 0x01, 0x00000011 }, 237 { 0x0006b1, 1, 0x01, 0x00000011 },
237 { 0x00078c, 1, 0x01, 0x00000008 }, 238 { 0x00078c, 1, 0x01, 0x00000008 },
238 { 0x000792, 1, 0x01, 0x00000001 }, 239 { 0x000792, 1, 0x01, 0x00000001 },
239 { 0x000794, 1, 0x01, 0x00000001 }, 240 { 0x000794, 3, 0x01, 0x00000001 },
240 { 0x000795, 2, 0x01, 0x00000001 },
241 { 0x000797, 1, 0x01, 0x000000cf }, 241 { 0x000797, 1, 0x01, 0x000000cf },
242 { 0x00079a, 1, 0x01, 0x00000002 }, 242 { 0x00079a, 1, 0x01, 0x00000002 },
243 { 0x000833, 1, 0x01, 0x04444480 }, 243 { 0x000833, 1, 0x01, 0x04444480 },
244 { 0x0007a1, 1, 0x01, 0x00000001 }, 244 { 0x0007a1, 1, 0x01, 0x00000001 },
245 { 0x0007a3, 1, 0x01, 0x00000001 }, 245 { 0x0007a3, 3, 0x01, 0x00000001 },
246 { 0x0007a4, 2, 0x01, 0x00000001 },
247 { 0x000831, 1, 0x01, 0x00000004 }, 246 { 0x000831, 1, 0x01, 0x00000004 },
248 { 0x01e100, 1, 0x01, 0x00000001 }, 247 { 0x01e100, 1, 0x01, 0x00000001 },
249 { 0x001000, 1, 0x01, 0x00000014 }, 248 { 0x001000, 1, 0x01, 0x00000014 },
@@ -268,8 +267,14 @@ nvc1_grctx_init_icmd[] = {
268 {} 267 {}
269}; 268};
270 269
271struct nvc0_graph_init 270static const struct nvc0_graph_pack
272nvc1_grctx_init_9097[] = { 271nvc1_grctx_pack_icmd[] = {
272 { nvc1_grctx_init_icmd_0 },
273 {}
274};
275
276const struct nvc0_graph_init
277nvc1_grctx_init_9097_0[] = {
273 { 0x000800, 8, 0x40, 0x00000000 }, 278 { 0x000800, 8, 0x40, 0x00000000 },
274 { 0x000804, 8, 0x40, 0x00000000 }, 279 { 0x000804, 8, 0x40, 0x00000000 },
275 { 0x000808, 8, 0x40, 0x00000400 }, 280 { 0x000808, 8, 0x40, 0x00000400 },
@@ -516,8 +521,7 @@ nvc1_grctx_init_9097[] = {
516 { 0x001350, 1, 0x04, 0x00000002 }, 521 { 0x001350, 1, 0x04, 0x00000002 },
517 { 0x001358, 1, 0x04, 0x00000001 }, 522 { 0x001358, 1, 0x04, 0x00000001 },
518 { 0x0012e4, 1, 0x04, 0x00000000 }, 523 { 0x0012e4, 1, 0x04, 0x00000000 },
519 { 0x00131c, 1, 0x04, 0x00000000 }, 524 { 0x00131c, 4, 0x04, 0x00000000 },
520 { 0x001320, 3, 0x04, 0x00000000 },
521 { 0x0019c0, 1, 0x04, 0x00000000 }, 525 { 0x0019c0, 1, 0x04, 0x00000000 },
522 { 0x001140, 1, 0x04, 0x00000000 }, 526 { 0x001140, 1, 0x04, 0x00000000 },
523 { 0x0019c4, 1, 0x04, 0x00000000 }, 527 { 0x0019c4, 1, 0x04, 0x00000000 },
@@ -571,15 +575,25 @@ nvc1_grctx_init_9097[] = {
571 {} 575 {}
572}; 576};
573 577
574static struct nvc0_graph_init 578static const struct nvc0_graph_init
575nvc1_grctx_init_9197[] = { 579nvc1_grctx_init_9197_0[] = {
576 { 0x003400, 128, 0x04, 0x00000000 }, 580 { 0x003400, 128, 0x04, 0x00000000 },
577 { 0x0002e4, 1, 0x04, 0x0000b001 }, 581 { 0x0002e4, 1, 0x04, 0x0000b001 },
578 {} 582 {}
579}; 583};
580 584
581static struct nvc0_graph_init 585static const struct nvc0_graph_pack
582nvc1_grctx_init_unk58xx[] = { 586nvc1_grctx_pack_mthd[] = {
587 { nvc1_grctx_init_9097_0, 0x9097 },
588 { nvc1_grctx_init_9197_0, 0x9197 },
589 { nvc0_grctx_init_902d_0, 0x902d },
590 { nvc0_grctx_init_9039_0, 0x9039 },
591 { nvc0_grctx_init_90c0_0, 0x90c0 },
592 {}
593};
594
595static const struct nvc0_graph_init
596nvc1_grctx_init_ds_0[] = {
583 { 0x405800, 1, 0x04, 0x0f8000bf }, 597 { 0x405800, 1, 0x04, 0x0f8000bf },
584 { 0x405830, 1, 0x04, 0x02180218 }, 598 { 0x405830, 1, 0x04, 0x02180218 },
585 { 0x405834, 2, 0x04, 0x00000000 }, 599 { 0x405834, 2, 0x04, 0x00000000 },
@@ -590,8 +604,20 @@ nvc1_grctx_init_unk58xx[] = {
590 {} 604 {}
591}; 605};
592 606
593static struct nvc0_graph_init 607static const struct nvc0_graph_init
594nvc1_grctx_init_rop[] = { 608nvc1_grctx_init_pd_0[] = {
609 { 0x406020, 1, 0x04, 0x000103c1 },
610 { 0x406028, 4, 0x04, 0x00000001 },
611 { 0x4064a8, 1, 0x04, 0x00000000 },
612 { 0x4064ac, 1, 0x04, 0x00003fff },
613 { 0x4064b4, 2, 0x04, 0x00000000 },
614 { 0x4064c0, 1, 0x04, 0x80140078 },
615 { 0x4064c4, 1, 0x04, 0x0086ffff },
616 {}
617};
618
619static const struct nvc0_graph_init
620nvc1_grctx_init_be_0[] = {
595 { 0x408800, 1, 0x04, 0x02802a3c }, 621 { 0x408800, 1, 0x04, 0x02802a3c },
596 { 0x408804, 1, 0x04, 0x00000040 }, 622 { 0x408804, 1, 0x04, 0x00000040 },
597 { 0x408808, 1, 0x04, 0x1003e005 }, 623 { 0x408808, 1, 0x04, 0x1003e005 },
@@ -602,25 +628,22 @@ nvc1_grctx_init_rop[] = {
602 {} 628 {}
603}; 629};
604 630
605static struct nvc0_graph_init 631static const struct nvc0_graph_pack
606nvc1_grctx_init_gpc_0[] = { 632nvc1_grctx_pack_hub[] = {
607 { 0x418380, 1, 0x04, 0x00000016 }, 633 { nvc0_grctx_init_main_0 },
608 { 0x418400, 1, 0x04, 0x38004e00 }, 634 { nvc0_grctx_init_fe_0 },
609 { 0x418404, 1, 0x04, 0x71e0ffff }, 635 { nvc0_grctx_init_pri_0 },
610 { 0x418408, 1, 0x04, 0x00000000 }, 636 { nvc0_grctx_init_memfmt_0 },
611 { 0x41840c, 1, 0x04, 0x00001008 }, 637 { nvc1_grctx_init_ds_0 },
612 { 0x418410, 1, 0x04, 0x0fff0fff }, 638 { nvc1_grctx_init_pd_0 },
613 { 0x418414, 1, 0x04, 0x00200fff }, 639 { nvc0_grctx_init_rstr2d_0 },
614 { 0x418450, 6, 0x04, 0x00000000 }, 640 { nvc0_grctx_init_scc_0 },
615 { 0x418468, 1, 0x04, 0x00000001 }, 641 { nvc1_grctx_init_be_0 },
616 { 0x41846c, 2, 0x04, 0x00000000 }, 642 {}
617 { 0x418600, 1, 0x04, 0x0000001f }, 643};
618 { 0x418684, 1, 0x04, 0x0000000f }, 644
619 { 0x418700, 1, 0x04, 0x00000002 }, 645static const struct nvc0_graph_init
620 { 0x418704, 1, 0x04, 0x00000080 }, 646nvc1_grctx_init_setup_0[] = {
621 { 0x418708, 1, 0x04, 0x00000000 },
622 { 0x41870c, 1, 0x04, 0x07c80000 },
623 { 0x418710, 1, 0x04, 0x00000000 },
624 { 0x418800, 1, 0x04, 0x0006860a }, 647 { 0x418800, 1, 0x04, 0x0006860a },
625 { 0x418808, 3, 0x04, 0x00000000 }, 648 { 0x418808, 3, 0x04, 0x00000000 },
626 { 0x418828, 1, 0x04, 0x00008442 }, 649 { 0x418828, 1, 0x04, 0x00008442 },
@@ -629,69 +652,44 @@ nvc1_grctx_init_gpc_0[] = {
629 { 0x4188e0, 1, 0x04, 0x01000000 }, 652 { 0x4188e0, 1, 0x04, 0x01000000 },
630 { 0x4188e8, 5, 0x04, 0x00000000 }, 653 { 0x4188e8, 5, 0x04, 0x00000000 },
631 { 0x4188fc, 1, 0x04, 0x00100018 }, 654 { 0x4188fc, 1, 0x04, 0x00100018 },
632 { 0x41891c, 1, 0x04, 0x00ff00ff }, 655 {}
633 { 0x418924, 1, 0x04, 0x00000000 }, 656};
634 { 0x418928, 1, 0x04, 0x00ffff00 }, 657
635 { 0x41892c, 1, 0x04, 0x0000ff00 }, 658const struct nvc0_graph_init
636 { 0x418a00, 3, 0x04, 0x00000000 }, 659nvc1_grctx_init_gpm_0[] = {
637 { 0x418a0c, 1, 0x04, 0x00010000 },
638 { 0x418a10, 3, 0x04, 0x00000000 },
639 { 0x418a20, 3, 0x04, 0x00000000 },
640 { 0x418a2c, 1, 0x04, 0x00010000 },
641 { 0x418a30, 3, 0x04, 0x00000000 },
642 { 0x418a40, 3, 0x04, 0x00000000 },
643 { 0x418a4c, 1, 0x04, 0x00010000 },
644 { 0x418a50, 3, 0x04, 0x00000000 },
645 { 0x418a60, 3, 0x04, 0x00000000 },
646 { 0x418a6c, 1, 0x04, 0x00010000 },
647 { 0x418a70, 3, 0x04, 0x00000000 },
648 { 0x418a80, 3, 0x04, 0x00000000 },
649 { 0x418a8c, 1, 0x04, 0x00010000 },
650 { 0x418a90, 3, 0x04, 0x00000000 },
651 { 0x418aa0, 3, 0x04, 0x00000000 },
652 { 0x418aac, 1, 0x04, 0x00010000 },
653 { 0x418ab0, 3, 0x04, 0x00000000 },
654 { 0x418ac0, 3, 0x04, 0x00000000 },
655 { 0x418acc, 1, 0x04, 0x00010000 },
656 { 0x418ad0, 3, 0x04, 0x00000000 },
657 { 0x418ae0, 3, 0x04, 0x00000000 },
658 { 0x418aec, 1, 0x04, 0x00010000 },
659 { 0x418af0, 3, 0x04, 0x00000000 },
660 { 0x418b00, 1, 0x04, 0x00000000 },
661 { 0x418b08, 1, 0x04, 0x0a418820 },
662 { 0x418b0c, 1, 0x04, 0x062080e6 },
663 { 0x418b10, 1, 0x04, 0x020398a4 },
664 { 0x418b14, 1, 0x04, 0x0e629062 },
665 { 0x418b18, 1, 0x04, 0x0a418820 },
666 { 0x418b1c, 1, 0x04, 0x000000e6 },
667 { 0x418bb8, 1, 0x04, 0x00000103 },
668 { 0x418c08, 1, 0x04, 0x00000001 }, 660 { 0x418c08, 1, 0x04, 0x00000001 },
669 { 0x418c10, 8, 0x04, 0x00000000 }, 661 { 0x418c10, 8, 0x04, 0x00000000 },
670 { 0x418c6c, 1, 0x04, 0x00000001 }, 662 { 0x418c6c, 1, 0x04, 0x00000001 },
671 { 0x418c80, 1, 0x04, 0x20200004 }, 663 { 0x418c80, 1, 0x04, 0x20200004 },
672 { 0x418c8c, 1, 0x04, 0x00000001 }, 664 { 0x418c8c, 1, 0x04, 0x00000001 },
673 { 0x419000, 1, 0x04, 0x00000780 },
674 { 0x419004, 2, 0x04, 0x00000000 },
675 { 0x419014, 1, 0x04, 0x00000004 },
676 {} 665 {}
677}; 666};
678 667
679static struct nvc0_graph_init 668static const struct nvc0_graph_pack
680nvc1_grctx_init_tpc[] = { 669nvc1_grctx_pack_gpc[] = {
670 { nvc0_grctx_init_gpc_unk_0 },
671 { nvc0_grctx_init_prop_0 },
672 { nvc0_grctx_init_gpc_unk_1 },
673 { nvc1_grctx_init_setup_0 },
674 { nvc0_grctx_init_zcull_0 },
675 { nvc0_grctx_init_crstr_0 },
676 { nvc1_grctx_init_gpm_0 },
677 { nvc0_grctx_init_gcc_0 },
678 {}
679};
680
681const struct nvc0_graph_init
682nvc1_grctx_init_pe_0[] = {
681 { 0x419818, 1, 0x04, 0x00000000 }, 683 { 0x419818, 1, 0x04, 0x00000000 },
682 { 0x41983c, 1, 0x04, 0x00038bc7 }, 684 { 0x41983c, 1, 0x04, 0x00038bc7 },
683 { 0x419848, 1, 0x04, 0x00000000 }, 685 { 0x419848, 1, 0x04, 0x00000000 },
684 { 0x419864, 1, 0x04, 0x00000129 }, 686 { 0x419864, 1, 0x04, 0x00000129 },
685 { 0x419888, 1, 0x04, 0x00000000 }, 687 { 0x419888, 1, 0x04, 0x00000000 },
686 { 0x419a00, 1, 0x04, 0x000001f0 }, 688 {}
687 { 0x419a04, 1, 0x04, 0x00000001 }, 689};
688 { 0x419a08, 1, 0x04, 0x00000023 }, 690
689 { 0x419a0c, 1, 0x04, 0x00020000 }, 691const struct nvc0_graph_init
690 { 0x419a10, 1, 0x04, 0x00000000 }, 692nvc1_grctx_init_wwdx_0[] = {
691 { 0x419a14, 1, 0x04, 0x00000200 },
692 { 0x419a1c, 1, 0x04, 0x00000000 },
693 { 0x419a20, 1, 0x04, 0x00000800 },
694 { 0x419ac4, 1, 0x04, 0x0007f440 },
695 { 0x419b00, 1, 0x04, 0x0a418820 }, 693 { 0x419b00, 1, 0x04, 0x0a418820 },
696 { 0x419b04, 1, 0x04, 0x062080e6 }, 694 { 0x419b04, 1, 0x04, 0x062080e6 },
697 { 0x419b08, 1, 0x04, 0x020398a4 }, 695 { 0x419b08, 1, 0x04, 0x020398a4 },
@@ -701,28 +699,33 @@ nvc1_grctx_init_tpc[] = {
701 { 0x419bd0, 1, 0x04, 0x00900103 }, 699 { 0x419bd0, 1, 0x04, 0x00900103 },
702 { 0x419be0, 1, 0x04, 0x00400001 }, 700 { 0x419be0, 1, 0x04, 0x00400001 },
703 { 0x419be4, 1, 0x04, 0x00000000 }, 701 { 0x419be4, 1, 0x04, 0x00000000 },
704 { 0x419c00, 1, 0x04, 0x00000002 }, 702 {}
705 { 0x419c04, 1, 0x04, 0x00000006 }, 703};
706 { 0x419c08, 1, 0x04, 0x00000002 }, 704
707 { 0x419c20, 1, 0x04, 0x00000000 }, 705const struct nvc0_graph_init
708 { 0x419cb0, 1, 0x04, 0x00020048 }, 706nvc1_grctx_init_tpccs_0[] = {
709 { 0x419ce8, 1, 0x04, 0x00000000 },
710 { 0x419cf4, 1, 0x04, 0x00000183 },
711 { 0x419d20, 1, 0x04, 0x12180000 }, 707 { 0x419d20, 1, 0x04, 0x12180000 },
712 { 0x419d24, 1, 0x04, 0x00001fff }, 708 { 0x419d24, 1, 0x04, 0x00001fff },
713 { 0x419d44, 1, 0x04, 0x02180218 }, 709 { 0x419d44, 1, 0x04, 0x02180218 },
714 { 0x419e04, 3, 0x04, 0x00000000 },
715 { 0x419e10, 1, 0x04, 0x00000002 },
716 { 0x419e44, 1, 0x04, 0x001beff2 },
717 { 0x419e48, 1, 0x04, 0x00000000 },
718 { 0x419e4c, 1, 0x04, 0x0000000f },
719 { 0x419e50, 17, 0x04, 0x00000000 },
720 { 0x419e98, 1, 0x04, 0x00000000 },
721 { 0x419ee0, 1, 0x04, 0x00011110 },
722 { 0x419f30, 11, 0x04, 0x00000000 },
723 {} 710 {}
724}; 711};
725 712
713static const struct nvc0_graph_pack
714nvc1_grctx_pack_tpc[] = {
715 { nvc1_grctx_init_pe_0 },
716 { nvc4_grctx_init_tex_0 },
717 { nvc1_grctx_init_wwdx_0 },
718 { nvc0_grctx_init_mpc_0 },
719 { nvc4_grctx_init_l1c_0 },
720 { nvc1_grctx_init_tpccs_0 },
721 { nvc4_grctx_init_sm_0 },
722 {}
723};
724
725/*******************************************************************************
726 * PGRAPH context implementation
727 ******************************************************************************/
728
726void 729void
727nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 730nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
728{ 731{
@@ -771,41 +774,6 @@ nvc1_grctx_generate_unkn(struct nvc0_graph_priv *priv)
771 nv_mask(priv, 0x419c00, 0x00000008, 0x00000008); 774 nv_mask(priv, 0x419c00, 0x00000008, 0x00000008);
772} 775}
773 776
774static struct nvc0_graph_init *
775nvc1_grctx_init_hub[] = {
776 nvc0_grctx_init_base,
777 nvc0_grctx_init_unk40xx,
778 nvc0_grctx_init_unk44xx,
779 nvc0_grctx_init_unk46xx,
780 nvc0_grctx_init_unk47xx,
781 nvc1_grctx_init_unk58xx,
782 nvc0_grctx_init_unk60xx,
783 nvc0_grctx_init_unk64xx,
784 nvc0_grctx_init_unk78xx,
785 nvc0_grctx_init_unk80xx,
786 nvc1_grctx_init_rop,
787 NULL
788};
789
790struct nvc0_graph_init *
791nvc1_grctx_init_gpc[] = {
792 nvc1_grctx_init_gpc_0,
793 nvc0_grctx_init_gpc_1,
794 nvc1_grctx_init_tpc,
795 NULL
796};
797
798static struct nvc0_graph_mthd
799nvc1_grctx_init_mthd[] = {
800 { 0x9097, nvc1_grctx_init_9097, },
801 { 0x9197, nvc1_grctx_init_9197, },
802 { 0x902d, nvc0_grctx_init_902d, },
803 { 0x9039, nvc0_grctx_init_9039, },
804 { 0x90c0, nvc0_grctx_init_90c0, },
805 { 0x902d, nvc0_grctx_init_mthd_magic, },
806 {}
807};
808
809struct nouveau_oclass * 777struct nouveau_oclass *
810nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) { 778nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
811 .base.handle = NV_ENGCTX(GR, 0xc1), 779 .base.handle = NV_ENGCTX(GR, 0xc1),
@@ -817,11 +785,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
817 .rd32 = _nouveau_graph_context_rd32, 785 .rd32 = _nouveau_graph_context_rd32,
818 .wr32 = _nouveau_graph_context_wr32, 786 .wr32 = _nouveau_graph_context_wr32,
819 }, 787 },
820 .main = nvc0_grctx_generate_main, 788 .main = nvc0_grctx_generate_main,
821 .mods = nvc1_grctx_generate_mods, 789 .mods = nvc1_grctx_generate_mods,
822 .unkn = nvc1_grctx_generate_unkn, 790 .unkn = nvc1_grctx_generate_unkn,
823 .hub = nvc1_grctx_init_hub, 791 .hub = nvc1_grctx_pack_hub,
824 .gpc = nvc1_grctx_init_gpc, 792 .gpc = nvc1_grctx_pack_gpc,
825 .icmd = nvc1_grctx_init_icmd, 793 .zcull = nvc0_grctx_pack_zcull,
826 .mthd = nvc1_grctx_init_mthd, 794 .tpc = nvc1_grctx_pack_tpc,
795 .icmd = nvc1_grctx_pack_icmd,
796 .mthd = nvc1_grctx_pack_mthd,
827}.base; 797}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
index 8f237b3bd8c6..e11ed5538193 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
@@ -22,15 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27static struct nvc0_graph_init 27/*******************************************************************************
28nvc3_grctx_init_tpc[] = { 28 * PGRAPH context register lists
29 { 0x419818, 1, 0x04, 0x00000000 }, 29 ******************************************************************************/
30 { 0x41983c, 1, 0x04, 0x00038bc7 }, 30
31 { 0x419848, 1, 0x04, 0x00000000 }, 31const struct nvc0_graph_init
32 { 0x419864, 1, 0x04, 0x0000012a }, 32nvc4_grctx_init_tex_0[] = {
33 { 0x419888, 1, 0x04, 0x00000000 },
34 { 0x419a00, 1, 0x04, 0x000001f0 }, 33 { 0x419a00, 1, 0x04, 0x000001f0 },
35 { 0x419a04, 1, 0x04, 0x00000001 }, 34 { 0x419a04, 1, 0x04, 0x00000001 },
36 { 0x419a08, 1, 0x04, 0x00000023 }, 35 { 0x419a08, 1, 0x04, 0x00000023 },
@@ -40,24 +39,19 @@ nvc3_grctx_init_tpc[] = {
40 { 0x419a1c, 1, 0x04, 0x00000000 }, 39 { 0x419a1c, 1, 0x04, 0x00000000 },
41 { 0x419a20, 1, 0x04, 0x00000800 }, 40 { 0x419a20, 1, 0x04, 0x00000800 },
42 { 0x419ac4, 1, 0x04, 0x0007f440 }, 41 { 0x419ac4, 1, 0x04, 0x0007f440 },
43 { 0x419b00, 1, 0x04, 0x0a418820 }, 42 {}
44 { 0x419b04, 1, 0x04, 0x062080e6 }, 43};
45 { 0x419b08, 1, 0x04, 0x020398a4 }, 44
46 { 0x419b0c, 1, 0x04, 0x0e629062 }, 45const struct nvc0_graph_init
47 { 0x419b10, 1, 0x04, 0x0a418820 }, 46nvc4_grctx_init_l1c_0[] = {
48 { 0x419b14, 1, 0x04, 0x000000e6 },
49 { 0x419bd0, 1, 0x04, 0x00900103 },
50 { 0x419be0, 1, 0x04, 0x00000001 },
51 { 0x419be4, 1, 0x04, 0x00000000 },
52 { 0x419c00, 1, 0x04, 0x00000002 },
53 { 0x419c04, 1, 0x04, 0x00000006 },
54 { 0x419c08, 1, 0x04, 0x00000002 },
55 { 0x419c20, 1, 0x04, 0x00000000 },
56 { 0x419cb0, 1, 0x04, 0x00020048 }, 47 { 0x419cb0, 1, 0x04, 0x00020048 },
57 { 0x419ce8, 1, 0x04, 0x00000000 }, 48 { 0x419ce8, 1, 0x04, 0x00000000 },
58 { 0x419cf4, 1, 0x04, 0x00000183 }, 49 { 0x419cf4, 1, 0x04, 0x00000183 },
59 { 0x419d20, 1, 0x04, 0x02180000 }, 50 {}
60 { 0x419d24, 1, 0x04, 0x00001fff }, 51};
52
53const struct nvc0_graph_init
54nvc4_grctx_init_sm_0[] = {
61 { 0x419e04, 3, 0x04, 0x00000000 }, 55 { 0x419e04, 3, 0x04, 0x00000000 },
62 { 0x419e10, 1, 0x04, 0x00000002 }, 56 { 0x419e10, 1, 0x04, 0x00000002 },
63 { 0x419e44, 1, 0x04, 0x001beff2 }, 57 { 0x419e44, 1, 0x04, 0x001beff2 },
@@ -70,16 +64,24 @@ nvc3_grctx_init_tpc[] = {
70 {} 64 {}
71}; 65};
72 66
73struct nvc0_graph_init * 67static const struct nvc0_graph_pack
74nvc3_grctx_init_gpc[] = { 68nvc4_grctx_pack_tpc[] = {
75 nvc0_grctx_init_gpc_0, 69 { nvc0_grctx_init_pe_0 },
76 nvc0_grctx_init_gpc_1, 70 { nvc4_grctx_init_tex_0 },
77 nvc3_grctx_init_tpc, 71 { nvc0_grctx_init_wwdx_0 },
78 NULL 72 { nvc0_grctx_init_mpc_0 },
73 { nvc4_grctx_init_l1c_0 },
74 { nvc0_grctx_init_tpccs_0 },
75 { nvc4_grctx_init_sm_0 },
76 {}
79}; 77};
80 78
79/*******************************************************************************
80 * PGRAPH context implementation
81 ******************************************************************************/
82
81struct nouveau_oclass * 83struct nouveau_oclass *
82nvc3_grctx_oclass = &(struct nvc0_grctx_oclass) { 84nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
83 .base.handle = NV_ENGCTX(GR, 0xc3), 85 .base.handle = NV_ENGCTX(GR, 0xc3),
84 .base.ofuncs = &(struct nouveau_ofuncs) { 86 .base.ofuncs = &(struct nouveau_ofuncs) {
85 .ctor = nvc0_graph_context_ctor, 87 .ctor = nvc0_graph_context_ctor,
@@ -89,11 +91,13 @@ nvc3_grctx_oclass = &(struct nvc0_grctx_oclass) {
89 .rd32 = _nouveau_graph_context_rd32, 91 .rd32 = _nouveau_graph_context_rd32,
90 .wr32 = _nouveau_graph_context_wr32, 92 .wr32 = _nouveau_graph_context_wr32,
91 }, 93 },
92 .main = nvc0_grctx_generate_main, 94 .main = nvc0_grctx_generate_main,
93 .mods = nvc0_grctx_generate_mods, 95 .mods = nvc0_grctx_generate_mods,
94 .unkn = nvc0_grctx_generate_unkn, 96 .unkn = nvc0_grctx_generate_unkn,
95 .hub = nvc0_grctx_init_hub, 97 .hub = nvc0_grctx_pack_hub,
96 .gpc = nvc3_grctx_init_gpc, 98 .gpc = nvc0_grctx_pack_gpc,
97 .icmd = nvc0_grctx_init_icmd, 99 .zcull = nvc0_grctx_pack_zcull,
98 .mthd = nvc0_grctx_init_mthd, 100 .tpc = nvc4_grctx_pack_tpc,
101 .icmd = nvc0_grctx_pack_icmd,
102 .mthd = nvc0_grctx_pack_mthd,
99}.base; 103}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
index d0d4ce3c4892..feebd58dfe8d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
@@ -22,10 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27static struct nvc0_graph_init 27/*******************************************************************************
28nvc8_grctx_init_icmd[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nvc8_grctx_init_icmd_0[] = {
29 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
30 { 0x0000a9, 1, 0x01, 0x0000ffff }, 34 { 0x0000a9, 1, 0x01, 0x0000ffff },
31 { 0x000038, 1, 0x01, 0x0fac6881 }, 35 { 0x000038, 1, 0x01, 0x0fac6881 },
@@ -141,8 +145,7 @@ nvc8_grctx_init_icmd[] = {
141 { 0x000586, 1, 0x01, 0x00000040 }, 145 { 0x000586, 1, 0x01, 0x00000040 },
142 { 0x000582, 2, 0x01, 0x00000080 }, 146 { 0x000582, 2, 0x01, 0x00000080 },
143 { 0x0005c2, 1, 0x01, 0x00000001 }, 147 { 0x0005c2, 1, 0x01, 0x00000001 },
144 { 0x000638, 1, 0x01, 0x00000001 }, 148 { 0x000638, 2, 0x01, 0x00000001 },
145 { 0x000639, 1, 0x01, 0x00000001 },
146 { 0x00063a, 1, 0x01, 0x00000002 }, 149 { 0x00063a, 1, 0x01, 0x00000002 },
147 { 0x00063b, 2, 0x01, 0x00000001 }, 150 { 0x00063b, 2, 0x01, 0x00000001 },
148 { 0x00063d, 1, 0x01, 0x00000002 }, 151 { 0x00063d, 1, 0x01, 0x00000002 },
@@ -203,15 +206,13 @@ nvc8_grctx_init_icmd[] = {
203 { 0x000787, 1, 0x01, 0x000000cf }, 206 { 0x000787, 1, 0x01, 0x000000cf },
204 { 0x00078c, 1, 0x01, 0x00000008 }, 207 { 0x00078c, 1, 0x01, 0x00000008 },
205 { 0x000792, 1, 0x01, 0x00000001 }, 208 { 0x000792, 1, 0x01, 0x00000001 },
206 { 0x000794, 1, 0x01, 0x00000001 }, 209 { 0x000794, 3, 0x01, 0x00000001 },
207 { 0x000795, 2, 0x01, 0x00000001 },
208 { 0x000797, 1, 0x01, 0x000000cf }, 210 { 0x000797, 1, 0x01, 0x000000cf },
209 { 0x000836, 1, 0x01, 0x00000001 }, 211 { 0x000836, 1, 0x01, 0x00000001 },
210 { 0x00079a, 1, 0x01, 0x00000002 }, 212 { 0x00079a, 1, 0x01, 0x00000002 },
211 { 0x000833, 1, 0x01, 0x04444480 }, 213 { 0x000833, 1, 0x01, 0x04444480 },
212 { 0x0007a1, 1, 0x01, 0x00000001 }, 214 { 0x0007a1, 1, 0x01, 0x00000001 },
213 { 0x0007a3, 1, 0x01, 0x00000001 }, 215 { 0x0007a3, 3, 0x01, 0x00000001 },
214 { 0x0007a4, 2, 0x01, 0x00000001 },
215 { 0x000831, 1, 0x01, 0x00000004 }, 216 { 0x000831, 1, 0x01, 0x00000004 },
216 { 0x00080c, 1, 0x01, 0x00000002 }, 217 { 0x00080c, 1, 0x01, 0x00000002 },
217 { 0x00080d, 2, 0x01, 0x00000100 }, 218 { 0x00080d, 2, 0x01, 0x00000100 },
@@ -237,14 +238,12 @@ nvc8_grctx_init_icmd[] = {
237 { 0x0006b1, 1, 0x01, 0x00000011 }, 238 { 0x0006b1, 1, 0x01, 0x00000011 },
238 { 0x00078c, 1, 0x01, 0x00000008 }, 239 { 0x00078c, 1, 0x01, 0x00000008 },
239 { 0x000792, 1, 0x01, 0x00000001 }, 240 { 0x000792, 1, 0x01, 0x00000001 },
240 { 0x000794, 1, 0x01, 0x00000001 }, 241 { 0x000794, 3, 0x01, 0x00000001 },
241 { 0x000795, 2, 0x01, 0x00000001 },
242 { 0x000797, 1, 0x01, 0x000000cf }, 242 { 0x000797, 1, 0x01, 0x000000cf },
243 { 0x00079a, 1, 0x01, 0x00000002 }, 243 { 0x00079a, 1, 0x01, 0x00000002 },
244 { 0x000833, 1, 0x01, 0x04444480 }, 244 { 0x000833, 1, 0x01, 0x04444480 },
245 { 0x0007a1, 1, 0x01, 0x00000001 }, 245 { 0x0007a1, 1, 0x01, 0x00000001 },
246 { 0x0007a3, 1, 0x01, 0x00000001 }, 246 { 0x0007a3, 3, 0x01, 0x00000001 },
247 { 0x0007a4, 2, 0x01, 0x00000001 },
248 { 0x000831, 1, 0x01, 0x00000004 }, 247 { 0x000831, 1, 0x01, 0x00000004 },
249 { 0x01e100, 1, 0x01, 0x00000001 }, 248 { 0x01e100, 1, 0x01, 0x00000001 },
250 { 0x001000, 1, 0x01, 0x00000014 }, 249 { 0x001000, 1, 0x01, 0x00000014 },
@@ -269,58 +268,20 @@ nvc8_grctx_init_icmd[] = {
269 {} 268 {}
270}; 269};
271 270
272static struct nvc0_graph_init 271static const struct nvc0_graph_pack
273nvc8_grctx_init_tpc[] = { 272nvc8_grctx_pack_icmd[] = {
274 { 0x419818, 1, 0x04, 0x00000000 }, 273 { nvc8_grctx_init_icmd_0 },
275 { 0x41983c, 1, 0x04, 0x00038bc7 },
276 { 0x419848, 1, 0x04, 0x00000000 },
277 { 0x419864, 1, 0x04, 0x0000012a },
278 { 0x419888, 1, 0x04, 0x00000000 },
279 { 0x419a00, 1, 0x04, 0x000001f0 },
280 { 0x419a04, 1, 0x04, 0x00000001 },
281 { 0x419a08, 1, 0x04, 0x00000023 },
282 { 0x419a0c, 1, 0x04, 0x00020000 },
283 { 0x419a10, 1, 0x04, 0x00000000 },
284 { 0x419a14, 1, 0x04, 0x00000200 },
285 { 0x419a1c, 1, 0x04, 0x00000000 },
286 { 0x419a20, 1, 0x04, 0x00000800 },
287 { 0x419b00, 1, 0x04, 0x0a418820 },
288 { 0x419b04, 1, 0x04, 0x062080e6 },
289 { 0x419b08, 1, 0x04, 0x020398a4 },
290 { 0x419b0c, 1, 0x04, 0x0e629062 },
291 { 0x419b10, 1, 0x04, 0x0a418820 },
292 { 0x419b14, 1, 0x04, 0x000000e6 },
293 { 0x419bd0, 1, 0x04, 0x00900103 },
294 { 0x419be0, 1, 0x04, 0x00000001 },
295 { 0x419be4, 1, 0x04, 0x00000000 },
296 { 0x419c00, 1, 0x04, 0x00000002 },
297 { 0x419c04, 1, 0x04, 0x00000006 },
298 { 0x419c08, 1, 0x04, 0x00000002 },
299 { 0x419c20, 1, 0x04, 0x00000000 },
300 { 0x419cb0, 1, 0x04, 0x00060048 },
301 { 0x419ce8, 1, 0x04, 0x00000000 },
302 { 0x419cf4, 1, 0x04, 0x00000183 },
303 { 0x419d20, 1, 0x04, 0x02180000 },
304 { 0x419d24, 1, 0x04, 0x00001fff },
305 { 0x419e04, 3, 0x04, 0x00000000 },
306 { 0x419e10, 1, 0x04, 0x00000002 },
307 { 0x419e44, 1, 0x04, 0x001beff2 },
308 { 0x419e48, 1, 0x04, 0x00000000 },
309 { 0x419e4c, 1, 0x04, 0x0000000f },
310 { 0x419e50, 17, 0x04, 0x00000000 },
311 { 0x419e98, 1, 0x04, 0x00000000 },
312 { 0x419f50, 2, 0x04, 0x00000000 },
313 {} 274 {}
314}; 275};
315 276
316struct nvc0_graph_init 277const struct nvc0_graph_init
317nvc8_grctx_init_9197[] = { 278nvc8_grctx_init_9197_0[] = {
318 { 0x0002e4, 1, 0x04, 0x0000b001 }, 279 { 0x0002e4, 1, 0x04, 0x0000b001 },
319 {} 280 {}
320}; 281};
321 282
322struct nvc0_graph_init 283const struct nvc0_graph_init
323nvc8_grctx_init_9297[] = { 284nvc8_grctx_init_9297_0[] = {
324 { 0x003400, 128, 0x04, 0x00000000 }, 285 { 0x003400, 128, 0x04, 0x00000000 },
325 { 0x00036c, 2, 0x04, 0x00000000 }, 286 { 0x00036c, 2, 0x04, 0x00000000 },
326 { 0x0007a4, 2, 0x04, 0x00000000 }, 287 { 0x0007a4, 2, 0x04, 0x00000000 },
@@ -329,26 +290,47 @@ nvc8_grctx_init_9297[] = {
329 {} 290 {}
330}; 291};
331 292
332static struct nvc0_graph_mthd 293static const struct nvc0_graph_pack
333nvc8_grctx_init_mthd[] = { 294nvc8_grctx_pack_mthd[] = {
334 { 0x9097, nvc1_grctx_init_9097, }, 295 { nvc1_grctx_init_9097_0, 0x9097 },
335 { 0x9197, nvc8_grctx_init_9197, }, 296 { nvc8_grctx_init_9197_0, 0x9197 },
336 { 0x9297, nvc8_grctx_init_9297, }, 297 { nvc8_grctx_init_9297_0, 0x9297 },
337 { 0x902d, nvc0_grctx_init_902d, }, 298 { nvc0_grctx_init_902d_0, 0x902d },
338 { 0x9039, nvc0_grctx_init_9039, }, 299 { nvc0_grctx_init_9039_0, 0x9039 },
339 { 0x90c0, nvc0_grctx_init_90c0, }, 300 { nvc0_grctx_init_90c0_0, 0x90c0 },
340 { 0x902d, nvc0_grctx_init_mthd_magic, }, 301 {}
302};
303
304static const struct nvc0_graph_init
305nvc8_grctx_init_setup_0[] = {
306 { 0x418800, 1, 0x04, 0x0006860a },
307 { 0x418808, 3, 0x04, 0x00000000 },
308 { 0x418828, 1, 0x04, 0x00008442 },
309 { 0x418830, 1, 0x04, 0x00000001 },
310 { 0x4188d8, 1, 0x04, 0x00000008 },
311 { 0x4188e0, 1, 0x04, 0x01000000 },
312 { 0x4188e8, 5, 0x04, 0x00000000 },
313 { 0x4188fc, 1, 0x04, 0x20100000 },
341 {} 314 {}
342}; 315};
343 316
344static struct nvc0_graph_init * 317static const struct nvc0_graph_pack
345nvc8_grctx_init_gpc[] = { 318nvc8_grctx_pack_gpc[] = {
346 nvc0_grctx_init_gpc_0, 319 { nvc0_grctx_init_gpc_unk_0 },
347 nvc0_grctx_init_gpc_1, 320 { nvc0_grctx_init_prop_0 },
348 nvc8_grctx_init_tpc, 321 { nvc0_grctx_init_gpc_unk_1 },
349 NULL 322 { nvc8_grctx_init_setup_0 },
323 { nvc0_grctx_init_zcull_0 },
324 { nvc0_grctx_init_crstr_0 },
325 { nvc0_grctx_init_gpm_0 },
326 { nvc0_grctx_init_gcc_0 },
327 {}
350}; 328};
351 329
330/*******************************************************************************
331 * PGRAPH context implementation
332 ******************************************************************************/
333
352struct nouveau_oclass * 334struct nouveau_oclass *
353nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) { 335nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
354 .base.handle = NV_ENGCTX(GR, 0xc8), 336 .base.handle = NV_ENGCTX(GR, 0xc8),
@@ -360,11 +342,13 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
360 .rd32 = _nouveau_graph_context_rd32, 342 .rd32 = _nouveau_graph_context_rd32,
361 .wr32 = _nouveau_graph_context_wr32, 343 .wr32 = _nouveau_graph_context_wr32,
362 }, 344 },
363 .main = nvc0_grctx_generate_main, 345 .main = nvc0_grctx_generate_main,
364 .mods = nvc0_grctx_generate_mods, 346 .mods = nvc0_grctx_generate_mods,
365 .unkn = nvc0_grctx_generate_unkn, 347 .unkn = nvc0_grctx_generate_unkn,
366 .hub = nvc0_grctx_init_hub, 348 .hub = nvc0_grctx_pack_hub,
367 .gpc = nvc8_grctx_init_gpc, 349 .gpc = nvc8_grctx_pack_gpc,
368 .icmd = nvc8_grctx_init_icmd, 350 .zcull = nvc0_grctx_pack_zcull,
369 .mthd = nvc8_grctx_init_mthd, 351 .tpc = nvc0_grctx_pack_tpc,
352 .icmd = nvc8_grctx_pack_icmd,
353 .mthd = nvc8_grctx_pack_mthd,
370}.base; 354}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
index c4740d528532..1dbc8d7f2e86 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
@@ -22,33 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27struct nvc0_graph_init 27/*******************************************************************************
28nvd7_grctx_init_unk40xx[] = { 28 * PGRAPH context register lists
29 { 0x404004, 10, 0x04, 0x00000000 }, 29 ******************************************************************************/
30 { 0x404044, 1, 0x04, 0x00000000 },
31 { 0x404094, 1, 0x04, 0x00000000 },
32 { 0x404098, 12, 0x04, 0x00000000 },
33 { 0x4040c8, 1, 0x04, 0xf0000087 },
34 { 0x4040d0, 6, 0x04, 0x00000000 },
35 { 0x4040e8, 1, 0x04, 0x00001000 },
36 { 0x4040f8, 1, 0x04, 0x00000000 },
37 { 0x404130, 1, 0x04, 0x00000000 },
38 { 0x404134, 1, 0x04, 0x00000000 },
39 { 0x404138, 1, 0x04, 0x20000040 },
40 { 0x404150, 1, 0x04, 0x0000002e },
41 { 0x404154, 1, 0x04, 0x00000400 },
42 { 0x404158, 1, 0x04, 0x00000200 },
43 { 0x404164, 1, 0x04, 0x00000055 },
44 { 0x404168, 1, 0x04, 0x00000000 },
45 { 0x404178, 2, 0x04, 0x00000000 },
46 { 0x404200, 8, 0x04, 0x00000000 },
47 {}
48};
49 30
50static struct nvc0_graph_init 31static const struct nvc0_graph_init
51nvd7_grctx_init_unk58xx[] = { 32nvd7_grctx_init_ds_0[] = {
52 { 0x405800, 1, 0x04, 0x0f8000bf }, 33 { 0x405800, 1, 0x04, 0x0f8000bf },
53 { 0x405830, 1, 0x04, 0x02180324 }, 34 { 0x405830, 1, 0x04, 0x02180324 },
54 { 0x405834, 1, 0x04, 0x08000000 }, 35 { 0x405834, 1, 0x04, 0x08000000 },
@@ -60,8 +41,10 @@ nvd7_grctx_init_unk58xx[] = {
60 {} 41 {}
61}; 42};
62 43
63static struct nvc0_graph_init 44static const struct nvc0_graph_init
64nvd7_grctx_init_unk64xx[] = { 45nvd7_grctx_init_pd_0[] = {
46 { 0x406020, 1, 0x04, 0x000103c1 },
47 { 0x406028, 4, 0x04, 0x00000001 },
65 { 0x4064a8, 1, 0x04, 0x00000000 }, 48 { 0x4064a8, 1, 0x04, 0x00000000 },
66 { 0x4064ac, 1, 0x04, 0x00003fff }, 49 { 0x4064ac, 1, 0x04, 0x00003fff },
67 { 0x4064b4, 3, 0x04, 0x00000000 }, 50 { 0x4064b4, 3, 0x04, 0x00000000 },
@@ -71,22 +54,22 @@ nvd7_grctx_init_unk64xx[] = {
71 {} 54 {}
72}; 55};
73 56
74static struct nvc0_graph_init 57static const struct nvc0_graph_pack
75nvd7_grctx_init_gpc_0[] = { 58nvd7_grctx_pack_hub[] = {
76 { 0x418380, 1, 0x04, 0x00000016 }, 59 { nvc0_grctx_init_main_0 },
77 { 0x418400, 1, 0x04, 0x38004e00 }, 60 { nvd9_grctx_init_fe_0 },
78 { 0x418404, 1, 0x04, 0x71e0ffff }, 61 { nvc0_grctx_init_pri_0 },
79 { 0x41840c, 1, 0x04, 0x00001008 }, 62 { nvc0_grctx_init_memfmt_0 },
80 { 0x418410, 1, 0x04, 0x0fff0fff }, 63 { nvd7_grctx_init_ds_0 },
81 { 0x418414, 1, 0x04, 0x02200fff }, 64 { nvd7_grctx_init_pd_0 },
82 { 0x418450, 6, 0x04, 0x00000000 }, 65 { nvc0_grctx_init_rstr2d_0 },
83 { 0x418468, 1, 0x04, 0x00000001 }, 66 { nvc0_grctx_init_scc_0 },
84 { 0x41846c, 2, 0x04, 0x00000000 }, 67 { nvd9_grctx_init_be_0 },
85 { 0x418600, 1, 0x04, 0x0000001f }, 68 {}
86 { 0x418684, 1, 0x04, 0x0000000f }, 69};
87 { 0x418700, 1, 0x04, 0x00000002 }, 70
88 { 0x418704, 1, 0x04, 0x00000080 }, 71static const struct nvc0_graph_init
89 { 0x418708, 3, 0x04, 0x00000000 }, 72nvd7_grctx_init_setup_0[] = {
90 { 0x418800, 1, 0x04, 0x7006860a }, 73 { 0x418800, 1, 0x04, 0x7006860a },
91 { 0x418808, 3, 0x04, 0x00000000 }, 74 { 0x418808, 3, 0x04, 0x00000000 },
92 { 0x418828, 1, 0x04, 0x00008442 }, 75 { 0x418828, 1, 0x04, 0x00008442 },
@@ -95,34 +78,32 @@ nvd7_grctx_init_gpc_0[] = {
95 { 0x4188e0, 1, 0x04, 0x01000000 }, 78 { 0x4188e0, 1, 0x04, 0x01000000 },
96 { 0x4188e8, 5, 0x04, 0x00000000 }, 79 { 0x4188e8, 5, 0x04, 0x00000000 },
97 { 0x4188fc, 1, 0x04, 0x20100018 }, 80 { 0x4188fc, 1, 0x04, 0x20100018 },
98 { 0x41891c, 1, 0x04, 0x00ff00ff },
99 { 0x418924, 1, 0x04, 0x00000000 },
100 { 0x418928, 1, 0x04, 0x00ffff00 },
101 { 0x41892c, 1, 0x04, 0x0000ff00 },
102 { 0x418b00, 1, 0x04, 0x00000006 },
103 { 0x418b08, 1, 0x04, 0x0a418820 },
104 { 0x418b0c, 1, 0x04, 0x062080e6 },
105 { 0x418b10, 1, 0x04, 0x020398a4 },
106 { 0x418b14, 1, 0x04, 0x0e629062 },
107 { 0x418b18, 1, 0x04, 0x0a418820 },
108 { 0x418b1c, 1, 0x04, 0x000000e6 },
109 { 0x418bb8, 1, 0x04, 0x00000103 },
110 { 0x418c08, 1, 0x04, 0x00000001 },
111 { 0x418c10, 8, 0x04, 0x00000000 },
112 { 0x418c6c, 1, 0x04, 0x00000001 },
113 { 0x418c80, 1, 0x04, 0x20200004 },
114 { 0x418c8c, 1, 0x04, 0x00000001 },
115 { 0x419000, 1, 0x04, 0x00000780 },
116 { 0x419004, 2, 0x04, 0x00000000 },
117 { 0x419014, 1, 0x04, 0x00000004 },
118 {} 81 {}
119}; 82};
120 83
121static struct nvc0_graph_init 84static const struct nvc0_graph_pack
122nvd7_grctx_init_tpc[] = { 85nvd7_grctx_pack_gpc[] = {
86 { nvc0_grctx_init_gpc_unk_0 },
87 { nvd9_grctx_init_prop_0 },
88 { nvd9_grctx_init_gpc_unk_1 },
89 { nvd7_grctx_init_setup_0 },
90 { nvc0_grctx_init_zcull_0 },
91 { nvd9_grctx_init_crstr_0 },
92 { nvc1_grctx_init_gpm_0 },
93 { nvc0_grctx_init_gcc_0 },
94 {}
95};
96
97const struct nvc0_graph_init
98nvd7_grctx_init_pe_0[] = {
123 { 0x419848, 1, 0x04, 0x00000000 }, 99 { 0x419848, 1, 0x04, 0x00000000 },
124 { 0x419864, 1, 0x04, 0x00000129 }, 100 { 0x419864, 1, 0x04, 0x00000129 },
125 { 0x419888, 1, 0x04, 0x00000000 }, 101 { 0x419888, 1, 0x04, 0x00000000 },
102 {}
103};
104
105static const struct nvc0_graph_init
106nvd7_grctx_init_tex_0[] = {
126 { 0x419a00, 1, 0x04, 0x000001f0 }, 107 { 0x419a00, 1, 0x04, 0x000001f0 },
127 { 0x419a04, 1, 0x04, 0x00000001 }, 108 { 0x419a04, 1, 0x04, 0x00000001 },
128 { 0x419a08, 1, 0x04, 0x00000023 }, 109 { 0x419a08, 1, 0x04, 0x00000023 },
@@ -132,33 +113,46 @@ nvd7_grctx_init_tpc[] = {
132 { 0x419a1c, 1, 0x04, 0x00008000 }, 113 { 0x419a1c, 1, 0x04, 0x00008000 },
133 { 0x419a20, 1, 0x04, 0x00000800 }, 114 { 0x419a20, 1, 0x04, 0x00000800 },
134 { 0x419ac4, 1, 0x04, 0x0017f440 }, 115 { 0x419ac4, 1, 0x04, 0x0017f440 },
116 {}
117};
118
119static const struct nvc0_graph_init
120nvd7_grctx_init_mpc_0[] = {
135 { 0x419c00, 1, 0x04, 0x0000000a }, 121 { 0x419c00, 1, 0x04, 0x0000000a },
136 { 0x419c04, 1, 0x04, 0x00000006 }, 122 { 0x419c04, 1, 0x04, 0x00000006 },
137 { 0x419c08, 1, 0x04, 0x00000002 }, 123 { 0x419c08, 1, 0x04, 0x00000002 },
138 { 0x419c20, 1, 0x04, 0x00000000 }, 124 { 0x419c20, 1, 0x04, 0x00000000 },
139 { 0x419c24, 1, 0x04, 0x00084210 }, 125 { 0x419c24, 1, 0x04, 0x00084210 },
140 { 0x419c28, 1, 0x04, 0x3efbefbe }, 126 { 0x419c28, 1, 0x04, 0x3efbefbe },
141 { 0x419cb0, 1, 0x04, 0x00020048 },
142 { 0x419ce8, 1, 0x04, 0x00000000 },
143 { 0x419cf4, 1, 0x04, 0x00000183 },
144 { 0x419e04, 3, 0x04, 0x00000000 },
145 { 0x419e10, 1, 0x04, 0x00000002 },
146 { 0x419e44, 1, 0x04, 0x001beff2 },
147 { 0x419e48, 1, 0x04, 0x00000000 },
148 { 0x419e4c, 1, 0x04, 0x0000000f },
149 { 0x419e50, 17, 0x04, 0x00000000 },
150 { 0x419e98, 1, 0x04, 0x00000000 },
151 { 0x419ee0, 1, 0x04, 0x00010110 },
152 { 0x419f30, 11, 0x04, 0x00000000 },
153 {} 127 {}
154}; 128};
155 129
156static struct nvc0_graph_init 130static const struct nvc0_graph_pack
157nvd7_grctx_init_unk[] = { 131nvd7_grctx_pack_tpc[] = {
132 { nvd7_grctx_init_pe_0 },
133 { nvd7_grctx_init_tex_0 },
134 { nvd7_grctx_init_mpc_0 },
135 { nvc4_grctx_init_l1c_0 },
136 { nvd9_grctx_init_sm_0 },
137 {}
138};
139
140static const struct nvc0_graph_init
141nvd7_grctx_init_pes_0[] = {
158 { 0x41be24, 1, 0x04, 0x00000002 }, 142 { 0x41be24, 1, 0x04, 0x00000002 },
143 {}
144};
145
146static const struct nvc0_graph_init
147nvd7_grctx_init_cbm_0[] = {
159 { 0x41bec0, 1, 0x04, 0x12180000 }, 148 { 0x41bec0, 1, 0x04, 0x12180000 },
160 { 0x41bec4, 1, 0x04, 0x00003fff }, 149 { 0x41bec4, 1, 0x04, 0x00003fff },
161 { 0x41bee4, 1, 0x04, 0x03240218 }, 150 { 0x41bee4, 1, 0x04, 0x03240218 },
151 {}
152};
153
154const struct nvc0_graph_init
155nvd7_grctx_init_wwdx_0[] = {
162 { 0x41bf00, 1, 0x04, 0x0a418820 }, 156 { 0x41bf00, 1, 0x04, 0x0a418820 },
163 { 0x41bf04, 1, 0x04, 0x062080e6 }, 157 { 0x41bf04, 1, 0x04, 0x062080e6 },
164 { 0x41bf08, 1, 0x04, 0x020398a4 }, 158 { 0x41bf08, 1, 0x04, 0x020398a4 },
@@ -171,6 +165,18 @@ nvd7_grctx_init_unk[] = {
171 {} 165 {}
172}; 166};
173 167
168static const struct nvc0_graph_pack
169nvd7_grctx_pack_ppc[] = {
170 { nvd7_grctx_init_pes_0 },
171 { nvd7_grctx_init_cbm_0 },
172 { nvd7_grctx_init_wwdx_0 },
173 {}
174};
175
176/*******************************************************************************
177 * PGRAPH context implementation
178 ******************************************************************************/
179
174static void 180static void
175nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 181nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
176{ 182{
@@ -219,10 +225,11 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
219 225
220 nv_mask(priv, 0x000260, 0x00000001, 0x00000000); 226 nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
221 227
222 for (i = 0; oclass->hub[i]; i++) 228 nvc0_graph_mmio(priv, oclass->hub);
223 nvc0_graph_mmio(priv, oclass->hub[i]); 229 nvc0_graph_mmio(priv, oclass->gpc);
224 for (i = 0; oclass->gpc[i]; i++) 230 nvc0_graph_mmio(priv, oclass->zcull);
225 nvc0_graph_mmio(priv, oclass->gpc[i]); 231 nvc0_graph_mmio(priv, oclass->tpc);
232 nvc0_graph_mmio(priv, oclass->ppc);
226 233
227 nv_wr32(priv, 0x404154, 0x00000000); 234 nv_wr32(priv, 0x404154, 0x00000000);
228 235
@@ -244,32 +251,6 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
244 nv_mask(priv, 0x000260, 0x00000001, 0x00000001); 251 nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
245} 252}
246 253
247
248static struct nvc0_graph_init *
249nvd7_grctx_init_hub[] = {
250 nvc0_grctx_init_base,
251 nvd7_grctx_init_unk40xx,
252 nvc0_grctx_init_unk44xx,
253 nvc0_grctx_init_unk46xx,
254 nvc0_grctx_init_unk47xx,
255 nvd7_grctx_init_unk58xx,
256 nvc0_grctx_init_unk60xx,
257 nvd7_grctx_init_unk64xx,
258 nvc0_grctx_init_unk78xx,
259 nvc0_grctx_init_unk80xx,
260 nvd9_grctx_init_rop,
261 NULL
262};
263
264struct nvc0_graph_init *
265nvd7_grctx_init_gpc[] = {
266 nvd7_grctx_init_gpc_0,
267 nvc0_grctx_init_gpc_1,
268 nvd7_grctx_init_tpc,
269 nvd7_grctx_init_unk,
270 NULL
271};
272
273struct nouveau_oclass * 254struct nouveau_oclass *
274nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) { 255nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
275 .base.handle = NV_ENGCTX(GR, 0xd7), 256 .base.handle = NV_ENGCTX(GR, 0xd7),
@@ -281,11 +262,14 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
281 .rd32 = _nouveau_graph_context_rd32, 262 .rd32 = _nouveau_graph_context_rd32,
282 .wr32 = _nouveau_graph_context_wr32, 263 .wr32 = _nouveau_graph_context_wr32,
283 }, 264 },
284 .main = nvd7_grctx_generate_main, 265 .main = nvd7_grctx_generate_main,
285 .mods = nvd7_grctx_generate_mods, 266 .mods = nvd7_grctx_generate_mods,
286 .unkn = nve4_grctx_generate_unkn, 267 .unkn = nve4_grctx_generate_unkn,
287 .hub = nvd7_grctx_init_hub, 268 .hub = nvd7_grctx_pack_hub,
288 .gpc = nvd7_grctx_init_gpc, 269 .gpc = nvd7_grctx_pack_gpc,
289 .icmd = nvd9_grctx_init_icmd, 270 .zcull = nvc0_grctx_pack_zcull,
290 .mthd = nvd9_grctx_init_mthd, 271 .tpc = nvd7_grctx_pack_tpc,
272 .ppc = nvd7_grctx_pack_ppc,
273 .icmd = nvd9_grctx_pack_icmd,
274 .mthd = nvd9_grctx_pack_mthd,
291}.base; 275}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
index a1102cbf2fdc..c665fb7e4660 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
@@ -22,38 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27struct nvc0_graph_init 27/*******************************************************************************
28nvd9_grctx_init_90c0[] = { 28 * PGRAPH context register lists
29 { 0x002700, 4, 0x40, 0x00000000 }, 29 ******************************************************************************/
30 { 0x002720, 4, 0x40, 0x00000000 },
31 { 0x002704, 4, 0x40, 0x00000000 },
32 { 0x002724, 4, 0x40, 0x00000000 },
33 { 0x002708, 4, 0x40, 0x00000000 },
34 { 0x002728, 4, 0x40, 0x00000000 },
35 { 0x00270c, 8, 0x20, 0x00000000 },
36 { 0x002710, 4, 0x40, 0x00014000 },
37 { 0x002730, 4, 0x40, 0x00014000 },
38 { 0x002714, 4, 0x40, 0x00000040 },
39 { 0x002734, 4, 0x40, 0x00000040 },
40 { 0x00030c, 1, 0x04, 0x00000001 },
41 { 0x001944, 1, 0x04, 0x00000000 },
42 { 0x000758, 1, 0x04, 0x00000100 },
43 { 0x0002c4, 1, 0x04, 0x00000000 },
44 { 0x000790, 5, 0x04, 0x00000000 },
45 { 0x00077c, 1, 0x04, 0x00000000 },
46 { 0x000204, 3, 0x04, 0x00000000 },
47 { 0x000214, 1, 0x04, 0x00000000 },
48 { 0x00024c, 1, 0x04, 0x00000000 },
49 { 0x000d94, 1, 0x04, 0x00000001 },
50 { 0x001608, 2, 0x04, 0x00000000 },
51 { 0x001664, 1, 0x04, 0x00000000 },
52 {}
53};
54 30
55struct nvc0_graph_init 31static const struct nvc0_graph_init
56nvd9_grctx_init_icmd[] = { 32nvd9_grctx_init_icmd_0[] = {
57 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
58 { 0x0000a9, 1, 0x01, 0x0000ffff }, 34 { 0x0000a9, 1, 0x01, 0x0000ffff },
59 { 0x000038, 1, 0x01, 0x0fac6881 }, 35 { 0x000038, 1, 0x01, 0x0fac6881 },
@@ -171,8 +147,7 @@ nvd9_grctx_init_icmd[] = {
171 { 0x000586, 1, 0x01, 0x00000040 }, 147 { 0x000586, 1, 0x01, 0x00000040 },
172 { 0x000582, 2, 0x01, 0x00000080 }, 148 { 0x000582, 2, 0x01, 0x00000080 },
173 { 0x0005c2, 1, 0x01, 0x00000001 }, 149 { 0x0005c2, 1, 0x01, 0x00000001 },
174 { 0x000638, 1, 0x01, 0x00000001 }, 150 { 0x000638, 2, 0x01, 0x00000001 },
175 { 0x000639, 1, 0x01, 0x00000001 },
176 { 0x00063a, 1, 0x01, 0x00000002 }, 151 { 0x00063a, 1, 0x01, 0x00000002 },
177 { 0x00063b, 2, 0x01, 0x00000001 }, 152 { 0x00063b, 2, 0x01, 0x00000001 },
178 { 0x00063d, 1, 0x01, 0x00000002 }, 153 { 0x00063d, 1, 0x01, 0x00000002 },
@@ -233,15 +208,13 @@ nvd9_grctx_init_icmd[] = {
233 { 0x000787, 1, 0x01, 0x000000cf }, 208 { 0x000787, 1, 0x01, 0x000000cf },
234 { 0x00078c, 1, 0x01, 0x00000008 }, 209 { 0x00078c, 1, 0x01, 0x00000008 },
235 { 0x000792, 1, 0x01, 0x00000001 }, 210 { 0x000792, 1, 0x01, 0x00000001 },
236 { 0x000794, 1, 0x01, 0x00000001 }, 211 { 0x000794, 3, 0x01, 0x00000001 },
237 { 0x000795, 2, 0x01, 0x00000001 },
238 { 0x000797, 1, 0x01, 0x000000cf }, 212 { 0x000797, 1, 0x01, 0x000000cf },
239 { 0x000836, 1, 0x01, 0x00000001 }, 213 { 0x000836, 1, 0x01, 0x00000001 },
240 { 0x00079a, 1, 0x01, 0x00000002 }, 214 { 0x00079a, 1, 0x01, 0x00000002 },
241 { 0x000833, 1, 0x01, 0x04444480 }, 215 { 0x000833, 1, 0x01, 0x04444480 },
242 { 0x0007a1, 1, 0x01, 0x00000001 }, 216 { 0x0007a1, 1, 0x01, 0x00000001 },
243 { 0x0007a3, 1, 0x01, 0x00000001 }, 217 { 0x0007a3, 3, 0x01, 0x00000001 },
244 { 0x0007a4, 2, 0x01, 0x00000001 },
245 { 0x000831, 1, 0x01, 0x00000004 }, 218 { 0x000831, 1, 0x01, 0x00000004 },
246 { 0x00080c, 1, 0x01, 0x00000002 }, 219 { 0x00080c, 1, 0x01, 0x00000002 },
247 { 0x00080d, 2, 0x01, 0x00000100 }, 220 { 0x00080d, 2, 0x01, 0x00000100 },
@@ -267,14 +240,12 @@ nvd9_grctx_init_icmd[] = {
267 { 0x0006b1, 1, 0x01, 0x00000011 }, 240 { 0x0006b1, 1, 0x01, 0x00000011 },
268 { 0x00078c, 1, 0x01, 0x00000008 }, 241 { 0x00078c, 1, 0x01, 0x00000008 },
269 { 0x000792, 1, 0x01, 0x00000001 }, 242 { 0x000792, 1, 0x01, 0x00000001 },
270 { 0x000794, 1, 0x01, 0x00000001 }, 243 { 0x000794, 3, 0x01, 0x00000001 },
271 { 0x000795, 2, 0x01, 0x00000001 },
272 { 0x000797, 1, 0x01, 0x000000cf }, 244 { 0x000797, 1, 0x01, 0x000000cf },
273 { 0x00079a, 1, 0x01, 0x00000002 }, 245 { 0x00079a, 1, 0x01, 0x00000002 },
274 { 0x000833, 1, 0x01, 0x04444480 }, 246 { 0x000833, 1, 0x01, 0x04444480 },
275 { 0x0007a1, 1, 0x01, 0x00000001 }, 247 { 0x0007a1, 1, 0x01, 0x00000001 },
276 { 0x0007a3, 1, 0x01, 0x00000001 }, 248 { 0x0007a3, 3, 0x01, 0x00000001 },
277 { 0x0007a4, 2, 0x01, 0x00000001 },
278 { 0x000831, 1, 0x01, 0x00000004 }, 249 { 0x000831, 1, 0x01, 0x00000004 },
279 { 0x01e100, 1, 0x01, 0x00000001 }, 250 { 0x01e100, 1, 0x01, 0x00000001 },
280 { 0x001000, 1, 0x01, 0x00000014 }, 251 { 0x001000, 1, 0x01, 0x00000014 },
@@ -299,18 +270,56 @@ nvd9_grctx_init_icmd[] = {
299 {} 270 {}
300}; 271};
301 272
302struct nvc0_graph_init 273const struct nvc0_graph_pack
303nvd9_grctx_init_unk40xx[] = { 274nvd9_grctx_pack_icmd[] = {
304 { 0x404004, 11, 0x04, 0x00000000 }, 275 { nvd9_grctx_init_icmd_0 },
276 {}
277};
278
279static const struct nvc0_graph_init
280nvd9_grctx_init_90c0_0[] = {
281 { 0x002700, 8, 0x20, 0x00000000 },
282 { 0x002704, 8, 0x20, 0x00000000 },
283 { 0x002708, 8, 0x20, 0x00000000 },
284 { 0x00270c, 8, 0x20, 0x00000000 },
285 { 0x002710, 8, 0x20, 0x00014000 },
286 { 0x002714, 8, 0x20, 0x00000040 },
287 { 0x00030c, 1, 0x04, 0x00000001 },
288 { 0x001944, 1, 0x04, 0x00000000 },
289 { 0x000758, 1, 0x04, 0x00000100 },
290 { 0x0002c4, 1, 0x04, 0x00000000 },
291 { 0x000790, 5, 0x04, 0x00000000 },
292 { 0x00077c, 1, 0x04, 0x00000000 },
293 { 0x000204, 3, 0x04, 0x00000000 },
294 { 0x000214, 1, 0x04, 0x00000000 },
295 { 0x00024c, 1, 0x04, 0x00000000 },
296 { 0x000d94, 1, 0x04, 0x00000001 },
297 { 0x001608, 2, 0x04, 0x00000000 },
298 { 0x001664, 1, 0x04, 0x00000000 },
299 {}
300};
301
302const struct nvc0_graph_pack
303nvd9_grctx_pack_mthd[] = {
304 { nvc1_grctx_init_9097_0, 0x9097 },
305 { nvc8_grctx_init_9197_0, 0x9197 },
306 { nvc8_grctx_init_9297_0, 0x9297 },
307 { nvc0_grctx_init_902d_0, 0x902d },
308 { nvc0_grctx_init_9039_0, 0x9039 },
309 { nvd9_grctx_init_90c0_0, 0x90c0 },
310 {}
311};
312
313const struct nvc0_graph_init
314nvd9_grctx_init_fe_0[] = {
315 { 0x404004, 10, 0x04, 0x00000000 },
305 { 0x404044, 1, 0x04, 0x00000000 }, 316 { 0x404044, 1, 0x04, 0x00000000 },
306 { 0x404094, 1, 0x04, 0x00000000 }, 317 { 0x404094, 13, 0x04, 0x00000000 },
307 { 0x404098, 12, 0x04, 0x00000000 },
308 { 0x4040c8, 1, 0x04, 0xf0000087 }, 318 { 0x4040c8, 1, 0x04, 0xf0000087 },
309 { 0x4040d0, 6, 0x04, 0x00000000 }, 319 { 0x4040d0, 6, 0x04, 0x00000000 },
310 { 0x4040e8, 1, 0x04, 0x00001000 }, 320 { 0x4040e8, 1, 0x04, 0x00001000 },
311 { 0x4040f8, 1, 0x04, 0x00000000 }, 321 { 0x4040f8, 1, 0x04, 0x00000000 },
312 { 0x404130, 1, 0x04, 0x00000000 }, 322 { 0x404130, 2, 0x04, 0x00000000 },
313 { 0x404134, 1, 0x04, 0x00000000 },
314 { 0x404138, 1, 0x04, 0x20000040 }, 323 { 0x404138, 1, 0x04, 0x20000040 },
315 { 0x404150, 1, 0x04, 0x0000002e }, 324 { 0x404150, 1, 0x04, 0x0000002e },
316 { 0x404154, 1, 0x04, 0x00000400 }, 325 { 0x404154, 1, 0x04, 0x00000400 },
@@ -322,8 +331,8 @@ nvd9_grctx_init_unk40xx[] = {
322 {} 331 {}
323}; 332};
324 333
325static struct nvc0_graph_init 334static const struct nvc0_graph_init
326nvd9_grctx_init_unk58xx[] = { 335nvd9_grctx_init_ds_0[] = {
327 { 0x405800, 1, 0x04, 0x0f8000bf }, 336 { 0x405800, 1, 0x04, 0x0f8000bf },
328 { 0x405830, 1, 0x04, 0x02180218 }, 337 { 0x405830, 1, 0x04, 0x02180218 },
329 { 0x405834, 1, 0x04, 0x08000000 }, 338 { 0x405834, 1, 0x04, 0x08000000 },
@@ -335,8 +344,10 @@ nvd9_grctx_init_unk58xx[] = {
335 {} 344 {}
336}; 345};
337 346
338static struct nvc0_graph_init 347static const struct nvc0_graph_init
339nvd9_grctx_init_unk64xx[] = { 348nvd9_grctx_init_pd_0[] = {
349 { 0x406020, 1, 0x04, 0x000103c1 },
350 { 0x406028, 4, 0x04, 0x00000001 },
340 { 0x4064a8, 1, 0x04, 0x00000000 }, 351 { 0x4064a8, 1, 0x04, 0x00000000 },
341 { 0x4064ac, 1, 0x04, 0x00003fff }, 352 { 0x4064ac, 1, 0x04, 0x00003fff },
342 { 0x4064b4, 3, 0x04, 0x00000000 }, 353 { 0x4064b4, 3, 0x04, 0x00000000 },
@@ -345,21 +356,34 @@ nvd9_grctx_init_unk64xx[] = {
345 {} 356 {}
346}; 357};
347 358
348struct nvc0_graph_init 359const struct nvc0_graph_init
349nvd9_grctx_init_rop[] = { 360nvd9_grctx_init_be_0[] = {
350 { 0x408800, 1, 0x04, 0x02802a3c }, 361 { 0x408800, 1, 0x04, 0x02802a3c },
351 { 0x408804, 1, 0x04, 0x00000040 }, 362 { 0x408804, 1, 0x04, 0x00000040 },
352 { 0x408808, 1, 0x04, 0x1043e005 }, 363 { 0x408808, 1, 0x04, 0x1043e005 },
353 { 0x408900, 1, 0x04, 0x3080b801 }, 364 { 0x408900, 1, 0x04, 0x3080b801 },
354 { 0x408904, 1, 0x04, 0x1043e005 }, 365 { 0x408904, 1, 0x04, 0x62000001 },
355 { 0x408908, 1, 0x04, 0x00c8102f }, 366 { 0x408908, 1, 0x04, 0x00c8102f },
356 { 0x408980, 1, 0x04, 0x0000011d }, 367 { 0x408980, 1, 0x04, 0x0000011d },
357 {} 368 {}
358}; 369};
359 370
360static struct nvc0_graph_init 371static const struct nvc0_graph_pack
361nvd9_grctx_init_gpc_0[] = { 372nvd9_grctx_pack_hub[] = {
362 { 0x418380, 1, 0x04, 0x00000016 }, 373 { nvc0_grctx_init_main_0 },
374 { nvd9_grctx_init_fe_0 },
375 { nvc0_grctx_init_pri_0 },
376 { nvc0_grctx_init_memfmt_0 },
377 { nvd9_grctx_init_ds_0 },
378 { nvd9_grctx_init_pd_0 },
379 { nvc0_grctx_init_rstr2d_0 },
380 { nvc0_grctx_init_scc_0 },
381 { nvd9_grctx_init_be_0 },
382 {}
383};
384
385const struct nvc0_graph_init
386nvd9_grctx_init_prop_0[] = {
363 { 0x418400, 1, 0x04, 0x38004e00 }, 387 { 0x418400, 1, 0x04, 0x38004e00 },
364 { 0x418404, 1, 0x04, 0x71e0ffff }, 388 { 0x418404, 1, 0x04, 0x71e0ffff },
365 { 0x41840c, 1, 0x04, 0x00001008 }, 389 { 0x41840c, 1, 0x04, 0x00001008 },
@@ -368,11 +392,21 @@ nvd9_grctx_init_gpc_0[] = {
368 { 0x418450, 6, 0x04, 0x00000000 }, 392 { 0x418450, 6, 0x04, 0x00000000 },
369 { 0x418468, 1, 0x04, 0x00000001 }, 393 { 0x418468, 1, 0x04, 0x00000001 },
370 { 0x41846c, 2, 0x04, 0x00000000 }, 394 { 0x41846c, 2, 0x04, 0x00000000 },
395 {}
396};
397
398const struct nvc0_graph_init
399nvd9_grctx_init_gpc_unk_1[] = {
371 { 0x418600, 1, 0x04, 0x0000001f }, 400 { 0x418600, 1, 0x04, 0x0000001f },
372 { 0x418684, 1, 0x04, 0x0000000f }, 401 { 0x418684, 1, 0x04, 0x0000000f },
373 { 0x418700, 1, 0x04, 0x00000002 }, 402 { 0x418700, 1, 0x04, 0x00000002 },
374 { 0x418704, 1, 0x04, 0x00000080 }, 403 { 0x418704, 1, 0x04, 0x00000080 },
375 { 0x418708, 3, 0x04, 0x00000000 }, 404 { 0x418708, 3, 0x04, 0x00000000 },
405 {}
406};
407
408static const struct nvc0_graph_init
409nvd9_grctx_init_setup_0[] = {
376 { 0x418800, 1, 0x04, 0x7006860a }, 410 { 0x418800, 1, 0x04, 0x7006860a },
377 { 0x418808, 3, 0x04, 0x00000000 }, 411 { 0x418808, 3, 0x04, 0x00000000 },
378 { 0x418828, 1, 0x04, 0x00008442 }, 412 { 0x418828, 1, 0x04, 0x00008442 },
@@ -381,10 +415,11 @@ nvd9_grctx_init_gpc_0[] = {
381 { 0x4188e0, 1, 0x04, 0x01000000 }, 415 { 0x4188e0, 1, 0x04, 0x01000000 },
382 { 0x4188e8, 5, 0x04, 0x00000000 }, 416 { 0x4188e8, 5, 0x04, 0x00000000 },
383 { 0x4188fc, 1, 0x04, 0x20100008 }, 417 { 0x4188fc, 1, 0x04, 0x20100008 },
384 { 0x41891c, 1, 0x04, 0x00ff00ff }, 418 {}
385 { 0x418924, 1, 0x04, 0x00000000 }, 419};
386 { 0x418928, 1, 0x04, 0x00ffff00 }, 420
387 { 0x41892c, 1, 0x04, 0x0000ff00 }, 421const struct nvc0_graph_init
422nvd9_grctx_init_crstr_0[] = {
388 { 0x418b00, 1, 0x04, 0x00000006 }, 423 { 0x418b00, 1, 0x04, 0x00000006 },
389 { 0x418b08, 1, 0x04, 0x0a418820 }, 424 { 0x418b08, 1, 0x04, 0x0a418820 },
390 { 0x418b0c, 1, 0x04, 0x062080e6 }, 425 { 0x418b0c, 1, 0x04, 0x062080e6 },
@@ -393,24 +428,24 @@ nvd9_grctx_init_gpc_0[] = {
393 { 0x418b18, 1, 0x04, 0x0a418820 }, 428 { 0x418b18, 1, 0x04, 0x0a418820 },
394 { 0x418b1c, 1, 0x04, 0x000000e6 }, 429 { 0x418b1c, 1, 0x04, 0x000000e6 },
395 { 0x418bb8, 1, 0x04, 0x00000103 }, 430 { 0x418bb8, 1, 0x04, 0x00000103 },
396 { 0x418c08, 1, 0x04, 0x00000001 },
397 { 0x418c10, 8, 0x04, 0x00000000 },
398 { 0x418c6c, 1, 0x04, 0x00000001 },
399 { 0x418c80, 1, 0x04, 0x20200004 },
400 { 0x418c8c, 1, 0x04, 0x00000001 },
401 { 0x419000, 1, 0x04, 0x00000780 },
402 { 0x419004, 2, 0x04, 0x00000000 },
403 { 0x419014, 1, 0x04, 0x00000004 },
404 {} 431 {}
405}; 432};
406 433
407static struct nvc0_graph_init 434static const struct nvc0_graph_pack
408nvd9_grctx_init_tpc[] = { 435nvd9_grctx_pack_gpc[] = {
409 { 0x419818, 1, 0x04, 0x00000000 }, 436 { nvc0_grctx_init_gpc_unk_0 },
410 { 0x41983c, 1, 0x04, 0x00038bc7 }, 437 { nvd9_grctx_init_prop_0 },
411 { 0x419848, 1, 0x04, 0x00000000 }, 438 { nvd9_grctx_init_gpc_unk_1 },
412 { 0x419864, 1, 0x04, 0x00000129 }, 439 { nvd9_grctx_init_setup_0 },
413 { 0x419888, 1, 0x04, 0x00000000 }, 440 { nvc0_grctx_init_zcull_0 },
441 { nvd9_grctx_init_crstr_0 },
442 { nvc1_grctx_init_gpm_0 },
443 { nvc0_grctx_init_gcc_0 },
444 {}
445};
446
447static const struct nvc0_graph_init
448nvd9_grctx_init_tex_0[] = {
414 { 0x419a00, 1, 0x04, 0x000001f0 }, 449 { 0x419a00, 1, 0x04, 0x000001f0 },
415 { 0x419a04, 1, 0x04, 0x00000001 }, 450 { 0x419a04, 1, 0x04, 0x00000001 },
416 { 0x419a08, 1, 0x04, 0x00000023 }, 451 { 0x419a08, 1, 0x04, 0x00000023 },
@@ -420,27 +455,22 @@ nvd9_grctx_init_tpc[] = {
420 { 0x419a1c, 1, 0x04, 0x00000000 }, 455 { 0x419a1c, 1, 0x04, 0x00000000 },
421 { 0x419a20, 1, 0x04, 0x00000800 }, 456 { 0x419a20, 1, 0x04, 0x00000800 },
422 { 0x419ac4, 1, 0x04, 0x0017f440 }, 457 { 0x419ac4, 1, 0x04, 0x0017f440 },
423 { 0x419b00, 1, 0x04, 0x0a418820 }, 458 {}
424 { 0x419b04, 1, 0x04, 0x062080e6 }, 459};
425 { 0x419b08, 1, 0x04, 0x020398a4 }, 460
426 { 0x419b0c, 1, 0x04, 0x0e629062 }, 461static const struct nvc0_graph_init
427 { 0x419b10, 1, 0x04, 0x0a418820 }, 462nvd9_grctx_init_mpc_0[] = {
428 { 0x419b14, 1, 0x04, 0x000000e6 },
429 { 0x419bd0, 1, 0x04, 0x00900103 },
430 { 0x419be0, 1, 0x04, 0x00400001 },
431 { 0x419be4, 1, 0x04, 0x00000000 },
432 { 0x419c00, 1, 0x04, 0x0000000a }, 463 { 0x419c00, 1, 0x04, 0x0000000a },
433 { 0x419c04, 1, 0x04, 0x00000006 }, 464 { 0x419c04, 1, 0x04, 0x00000006 },
434 { 0x419c08, 1, 0x04, 0x00000002 }, 465 { 0x419c08, 1, 0x04, 0x00000002 },
435 { 0x419c20, 1, 0x04, 0x00000000 }, 466 { 0x419c20, 1, 0x04, 0x00000000 },
436 { 0x419c24, 1, 0x04, 0x00084210 }, 467 { 0x419c24, 1, 0x04, 0x00084210 },
437 { 0x419c28, 1, 0x04, 0x3cf3cf3c }, 468 { 0x419c28, 1, 0x04, 0x3cf3cf3c },
438 { 0x419cb0, 1, 0x04, 0x00020048 }, 469 {}
439 { 0x419ce8, 1, 0x04, 0x00000000 }, 470};
440 { 0x419cf4, 1, 0x04, 0x00000183 }, 471
441 { 0x419d20, 1, 0x04, 0x12180000 }, 472const struct nvc0_graph_init
442 { 0x419d24, 1, 0x04, 0x00001fff }, 473nvd9_grctx_init_sm_0[] = {
443 { 0x419d44, 1, 0x04, 0x02180218 },
444 { 0x419e04, 3, 0x04, 0x00000000 }, 474 { 0x419e04, 3, 0x04, 0x00000000 },
445 { 0x419e10, 1, 0x04, 0x00000002 }, 475 { 0x419e10, 1, 0x04, 0x00000002 },
446 { 0x419e44, 1, 0x04, 0x001beff2 }, 476 { 0x419e44, 1, 0x04, 0x001beff2 },
@@ -453,47 +483,21 @@ nvd9_grctx_init_tpc[] = {
453 {} 483 {}
454}; 484};
455 485
456static struct nvc0_graph_init * 486static const struct nvc0_graph_pack
457nvd9_grctx_init_hub[] = { 487nvd9_grctx_pack_tpc[] = {
458 nvc0_grctx_init_base, 488 { nvc1_grctx_init_pe_0 },
459 nvd9_grctx_init_unk40xx, 489 { nvd9_grctx_init_tex_0 },
460 nvc0_grctx_init_unk44xx, 490 { nvc1_grctx_init_wwdx_0 },
461 nvc0_grctx_init_unk46xx, 491 { nvd9_grctx_init_mpc_0 },
462 nvc0_grctx_init_unk47xx, 492 { nvc4_grctx_init_l1c_0 },
463 nvd9_grctx_init_unk58xx, 493 { nvc1_grctx_init_tpccs_0 },
464 nvc0_grctx_init_unk60xx, 494 { nvd9_grctx_init_sm_0 },
465 nvd9_grctx_init_unk64xx,
466 nvc0_grctx_init_unk78xx,
467 nvc0_grctx_init_unk80xx,
468 nvd9_grctx_init_rop,
469 NULL
470};
471
472struct nvc0_graph_init *
473nvd9_grctx_init_gpc[] = {
474 nvd9_grctx_init_gpc_0,
475 nvc0_grctx_init_gpc_1,
476 nvd9_grctx_init_tpc,
477 NULL
478};
479
480struct nvc0_graph_init
481nvd9_grctx_init_mthd_magic[] = {
482 { 0x3410, 1, 0x04, 0x80002006 },
483 {} 495 {}
484}; 496};
485 497
486struct nvc0_graph_mthd 498/*******************************************************************************
487nvd9_grctx_init_mthd[] = { 499 * PGRAPH context implementation
488 { 0x9097, nvc1_grctx_init_9097, }, 500 ******************************************************************************/
489 { 0x9197, nvc8_grctx_init_9197, },
490 { 0x9297, nvc8_grctx_init_9297, },
491 { 0x902d, nvc0_grctx_init_902d, },
492 { 0x9039, nvc0_grctx_init_9039, },
493 { 0x90c0, nvd9_grctx_init_90c0, },
494 { 0x902d, nvd9_grctx_init_mthd_magic, },
495 {}
496};
497 501
498struct nouveau_oclass * 502struct nouveau_oclass *
499nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) { 503nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
@@ -506,11 +510,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
506 .rd32 = _nouveau_graph_context_rd32, 510 .rd32 = _nouveau_graph_context_rd32,
507 .wr32 = _nouveau_graph_context_wr32, 511 .wr32 = _nouveau_graph_context_wr32,
508 }, 512 },
509 .main = nvc0_grctx_generate_main, 513 .main = nvc0_grctx_generate_main,
510 .mods = nvc1_grctx_generate_mods, 514 .mods = nvc1_grctx_generate_mods,
511 .unkn = nvc1_grctx_generate_unkn, 515 .unkn = nvc1_grctx_generate_unkn,
512 .hub = nvd9_grctx_init_hub, 516 .hub = nvd9_grctx_pack_hub,
513 .gpc = nvd9_grctx_init_gpc, 517 .gpc = nvd9_grctx_pack_gpc,
514 .icmd = nvd9_grctx_init_icmd, 518 .zcull = nvc0_grctx_pack_zcull,
515 .mthd = nvd9_grctx_init_mthd, 519 .tpc = nvd9_grctx_pack_tpc,
520 .icmd = nvd9_grctx_pack_icmd,
521 .mthd = nvd9_grctx_pack_mthd,
516}.base; 522}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
index e2de73ee5eee..49a14b116a5f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
@@ -22,10 +22,14 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27struct nvc0_graph_init 27/*******************************************************************************
28nve4_grctx_init_icmd[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nve4_grctx_init_icmd_0[] = {
29 { 0x001000, 1, 0x01, 0x00000004 }, 33 { 0x001000, 1, 0x01, 0x00000004 },
30 { 0x000039, 3, 0x01, 0x00000000 }, 34 { 0x000039, 3, 0x01, 0x00000000 },
31 { 0x0000a9, 1, 0x01, 0x0000ffff }, 35 { 0x0000a9, 1, 0x01, 0x0000ffff },
@@ -138,8 +142,7 @@ nve4_grctx_init_icmd[] = {
138 { 0x000586, 1, 0x01, 0x00000040 }, 142 { 0x000586, 1, 0x01, 0x00000040 },
139 { 0x000582, 2, 0x01, 0x00000080 }, 143 { 0x000582, 2, 0x01, 0x00000080 },
140 { 0x0005c2, 1, 0x01, 0x00000001 }, 144 { 0x0005c2, 1, 0x01, 0x00000001 },
141 { 0x000638, 1, 0x01, 0x00000001 }, 145 { 0x000638, 2, 0x01, 0x00000001 },
142 { 0x000639, 1, 0x01, 0x00000001 },
143 { 0x00063a, 1, 0x01, 0x00000002 }, 146 { 0x00063a, 1, 0x01, 0x00000002 },
144 { 0x00063b, 2, 0x01, 0x00000001 }, 147 { 0x00063b, 2, 0x01, 0x00000001 },
145 { 0x00063d, 1, 0x01, 0x00000002 }, 148 { 0x00063d, 1, 0x01, 0x00000002 },
@@ -197,15 +200,13 @@ nve4_grctx_init_icmd[] = {
197 { 0x000787, 1, 0x01, 0x000000cf }, 200 { 0x000787, 1, 0x01, 0x000000cf },
198 { 0x00078c, 1, 0x01, 0x00000008 }, 201 { 0x00078c, 1, 0x01, 0x00000008 },
199 { 0x000792, 1, 0x01, 0x00000001 }, 202 { 0x000792, 1, 0x01, 0x00000001 },
200 { 0x000794, 1, 0x01, 0x00000001 }, 203 { 0x000794, 3, 0x01, 0x00000001 },
201 { 0x000795, 2, 0x01, 0x00000001 },
202 { 0x000797, 1, 0x01, 0x000000cf }, 204 { 0x000797, 1, 0x01, 0x000000cf },
203 { 0x000836, 1, 0x01, 0x00000001 }, 205 { 0x000836, 1, 0x01, 0x00000001 },
204 { 0x00079a, 1, 0x01, 0x00000002 }, 206 { 0x00079a, 1, 0x01, 0x00000002 },
205 { 0x000833, 1, 0x01, 0x04444480 }, 207 { 0x000833, 1, 0x01, 0x04444480 },
206 { 0x0007a1, 1, 0x01, 0x00000001 }, 208 { 0x0007a1, 1, 0x01, 0x00000001 },
207 { 0x0007a3, 1, 0x01, 0x00000001 }, 209 { 0x0007a3, 3, 0x01, 0x00000001 },
208 { 0x0007a4, 2, 0x01, 0x00000001 },
209 { 0x000831, 1, 0x01, 0x00000004 }, 210 { 0x000831, 1, 0x01, 0x00000004 },
210 { 0x000b07, 1, 0x01, 0x00000002 }, 211 { 0x000b07, 1, 0x01, 0x00000002 },
211 { 0x000b08, 2, 0x01, 0x00000100 }, 212 { 0x000b08, 2, 0x01, 0x00000100 },
@@ -231,14 +232,12 @@ nve4_grctx_init_icmd[] = {
231 { 0x0006b1, 1, 0x01, 0x00000011 }, 232 { 0x0006b1, 1, 0x01, 0x00000011 },
232 { 0x00078c, 1, 0x01, 0x00000008 }, 233 { 0x00078c, 1, 0x01, 0x00000008 },
233 { 0x000792, 1, 0x01, 0x00000001 }, 234 { 0x000792, 1, 0x01, 0x00000001 },
234 { 0x000794, 1, 0x01, 0x00000001 }, 235 { 0x000794, 3, 0x01, 0x00000001 },
235 { 0x000795, 2, 0x01, 0x00000001 },
236 { 0x000797, 1, 0x01, 0x000000cf }, 236 { 0x000797, 1, 0x01, 0x000000cf },
237 { 0x00079a, 1, 0x01, 0x00000002 }, 237 { 0x00079a, 1, 0x01, 0x00000002 },
238 { 0x000833, 1, 0x01, 0x04444480 }, 238 { 0x000833, 1, 0x01, 0x04444480 },
239 { 0x0007a1, 1, 0x01, 0x00000001 }, 239 { 0x0007a1, 1, 0x01, 0x00000001 },
240 { 0x0007a3, 1, 0x01, 0x00000001 }, 240 { 0x0007a3, 3, 0x01, 0x00000001 },
241 { 0x0007a4, 2, 0x01, 0x00000001 },
242 { 0x000831, 1, 0x01, 0x00000004 }, 241 { 0x000831, 1, 0x01, 0x00000004 },
243 { 0x01e100, 1, 0x01, 0x00000001 }, 242 { 0x01e100, 1, 0x01, 0x00000001 },
244 { 0x001000, 1, 0x01, 0x00000008 }, 243 { 0x001000, 1, 0x01, 0x00000008 },
@@ -273,8 +272,14 @@ nve4_grctx_init_icmd[] = {
273 {} 272 {}
274}; 273};
275 274
276struct nvc0_graph_init 275static const struct nvc0_graph_pack
277nve4_grctx_init_a097[] = { 276nve4_grctx_pack_icmd[] = {
277 { nve4_grctx_init_icmd_0 },
278 {}
279};
280
281static const struct nvc0_graph_init
282nve4_grctx_init_a097_0[] = {
278 { 0x000800, 8, 0x40, 0x00000000 }, 283 { 0x000800, 8, 0x40, 0x00000000 },
279 { 0x000804, 8, 0x40, 0x00000000 }, 284 { 0x000804, 8, 0x40, 0x00000000 },
280 { 0x000808, 8, 0x40, 0x00000400 }, 285 { 0x000808, 8, 0x40, 0x00000400 },
@@ -517,8 +522,7 @@ nve4_grctx_init_a097[] = {
517 { 0x001350, 1, 0x04, 0x00000002 }, 522 { 0x001350, 1, 0x04, 0x00000002 },
518 { 0x001358, 1, 0x04, 0x00000001 }, 523 { 0x001358, 1, 0x04, 0x00000001 },
519 { 0x0012e4, 1, 0x04, 0x00000000 }, 524 { 0x0012e4, 1, 0x04, 0x00000000 },
520 { 0x00131c, 1, 0x04, 0x00000000 }, 525 { 0x00131c, 4, 0x04, 0x00000000 },
521 { 0x001320, 3, 0x04, 0x00000000 },
522 { 0x0019c0, 1, 0x04, 0x00000000 }, 526 { 0x0019c0, 1, 0x04, 0x00000000 },
523 { 0x001140, 1, 0x04, 0x00000000 }, 527 { 0x001140, 1, 0x04, 0x00000000 },
524 { 0x0019c4, 1, 0x04, 0x00000000 }, 528 { 0x0019c4, 1, 0x04, 0x00000000 },
@@ -574,19 +578,24 @@ nve4_grctx_init_a097[] = {
574 {} 578 {}
575}; 579};
576 580
577static struct nvc0_graph_init 581static const struct nvc0_graph_pack
578nve4_grctx_init_unk40xx[] = { 582nve4_grctx_pack_mthd[] = {
583 { nve4_grctx_init_a097_0, 0xa097 },
584 { nvc0_grctx_init_902d_0, 0x902d },
585 {}
586};
587
588static const struct nvc0_graph_init
589nve4_grctx_init_fe_0[] = {
579 { 0x404010, 5, 0x04, 0x00000000 }, 590 { 0x404010, 5, 0x04, 0x00000000 },
580 { 0x404024, 1, 0x04, 0x0000e000 }, 591 { 0x404024, 1, 0x04, 0x0000e000 },
581 { 0x404028, 1, 0x04, 0x00000000 }, 592 { 0x404028, 1, 0x04, 0x00000000 },
582 { 0x4040a8, 1, 0x04, 0x00000000 }, 593 { 0x4040a8, 8, 0x04, 0x00000000 },
583 { 0x4040ac, 7, 0x04, 0x00000000 },
584 { 0x4040c8, 1, 0x04, 0xf800008f }, 594 { 0x4040c8, 1, 0x04, 0xf800008f },
585 { 0x4040d0, 6, 0x04, 0x00000000 }, 595 { 0x4040d0, 6, 0x04, 0x00000000 },
586 { 0x4040e8, 1, 0x04, 0x00001000 }, 596 { 0x4040e8, 1, 0x04, 0x00001000 },
587 { 0x4040f8, 1, 0x04, 0x00000000 }, 597 { 0x4040f8, 1, 0x04, 0x00000000 },
588 { 0x404130, 1, 0x04, 0x00000000 }, 598 { 0x404130, 2, 0x04, 0x00000000 },
589 { 0x404134, 1, 0x04, 0x00000000 },
590 { 0x404138, 1, 0x04, 0x20000040 }, 599 { 0x404138, 1, 0x04, 0x20000040 },
591 { 0x404150, 1, 0x04, 0x0000002e }, 600 { 0x404150, 1, 0x04, 0x0000002e },
592 { 0x404154, 1, 0x04, 0x00000400 }, 601 { 0x404154, 1, 0x04, 0x00000400 },
@@ -597,8 +606,8 @@ nve4_grctx_init_unk40xx[] = {
597 {} 606 {}
598}; 607};
599 608
600struct nvc0_graph_init 609const struct nvc0_graph_init
601nve4_grctx_init_unk46xx[] = { 610nve4_grctx_init_memfmt_0[] = {
602 { 0x404604, 1, 0x04, 0x00000014 }, 611 { 0x404604, 1, 0x04, 0x00000014 },
603 { 0x404608, 1, 0x04, 0x00000000 }, 612 { 0x404608, 1, 0x04, 0x00000000 },
604 { 0x40460c, 1, 0x04, 0x00003fff }, 613 { 0x40460c, 1, 0x04, 0x00003fff },
@@ -614,11 +623,6 @@ nve4_grctx_init_unk46xx[] = {
614 { 0x4046a0, 1, 0x04, 0x007f0080 }, 623 { 0x4046a0, 1, 0x04, 0x007f0080 },
615 { 0x4046a4, 8, 0x04, 0x00000000 }, 624 { 0x4046a4, 8, 0x04, 0x00000000 },
616 { 0x4046c8, 3, 0x04, 0x00000000 }, 625 { 0x4046c8, 3, 0x04, 0x00000000 },
617 {}
618};
619
620struct nvc0_graph_init
621nve4_grctx_init_unk47xx[] = {
622 { 0x404700, 3, 0x04, 0x00000000 }, 626 { 0x404700, 3, 0x04, 0x00000000 },
623 { 0x404718, 7, 0x04, 0x00000000 }, 627 { 0x404718, 7, 0x04, 0x00000000 },
624 { 0x404734, 1, 0x04, 0x00000100 }, 628 { 0x404734, 1, 0x04, 0x00000100 },
@@ -628,8 +632,8 @@ nve4_grctx_init_unk47xx[] = {
628 {} 632 {}
629}; 633};
630 634
631struct nvc0_graph_init 635const struct nvc0_graph_init
632nve4_grctx_init_unk58xx[] = { 636nve4_grctx_init_ds_0[] = {
633 { 0x405800, 1, 0x04, 0x0f8000bf }, 637 { 0x405800, 1, 0x04, 0x0f8000bf },
634 { 0x405830, 1, 0x04, 0x02180648 }, 638 { 0x405830, 1, 0x04, 0x02180648 },
635 { 0x405834, 1, 0x04, 0x08000000 }, 639 { 0x405834, 1, 0x04, 0x08000000 },
@@ -641,22 +645,17 @@ nve4_grctx_init_unk58xx[] = {
641 {} 645 {}
642}; 646};
643 647
644static struct nvc0_graph_init 648static const struct nvc0_graph_init
645nve4_grctx_init_unk5bxx[] = { 649nve4_grctx_init_cwd_0[] = {
646 { 0x405b00, 1, 0x04, 0x00000000 }, 650 { 0x405b00, 1, 0x04, 0x00000000 },
647 { 0x405b10, 1, 0x04, 0x00001000 }, 651 { 0x405b10, 1, 0x04, 0x00001000 },
648 {} 652 {}
649}; 653};
650 654
651static struct nvc0_graph_init 655static const struct nvc0_graph_init
652nve4_grctx_init_unk60xx[] = { 656nve4_grctx_init_pd_0[] = {
653 { 0x406020, 1, 0x04, 0x004103c1 }, 657 { 0x406020, 1, 0x04, 0x004103c1 },
654 { 0x406028, 4, 0x04, 0x00000001 }, 658 { 0x406028, 4, 0x04, 0x00000001 },
655 {}
656};
657
658static struct nvc0_graph_init
659nve4_grctx_init_unk64xx[] = {
660 { 0x4064a8, 1, 0x04, 0x00000000 }, 659 { 0x4064a8, 1, 0x04, 0x00000000 },
661 { 0x4064ac, 1, 0x04, 0x00003fff }, 660 { 0x4064ac, 1, 0x04, 0x00003fff },
662 { 0x4064b4, 2, 0x04, 0x00000000 }, 661 { 0x4064b4, 2, 0x04, 0x00000000 },
@@ -668,14 +667,14 @@ nve4_grctx_init_unk64xx[] = {
668 {} 667 {}
669}; 668};
670 669
671static struct nvc0_graph_init 670static const struct nvc0_graph_init
672nve4_grctx_init_unk70xx[] = { 671nve4_grctx_init_sked_0[] = {
673 { 0x407040, 1, 0x04, 0x00000000 }, 672 { 0x407040, 1, 0x04, 0x00000000 },
674 {} 673 {}
675}; 674};
676 675
677struct nvc0_graph_init 676const struct nvc0_graph_init
678nve4_grctx_init_unk80xx[] = { 677nve4_grctx_init_scc_0[] = {
679 { 0x408000, 2, 0x04, 0x00000000 }, 678 { 0x408000, 2, 0x04, 0x00000000 },
680 { 0x408008, 1, 0x04, 0x00000030 }, 679 { 0x408008, 1, 0x04, 0x00000030 },
681 { 0x40800c, 2, 0x04, 0x00000000 }, 680 { 0x40800c, 2, 0x04, 0x00000000 },
@@ -685,8 +684,8 @@ nve4_grctx_init_unk80xx[] = {
685 {} 684 {}
686}; 685};
687 686
688static struct nvc0_graph_init 687static const struct nvc0_graph_init
689nve4_grctx_init_rop[] = { 688nve4_grctx_init_be_0[] = {
690 { 0x408800, 1, 0x04, 0x02802a3c }, 689 { 0x408800, 1, 0x04, 0x02802a3c },
691 { 0x408804, 1, 0x04, 0x00000040 }, 690 { 0x408804, 1, 0x04, 0x00000040 },
692 { 0x408808, 1, 0x04, 0x1043e005 }, 691 { 0x408808, 1, 0x04, 0x1043e005 },
@@ -698,22 +697,24 @@ nve4_grctx_init_rop[] = {
698 {} 697 {}
699}; 698};
700 699
701static struct nvc0_graph_init 700static const struct nvc0_graph_pack
702nve4_grctx_init_gpc_0[] = { 701nve4_grctx_pack_hub[] = {
703 { 0x418380, 1, 0x04, 0x00000016 }, 702 { nvc0_grctx_init_main_0 },
704 { 0x418400, 1, 0x04, 0x38004e00 }, 703 { nve4_grctx_init_fe_0 },
705 { 0x418404, 1, 0x04, 0x71e0ffff }, 704 { nvc0_grctx_init_pri_0 },
706 { 0x41840c, 1, 0x04, 0x00001008 }, 705 { nve4_grctx_init_memfmt_0 },
707 { 0x418410, 1, 0x04, 0x0fff0fff }, 706 { nve4_grctx_init_ds_0 },
708 { 0x418414, 1, 0x04, 0x02200fff }, 707 { nve4_grctx_init_cwd_0 },
709 { 0x418450, 6, 0x04, 0x00000000 }, 708 { nve4_grctx_init_pd_0 },
710 { 0x418468, 1, 0x04, 0x00000001 }, 709 { nve4_grctx_init_sked_0 },
711 { 0x41846c, 2, 0x04, 0x00000000 }, 710 { nvc0_grctx_init_rstr2d_0 },
712 { 0x418600, 1, 0x04, 0x0000001f }, 711 { nve4_grctx_init_scc_0 },
713 { 0x418684, 1, 0x04, 0x0000000f }, 712 { nve4_grctx_init_be_0 },
714 { 0x418700, 1, 0x04, 0x00000002 }, 713 {}
715 { 0x418704, 1, 0x04, 0x00000080 }, 714};
716 { 0x418708, 3, 0x04, 0x00000000 }, 715
716static const struct nvc0_graph_init
717nve4_grctx_init_setup_0[] = {
717 { 0x418800, 1, 0x04, 0x7006860a }, 718 { 0x418800, 1, 0x04, 0x7006860a },
718 { 0x418808, 3, 0x04, 0x00000000 }, 719 { 0x418808, 3, 0x04, 0x00000000 },
719 { 0x418828, 1, 0x04, 0x00000044 }, 720 { 0x418828, 1, 0x04, 0x00000044 },
@@ -722,35 +723,35 @@ nve4_grctx_init_gpc_0[] = {
722 { 0x4188e0, 1, 0x04, 0x01000000 }, 723 { 0x4188e0, 1, 0x04, 0x01000000 },
723 { 0x4188e8, 5, 0x04, 0x00000000 }, 724 { 0x4188e8, 5, 0x04, 0x00000000 },
724 { 0x4188fc, 1, 0x04, 0x20100018 }, 725 { 0x4188fc, 1, 0x04, 0x20100018 },
725 { 0x41891c, 1, 0x04, 0x00ff00ff }, 726 {}
726 { 0x418924, 1, 0x04, 0x00000000 }, 727};
727 { 0x418928, 1, 0x04, 0x00ffff00 }, 728
728 { 0x41892c, 1, 0x04, 0x0000ff00 }, 729const struct nvc0_graph_init
729 { 0x418b00, 1, 0x04, 0x00000006 }, 730nve4_grctx_init_gpm_0[] = {
730 { 0x418b08, 1, 0x04, 0x0a418820 },
731 { 0x418b0c, 1, 0x04, 0x062080e6 },
732 { 0x418b10, 1, 0x04, 0x020398a4 },
733 { 0x418b14, 1, 0x04, 0x0e629062 },
734 { 0x418b18, 1, 0x04, 0x0a418820 },
735 { 0x418b1c, 1, 0x04, 0x000000e6 },
736 { 0x418bb8, 1, 0x04, 0x00000103 },
737 { 0x418c08, 1, 0x04, 0x00000001 }, 731 { 0x418c08, 1, 0x04, 0x00000001 },
738 { 0x418c10, 8, 0x04, 0x00000000 }, 732 { 0x418c10, 8, 0x04, 0x00000000 },
739 { 0x418c40, 1, 0x04, 0xffffffff }, 733 { 0x418c40, 1, 0x04, 0xffffffff },
740 { 0x418c6c, 1, 0x04, 0x00000001 }, 734 { 0x418c6c, 1, 0x04, 0x00000001 },
741 { 0x418c80, 1, 0x04, 0x20200004 }, 735 { 0x418c80, 1, 0x04, 0x20200004 },
742 { 0x418c8c, 1, 0x04, 0x00000001 }, 736 { 0x418c8c, 1, 0x04, 0x00000001 },
743 { 0x419000, 1, 0x04, 0x00000780 },
744 { 0x419004, 2, 0x04, 0x00000000 },
745 { 0x419014, 1, 0x04, 0x00000004 },
746 {} 737 {}
747}; 738};
748 739
749static struct nvc0_graph_init 740static const struct nvc0_graph_pack
750nve4_grctx_init_tpc[] = { 741nve4_grctx_pack_gpc[] = {
751 { 0x419848, 1, 0x04, 0x00000000 }, 742 { nvc0_grctx_init_gpc_unk_0 },
752 { 0x419864, 1, 0x04, 0x00000129 }, 743 { nvd9_grctx_init_prop_0 },
753 { 0x419888, 1, 0x04, 0x00000000 }, 744 { nvd9_grctx_init_gpc_unk_1 },
745 { nve4_grctx_init_setup_0 },
746 { nvc0_grctx_init_zcull_0 },
747 { nvd9_grctx_init_crstr_0 },
748 { nve4_grctx_init_gpm_0 },
749 { nvc0_grctx_init_gcc_0 },
750 {}
751};
752
753static const struct nvc0_graph_init
754nve4_grctx_init_tex_0[] = {
754 { 0x419a00, 1, 0x04, 0x000000f0 }, 755 { 0x419a00, 1, 0x04, 0x000000f0 },
755 { 0x419a04, 1, 0x04, 0x00000001 }, 756 { 0x419a04, 1, 0x04, 0x00000001 },
756 { 0x419a08, 1, 0x04, 0x00000021 }, 757 { 0x419a08, 1, 0x04, 0x00000021 },
@@ -761,14 +762,29 @@ nve4_grctx_init_tpc[] = {
761 { 0x419a20, 1, 0x04, 0x00000800 }, 762 { 0x419a20, 1, 0x04, 0x00000800 },
762 { 0x419a30, 1, 0x04, 0x00000001 }, 763 { 0x419a30, 1, 0x04, 0x00000001 },
763 { 0x419ac4, 1, 0x04, 0x0037f440 }, 764 { 0x419ac4, 1, 0x04, 0x0037f440 },
765 {}
766};
767
768static const struct nvc0_graph_init
769nve4_grctx_init_mpc_0[] = {
764 { 0x419c00, 1, 0x04, 0x0000000a }, 770 { 0x419c00, 1, 0x04, 0x0000000a },
765 { 0x419c04, 1, 0x04, 0x80000006 }, 771 { 0x419c04, 1, 0x04, 0x80000006 },
766 { 0x419c08, 1, 0x04, 0x00000002 }, 772 { 0x419c08, 1, 0x04, 0x00000002 },
767 { 0x419c20, 1, 0x04, 0x00000000 }, 773 { 0x419c20, 1, 0x04, 0x00000000 },
768 { 0x419c24, 1, 0x04, 0x00084210 }, 774 { 0x419c24, 1, 0x04, 0x00084210 },
769 { 0x419c28, 1, 0x04, 0x3efbefbe }, 775 { 0x419c28, 1, 0x04, 0x3efbefbe },
776 {}
777};
778
779static const struct nvc0_graph_init
780nve4_grctx_init_l1c_0[] = {
770 { 0x419ce8, 1, 0x04, 0x00000000 }, 781 { 0x419ce8, 1, 0x04, 0x00000000 },
771 { 0x419cf4, 1, 0x04, 0x00003203 }, 782 { 0x419cf4, 1, 0x04, 0x00003203 },
783 {}
784};
785
786static const struct nvc0_graph_init
787nve4_grctx_init_sm_0[] = {
772 { 0x419e04, 3, 0x04, 0x00000000 }, 788 { 0x419e04, 3, 0x04, 0x00000000 },
773 { 0x419e10, 1, 0x04, 0x00000402 }, 789 { 0x419e10, 1, 0x04, 0x00000402 },
774 { 0x419e44, 1, 0x04, 0x0013eff2 }, 790 { 0x419e44, 1, 0x04, 0x0013eff2 },
@@ -782,28 +798,46 @@ nve4_grctx_init_tpc[] = {
782 { 0x419f58, 1, 0x04, 0x00000000 }, 798 { 0x419f58, 1, 0x04, 0x00000000 },
783 { 0x419f70, 1, 0x04, 0x00000000 }, 799 { 0x419f70, 1, 0x04, 0x00000000 },
784 { 0x419f78, 1, 0x04, 0x0000000b }, 800 { 0x419f78, 1, 0x04, 0x0000000b },
785 { 0x419f7c, 1, 0x04, 0x0000027a }, 801 { 0x419f7c, 1, 0x04, 0x0000027c },
802 {}
803};
804
805static const struct nvc0_graph_pack
806nve4_grctx_pack_tpc[] = {
807 { nvd7_grctx_init_pe_0 },
808 { nve4_grctx_init_tex_0 },
809 { nve4_grctx_init_mpc_0 },
810 { nve4_grctx_init_l1c_0 },
811 { nve4_grctx_init_sm_0 },
786 {} 812 {}
787}; 813};
788 814
789static struct nvc0_graph_init 815const struct nvc0_graph_init
790nve4_grctx_init_unk[] = { 816nve4_grctx_init_pes_0[] = {
791 { 0x41be24, 1, 0x04, 0x00000006 }, 817 { 0x41be24, 1, 0x04, 0x00000006 },
818 {}
819};
820
821static const struct nvc0_graph_init
822nve4_grctx_init_cbm_0[] = {
792 { 0x41bec0, 1, 0x04, 0x12180000 }, 823 { 0x41bec0, 1, 0x04, 0x12180000 },
793 { 0x41bec4, 1, 0x04, 0x00037f7f }, 824 { 0x41bec4, 1, 0x04, 0x00037f7f },
794 { 0x41bee4, 1, 0x04, 0x06480430 }, 825 { 0x41bee4, 1, 0x04, 0x06480430 },
795 { 0x41bf00, 1, 0x04, 0x0a418820 },
796 { 0x41bf04, 1, 0x04, 0x062080e6 },
797 { 0x41bf08, 1, 0x04, 0x020398a4 },
798 { 0x41bf0c, 1, 0x04, 0x0e629062 },
799 { 0x41bf10, 1, 0x04, 0x0a418820 },
800 { 0x41bf14, 1, 0x04, 0x000000e6 },
801 { 0x41bfd0, 1, 0x04, 0x00900103 },
802 { 0x41bfe0, 1, 0x04, 0x00400001 },
803 { 0x41bfe4, 1, 0x04, 0x00000000 },
804 {} 826 {}
805}; 827};
806 828
829static const struct nvc0_graph_pack
830nve4_grctx_pack_ppc[] = {
831 { nve4_grctx_init_pes_0 },
832 { nve4_grctx_init_cbm_0 },
833 { nvd7_grctx_init_wwdx_0 },
834 {}
835};
836
837/*******************************************************************************
838 * PGRAPH context implementation
839 ******************************************************************************/
840
807static void 841static void
808nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 842nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
809{ 843{
@@ -925,10 +959,11 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
925 959
926 nv_mask(priv, 0x000260, 0x00000001, 0x00000000); 960 nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
927 961
928 for (i = 0; oclass->hub[i]; i++) 962 nvc0_graph_mmio(priv, oclass->hub);
929 nvc0_graph_mmio(priv, oclass->hub[i]); 963 nvc0_graph_mmio(priv, oclass->gpc);
930 for (i = 0; oclass->gpc[i]; i++) 964 nvc0_graph_mmio(priv, oclass->zcull);
931 nvc0_graph_mmio(priv, oclass->gpc[i]); 965 nvc0_graph_mmio(priv, oclass->tpc);
966 nvc0_graph_mmio(priv, oclass->ppc);
932 967
933 nv_wr32(priv, 0x404154, 0x00000000); 968 nv_wr32(priv, 0x404154, 0x00000000);
934 969
@@ -962,41 +997,6 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
962 nv_mask(priv, 0x41be10, 0x00800000, 0x00800000); 997 nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);
963} 998}
964 999
965static struct nvc0_graph_init *
966nve4_grctx_init_hub[] = {
967 nvc0_grctx_init_base,
968 nve4_grctx_init_unk40xx,
969 nvc0_grctx_init_unk44xx,
970 nve4_grctx_init_unk46xx,
971 nve4_grctx_init_unk47xx,
972 nve4_grctx_init_unk58xx,
973 nve4_grctx_init_unk5bxx,
974 nve4_grctx_init_unk60xx,
975 nve4_grctx_init_unk64xx,
976 nve4_grctx_init_unk70xx,
977 nvc0_grctx_init_unk78xx,
978 nve4_grctx_init_unk80xx,
979 nve4_grctx_init_rop,
980 NULL
981};
982
983struct nvc0_graph_init *
984nve4_grctx_init_gpc[] = {
985 nve4_grctx_init_gpc_0,
986 nvc0_grctx_init_gpc_1,
987 nve4_grctx_init_tpc,
988 nve4_grctx_init_unk,
989 NULL
990};
991
992static struct nvc0_graph_mthd
993nve4_grctx_init_mthd[] = {
994 { 0xa097, nve4_grctx_init_a097, },
995 { 0x902d, nvc0_grctx_init_902d, },
996 { 0x902d, nvc0_grctx_init_mthd_magic, },
997 {}
998};
999
1000struct nouveau_oclass * 1000struct nouveau_oclass *
1001nve4_grctx_oclass = &(struct nvc0_grctx_oclass) { 1001nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
1002 .base.handle = NV_ENGCTX(GR, 0xe4), 1002 .base.handle = NV_ENGCTX(GR, 0xe4),
@@ -1008,11 +1008,14 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
1008 .rd32 = _nouveau_graph_context_rd32, 1008 .rd32 = _nouveau_graph_context_rd32,
1009 .wr32 = _nouveau_graph_context_wr32, 1009 .wr32 = _nouveau_graph_context_wr32,
1010 }, 1010 },
1011 .main = nve4_grctx_generate_main, 1011 .main = nve4_grctx_generate_main,
1012 .mods = nve4_grctx_generate_mods, 1012 .mods = nve4_grctx_generate_mods,
1013 .unkn = nve4_grctx_generate_unkn, 1013 .unkn = nve4_grctx_generate_unkn,
1014 .hub = nve4_grctx_init_hub, 1014 .hub = nve4_grctx_pack_hub,
1015 .gpc = nve4_grctx_init_gpc, 1015 .gpc = nve4_grctx_pack_gpc,
1016 .icmd = nve4_grctx_init_icmd, 1016 .zcull = nvc0_grctx_pack_zcull,
1017 .mthd = nve4_grctx_init_mthd, 1017 .tpc = nve4_grctx_pack_tpc,
1018 .ppc = nve4_grctx_pack_ppc,
1019 .icmd = nve4_grctx_pack_icmd,
1020 .mthd = nve4_grctx_pack_mthd,
1018}.base; 1021}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
index 44012c3da538..0fab95e49f53 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
@@ -22,10 +22,580 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "ctxnvc0.h"
26 26
27static struct nvc0_graph_init 27/*******************************************************************************
28nvf0_grctx_init_unk40xx[] = { 28 * PGRAPH context register lists
29 ******************************************************************************/
30
31static const struct nvc0_graph_init
32nvf0_grctx_init_icmd_0[] = {
33 { 0x001000, 1, 0x01, 0x00000004 },
34 { 0x000039, 3, 0x01, 0x00000000 },
35 { 0x0000a9, 1, 0x01, 0x0000ffff },
36 { 0x000038, 1, 0x01, 0x0fac6881 },
37 { 0x00003d, 1, 0x01, 0x00000001 },
38 { 0x0000e8, 8, 0x01, 0x00000400 },
39 { 0x000078, 8, 0x01, 0x00000300 },
40 { 0x000050, 1, 0x01, 0x00000011 },
41 { 0x000058, 8, 0x01, 0x00000008 },
42 { 0x000208, 8, 0x01, 0x00000001 },
43 { 0x000081, 1, 0x01, 0x00000001 },
44 { 0x000085, 1, 0x01, 0x00000004 },
45 { 0x000088, 1, 0x01, 0x00000400 },
46 { 0x000090, 1, 0x01, 0x00000300 },
47 { 0x000098, 1, 0x01, 0x00001001 },
48 { 0x0000e3, 1, 0x01, 0x00000001 },
49 { 0x0000da, 1, 0x01, 0x00000001 },
50 { 0x0000f8, 1, 0x01, 0x00000003 },
51 { 0x0000fa, 1, 0x01, 0x00000001 },
52 { 0x00009f, 4, 0x01, 0x0000ffff },
53 { 0x0000b1, 1, 0x01, 0x00000001 },
54 { 0x0000ad, 1, 0x01, 0x0000013e },
55 { 0x0000e1, 1, 0x01, 0x00000010 },
56 { 0x000290, 16, 0x01, 0x00000000 },
57 { 0x0003b0, 16, 0x01, 0x00000000 },
58 { 0x0002a0, 16, 0x01, 0x00000000 },
59 { 0x000420, 16, 0x01, 0x00000000 },
60 { 0x0002b0, 16, 0x01, 0x00000000 },
61 { 0x000430, 16, 0x01, 0x00000000 },
62 { 0x0002c0, 16, 0x01, 0x00000000 },
63 { 0x0004d0, 16, 0x01, 0x00000000 },
64 { 0x000720, 16, 0x01, 0x00000000 },
65 { 0x0008c0, 16, 0x01, 0x00000000 },
66 { 0x000890, 16, 0x01, 0x00000000 },
67 { 0x0008e0, 16, 0x01, 0x00000000 },
68 { 0x0008a0, 16, 0x01, 0x00000000 },
69 { 0x0008f0, 16, 0x01, 0x00000000 },
70 { 0x00094c, 1, 0x01, 0x000000ff },
71 { 0x00094d, 1, 0x01, 0xffffffff },
72 { 0x00094e, 1, 0x01, 0x00000002 },
73 { 0x0002ec, 1, 0x01, 0x00000001 },
74 { 0x0002f2, 2, 0x01, 0x00000001 },
75 { 0x0002f5, 1, 0x01, 0x00000001 },
76 { 0x0002f7, 1, 0x01, 0x00000001 },
77 { 0x000303, 1, 0x01, 0x00000001 },
78 { 0x0002e6, 1, 0x01, 0x00000001 },
79 { 0x000466, 1, 0x01, 0x00000052 },
80 { 0x000301, 1, 0x01, 0x3f800000 },
81 { 0x000304, 1, 0x01, 0x30201000 },
82 { 0x000305, 1, 0x01, 0x70605040 },
83 { 0x000306, 1, 0x01, 0xb8a89888 },
84 { 0x000307, 1, 0x01, 0xf8e8d8c8 },
85 { 0x00030a, 1, 0x01, 0x00ffff00 },
86 { 0x00030b, 1, 0x01, 0x0000001a },
87 { 0x00030c, 1, 0x01, 0x00000001 },
88 { 0x000318, 1, 0x01, 0x00000001 },
89 { 0x000340, 1, 0x01, 0x00000000 },
90 { 0x000375, 1, 0x01, 0x00000001 },
91 { 0x00037d, 1, 0x01, 0x00000006 },
92 { 0x0003a0, 1, 0x01, 0x00000002 },
93 { 0x0003aa, 1, 0x01, 0x00000001 },
94 { 0x0003a9, 1, 0x01, 0x00000001 },
95 { 0x000380, 1, 0x01, 0x00000001 },
96 { 0x000383, 1, 0x01, 0x00000011 },
97 { 0x000360, 1, 0x01, 0x00000040 },
98 { 0x000366, 2, 0x01, 0x00000000 },
99 { 0x000368, 1, 0x01, 0x00000fff },
100 { 0x000370, 2, 0x01, 0x00000000 },
101 { 0x000372, 1, 0x01, 0x000fffff },
102 { 0x00037a, 1, 0x01, 0x00000012 },
103 { 0x000619, 1, 0x01, 0x00000003 },
104 { 0x000811, 1, 0x01, 0x00000003 },
105 { 0x000812, 1, 0x01, 0x00000004 },
106 { 0x000813, 1, 0x01, 0x00000006 },
107 { 0x000814, 1, 0x01, 0x00000008 },
108 { 0x000815, 1, 0x01, 0x0000000b },
109 { 0x000800, 6, 0x01, 0x00000001 },
110 { 0x000632, 1, 0x01, 0x00000001 },
111 { 0x000633, 1, 0x01, 0x00000002 },
112 { 0x000634, 1, 0x01, 0x00000003 },
113 { 0x000635, 1, 0x01, 0x00000004 },
114 { 0x000654, 1, 0x01, 0x3f800000 },
115 { 0x000657, 1, 0x01, 0x3f800000 },
116 { 0x000655, 2, 0x01, 0x3f800000 },
117 { 0x0006cd, 1, 0x01, 0x3f800000 },
118 { 0x0007f5, 1, 0x01, 0x3f800000 },
119 { 0x0007dc, 1, 0x01, 0x39291909 },
120 { 0x0007dd, 1, 0x01, 0x79695949 },
121 { 0x0007de, 1, 0x01, 0xb9a99989 },
122 { 0x0007df, 1, 0x01, 0xf9e9d9c9 },
123 { 0x0007e8, 1, 0x01, 0x00003210 },
124 { 0x0007e9, 1, 0x01, 0x00007654 },
125 { 0x0007ea, 1, 0x01, 0x00000098 },
126 { 0x0007ec, 1, 0x01, 0x39291909 },
127 { 0x0007ed, 1, 0x01, 0x79695949 },
128 { 0x0007ee, 1, 0x01, 0xb9a99989 },
129 { 0x0007ef, 1, 0x01, 0xf9e9d9c9 },
130 { 0x0007f0, 1, 0x01, 0x00003210 },
131 { 0x0007f1, 1, 0x01, 0x00007654 },
132 { 0x0007f2, 1, 0x01, 0x00000098 },
133 { 0x0005a5, 1, 0x01, 0x00000001 },
134 { 0x000980, 128, 0x01, 0x00000000 },
135 { 0x000468, 1, 0x01, 0x00000004 },
136 { 0x00046c, 1, 0x01, 0x00000001 },
137 { 0x000470, 96, 0x01, 0x00000000 },
138 { 0x000510, 16, 0x01, 0x3f800000 },
139 { 0x000520, 1, 0x01, 0x000002b6 },
140 { 0x000529, 1, 0x01, 0x00000001 },
141 { 0x000530, 16, 0x01, 0xffff0000 },
142 { 0x000585, 1, 0x01, 0x0000003f },
143 { 0x000576, 1, 0x01, 0x00000003 },
144 { 0x00057b, 1, 0x01, 0x00000059 },
145 { 0x000586, 1, 0x01, 0x00000040 },
146 { 0x000582, 2, 0x01, 0x00000080 },
147 { 0x0005c2, 1, 0x01, 0x00000001 },
148 { 0x000638, 2, 0x01, 0x00000001 },
149 { 0x00063a, 1, 0x01, 0x00000002 },
150 { 0x00063b, 2, 0x01, 0x00000001 },
151 { 0x00063d, 1, 0x01, 0x00000002 },
152 { 0x00063e, 1, 0x01, 0x00000001 },
153 { 0x0008b8, 8, 0x01, 0x00000001 },
154 { 0x000900, 8, 0x01, 0x00000001 },
155 { 0x000908, 8, 0x01, 0x00000002 },
156 { 0x000910, 16, 0x01, 0x00000001 },
157 { 0x000920, 8, 0x01, 0x00000002 },
158 { 0x000928, 8, 0x01, 0x00000001 },
159 { 0x000662, 1, 0x01, 0x00000001 },
160 { 0x000648, 9, 0x01, 0x00000001 },
161 { 0x000658, 1, 0x01, 0x0000000f },
162 { 0x0007ff, 1, 0x01, 0x0000000a },
163 { 0x00066a, 1, 0x01, 0x40000000 },
164 { 0x00066b, 1, 0x01, 0x10000000 },
165 { 0x00066c, 2, 0x01, 0xffff0000 },
166 { 0x0007af, 2, 0x01, 0x00000008 },
167 { 0x0007f6, 1, 0x01, 0x00000001 },
168 { 0x00080b, 1, 0x01, 0x00000002 },
169 { 0x0006b2, 1, 0x01, 0x00000055 },
170 { 0x0007ad, 1, 0x01, 0x00000003 },
171 { 0x000937, 1, 0x01, 0x00000001 },
172 { 0x000971, 1, 0x01, 0x00000008 },
173 { 0x000972, 1, 0x01, 0x00000040 },
174 { 0x000973, 1, 0x01, 0x0000012c },
175 { 0x00097c, 1, 0x01, 0x00000040 },
176 { 0x000979, 1, 0x01, 0x00000003 },
177 { 0x000975, 1, 0x01, 0x00000020 },
178 { 0x000976, 1, 0x01, 0x00000001 },
179 { 0x000977, 1, 0x01, 0x00000020 },
180 { 0x000978, 1, 0x01, 0x00000001 },
181 { 0x000957, 1, 0x01, 0x00000003 },
182 { 0x00095e, 1, 0x01, 0x20164010 },
183 { 0x00095f, 1, 0x01, 0x00000020 },
184 { 0x000a0d, 1, 0x01, 0x00000006 },
185 { 0x00097d, 1, 0x01, 0x00000020 },
186 { 0x000683, 1, 0x01, 0x00000006 },
187 { 0x000685, 1, 0x01, 0x003fffff },
188 { 0x000687, 1, 0x01, 0x003fffff },
189 { 0x0006a0, 1, 0x01, 0x00000005 },
190 { 0x000840, 1, 0x01, 0x00400008 },
191 { 0x000841, 1, 0x01, 0x08000080 },
192 { 0x000842, 1, 0x01, 0x00400008 },
193 { 0x000843, 1, 0x01, 0x08000080 },
194 { 0x0006aa, 1, 0x01, 0x00000001 },
195 { 0x0006ab, 1, 0x01, 0x00000002 },
196 { 0x0006ac, 1, 0x01, 0x00000080 },
197 { 0x0006ad, 2, 0x01, 0x00000100 },
198 { 0x0006b1, 1, 0x01, 0x00000011 },
199 { 0x0006bb, 1, 0x01, 0x000000cf },
200 { 0x0006ce, 1, 0x01, 0x2a712488 },
201 { 0x000739, 1, 0x01, 0x4085c000 },
202 { 0x00073a, 1, 0x01, 0x00000080 },
203 { 0x000786, 1, 0x01, 0x80000100 },
204 { 0x00073c, 1, 0x01, 0x00010100 },
205 { 0x00073d, 1, 0x01, 0x02800000 },
206 { 0x000787, 1, 0x01, 0x000000cf },
207 { 0x00078c, 1, 0x01, 0x00000008 },
208 { 0x000792, 1, 0x01, 0x00000001 },
209 { 0x000794, 3, 0x01, 0x00000001 },
210 { 0x000797, 1, 0x01, 0x000000cf },
211 { 0x000836, 1, 0x01, 0x00000001 },
212 { 0x00079a, 1, 0x01, 0x00000002 },
213 { 0x000833, 1, 0x01, 0x04444480 },
214 { 0x0007a1, 1, 0x01, 0x00000001 },
215 { 0x0007a3, 3, 0x01, 0x00000001 },
216 { 0x000831, 1, 0x01, 0x00000004 },
217 { 0x000b07, 1, 0x01, 0x00000002 },
218 { 0x000b08, 2, 0x01, 0x00000100 },
219 { 0x000b0a, 1, 0x01, 0x00000001 },
220 { 0x000a04, 1, 0x01, 0x000000ff },
221 { 0x000a0b, 1, 0x01, 0x00000040 },
222 { 0x00097f, 1, 0x01, 0x00000100 },
223 { 0x000a02, 1, 0x01, 0x00000001 },
224 { 0x000809, 1, 0x01, 0x00000007 },
225 { 0x00c221, 1, 0x01, 0x00000040 },
226 { 0x00c1b0, 8, 0x01, 0x0000000f },
227 { 0x00c1b8, 1, 0x01, 0x0fac6881 },
228 { 0x00c1b9, 1, 0x01, 0x00fac688 },
229 { 0x00c401, 1, 0x01, 0x00000001 },
230 { 0x00c402, 1, 0x01, 0x00010001 },
231 { 0x00c403, 2, 0x01, 0x00000001 },
232 { 0x00c40e, 1, 0x01, 0x00000020 },
233 { 0x00c500, 1, 0x01, 0x00000003 },
234 { 0x01e100, 1, 0x01, 0x00000001 },
235 { 0x001000, 1, 0x01, 0x00000002 },
236 { 0x0006aa, 1, 0x01, 0x00000001 },
237 { 0x0006ad, 2, 0x01, 0x00000100 },
238 { 0x0006b1, 1, 0x01, 0x00000011 },
239 { 0x00078c, 1, 0x01, 0x00000008 },
240 { 0x000792, 1, 0x01, 0x00000001 },
241 { 0x000794, 3, 0x01, 0x00000001 },
242 { 0x000797, 1, 0x01, 0x000000cf },
243 { 0x00079a, 1, 0x01, 0x00000002 },
244 { 0x000833, 1, 0x01, 0x04444480 },
245 { 0x0007a1, 1, 0x01, 0x00000001 },
246 { 0x0007a3, 3, 0x01, 0x00000001 },
247 { 0x000831, 1, 0x01, 0x00000004 },
248 { 0x01e100, 1, 0x01, 0x00000001 },
249 { 0x001000, 1, 0x01, 0x00000008 },
250 { 0x000039, 3, 0x01, 0x00000000 },
251 { 0x000380, 1, 0x01, 0x00000001 },
252 { 0x000366, 2, 0x01, 0x00000000 },
253 { 0x000368, 1, 0x01, 0x00000fff },
254 { 0x000370, 2, 0x01, 0x00000000 },
255 { 0x000372, 1, 0x01, 0x000fffff },
256 { 0x000813, 1, 0x01, 0x00000006 },
257 { 0x000814, 1, 0x01, 0x00000008 },
258 { 0x000957, 1, 0x01, 0x00000003 },
259 { 0x000b07, 1, 0x01, 0x00000002 },
260 { 0x000b08, 2, 0x01, 0x00000100 },
261 { 0x000b0a, 1, 0x01, 0x00000001 },
262 { 0x000a04, 1, 0x01, 0x000000ff },
263 { 0x000a0b, 1, 0x01, 0x00000040 },
264 { 0x00097f, 1, 0x01, 0x00000100 },
265 { 0x000a02, 1, 0x01, 0x00000001 },
266 { 0x000809, 1, 0x01, 0x00000007 },
267 { 0x00c221, 1, 0x01, 0x00000040 },
268 { 0x00c401, 1, 0x01, 0x00000001 },
269 { 0x00c402, 1, 0x01, 0x00010001 },
270 { 0x00c403, 2, 0x01, 0x00000001 },
271 { 0x00c40e, 1, 0x01, 0x00000020 },
272 { 0x00c500, 1, 0x01, 0x00000003 },
273 { 0x01e100, 1, 0x01, 0x00000001 },
274 { 0x001000, 1, 0x01, 0x00000001 },
275 { 0x000b07, 1, 0x01, 0x00000002 },
276 { 0x000b08, 2, 0x01, 0x00000100 },
277 { 0x000b0a, 1, 0x01, 0x00000001 },
278 { 0x01e100, 1, 0x01, 0x00000001 },
279 {}
280};
281
282static const struct nvc0_graph_pack
283nvf0_grctx_pack_icmd[] = {
284 { nvf0_grctx_init_icmd_0 },
285 {}
286};
287
288static const struct nvc0_graph_init
289nvf0_grctx_init_a197_0[] = {
290 { 0x000800, 8, 0x40, 0x00000000 },
291 { 0x000804, 8, 0x40, 0x00000000 },
292 { 0x000808, 8, 0x40, 0x00000400 },
293 { 0x00080c, 8, 0x40, 0x00000300 },
294 { 0x000810, 1, 0x04, 0x000000cf },
295 { 0x000850, 7, 0x40, 0x00000000 },
296 { 0x000814, 8, 0x40, 0x00000040 },
297 { 0x000818, 8, 0x40, 0x00000001 },
298 { 0x00081c, 8, 0x40, 0x00000000 },
299 { 0x000820, 8, 0x40, 0x00000000 },
300 { 0x001c00, 16, 0x10, 0x00000000 },
301 { 0x001c04, 16, 0x10, 0x00000000 },
302 { 0x001c08, 16, 0x10, 0x00000000 },
303 { 0x001c0c, 16, 0x10, 0x00000000 },
304 { 0x001d00, 16, 0x10, 0x00000000 },
305 { 0x001d04, 16, 0x10, 0x00000000 },
306 { 0x001d08, 16, 0x10, 0x00000000 },
307 { 0x001d0c, 16, 0x10, 0x00000000 },
308 { 0x001f00, 16, 0x08, 0x00000000 },
309 { 0x001f04, 16, 0x08, 0x00000000 },
310 { 0x001f80, 16, 0x08, 0x00000000 },
311 { 0x001f84, 16, 0x08, 0x00000000 },
312 { 0x002000, 1, 0x04, 0x00000000 },
313 { 0x002040, 1, 0x04, 0x00000011 },
314 { 0x002080, 1, 0x04, 0x00000020 },
315 { 0x0020c0, 1, 0x04, 0x00000030 },
316 { 0x002100, 1, 0x04, 0x00000040 },
317 { 0x002140, 1, 0x04, 0x00000051 },
318 { 0x00200c, 6, 0x40, 0x00000001 },
319 { 0x002010, 1, 0x04, 0x00000000 },
320 { 0x002050, 1, 0x04, 0x00000000 },
321 { 0x002090, 1, 0x04, 0x00000001 },
322 { 0x0020d0, 1, 0x04, 0x00000002 },
323 { 0x002110, 1, 0x04, 0x00000003 },
324 { 0x002150, 1, 0x04, 0x00000004 },
325 { 0x000380, 4, 0x20, 0x00000000 },
326 { 0x000384, 4, 0x20, 0x00000000 },
327 { 0x000388, 4, 0x20, 0x00000000 },
328 { 0x00038c, 4, 0x20, 0x00000000 },
329 { 0x000700, 4, 0x10, 0x00000000 },
330 { 0x000704, 4, 0x10, 0x00000000 },
331 { 0x000708, 4, 0x10, 0x00000000 },
332 { 0x002800, 128, 0x04, 0x00000000 },
333 { 0x000a00, 16, 0x20, 0x00000000 },
334 { 0x000a04, 16, 0x20, 0x00000000 },
335 { 0x000a08, 16, 0x20, 0x00000000 },
336 { 0x000a0c, 16, 0x20, 0x00000000 },
337 { 0x000a10, 16, 0x20, 0x00000000 },
338 { 0x000a14, 16, 0x20, 0x00000000 },
339 { 0x000c00, 16, 0x10, 0x00000000 },
340 { 0x000c04, 16, 0x10, 0x00000000 },
341 { 0x000c08, 16, 0x10, 0x00000000 },
342 { 0x000c0c, 16, 0x10, 0x3f800000 },
343 { 0x000d00, 8, 0x08, 0xffff0000 },
344 { 0x000d04, 8, 0x08, 0xffff0000 },
345 { 0x000e00, 16, 0x10, 0x00000000 },
346 { 0x000e04, 16, 0x10, 0xffff0000 },
347 { 0x000e08, 16, 0x10, 0xffff0000 },
348 { 0x000d40, 4, 0x08, 0x00000000 },
349 { 0x000d44, 4, 0x08, 0x00000000 },
350 { 0x001e00, 8, 0x20, 0x00000001 },
351 { 0x001e04, 8, 0x20, 0x00000001 },
352 { 0x001e08, 8, 0x20, 0x00000002 },
353 { 0x001e0c, 8, 0x20, 0x00000001 },
354 { 0x001e10, 8, 0x20, 0x00000001 },
355 { 0x001e14, 8, 0x20, 0x00000002 },
356 { 0x001e18, 8, 0x20, 0x00000001 },
357 { 0x003400, 128, 0x04, 0x00000000 },
358 { 0x00030c, 1, 0x04, 0x00000001 },
359 { 0x001944, 1, 0x04, 0x00000000 },
360 { 0x001514, 1, 0x04, 0x00000000 },
361 { 0x000d68, 1, 0x04, 0x0000ffff },
362 { 0x00121c, 1, 0x04, 0x0fac6881 },
363 { 0x000fac, 1, 0x04, 0x00000001 },
364 { 0x001538, 1, 0x04, 0x00000001 },
365 { 0x000fe0, 2, 0x04, 0x00000000 },
366 { 0x000fe8, 1, 0x04, 0x00000014 },
367 { 0x000fec, 1, 0x04, 0x00000040 },
368 { 0x000ff0, 1, 0x04, 0x00000000 },
369 { 0x00179c, 1, 0x04, 0x00000000 },
370 { 0x001228, 1, 0x04, 0x00000400 },
371 { 0x00122c, 1, 0x04, 0x00000300 },
372 { 0x001230, 1, 0x04, 0x00010001 },
373 { 0x0007f8, 1, 0x04, 0x00000000 },
374 { 0x0015b4, 1, 0x04, 0x00000001 },
375 { 0x0015cc, 1, 0x04, 0x00000000 },
376 { 0x001534, 1, 0x04, 0x00000000 },
377 { 0x000fb0, 1, 0x04, 0x00000000 },
378 { 0x0015d0, 1, 0x04, 0x00000000 },
379 { 0x00153c, 1, 0x04, 0x00000000 },
380 { 0x0016b4, 1, 0x04, 0x00000003 },
381 { 0x000fbc, 4, 0x04, 0x0000ffff },
382 { 0x000df8, 2, 0x04, 0x00000000 },
383 { 0x001948, 1, 0x04, 0x00000000 },
384 { 0x001970, 1, 0x04, 0x00000001 },
385 { 0x00161c, 1, 0x04, 0x000009f0 },
386 { 0x000dcc, 1, 0x04, 0x00000010 },
387 { 0x00163c, 1, 0x04, 0x00000000 },
388 { 0x0015e4, 1, 0x04, 0x00000000 },
389 { 0x001160, 32, 0x04, 0x25e00040 },
390 { 0x001880, 32, 0x04, 0x00000000 },
391 { 0x000f84, 2, 0x04, 0x00000000 },
392 { 0x0017c8, 2, 0x04, 0x00000000 },
393 { 0x0017d0, 1, 0x04, 0x000000ff },
394 { 0x0017d4, 1, 0x04, 0xffffffff },
395 { 0x0017d8, 1, 0x04, 0x00000002 },
396 { 0x0017dc, 1, 0x04, 0x00000000 },
397 { 0x0015f4, 2, 0x04, 0x00000000 },
398 { 0x001434, 2, 0x04, 0x00000000 },
399 { 0x000d74, 1, 0x04, 0x00000000 },
400 { 0x000dec, 1, 0x04, 0x00000001 },
401 { 0x0013a4, 1, 0x04, 0x00000000 },
402 { 0x001318, 1, 0x04, 0x00000001 },
403 { 0x001644, 1, 0x04, 0x00000000 },
404 { 0x000748, 1, 0x04, 0x00000000 },
405 { 0x000de8, 1, 0x04, 0x00000000 },
406 { 0x001648, 1, 0x04, 0x00000000 },
407 { 0x0012a4, 1, 0x04, 0x00000000 },
408 { 0x001120, 4, 0x04, 0x00000000 },
409 { 0x001118, 1, 0x04, 0x00000000 },
410 { 0x00164c, 1, 0x04, 0x00000000 },
411 { 0x001658, 1, 0x04, 0x00000000 },
412 { 0x001910, 1, 0x04, 0x00000290 },
413 { 0x001518, 1, 0x04, 0x00000000 },
414 { 0x00165c, 1, 0x04, 0x00000001 },
415 { 0x001520, 1, 0x04, 0x00000000 },
416 { 0x001604, 1, 0x04, 0x00000000 },
417 { 0x001570, 1, 0x04, 0x00000000 },
418 { 0x0013b0, 2, 0x04, 0x3f800000 },
419 { 0x00020c, 1, 0x04, 0x00000000 },
420 { 0x001670, 1, 0x04, 0x30201000 },
421 { 0x001674, 1, 0x04, 0x70605040 },
422 { 0x001678, 1, 0x04, 0xb8a89888 },
423 { 0x00167c, 1, 0x04, 0xf8e8d8c8 },
424 { 0x00166c, 1, 0x04, 0x00000000 },
425 { 0x001680, 1, 0x04, 0x00ffff00 },
426 { 0x0012d0, 1, 0x04, 0x00000003 },
427 { 0x0012d4, 1, 0x04, 0x00000002 },
428 { 0x001684, 2, 0x04, 0x00000000 },
429 { 0x000dac, 2, 0x04, 0x00001b02 },
430 { 0x000db4, 1, 0x04, 0x00000000 },
431 { 0x00168c, 1, 0x04, 0x00000000 },
432 { 0x0015bc, 1, 0x04, 0x00000000 },
433 { 0x00156c, 1, 0x04, 0x00000000 },
434 { 0x00187c, 1, 0x04, 0x00000000 },
435 { 0x001110, 1, 0x04, 0x00000001 },
436 { 0x000dc0, 3, 0x04, 0x00000000 },
437 { 0x001234, 1, 0x04, 0x00000000 },
438 { 0x001690, 1, 0x04, 0x00000000 },
439 { 0x0012ac, 1, 0x04, 0x00000001 },
440 { 0x0002c4, 1, 0x04, 0x00000000 },
441 { 0x000790, 5, 0x04, 0x00000000 },
442 { 0x00077c, 1, 0x04, 0x00000000 },
443 { 0x001000, 1, 0x04, 0x00000010 },
444 { 0x0010fc, 1, 0x04, 0x00000000 },
445 { 0x001290, 1, 0x04, 0x00000000 },
446 { 0x000218, 1, 0x04, 0x00000010 },
447 { 0x0012d8, 1, 0x04, 0x00000000 },
448 { 0x0012dc, 1, 0x04, 0x00000010 },
449 { 0x000d94, 1, 0x04, 0x00000001 },
450 { 0x00155c, 2, 0x04, 0x00000000 },
451 { 0x001564, 1, 0x04, 0x00000fff },
452 { 0x001574, 2, 0x04, 0x00000000 },
453 { 0x00157c, 1, 0x04, 0x000fffff },
454 { 0x001354, 1, 0x04, 0x00000000 },
455 { 0x001610, 1, 0x04, 0x00000012 },
456 { 0x001608, 2, 0x04, 0x00000000 },
457 { 0x00260c, 1, 0x04, 0x00000000 },
458 { 0x0007ac, 1, 0x04, 0x00000000 },
459 { 0x00162c, 1, 0x04, 0x00000003 },
460 { 0x000210, 1, 0x04, 0x00000000 },
461 { 0x000320, 1, 0x04, 0x00000000 },
462 { 0x000324, 6, 0x04, 0x3f800000 },
463 { 0x000750, 1, 0x04, 0x00000000 },
464 { 0x000760, 1, 0x04, 0x39291909 },
465 { 0x000764, 1, 0x04, 0x79695949 },
466 { 0x000768, 1, 0x04, 0xb9a99989 },
467 { 0x00076c, 1, 0x04, 0xf9e9d9c9 },
468 { 0x000770, 1, 0x04, 0x30201000 },
469 { 0x000774, 1, 0x04, 0x70605040 },
470 { 0x000778, 1, 0x04, 0x00009080 },
471 { 0x000780, 1, 0x04, 0x39291909 },
472 { 0x000784, 1, 0x04, 0x79695949 },
473 { 0x000788, 1, 0x04, 0xb9a99989 },
474 { 0x00078c, 1, 0x04, 0xf9e9d9c9 },
475 { 0x0007d0, 1, 0x04, 0x30201000 },
476 { 0x0007d4, 1, 0x04, 0x70605040 },
477 { 0x0007d8, 1, 0x04, 0x00009080 },
478 { 0x00037c, 1, 0x04, 0x00000001 },
479 { 0x000740, 2, 0x04, 0x00000000 },
480 { 0x002600, 1, 0x04, 0x00000000 },
481 { 0x001918, 1, 0x04, 0x00000000 },
482 { 0x00191c, 1, 0x04, 0x00000900 },
483 { 0x001920, 1, 0x04, 0x00000405 },
484 { 0x001308, 1, 0x04, 0x00000001 },
485 { 0x001924, 1, 0x04, 0x00000000 },
486 { 0x0013ac, 1, 0x04, 0x00000000 },
487 { 0x00192c, 1, 0x04, 0x00000001 },
488 { 0x00193c, 1, 0x04, 0x00002c1c },
489 { 0x000d7c, 1, 0x04, 0x00000000 },
490 { 0x000f8c, 1, 0x04, 0x00000000 },
491 { 0x0002c0, 1, 0x04, 0x00000001 },
492 { 0x001510, 1, 0x04, 0x00000000 },
493 { 0x001940, 1, 0x04, 0x00000000 },
494 { 0x000ff4, 2, 0x04, 0x00000000 },
495 { 0x00194c, 2, 0x04, 0x00000000 },
496 { 0x001968, 1, 0x04, 0x00000000 },
497 { 0x001590, 1, 0x04, 0x0000003f },
498 { 0x0007e8, 4, 0x04, 0x00000000 },
499 { 0x00196c, 1, 0x04, 0x00000011 },
500 { 0x0002e4, 1, 0x04, 0x0000b001 },
501 { 0x00036c, 2, 0x04, 0x00000000 },
502 { 0x00197c, 1, 0x04, 0x00000000 },
503 { 0x000fcc, 2, 0x04, 0x00000000 },
504 { 0x0002d8, 1, 0x04, 0x00000040 },
505 { 0x001980, 1, 0x04, 0x00000080 },
506 { 0x001504, 1, 0x04, 0x00000080 },
507 { 0x001984, 1, 0x04, 0x00000000 },
508 { 0x000300, 1, 0x04, 0x00000001 },
509 { 0x0013a8, 1, 0x04, 0x00000000 },
510 { 0x0012ec, 1, 0x04, 0x00000000 },
511 { 0x001310, 1, 0x04, 0x00000000 },
512 { 0x001314, 1, 0x04, 0x00000001 },
513 { 0x001380, 1, 0x04, 0x00000000 },
514 { 0x001384, 4, 0x04, 0x00000001 },
515 { 0x001394, 1, 0x04, 0x00000000 },
516 { 0x00139c, 1, 0x04, 0x00000000 },
517 { 0x001398, 1, 0x04, 0x00000000 },
518 { 0x001594, 1, 0x04, 0x00000000 },
519 { 0x001598, 4, 0x04, 0x00000001 },
520 { 0x000f54, 3, 0x04, 0x00000000 },
521 { 0x0019bc, 1, 0x04, 0x00000000 },
522 { 0x000f9c, 2, 0x04, 0x00000000 },
523 { 0x0012cc, 1, 0x04, 0x00000000 },
524 { 0x0012e8, 1, 0x04, 0x00000000 },
525 { 0x00130c, 1, 0x04, 0x00000001 },
526 { 0x001360, 8, 0x04, 0x00000000 },
527 { 0x00133c, 2, 0x04, 0x00000001 },
528 { 0x001344, 1, 0x04, 0x00000002 },
529 { 0x001348, 2, 0x04, 0x00000001 },
530 { 0x001350, 1, 0x04, 0x00000002 },
531 { 0x001358, 1, 0x04, 0x00000001 },
532 { 0x0012e4, 1, 0x04, 0x00000000 },
533 { 0x00131c, 4, 0x04, 0x00000000 },
534 { 0x0019c0, 1, 0x04, 0x00000000 },
535 { 0x001140, 1, 0x04, 0x00000000 },
536 { 0x0019c4, 1, 0x04, 0x00000000 },
537 { 0x0019c8, 1, 0x04, 0x00001500 },
538 { 0x00135c, 1, 0x04, 0x00000000 },
539 { 0x000f90, 1, 0x04, 0x00000000 },
540 { 0x0019e0, 8, 0x04, 0x00000001 },
541 { 0x0019cc, 1, 0x04, 0x00000001 },
542 { 0x0015b8, 1, 0x04, 0x00000000 },
543 { 0x001a00, 1, 0x04, 0x00001111 },
544 { 0x001a04, 7, 0x04, 0x00000000 },
545 { 0x000d6c, 2, 0x04, 0xffff0000 },
546 { 0x0010f8, 1, 0x04, 0x00001010 },
547 { 0x000d80, 5, 0x04, 0x00000000 },
548 { 0x000da0, 1, 0x04, 0x00000000 },
549 { 0x0007a4, 2, 0x04, 0x00000000 },
550 { 0x001508, 1, 0x04, 0x80000000 },
551 { 0x00150c, 1, 0x04, 0x40000000 },
552 { 0x001668, 1, 0x04, 0x00000000 },
553 { 0x000318, 2, 0x04, 0x00000008 },
554 { 0x000d9c, 1, 0x04, 0x00000001 },
555 { 0x000ddc, 1, 0x04, 0x00000002 },
556 { 0x000374, 1, 0x04, 0x00000000 },
557 { 0x000378, 1, 0x04, 0x00000020 },
558 { 0x0007dc, 1, 0x04, 0x00000000 },
559 { 0x00074c, 1, 0x04, 0x00000055 },
560 { 0x001420, 1, 0x04, 0x00000003 },
561 { 0x0017bc, 2, 0x04, 0x00000000 },
562 { 0x0017c4, 1, 0x04, 0x00000001 },
563 { 0x001008, 1, 0x04, 0x00000008 },
564 { 0x00100c, 1, 0x04, 0x00000040 },
565 { 0x001010, 1, 0x04, 0x0000012c },
566 { 0x000d60, 1, 0x04, 0x00000040 },
567 { 0x00075c, 1, 0x04, 0x00000003 },
568 { 0x001018, 1, 0x04, 0x00000020 },
569 { 0x00101c, 1, 0x04, 0x00000001 },
570 { 0x001020, 1, 0x04, 0x00000020 },
571 { 0x001024, 1, 0x04, 0x00000001 },
572 { 0x001444, 3, 0x04, 0x00000000 },
573 { 0x000360, 1, 0x04, 0x20164010 },
574 { 0x000364, 1, 0x04, 0x00000020 },
575 { 0x000368, 1, 0x04, 0x00000000 },
576 { 0x000de4, 1, 0x04, 0x00000000 },
577 { 0x000204, 1, 0x04, 0x00000006 },
578 { 0x000208, 1, 0x04, 0x00000000 },
579 { 0x0002cc, 2, 0x04, 0x003fffff },
580 { 0x001220, 1, 0x04, 0x00000005 },
581 { 0x000fdc, 1, 0x04, 0x00000000 },
582 { 0x000f98, 1, 0x04, 0x00400008 },
583 { 0x001284, 1, 0x04, 0x08000080 },
584 { 0x001450, 1, 0x04, 0x00400008 },
585 { 0x001454, 1, 0x04, 0x08000080 },
586 { 0x000214, 1, 0x04, 0x00000000 },
587 {}
588};
589
590const struct nvc0_graph_pack
591nvf0_grctx_pack_mthd[] = {
592 { nvf0_grctx_init_a197_0, 0xa197 },
593 { nvc0_grctx_init_902d_0, 0x902d },
594 {}
595};
596
597static const struct nvc0_graph_init
598nvf0_grctx_init_fe_0[] = {
29 { 0x404004, 8, 0x04, 0x00000000 }, 599 { 0x404004, 8, 0x04, 0x00000000 },
30 { 0x404024, 1, 0x04, 0x0000e000 }, 600 { 0x404024, 1, 0x04, 0x0000e000 },
31 { 0x404028, 8, 0x04, 0x00000000 }, 601 { 0x404028, 8, 0x04, 0x00000000 },
@@ -50,8 +620,8 @@ nvf0_grctx_init_unk40xx[] = {
50 {} 620 {}
51}; 621};
52 622
53struct nvc0_graph_init 623const struct nvc0_graph_init
54nvf0_grctx_init_unk44xx[] = { 624nvf0_grctx_init_pri_0[] = {
55 { 0x404404, 12, 0x04, 0x00000000 }, 625 { 0x404404, 12, 0x04, 0x00000000 },
56 { 0x404438, 1, 0x04, 0x00000000 }, 626 { 0x404438, 1, 0x04, 0x00000000 },
57 { 0x404460, 2, 0x04, 0x00000000 }, 627 { 0x404460, 2, 0x04, 0x00000000 },
@@ -62,23 +632,18 @@ nvf0_grctx_init_unk44xx[] = {
62 {} 632 {}
63}; 633};
64 634
65struct nvc0_graph_init 635const struct nvc0_graph_init
66nvf0_grctx_init_unk5bxx[] = { 636nvf0_grctx_init_cwd_0[] = {
67 { 0x405b00, 1, 0x04, 0x00000000 }, 637 { 0x405b00, 1, 0x04, 0x00000000 },
68 { 0x405b10, 1, 0x04, 0x00001000 }, 638 { 0x405b10, 1, 0x04, 0x00001000 },
69 { 0x405b20, 1, 0x04, 0x04000000 }, 639 { 0x405b20, 1, 0x04, 0x04000000 },
70 {} 640 {}
71}; 641};
72 642
73struct nvc0_graph_init 643static const struct nvc0_graph_init
74nvf0_grctx_init_unk60xx[] = { 644nvf0_grctx_init_pd_0[] = {
75 { 0x406020, 1, 0x04, 0x034103c1 }, 645 { 0x406020, 1, 0x04, 0x034103c1 },
76 { 0x406028, 4, 0x04, 0x00000001 }, 646 { 0x406028, 4, 0x04, 0x00000001 },
77 {}
78};
79
80static struct nvc0_graph_init
81nvf0_grctx_init_unk64xx[] = {
82 { 0x4064a8, 1, 0x04, 0x00000000 }, 647 { 0x4064a8, 1, 0x04, 0x00000000 },
83 { 0x4064ac, 1, 0x04, 0x00003fff }, 648 { 0x4064ac, 1, 0x04, 0x00003fff },
84 { 0x4064b0, 3, 0x04, 0x00000000 }, 649 { 0x4064b0, 3, 0x04, 0x00000000 },
@@ -90,8 +655,8 @@ nvf0_grctx_init_unk64xx[] = {
90 {} 655 {}
91}; 656};
92 657
93static struct nvc0_graph_init 658static const struct nvc0_graph_init
94nvf0_grctx_init_unk88xx[] = { 659nvf0_grctx_init_be_0[] = {
95 { 0x408800, 1, 0x04, 0x12802a3c }, 660 { 0x408800, 1, 0x04, 0x12802a3c },
96 { 0x408804, 1, 0x04, 0x00000040 }, 661 { 0x408804, 1, 0x04, 0x00000040 },
97 { 0x408808, 1, 0x04, 0x1003e005 }, 662 { 0x408808, 1, 0x04, 0x1003e005 },
@@ -103,22 +668,23 @@ nvf0_grctx_init_unk88xx[] = {
103 {} 668 {}
104}; 669};
105 670
106static struct nvc0_graph_init 671static const struct nvc0_graph_pack
107nvf0_grctx_init_gpc_0[] = { 672nvf0_grctx_pack_hub[] = {
108 { 0x418380, 1, 0x04, 0x00000016 }, 673 { nvc0_grctx_init_main_0 },
109 { 0x418400, 1, 0x04, 0x38004e00 }, 674 { nvf0_grctx_init_fe_0 },
110 { 0x418404, 1, 0x04, 0x71e0ffff }, 675 { nvf0_grctx_init_pri_0 },
111 { 0x41840c, 1, 0x04, 0x00001008 }, 676 { nve4_grctx_init_memfmt_0 },
112 { 0x418410, 1, 0x04, 0x0fff0fff }, 677 { nve4_grctx_init_ds_0 },
113 { 0x418414, 1, 0x04, 0x02200fff }, 678 { nvf0_grctx_init_cwd_0 },
114 { 0x418450, 6, 0x04, 0x00000000 }, 679 { nvf0_grctx_init_pd_0 },
115 { 0x418468, 1, 0x04, 0x00000001 }, 680 { nvc0_grctx_init_rstr2d_0 },
116 { 0x41846c, 2, 0x04, 0x00000000 }, 681 { nve4_grctx_init_scc_0 },
117 { 0x418600, 1, 0x04, 0x0000001f }, 682 { nvf0_grctx_init_be_0 },
118 { 0x418684, 1, 0x04, 0x0000000f }, 683 {}
119 { 0x418700, 1, 0x04, 0x00000002 }, 684};
120 { 0x418704, 1, 0x04, 0x00000080 }, 685
121 { 0x418708, 3, 0x04, 0x00000000 }, 686static const struct nvc0_graph_init
687nvf0_grctx_init_setup_0[] = {
122 { 0x418800, 1, 0x04, 0x7006860a }, 688 { 0x418800, 1, 0x04, 0x7006860a },
123 { 0x418808, 1, 0x04, 0x00000000 }, 689 { 0x418808, 1, 0x04, 0x00000000 },
124 { 0x41880c, 1, 0x04, 0x00000030 }, 690 { 0x41880c, 1, 0x04, 0x00000030 },
@@ -129,36 +695,31 @@ nvf0_grctx_init_gpc_0[] = {
129 { 0x4188e0, 1, 0x04, 0x01000000 }, 695 { 0x4188e0, 1, 0x04, 0x01000000 },
130 { 0x4188e8, 5, 0x04, 0x00000000 }, 696 { 0x4188e8, 5, 0x04, 0x00000000 },
131 { 0x4188fc, 1, 0x04, 0x20100018 }, 697 { 0x4188fc, 1, 0x04, 0x20100018 },
132 { 0x41891c, 1, 0x04, 0x00ff00ff }, 698 {}
133 { 0x418924, 1, 0x04, 0x00000000 }, 699};
134 { 0x418928, 1, 0x04, 0x00ffff00 }, 700
135 { 0x41892c, 1, 0x04, 0x0000ff00 }, 701const struct nvc0_graph_init
136 { 0x418b00, 1, 0x04, 0x00000006 }, 702nvf0_grctx_init_gpc_unk_2[] = {
137 { 0x418b08, 1, 0x04, 0x0a418820 },
138 { 0x418b0c, 1, 0x04, 0x062080e6 },
139 { 0x418b10, 1, 0x04, 0x020398a4 },
140 { 0x418b14, 1, 0x04, 0x0e629062 },
141 { 0x418b18, 1, 0x04, 0x0a418820 },
142 { 0x418b1c, 1, 0x04, 0x000000e6 },
143 { 0x418bb8, 1, 0x04, 0x00000103 },
144 { 0x418c08, 1, 0x04, 0x00000001 },
145 { 0x418c10, 8, 0x04, 0x00000000 },
146 { 0x418c40, 1, 0x04, 0xffffffff },
147 { 0x418c6c, 1, 0x04, 0x00000001 },
148 { 0x418c80, 1, 0x04, 0x20200004 },
149 { 0x418c8c, 1, 0x04, 0x00000001 },
150 { 0x418d24, 1, 0x04, 0x00000000 }, 703 { 0x418d24, 1, 0x04, 0x00000000 },
151 { 0x419000, 1, 0x04, 0x00000780 },
152 { 0x419004, 2, 0x04, 0x00000000 },
153 { 0x419014, 1, 0x04, 0x00000004 },
154 {} 704 {}
155}; 705};
156 706
157static struct nvc0_graph_init 707static const struct nvc0_graph_pack
158nvf0_grctx_init_tpc[] = { 708nvf0_grctx_pack_gpc[] = {
159 { 0x419848, 1, 0x04, 0x00000000 }, 709 { nvc0_grctx_init_gpc_unk_0 },
160 { 0x419864, 1, 0x04, 0x00000129 }, 710 { nvd9_grctx_init_prop_0 },
161 { 0x419888, 1, 0x04, 0x00000000 }, 711 { nvd9_grctx_init_gpc_unk_1 },
712 { nvf0_grctx_init_setup_0 },
713 { nvc0_grctx_init_zcull_0 },
714 { nvd9_grctx_init_crstr_0 },
715 { nve4_grctx_init_gpm_0 },
716 { nvf0_grctx_init_gpc_unk_2 },
717 { nvc0_grctx_init_gcc_0 },
718 {}
719};
720
721static const struct nvc0_graph_init
722nvf0_grctx_init_tex_0[] = {
162 { 0x419a00, 1, 0x04, 0x000000f0 }, 723 { 0x419a00, 1, 0x04, 0x000000f0 },
163 { 0x419a04, 1, 0x04, 0x00000001 }, 724 { 0x419a04, 1, 0x04, 0x00000001 },
164 { 0x419a08, 1, 0x04, 0x00000021 }, 725 { 0x419a08, 1, 0x04, 0x00000021 },
@@ -169,14 +730,29 @@ nvf0_grctx_init_tpc[] = {
169 { 0x419a20, 1, 0x04, 0x00020800 }, 730 { 0x419a20, 1, 0x04, 0x00020800 },
170 { 0x419a30, 1, 0x04, 0x00000001 }, 731 { 0x419a30, 1, 0x04, 0x00000001 },
171 { 0x419ac4, 1, 0x04, 0x0037f440 }, 732 { 0x419ac4, 1, 0x04, 0x0037f440 },
733 {}
734};
735
736const struct nvc0_graph_init
737nvf0_grctx_init_mpc_0[] = {
172 { 0x419c00, 1, 0x04, 0x0000001a }, 738 { 0x419c00, 1, 0x04, 0x0000001a },
173 { 0x419c04, 1, 0x04, 0x80000006 }, 739 { 0x419c04, 1, 0x04, 0x80000006 },
174 { 0x419c08, 1, 0x04, 0x00000002 }, 740 { 0x419c08, 1, 0x04, 0x00000002 },
175 { 0x419c20, 1, 0x04, 0x00000000 }, 741 { 0x419c20, 1, 0x04, 0x00000000 },
176 { 0x419c24, 1, 0x04, 0x00084210 }, 742 { 0x419c24, 1, 0x04, 0x00084210 },
177 { 0x419c28, 1, 0x04, 0x3efbefbe }, 743 { 0x419c28, 1, 0x04, 0x3efbefbe },
744 {}
745};
746
747const struct nvc0_graph_init
748nvf0_grctx_init_l1c_0[] = {
178 { 0x419ce8, 1, 0x04, 0x00000000 }, 749 { 0x419ce8, 1, 0x04, 0x00000000 },
179 { 0x419cf4, 1, 0x04, 0x00000203 }, 750 { 0x419cf4, 1, 0x04, 0x00000203 },
751 {}
752};
753
754static const struct nvc0_graph_init
755nvf0_grctx_init_sm_0[] = {
180 { 0x419e04, 1, 0x04, 0x00000000 }, 756 { 0x419e04, 1, 0x04, 0x00000000 },
181 { 0x419e08, 1, 0x04, 0x0000001d }, 757 { 0x419e08, 1, 0x04, 0x0000001d },
182 { 0x419e0c, 1, 0x04, 0x00000000 }, 758 { 0x419e0c, 1, 0x04, 0x00000000 },
@@ -189,8 +765,8 @@ nvf0_grctx_init_tpc[] = {
189 { 0x419e5c, 3, 0x04, 0x00000000 }, 765 { 0x419e5c, 3, 0x04, 0x00000000 },
190 { 0x419e68, 1, 0x04, 0x00000002 }, 766 { 0x419e68, 1, 0x04, 0x00000002 },
191 { 0x419e6c, 12, 0x04, 0x00000000 }, 767 { 0x419e6c, 12, 0x04, 0x00000000 },
192 { 0x419eac, 1, 0x04, 0x00001fcf }, 768 { 0x419eac, 1, 0x04, 0x00001f8f },
193 { 0x419eb0, 1, 0x04, 0x0db00da0 }, 769 { 0x419eb0, 1, 0x04, 0x0db00d2f },
194 { 0x419eb8, 1, 0x04, 0x00000000 }, 770 { 0x419eb8, 1, 0x04, 0x00000000 },
195 { 0x419ec8, 1, 0x04, 0x0001304f }, 771 { 0x419ec8, 1, 0x04, 0x0001304f },
196 { 0x419f30, 4, 0x04, 0x00000000 }, 772 { 0x419f30, 4, 0x04, 0x00000000 },
@@ -203,24 +779,36 @@ nvf0_grctx_init_tpc[] = {
203 {} 779 {}
204}; 780};
205 781
206static struct nvc0_graph_init 782static const struct nvc0_graph_pack
207nvf0_grctx_init_unk[] = { 783nvf0_grctx_pack_tpc[] = {
208 { 0x41be24, 1, 0x04, 0x00000006 }, 784 { nvd7_grctx_init_pe_0 },
785 { nvf0_grctx_init_tex_0 },
786 { nvf0_grctx_init_mpc_0 },
787 { nvf0_grctx_init_l1c_0 },
788 { nvf0_grctx_init_sm_0 },
789 {}
790};
791
792static const struct nvc0_graph_init
793nvf0_grctx_init_cbm_0[] = {
209 { 0x41bec0, 1, 0x04, 0x10000000 }, 794 { 0x41bec0, 1, 0x04, 0x10000000 },
210 { 0x41bec4, 1, 0x04, 0x00037f7f }, 795 { 0x41bec4, 1, 0x04, 0x00037f7f },
211 { 0x41bee4, 1, 0x04, 0x00000000 }, 796 { 0x41bee4, 1, 0x04, 0x00000000 },
212 { 0x41bf00, 1, 0x04, 0x0a418820 },
213 { 0x41bf04, 1, 0x04, 0x062080e6 },
214 { 0x41bf08, 1, 0x04, 0x020398a4 },
215 { 0x41bf0c, 1, 0x04, 0x0e629062 },
216 { 0x41bf10, 1, 0x04, 0x0a418820 },
217 { 0x41bf14, 1, 0x04, 0x000000e6 },
218 { 0x41bfd0, 1, 0x04, 0x00900103 },
219 { 0x41bfe0, 1, 0x04, 0x00400001 },
220 { 0x41bfe4, 1, 0x04, 0x00000000 },
221 {} 797 {}
222}; 798};
223 799
800static const struct nvc0_graph_pack
801nvf0_grctx_pack_ppc[] = {
802 { nve4_grctx_init_pes_0 },
803 { nvf0_grctx_init_cbm_0 },
804 { nvd7_grctx_init_wwdx_0 },
805 {}
806};
807
808/*******************************************************************************
809 * PGRAPH context implementation
810 ******************************************************************************/
811
224static void 812static void
225nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) 813nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
226{ 814{
@@ -273,39 +861,6 @@ nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
273 mmio_list(0x17e920, 0x00090a05, 0, 0); 861 mmio_list(0x17e920, 0x00090a05, 0, 0);
274} 862}
275 863
276static struct nvc0_graph_init *
277nvf0_grctx_init_hub[] = {
278 nvc0_grctx_init_base,
279 nvf0_grctx_init_unk40xx,
280 nvf0_grctx_init_unk44xx,
281 nve4_grctx_init_unk46xx,
282 nve4_grctx_init_unk47xx,
283 nve4_grctx_init_unk58xx,
284 nvf0_grctx_init_unk5bxx,
285 nvf0_grctx_init_unk60xx,
286 nvf0_grctx_init_unk64xx,
287 nve4_grctx_init_unk80xx,
288 nvf0_grctx_init_unk88xx,
289 NULL
290};
291
292struct nvc0_graph_init *
293nvf0_grctx_init_gpc[] = {
294 nvf0_grctx_init_gpc_0,
295 nvc0_grctx_init_gpc_1,
296 nvf0_grctx_init_tpc,
297 nvf0_grctx_init_unk,
298 NULL
299};
300
301static struct nvc0_graph_mthd
302nvf0_grctx_init_mthd[] = {
303 { 0xa197, nvc1_grctx_init_9097, },
304 { 0x902d, nvc0_grctx_init_902d, },
305 { 0x902d, nvc0_grctx_init_mthd_magic, },
306 {}
307};
308
309struct nouveau_oclass * 864struct nouveau_oclass *
310nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) { 865nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
311 .base.handle = NV_ENGCTX(GR, 0xf0), 866 .base.handle = NV_ENGCTX(GR, 0xf0),
@@ -317,11 +872,14 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
317 .rd32 = _nouveau_graph_context_rd32, 872 .rd32 = _nouveau_graph_context_rd32,
318 .wr32 = _nouveau_graph_context_wr32, 873 .wr32 = _nouveau_graph_context_wr32,
319 }, 874 },
320 .main = nve4_grctx_generate_main, 875 .main = nve4_grctx_generate_main,
321 .mods = nvf0_grctx_generate_mods, 876 .mods = nvf0_grctx_generate_mods,
322 .unkn = nve4_grctx_generate_unkn, 877 .unkn = nve4_grctx_generate_unkn,
323 .hub = nvf0_grctx_init_hub, 878 .hub = nvf0_grctx_pack_hub,
324 .gpc = nvf0_grctx_init_gpc, 879 .gpc = nvf0_grctx_pack_gpc,
325 .icmd = nvc0_grctx_init_icmd, 880 .zcull = nvc0_grctx_pack_zcull,
326 .mthd = nvf0_grctx_init_mthd, 881 .tpc = nvf0_grctx_pack_tpc,
882 .ppc = nvf0_grctx_pack_ppc,
883 .icmd = nvf0_grctx_pack_icmd,
884 .mthd = nvf0_grctx_pack_mthd,
327}.base; 885}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
index e148961b8075..e37d8106ae1a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
@@ -228,7 +228,7 @@ mmctx_xfer:
228 and $r11 0x1f 228 and $r11 0x1f
229 cmpu b32 $r11 0x10 229 cmpu b32 $r11 0x10
230 bra ne #mmctx_fini_wait 230 bra ne #mmctx_fini_wait
231 mov $r10 2 // DONE_MMCTX 231 mov $r10 5 // DONE_MMCTX
232 call(wait_donez) 232 call(wait_donez)
233 bra #mmctx_done 233 bra #mmctx_done
234 mmctx_stop: 234 mmctx_stop:
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
index 96cbcea3b2c9..2f7345f7fe07 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
@@ -78,7 +78,12 @@ error:
78// 78//
79init: 79init:
80 clear b32 $r0 80 clear b32 $r0
81 mov $sp $r0 81
82 // setup stack
83 nv_iord($r1, NV_PGRAPH_GPCX_GPCCS_CAPS, 0)
84 extr $r1 $r1 9:17
85 shl b32 $r1 8
86 mov $sp $r1
82 87
83 // enable fifo access 88 // enable fifo access
84 mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO 89 mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5
new file mode 100644
index 000000000000..e730603891d7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#define NV_PGRAPH_GPCX_UNK__SIZE 0x00000002
26
27#define CHIPSET GK208
28#include "macros.fuc"
29
30.section #gm107_grgpc_data
31#define INCLUDE_DATA
32#include "com.fuc"
33#include "gpc.fuc"
34#undef INCLUDE_DATA
35
36.section #gm107_grgpc_code
37#define INCLUDE_CODE
38bra #init
39#include "com.fuc"
40#include "gpc.fuc"
41.align 256
42#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h
new file mode 100644
index 000000000000..6d53b67dd3c4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h
@@ -0,0 +1,473 @@
1uint32_t gm107_grgpc_data[] = {
2/* 0x0000: gpc_mmio_list_head */
3 0x0000006c,
4/* 0x0004: gpc_mmio_list_tail */
5/* 0x0004: tpc_mmio_list_head */
6 0x0000006c,
7/* 0x0008: tpc_mmio_list_tail */
8/* 0x0008: unk_mmio_list_head */
9 0x0000006c,
10/* 0x000c: unk_mmio_list_tail */
11 0x0000006c,
12/* 0x0010: gpc_id */
13 0x00000000,
14/* 0x0014: tpc_count */
15 0x00000000,
16/* 0x0018: tpc_mask */
17 0x00000000,
18/* 0x001c: unk_count */
19 0x00000000,
20/* 0x0020: unk_mask */
21 0x00000000,
22/* 0x0024: cmd_queue */
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29 0x00000000,
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41};
42
43uint32_t gm107_grgpc_code[] = {
44 0x03140ef5,
45/* 0x0004: queue_put */
46 0x9800d898,
47 0x86f001d9,
48 0xf489a408,
49 0x020f0b1b,
50 0x0002f87e,
51/* 0x001a: queue_put_next */
52 0x98c400f8,
53 0x0384b607,
54 0xb6008dbb,
55 0x8eb50880,
56 0x018fb500,
57 0xf00190b6,
58 0xd9b50f94,
59/* 0x0037: queue_get */
60 0xf400f801,
61 0xd8980131,
62 0x01d99800,
63 0x0bf489a4,
64 0x0789c421,
65 0xbb0394b6,
66 0x90b6009d,
67 0x009e9808,
68 0xb6019f98,
69 0x84f00180,
70 0x00d8b50f,
71/* 0x0063: queue_get_done */
72 0xf80132f4,
73/* 0x0065: nv_rd32 */
74 0xf0ecb200,
75 0x00801fc9,
76 0x0cf601ca,
77/* 0x0073: nv_rd32_wait */
78 0x8c04bd00,
79 0xcf01ca00,
80 0xccc800cc,
81 0xf61bf41f,
82 0xec7e060a,
83 0x008f0000,
84 0xffcf01cb,
85/* 0x008f: nv_wr32 */
86 0x8000f800,
87 0xf601cc00,
88 0x04bd000f,
89 0xc9f0ecb2,
90 0x1ec9f01f,
91 0x01ca0080,
92 0xbd000cf6,
93/* 0x00a9: nv_wr32_wait */
94 0xca008c04,
95 0x00cccf01,
96 0xf41fccc8,
97 0x00f8f61b,
98/* 0x00b8: wait_donez */
99 0x99f094bd,
100 0x37008000,
101 0x0009f602,
102 0x008004bd,
103 0x0af60206,
104/* 0x00cf: wait_donez_ne */
105 0x8804bd00,
106 0xcf010000,
107 0x8aff0088,
108 0xf61bf488,
109 0x99f094bd,
110 0x17008000,
111 0x0009f602,
112 0x00f804bd,
113/* 0x00ec: wait_doneo */
114 0x99f094bd,
115 0x37008000,
116 0x0009f602,
117 0x008004bd,
118 0x0af60206,
119/* 0x0103: wait_doneo_e */
120 0x8804bd00,
121 0xcf010000,
122 0x8aff0088,
123 0xf60bf488,
124 0x99f094bd,
125 0x17008000,
126 0x0009f602,
127 0x00f804bd,
128/* 0x0120: mmctx_size */
129/* 0x0122: nv_mmctx_size_loop */
130 0xe89894bd,
131 0x1a85b600,
132 0xb60180b6,
133 0x98bb0284,
134 0x04e0b600,
135 0x1bf4efa4,
136 0xf89fb2ec,
137/* 0x013d: mmctx_xfer */
138 0xf094bd00,
139 0x00800199,
140 0x09f60237,
141 0xbd04bd00,
142 0x05bbfd94,
143 0x800f0bf4,
144 0xf601c400,
145 0x04bd000b,
146/* 0x015f: mmctx_base_disabled */
147 0xfd0099f0,
148 0x0bf405ee,
149 0xc6008018,
150 0x000ef601,
151 0x008004bd,
152 0x0ff601c7,
153 0xf004bd00,
154/* 0x017a: mmctx_multi_disabled */
155 0xabc80199,
156 0x10b4b600,
157 0xc80cb9f0,
158 0xe4b601ae,
159 0x05befd11,
160 0x01c50080,
161 0xbd000bf6,
162/* 0x0195: mmctx_exec_loop */
163/* 0x0195: mmctx_wait_free */
164 0xc5008e04,
165 0x00eecf01,
166 0xf41fe4f0,
167 0xce98f60b,
168 0x05e9fd00,
169 0x01c80080,
170 0xbd000ef6,
171 0x04c0b604,
172 0x1bf4cda4,
173 0x02abc8df,
174/* 0x01bf: mmctx_fini_wait */
175 0x8b1c1bf4,
176 0xcf01c500,
177 0xb4f000bb,
178 0x10b4b01f,
179 0x0af31bf4,
180 0x00b87e05,
181 0x250ef400,
182/* 0x01d8: mmctx_stop */
183 0xb600abc8,
184 0xb9f010b4,
185 0x12b9f00c,
186 0x01c50080,
187 0xbd000bf6,
188/* 0x01ed: mmctx_stop_wait */
189 0xc5008b04,
190 0x00bbcf01,
191 0xf412bbc8,
192/* 0x01fa: mmctx_done */
193 0x94bdf61b,
194 0x800199f0,
195 0xf6021700,
196 0x04bd0009,
197/* 0x020a: strand_wait */
198 0xa0f900f8,
199 0xb87e020a,
200 0xa0fc0000,
201/* 0x0216: strand_pre */
202 0x0c0900f8,
203 0x024afc80,
204 0xbd0009f6,
205 0x020a7e04,
206/* 0x0227: strand_post */
207 0x0900f800,
208 0x4afc800d,
209 0x0009f602,
210 0x0a7e04bd,
211 0x00f80002,
212/* 0x0238: strand_set */
213 0xfc800f0c,
214 0x0cf6024f,
215 0x0c04bd00,
216 0x4afc800b,
217 0x000cf602,
218 0xfc8004bd,
219 0x0ef6024f,
220 0x0c04bd00,
221 0x4afc800a,
222 0x000cf602,
223 0x0a7e04bd,
224 0x00f80002,
225/* 0x0268: strand_ctx_init */
226 0x99f094bd,
227 0x37008003,
228 0x0009f602,
229 0x167e04bd,
230 0x030e0002,
231 0x0002387e,
232 0xfc80c4bd,
233 0x0cf60247,
234 0x0c04bd00,
235 0x4afc8001,
236 0x000cf602,
237 0x0a7e04bd,
238 0x0c920002,
239 0x46fc8001,
240 0x000cf602,
241 0x020c04bd,
242 0x024afc80,
243 0xbd000cf6,
244 0x020a7e04,
245 0x02277e00,
246 0x42008800,
247 0x20008902,
248 0x0099cf02,
249/* 0x02c7: ctx_init_strand_loop */
250 0xf608fe95,
251 0x8ef6008e,
252 0x808acf40,
253 0xb606a5b6,
254 0xeabb01a0,
255 0x0480b600,
256 0xf40192b6,
257 0xe4b6e81b,
258 0xf2efbc08,
259 0x99f094bd,
260 0x17008003,
261 0x0009f602,
262 0x00f804bd,
263/* 0x02f8: error */
264 0xffb2e0f9,
265 0x4098148e,
266 0x00008f7e,
267 0xffb2010f,
268 0x409c1c8e,
269 0x00008f7e,
270 0x00f8e0fc,
271/* 0x0314: init */
272 0x004104bd,
273 0x0011cf42,
274 0x010911e7,
275 0xfe0814b6,
276 0x02020014,
277 0xf6120040,
278 0x04bd0002,
279 0xfe047241,
280 0x00400010,
281 0x0000f607,
282 0x040204bd,
283 0xf6040040,
284 0x04bd0002,
285 0x821031f4,
286 0xcf018200,
287 0x01030022,
288 0xbb1f24f0,
289 0x32b60432,
290 0x0502b501,
291 0x820603b5,
292 0xcf018600,
293 0x02b50022,
294 0x0c308e04,
295 0xbd24bd50,
296/* 0x0377: init_unk_loop */
297 0x7e44bd34,
298 0xb0000065,
299 0x0bf400f6,
300 0xbb010f0e,
301 0x4ffd04f2,
302 0x0130b605,
303/* 0x038c: init_unk_next */
304 0xb60120b6,
305 0x26b004e0,
306 0xe21bf402,
307/* 0x0398: init_unk_done */
308 0xb50703b5,
309 0x00820804,
310 0x22cf0201,
311 0x9534bd00,
312 0x00800825,
313 0x05f601c0,
314 0x8004bd00,
315 0xf601c100,
316 0x04bd0005,
317 0x98000e98,
318 0x207e010f,
319 0x2fbb0001,
320 0x003fbb00,
321 0x98010e98,
322 0x207e020f,
323 0x0e980001,
324 0x00effd05,
325 0xbb002ebb,
326 0x0e98003e,
327 0x030f9802,
328 0x0001207e,
329 0xfd070e98,
330 0x2ebb00ef,
331 0x003ebb00,
332 0x800235b6,
333 0xf601d300,
334 0x04bd0003,
335 0xb60825b6,
336 0x20b60635,
337 0x0130b601,
338 0xb60824b6,
339 0x2fb20834,
340 0x0002687e,
341 0x80003fbb,
342 0xf6020100,
343 0x04bd0003,
344 0x29f024bd,
345 0x3000801f,
346 0x0002f602,
347/* 0x0436: main */
348 0x31f404bd,
349 0x0028f400,
350 0x377e240d,
351 0x01f40000,
352 0x04e4b0f4,
353 0xfe1d18f4,
354 0x06020181,
355 0x12fd20bd,
356 0x01e4b604,
357 0xfe051efd,
358 0x097e0018,
359 0x0ef40005,
360/* 0x0465: main_not_ctx_xfer */
361 0x10ef94d4,
362 0x7e01f5f0,
363 0xf40002f8,
364/* 0x0472: ih */
365 0x80f9c70e,
366 0xf90188fe,
367 0xf990f980,
368 0xf9b0f9a0,
369 0xf9e0f9d0,
370 0x4a04bdf0,
371 0xaacf0200,
372 0x04abc400,
373 0x0d1f0bf4,
374 0x1a004e24,
375 0x4f00eecf,
376 0xffcf1900,
377 0x00047e00,
378 0x40010e00,
379 0x0ef61d00,
380/* 0x04af: ih_no_fifo */
381 0x4004bd00,
382 0x0af60100,
383 0xfc04bd00,
384 0xfce0fcf0,
385 0xfcb0fcd0,
386 0xfc90fca0,
387 0x0088fe80,
388 0x32f480fc,
389/* 0x04cf: hub_barrier_done */
390 0x0f01f800,
391 0x040e9801,
392 0xb204febb,
393 0x94188eff,
394 0x008f7e40,
395/* 0x04e3: ctx_redswitch */
396 0x0f00f800,
397 0x85008020,
398 0x000ff601,
399 0x080e04bd,
400/* 0x04f0: ctx_redswitch_delay */
401 0xf401e2b6,
402 0xf5f1fd1b,
403 0xf5f10800,
404 0x00800200,
405 0x0ff60185,
406 0xf804bd00,
407/* 0x0509: ctx_xfer */
408 0x81008000,
409 0x000ff602,
410 0x11f404bd,
411 0x04e37e07,
412/* 0x0519: ctx_xfer_not_load */
413 0x02167e00,
414 0x8024bd00,
415 0xf60247fc,
416 0x04bd0002,
417 0xb6012cf0,
418 0xfc800320,
419 0x02f6024a,
420 0xf004bd00,
421 0xa5f001ac,
422 0x00008b02,
423 0x040c9850,
424 0xbb0fc4b6,
425 0x0c9800bc,
426 0x010d9800,
427 0x3d7e000e,
428 0xacf00001,
429 0x40008b01,
430 0x040c9850,
431 0xbb0fc4b6,
432 0x0c9800bc,
433 0x020d9801,
434 0x4e060f98,
435 0x3d7e0800,
436 0xacf00001,
437 0x04a5f001,
438 0x5030008b,
439 0xb6040c98,
440 0xbcbb0fc4,
441 0x020c9800,
442 0x98030d98,
443 0x004e080f,
444 0x013d7e02,
445 0x020a7e00,
446 0x0601f400,
447/* 0x05a3: ctx_xfer_post */
448 0x7e0712f4,
449/* 0x05a7: ctx_xfer_done */
450 0x7e000227,
451 0xf80004cf,
452 0x00000000,
453 0x00000000,
454 0x00000000,
455 0x00000000,
456 0x00000000,
457 0x00000000,
458 0x00000000,
459 0x00000000,
460 0x00000000,
461 0x00000000,
462 0x00000000,
463 0x00000000,
464 0x00000000,
465 0x00000000,
466 0x00000000,
467 0x00000000,
468 0x00000000,
469 0x00000000,
470 0x00000000,
471 0x00000000,
472 0x00000000,
473};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
index 27dc1280dc10..31922707794f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
@@ -177,7 +177,7 @@ uint32_t nv108_grgpc_code[] = {
177 0xb4f000bb, 177 0xb4f000bb,
178 0x10b4b01f, 178 0x10b4b01f,
179 0x0af31bf4, 179 0x0af31bf4,
180 0x00b87e02, 180 0x00b87e05,
181 0x250ef400, 181 0x250ef400,
182/* 0x01d8: mmctx_stop */ 182/* 0x01d8: mmctx_stop */
183 0xb600abc8, 183 0xb600abc8,
@@ -269,186 +269,186 @@ uint32_t nv108_grgpc_code[] = {
269 0x00008f7e, 269 0x00008f7e,
270 0x00f8e0fc, 270 0x00f8e0fc,
271/* 0x0314: init */ 271/* 0x0314: init */
272 0x04fe04bd, 272 0x004104bd,
273 0x40020200, 273 0x0011cf42,
274 0x02f61200, 274 0x010911e7,
275 0x4104bd00, 275 0xfe0814b6,
276 0x10fe0465, 276 0x02020014,
277 0x07004000, 277 0xf6120040,
278 0xbd0000f6, 278 0x04bd0002,
279 0x40040204, 279 0xfe047241,
280 0x02f60400, 280 0x00400010,
281 0xf404bd00, 281 0x0000f607,
282 0x00821031, 282 0x040204bd,
283 0x22cf0182, 283 0xf6040040,
284 0xf0010300, 284 0x04bd0002,
285 0x32bb1f24, 285 0x821031f4,
286 0x0132b604, 286 0xcf018200,
287 0xb50502b5, 287 0x01030022,
288 0x00820603, 288 0xbb1f24f0,
289 0x22cf0186, 289 0x32b60432,
290 0x0402b500, 290 0x0502b501,
291 0x500c308e, 291 0x820603b5,
292 0x34bd24bd, 292 0xcf018600,
293/* 0x036a: init_unk_loop */ 293 0x02b50022,
294 0x657e44bd, 294 0x0c308e04,
295 0xf6b00000, 295 0xbd24bd50,
296 0x0e0bf400, 296/* 0x0377: init_unk_loop */
297 0xf2bb010f, 297 0x7e44bd34,
298 0x054ffd04, 298 0xb0000065,
299/* 0x037f: init_unk_next */ 299 0x0bf400f6,
300 0xb60130b6, 300 0xbb010f0e,
301 0xe0b60120, 301 0x4ffd04f2,
302 0x0126b004, 302 0x0130b605,
303/* 0x038b: init_unk_done */ 303/* 0x038c: init_unk_next */
304 0xb5e21bf4, 304 0xb60120b6,
305 0x04b50703, 305 0x26b004e0,
306 0x01008208, 306 0xe21bf401,
307 0x0022cf02, 307/* 0x0398: init_unk_done */
308 0x259534bd, 308 0xb50703b5,
309 0xc0008008, 309 0x00820804,
310 0x0005f601, 310 0x22cf0201,
311 0x008004bd, 311 0x9534bd00,
312 0x05f601c1, 312 0x00800825,
313 0x9804bd00, 313 0x05f601c0,
314 0x0f98000e, 314 0x8004bd00,
315 0x01207e01, 315 0xf601c100,
316 0x002fbb00, 316 0x04bd0005,
317 0x98003fbb, 317 0x98000e98,
318 0x0f98010e, 318 0x207e010f,
319 0x01207e02, 319 0x2fbb0001,
320 0x050e9800, 320 0x003fbb00,
321 0xbb00effd, 321 0x98010e98,
322 0x3ebb002e, 322 0x207e020f,
323 0x020e9800, 323 0x0e980001,
324 0x7e030f98, 324 0x00effd05,
325 0x98000120, 325 0xbb002ebb,
326 0xeffd070e, 326 0x0e98003e,
327 0x002ebb00, 327 0x030f9802,
328 0xb6003ebb, 328 0x0001207e,
329 0x00800235, 329 0xfd070e98,
330 0x03f601d3, 330 0x2ebb00ef,
331 0xb604bd00, 331 0x003ebb00,
332 0x35b60825, 332 0x800235b6,
333 0x0120b606, 333 0xf601d300,
334 0xb60130b6, 334 0x04bd0003,
335 0x34b60824, 335 0xb60825b6,
336 0x7e2fb208, 336 0x20b60635,
337 0xbb000268, 337 0x0130b601,
338 0x0080003f, 338 0xb60824b6,
339 0x03f60201, 339 0x2fb20834,
340 0xbd04bd00, 340 0x0002687e,
341 0x1f29f024, 341 0x80003fbb,
342 0x02300080, 342 0xf6020100,
343 0xbd0002f6, 343 0x04bd0003,
344/* 0x0429: main */ 344 0x29f024bd,
345 0x0031f404, 345 0x3000801f,
346 0x0d0028f4, 346 0x0002f602,
347 0x00377e24, 347/* 0x0436: main */
348 0xf401f400, 348 0x31f404bd,
349 0xf404e4b0, 349 0x0028f400,
350 0x81fe1d18, 350 0x377e240d,
351 0xbd060201, 351 0x01f40000,
352 0x0412fd20, 352 0x04e4b0f4,
353 0xfd01e4b6, 353 0xfe1d18f4,
354 0x18fe051e, 354 0x06020181,
355 0x04fc7e00, 355 0x12fd20bd,
356 0xd40ef400, 356 0x01e4b604,
357/* 0x0458: main_not_ctx_xfer */ 357 0xfe051efd,
358 0xf010ef94, 358 0x097e0018,
359 0xf87e01f5, 359 0x0ef40005,
360 0x0ef40002, 360/* 0x0465: main_not_ctx_xfer */
361/* 0x0465: ih */ 361 0x10ef94d4,
362 0xfe80f9c7, 362 0x7e01f5f0,
363 0x80f90188, 363 0xf40002f8,
364 0xa0f990f9, 364/* 0x0472: ih */
365 0xd0f9b0f9, 365 0x80f9c70e,
366 0xf0f9e0f9, 366 0xf90188fe,
367 0x004a04bd, 367 0xf990f980,
368 0x00aacf02, 368 0xf9b0f9a0,
369 0xf404abc4, 369 0xf9e0f9d0,
370 0x240d1f0b, 370 0x4a04bdf0,
371 0xcf1a004e, 371 0xaacf0200,
372 0x004f00ee, 372 0x04abc400,
373 0x00ffcf19, 373 0x0d1f0bf4,
374 0x0000047e, 374 0x1a004e24,
375 0x0040010e, 375 0x4f00eecf,
376 0x000ef61d, 376 0xffcf1900,
377/* 0x04a2: ih_no_fifo */ 377 0x00047e00,
378 0x004004bd, 378 0x40010e00,
379 0x000af601, 379 0x0ef61d00,
380 0xf0fc04bd, 380/* 0x04af: ih_no_fifo */
381 0xd0fce0fc, 381 0x4004bd00,
382 0xa0fcb0fc, 382 0x0af60100,
383 0x80fc90fc, 383 0xfc04bd00,
384 0xfc0088fe, 384 0xfce0fcf0,
385 0x0032f480, 385 0xfcb0fcd0,
386/* 0x04c2: hub_barrier_done */ 386 0xfc90fca0,
387 0x010f01f8, 387 0x0088fe80,
388 0xbb040e98, 388 0x32f480fc,
389 0xffb204fe, 389/* 0x04cf: hub_barrier_done */
390 0x4094188e, 390 0x0f01f800,
391 0x00008f7e, 391 0x040e9801,
392/* 0x04d6: ctx_redswitch */ 392 0xb204febb,
393 0x200f00f8, 393 0x94188eff,
394 0x01850080, 394 0x008f7e40,
395 0xbd000ff6, 395/* 0x04e3: ctx_redswitch */
396/* 0x04e3: ctx_redswitch_delay */ 396 0x0f00f800,
397 0xb6080e04, 397 0x85008020,
398 0x1bf401e2,
399 0x00f5f1fd,
400 0x00f5f108,
401 0x85008002,
402 0x000ff601, 398 0x000ff601,
403 0x00f804bd, 399 0x080e04bd,
404/* 0x04fc: ctx_xfer */ 400/* 0x04f0: ctx_redswitch_delay */
405 0x02810080, 401 0xf401e2b6,
406 0xbd000ff6, 402 0xf5f1fd1b,
407 0x0711f404, 403 0xf5f10800,
408 0x0004d67e, 404 0x00800200,
409/* 0x050c: ctx_xfer_not_load */ 405 0x0ff60185,
410 0x0002167e, 406 0xf804bd00,
411 0xfc8024bd, 407/* 0x0509: ctx_xfer */
412 0x02f60247, 408 0x81008000,
409 0x000ff602,
410 0x11f404bd,
411 0x04e37e07,
412/* 0x0519: ctx_xfer_not_load */
413 0x02167e00,
414 0x8024bd00,
415 0xf60247fc,
416 0x04bd0002,
417 0xb6012cf0,
418 0xfc800320,
419 0x02f6024a,
413 0xf004bd00, 420 0xf004bd00,
414 0x20b6012c, 421 0xa5f001ac,
415 0x4afc8003, 422 0x00008b02,
416 0x0002f602, 423 0x040c9850,
417 0xacf004bd, 424 0xbb0fc4b6,
418 0x02a5f001, 425 0x0c9800bc,
419 0x5000008b, 426 0x010d9800,
427 0x3d7e000e,
428 0xacf00001,
429 0x40008b01,
430 0x040c9850,
431 0xbb0fc4b6,
432 0x0c9800bc,
433 0x020d9801,
434 0x4e060f98,
435 0x3d7e0800,
436 0xacf00001,
437 0x04a5f001,
438 0x5030008b,
420 0xb6040c98, 439 0xb6040c98,
421 0xbcbb0fc4, 440 0xbcbb0fc4,
422 0x000c9800, 441 0x020c9800,
423 0x0e010d98, 442 0x98030d98,
424 0x013d7e00, 443 0x004e080f,
425 0x01acf000, 444 0x013d7e02,
426 0x5040008b, 445 0x020a7e00,
427 0xb6040c98, 446 0x0601f400,
428 0xbcbb0fc4, 447/* 0x05a3: ctx_xfer_post */
429 0x010c9800, 448 0x7e0712f4,
430 0x98020d98, 449/* 0x05a7: ctx_xfer_done */
431 0x004e060f, 450 0x7e000227,
432 0x013d7e08, 451 0xf80004cf,
433 0x01acf000,
434 0x8b04a5f0,
435 0x98503000,
436 0xc4b6040c,
437 0x00bcbb0f,
438 0x98020c98,
439 0x0f98030d,
440 0x02004e08,
441 0x00013d7e,
442 0x00020a7e,
443 0xf40601f4,
444/* 0x0596: ctx_xfer_post */
445 0x277e0712,
446/* 0x059a: ctx_xfer_done */
447 0xc27e0002,
448 0x00f80004,
449 0x00000000,
450 0x00000000,
451 0x00000000,
452 0x00000000, 452 0x00000000,
453 0x00000000, 453 0x00000000,
454 0x00000000, 454 0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
index 0e7b01efae8d..325cc7b7b2fb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
@@ -192,7 +192,7 @@ uint32_t nvc0_grgpc_code[] = {
192 0x1fb4f000, 192 0x1fb4f000,
193 0xf410b4b0, 193 0xf410b4b0,
194 0xa7f0f01b, 194 0xa7f0f01b,
195 0xd021f402, 195 0xd021f405,
196/* 0x0223: mmctx_stop */ 196/* 0x0223: mmctx_stop */
197 0xc82b0ef4, 197 0xc82b0ef4,
198 0xb4b600ab, 198 0xb4b600ab,
@@ -300,182 +300,182 @@ uint32_t nvc0_grgpc_code[] = {
300 0x21f440e3, 300 0x21f440e3,
301 0xf8e0fc9d, 301 0xf8e0fc9d,
302/* 0x03a1: init */ 302/* 0x03a1: init */
303 0xfe04bd00, 303 0xf104bd00,
304 0x27f00004, 304 0xf0420017,
305 0x0007f102, 305 0x11cf0013,
306 0x0003f012, 306 0x0911e700,
307 0xbd0002d0, 307 0x0814b601,
308 0xd517f104, 308 0xf00014fe,
309 0x0010fe04, 309 0x07f10227,
310 0x070007f1, 310 0x03f01200,
311 0x0002d000,
312 0x17f104bd,
313 0x10fe04e6,
314 0x0007f100,
315 0x0003f007,
316 0xbd0000d0,
317 0x0427f004,
318 0x040007f1,
311 0xd00003f0, 319 0xd00003f0,
312 0x04bd0000,
313 0xf10427f0,
314 0xf0040007,
315 0x02d00003,
316 0xf404bd00,
317 0x27f11031,
318 0x23f08200,
319 0x0022cf01,
320 0xf00137f0,
321 0x32bb1f24,
322 0x0132b604,
323 0x80050280,
324 0x27f10603,
325 0x23f08600,
326 0x0022cf01,
327 0xf1040280,
328 0xf0010027,
329 0x22cf0223,
330 0x9534bd00,
331 0x07f10825,
332 0x03f0c000,
333 0x0005d001,
334 0x07f104bd,
335 0x03f0c100,
336 0x0005d001,
337 0x0e9804bd,
338 0x010f9800,
339 0x015021f5,
340 0xbb002fbb,
341 0x0e98003f,
342 0x020f9801,
343 0x015021f5,
344 0xfd050e98,
345 0x2ebb00ef,
346 0x003ebb00,
347 0xf10235b6,
348 0xf0d30007,
349 0x03d00103,
350 0xb604bd00,
351 0x35b60825,
352 0x0120b606,
353 0xb60130b6,
354 0x34b60824,
355 0x022fb908,
356 0x02d321f5,
357 0xf1003fbb,
358 0xf0010007,
359 0x03d00203,
360 0xbd04bd00,
361 0x1f29f024,
362 0x080007f1,
363 0xd00203f0,
364 0x04bd0002, 320 0x04bd0002,
365/* 0x0498: main */ 321 0xf11031f4,
366 0xf40031f4, 322 0xf0820027,
367 0xd7f00028, 323 0x22cf0123,
368 0x3921f41c, 324 0x0137f000,
369 0xb0f401f4, 325 0xbb1f24f0,
370 0x18f404e4, 326 0x32b60432,
371 0x0181fe1e, 327 0x05028001,
372 0xbd0627f0, 328 0xf1060380,
373 0x0412fd20, 329 0xf0860027,
374 0xfd01e4b6, 330 0x22cf0123,
375 0x18fe051e, 331 0x04028000,
376 0x8d21f500, 332 0x010027f1,
377 0xd30ef405, 333 0xcf0223f0,
378/* 0x04c8: main_not_ctx_xfer */ 334 0x34bd0022,
379 0xf010ef94, 335 0xf1082595,
380 0x21f501f5, 336 0xf0c00007,
381 0x0ef4037e, 337 0x05d00103,
382/* 0x04d5: ih */
383 0xfe80f9c6,
384 0x80f90188,
385 0xa0f990f9,
386 0xd0f9b0f9,
387 0xf0f9e0f9,
388 0xa7f104bd,
389 0xa3f00200,
390 0x00aacf00,
391 0xf404abc4,
392 0xd7f02c0b,
393 0x00e7f11c,
394 0x00e3f01a,
395 0xf100eecf,
396 0xf01900f7,
397 0xffcf00f3,
398 0x0421f400,
399 0xf101e7f0,
400 0xf01d0007,
401 0x0ed00003,
402/* 0x0523: ih_no_fifo */
403 0xf104bd00, 338 0xf104bd00,
404 0xf0010007, 339 0xf0c10007,
405 0x0ad00003, 340 0x05d00103,
406 0xfc04bd00, 341 0x9804bd00,
407 0xfce0fcf0, 342 0x0f98000e,
408 0xfcb0fcd0, 343 0x5021f501,
409 0xfc90fca0, 344 0x002fbb01,
410 0x0088fe80, 345 0x98003fbb,
411 0x32f480fc, 346 0x0f98010e,
412/* 0x0547: hub_barrier_done */ 347 0x5021f502,
413 0xf001f800, 348 0x050e9801,
414 0x0e9801f7, 349 0xbb00effd,
415 0x04febb04, 350 0x3ebb002e,
416 0xf102ffb9, 351 0x0235b600,
417 0xf09418e7, 352 0xd30007f1,
418 0x21f440e3, 353 0xd00103f0,
419/* 0x055f: ctx_redswitch */ 354 0x04bd0003,
420 0xf000f89d, 355 0xb60825b6,
421 0x07f120f7, 356 0x20b60635,
422 0x03f08500, 357 0x0130b601,
423 0x000fd001, 358 0xb60824b6,
424 0xe7f004bd, 359 0x2fb90834,
425/* 0x0571: ctx_redswitch_delay */ 360 0xd321f502,
426 0x01e2b608, 361 0x003fbb02,
427 0xf1fd1bf4, 362 0x010007f1,
428 0xf10800f5, 363 0xd00203f0,
429 0xf10200f5, 364 0x04bd0003,
365 0x29f024bd,
366 0x0007f11f,
367 0x0203f008,
368 0xbd0002d0,
369/* 0x04a9: main */
370 0x0031f404,
371 0xf00028f4,
372 0x21f41cd7,
373 0xf401f439,
374 0xf404e4b0,
375 0x81fe1e18,
376 0x0627f001,
377 0x12fd20bd,
378 0x01e4b604,
379 0xfe051efd,
380 0x21f50018,
381 0x0ef4059e,
382/* 0x04d9: main_not_ctx_xfer */
383 0x10ef94d3,
384 0xf501f5f0,
385 0xf4037e21,
386/* 0x04e6: ih */
387 0x80f9c60e,
388 0xf90188fe,
389 0xf990f980,
390 0xf9b0f9a0,
391 0xf9e0f9d0,
392 0xf104bdf0,
393 0xf00200a7,
394 0xaacf00a3,
395 0x04abc400,
396 0xf02c0bf4,
397 0xe7f11cd7,
398 0xe3f01a00,
399 0x00eecf00,
400 0x1900f7f1,
401 0xcf00f3f0,
402 0x21f400ff,
403 0x01e7f004,
404 0x1d0007f1,
405 0xd00003f0,
406 0x04bd000e,
407/* 0x0534: ih_no_fifo */
408 0x010007f1,
409 0xd00003f0,
410 0x04bd000a,
411 0xe0fcf0fc,
412 0xb0fcd0fc,
413 0x90fca0fc,
414 0x88fe80fc,
415 0xf480fc00,
416 0x01f80032,
417/* 0x0558: hub_barrier_done */
418 0x9801f7f0,
419 0xfebb040e,
420 0x02ffb904,
421 0x9418e7f1,
422 0xf440e3f0,
423 0x00f89d21,
424/* 0x0570: ctx_redswitch */
425 0xf120f7f0,
430 0xf0850007, 426 0xf0850007,
431 0x0fd00103, 427 0x0fd00103,
432 0xf804bd00, 428 0xf004bd00,
433/* 0x058d: ctx_xfer */ 429/* 0x0582: ctx_redswitch_delay */
434 0x0007f100, 430 0xe2b608e7,
435 0x0203f081, 431 0xfd1bf401,
436 0xbd000fd0, 432 0x0800f5f1,
437 0x0711f404, 433 0x0200f5f1,
438 0x055f21f5, 434 0x850007f1,
439/* 0x05a0: ctx_xfer_not_load */ 435 0xd00103f0,
440 0x026a21f5, 436 0x04bd000f,
441 0x07f124bd, 437/* 0x059e: ctx_xfer */
442 0x03f047fc, 438 0x07f100f8,
443 0x0002d002, 439 0x03f08100,
444 0x2cf004bd, 440 0x000fd002,
445 0x0320b601, 441 0x11f404bd,
446 0x4afc07f1, 442 0x7021f507,
447 0xd00203f0, 443/* 0x05b1: ctx_xfer_not_load */
448 0x04bd0002, 444 0x6a21f505,
445 0xf124bd02,
446 0xf047fc07,
447 0x02d00203,
448 0xf004bd00,
449 0x20b6012c,
450 0xfc07f103,
451 0x0203f04a,
452 0xbd0002d0,
453 0x01acf004,
454 0xf102a5f0,
455 0xf00000b7,
456 0x0c9850b3,
457 0x0fc4b604,
458 0x9800bcbb,
459 0x0d98000c,
460 0x00e7f001,
461 0x016f21f5,
449 0xf001acf0, 462 0xf001acf0,
450 0xb7f102a5, 463 0xb7f104a5,
451 0xb3f00000, 464 0xb3f04000,
452 0x040c9850, 465 0x040c9850,
453 0xbb0fc4b6, 466 0xbb0fc4b6,
454 0x0c9800bc, 467 0x0c9800bc,
455 0x010d9800, 468 0x020d9801,
456 0xf500e7f0, 469 0xf1060f98,
457 0xf0016f21, 470 0xf50800e7,
458 0xa5f001ac, 471 0xf5016f21,
459 0x00b7f104, 472 0xf4025e21,
460 0x50b3f040, 473 0x12f40601,
461 0xb6040c98, 474/* 0x0629: ctx_xfer_post */
462 0xbcbb0fc4, 475 0x7f21f507,
463 0x010c9800, 476/* 0x062d: ctx_xfer_done */
464 0x98020d98, 477 0x5821f502,
465 0xe7f1060f, 478 0x0000f805,
466 0x21f50800,
467 0x21f5016f,
468 0x01f4025e,
469 0x0712f406,
470/* 0x0618: ctx_xfer_post */
471 0x027f21f5,
472/* 0x061c: ctx_xfer_done */
473 0x054721f5,
474 0x000000f8,
475 0x00000000,
476 0x00000000,
477 0x00000000,
478 0x00000000,
479 0x00000000, 479 0x00000000,
480 0x00000000, 480 0x00000000,
481 0x00000000, 481 0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
index 84dd32db28a0..d1504a4059c6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
@@ -196,7 +196,7 @@ uint32_t nvd7_grgpc_code[] = {
196 0x1fb4f000, 196 0x1fb4f000,
197 0xf410b4b0, 197 0xf410b4b0,
198 0xa7f0f01b, 198 0xa7f0f01b,
199 0xd021f402, 199 0xd021f405,
200/* 0x0223: mmctx_stop */ 200/* 0x0223: mmctx_stop */
201 0xc82b0ef4, 201 0xc82b0ef4,
202 0xb4b600ab, 202 0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nvd7_grgpc_code[] = {
304 0x21f440e3, 304 0x21f440e3,
305 0xf8e0fc9d, 305 0xf8e0fc9d,
306/* 0x03a1: init */ 306/* 0x03a1: init */
307 0xfe04bd00, 307 0xf104bd00,
308 0x27f00004, 308 0xf0420017,
309 0x0007f102, 309 0x11cf0013,
310 0x0003f012, 310 0x0911e700,
311 0xbd0002d0, 311 0x0814b601,
312 0x1f17f104, 312 0xf00014fe,
313 0x0010fe05, 313 0x07f10227,
314 0x070007f1, 314 0x03f01200,
315 0x0002d000,
316 0x17f104bd,
317 0x10fe0530,
318 0x0007f100,
319 0x0003f007,
320 0xbd0000d0,
321 0x0427f004,
322 0x040007f1,
315 0xd00003f0, 323 0xd00003f0,
316 0x04bd0000, 324 0x04bd0002,
317 0xf10427f0, 325 0xf11031f4,
318 0xf0040007, 326 0xf0820027,
319 0x02d00003, 327 0x22cf0123,
328 0x0137f000,
329 0xbb1f24f0,
330 0x32b60432,
331 0x05028001,
332 0xf1060380,
333 0xf0860027,
334 0x22cf0123,
335 0x04028000,
336 0x0c30e7f1,
337 0xbd50e3f0,
338 0xbd34bd24,
339/* 0x0421: init_unk_loop */
340 0x6821f444,
341 0xf400f6b0,
342 0xf7f00f0b,
343 0x04f2bb01,
344 0xb6054ffd,
345/* 0x0436: init_unk_next */
346 0x20b60130,
347 0x04e0b601,
348 0xf40126b0,
349/* 0x0442: init_unk_done */
350 0x0380e21b,
351 0x08048007,
352 0x010027f1,
353 0xcf0223f0,
354 0x34bd0022,
355 0xf1082595,
356 0xf0c00007,
357 0x05d00103,
358 0xf104bd00,
359 0xf0c10007,
360 0x05d00103,
361 0x9804bd00,
362 0x0f98000e,
363 0x5021f501,
364 0x002fbb01,
365 0x98003fbb,
366 0x0f98010e,
367 0x5021f502,
368 0x050e9801,
369 0xbb00effd,
370 0x3ebb002e,
371 0x020e9800,
372 0xf5030f98,
373 0x98015021,
374 0xeffd070e,
375 0x002ebb00,
376 0xb6003ebb,
377 0x07f10235,
378 0x03f0d300,
379 0x0003d001,
380 0x25b604bd,
381 0x0635b608,
382 0xb60120b6,
383 0x24b60130,
384 0x0834b608,
385 0xf5022fb9,
386 0xbb02d321,
387 0x07f1003f,
388 0x03f00100,
389 0x0003d002,
390 0x24bd04bd,
391 0xf11f29f0,
392 0xf0080007,
393 0x02d00203,
394/* 0x04f3: main */
320 0xf404bd00, 395 0xf404bd00,
321 0x27f11031, 396 0x28f40031,
322 0x23f08200, 397 0x24d7f000,
323 0x0022cf01, 398 0xf43921f4,
324 0xf00137f0, 399 0xe4b0f401,
325 0x32bb1f24, 400 0x1e18f404,
326 0x0132b604, 401 0xf00181fe,
327 0x80050280, 402 0x20bd0627,
328 0x27f10603, 403 0xb60412fd,
329 0x23f08600, 404 0x1efd01e4,
330 0x0022cf01, 405 0x0018fe05,
331 0xf1040280, 406 0x05e821f5,
332 0xf00c30e7, 407/* 0x0523: main_not_ctx_xfer */
333 0x24bd50e3, 408 0x94d30ef4,
334 0x44bd34bd, 409 0xf5f010ef,
335/* 0x0410: init_unk_loop */ 410 0x7e21f501,
336 0xb06821f4, 411 0xc60ef403,
337 0x0bf400f6, 412/* 0x0530: ih */
338 0x01f7f00f, 413 0x88fe80f9,
339 0xfd04f2bb, 414 0xf980f901,
340 0x30b6054f, 415 0xf9a0f990,
341/* 0x0425: init_unk_next */ 416 0xf9d0f9b0,
342 0x0120b601, 417 0xbdf0f9e0,
343 0xb004e0b6, 418 0x00a7f104,
344 0x1bf40126, 419 0x00a3f002,
345/* 0x0431: init_unk_done */ 420 0xc400aacf,
346 0x070380e2, 421 0x0bf404ab,
347 0xf1080480, 422 0x24d7f02c,
348 0xf0010027, 423 0x1a00e7f1,
349 0x22cf0223, 424 0xcf00e3f0,
350 0x9534bd00, 425 0xf7f100ee,
351 0x07f10825, 426 0xf3f01900,
352 0x03f0c000, 427 0x00ffcf00,
353 0x0005d001, 428 0xf00421f4,
429 0x07f101e7,
430 0x03f01d00,
431 0x000ed000,
432/* 0x057e: ih_no_fifo */
354 0x07f104bd, 433 0x07f104bd,
355 0x03f0c100, 434 0x03f00100,
356 0x0005d001, 435 0x000ad000,
357 0x0e9804bd, 436 0xf0fc04bd,
358 0x010f9800, 437 0xd0fce0fc,
359 0x015021f5, 438 0xa0fcb0fc,
360 0xbb002fbb, 439 0x80fc90fc,
361 0x0e98003f, 440 0xfc0088fe,
362 0x020f9801, 441 0x0032f480,
363 0x015021f5, 442/* 0x05a2: hub_barrier_done */
364 0xfd050e98, 443 0xf7f001f8,
365 0x2ebb00ef, 444 0x040e9801,
366 0x003ebb00, 445 0xb904febb,
367 0x98020e98, 446 0xe7f102ff,
368 0x21f5030f, 447 0xe3f09418,
369 0x0e980150, 448 0x9d21f440,
370 0x00effd07, 449/* 0x05ba: ctx_redswitch */
371 0xbb002ebb, 450 0xf7f000f8,
372 0x35b6003e, 451 0x0007f120,
373 0x0007f102,
374 0x0103f0d3,
375 0xbd0003d0,
376 0x0825b604,
377 0xb60635b6,
378 0x30b60120,
379 0x0824b601,
380 0xb90834b6,
381 0x21f5022f,
382 0x3fbb02d3,
383 0x0007f100,
384 0x0203f001,
385 0xbd0003d0,
386 0xf024bd04,
387 0x07f11f29,
388 0x03f00800,
389 0x0002d002,
390/* 0x04e2: main */
391 0x31f404bd,
392 0x0028f400,
393 0xf424d7f0,
394 0x01f43921,
395 0x04e4b0f4,
396 0xfe1e18f4,
397 0x27f00181,
398 0xfd20bd06,
399 0xe4b60412,
400 0x051efd01,
401 0xf50018fe,
402 0xf405d721,
403/* 0x0512: main_not_ctx_xfer */
404 0xef94d30e,
405 0x01f5f010,
406 0x037e21f5,
407/* 0x051f: ih */
408 0xf9c60ef4,
409 0x0188fe80,
410 0x90f980f9,
411 0xb0f9a0f9,
412 0xe0f9d0f9,
413 0x04bdf0f9,
414 0x0200a7f1,
415 0xcf00a3f0,
416 0xabc400aa,
417 0x2c0bf404,
418 0xf124d7f0,
419 0xf01a00e7,
420 0xeecf00e3,
421 0x00f7f100,
422 0x00f3f019,
423 0xf400ffcf,
424 0xe7f00421,
425 0x0007f101,
426 0x0003f01d,
427 0xbd000ed0,
428/* 0x056d: ih_no_fifo */
429 0x0007f104,
430 0x0003f001,
431 0xbd000ad0,
432 0xfcf0fc04,
433 0xfcd0fce0,
434 0xfca0fcb0,
435 0xfe80fc90,
436 0x80fc0088,
437 0xf80032f4,
438/* 0x0591: hub_barrier_done */
439 0x01f7f001,
440 0xbb040e98,
441 0xffb904fe,
442 0x18e7f102,
443 0x40e3f094,
444 0xf89d21f4,
445/* 0x05a9: ctx_redswitch */
446 0x20f7f000,
447 0x850007f1,
448 0xd00103f0,
449 0x04bd000f,
450/* 0x05bb: ctx_redswitch_delay */
451 0xb608e7f0,
452 0x1bf401e2,
453 0x00f5f1fd,
454 0x00f5f108,
455 0x0007f102,
456 0x0103f085, 452 0x0103f085,
457 0xbd000fd0, 453 0xbd000fd0,
458/* 0x05d7: ctx_xfer */ 454 0x08e7f004,
459 0xf100f804, 455/* 0x05cc: ctx_redswitch_delay */
460 0xf0810007, 456 0xf401e2b6,
461 0x0fd00203, 457 0xf5f1fd1b,
462 0xf404bd00, 458 0xf5f10800,
463 0x21f50711, 459 0x07f10200,
464/* 0x05ea: ctx_xfer_not_load */ 460 0x03f08500,
465 0x21f505a9, 461 0x000fd001,
466 0x24bd026a, 462 0x00f804bd,
467 0x47fc07f1, 463/* 0x05e8: ctx_xfer */
464 0x810007f1,
468 0xd00203f0, 465 0xd00203f0,
469 0x04bd0002, 466 0x04bd000f,
470 0xb6012cf0, 467 0xf50711f4,
471 0x07f10320, 468/* 0x05fb: ctx_xfer_not_load */
472 0x03f04afc, 469 0xf505ba21,
473 0x0002d002, 470 0xbd026a21,
474 0xacf004bd, 471 0xfc07f124,
475 0x02a5f001, 472 0x0203f047,
476 0x0000b7f1, 473 0xbd0002d0,
477 0x9850b3f0, 474 0x012cf004,
478 0xc4b6040c, 475 0xf10320b6,
479 0x00bcbb0f, 476 0xf04afc07,
480 0x98000c98, 477 0x02d00203,
481 0xe7f0010d, 478 0xf004bd00,
482 0x6f21f500, 479 0xa5f001ac,
483 0x01acf001, 480 0x00b7f102,
484 0x4000b7f1, 481 0x50b3f000,
482 0xb6040c98,
483 0xbcbb0fc4,
484 0x000c9800,
485 0xf0010d98,
486 0x21f500e7,
487 0xacf0016f,
488 0x00b7f101,
489 0x50b3f040,
490 0xb6040c98,
491 0xbcbb0fc4,
492 0x010c9800,
493 0x98020d98,
494 0xe7f1060f,
495 0x21f50800,
496 0xacf0016f,
497 0x04a5f001,
498 0x3000b7f1,
485 0x9850b3f0, 499 0x9850b3f0,
486 0xc4b6040c, 500 0xc4b6040c,
487 0x00bcbb0f, 501 0x00bcbb0f,
488 0x98010c98, 502 0x98020c98,
489 0x0f98020d, 503 0x0f98030d,
490 0x00e7f106, 504 0x00e7f108,
491 0x6f21f508, 505 0x6f21f502,
492 0x01acf001, 506 0x5e21f501,
493 0xf104a5f0, 507 0x0601f402,
494 0xf03000b7, 508/* 0x0697: ctx_xfer_post */
495 0x0c9850b3, 509 0xf50712f4,
496 0x0fc4b604, 510/* 0x069b: ctx_xfer_done */
497 0x9800bcbb, 511 0xf5027f21,
498 0x0d98020c, 512 0xf805a221,
499 0x080f9803,
500 0x0200e7f1,
501 0x016f21f5,
502 0x025e21f5,
503 0xf40601f4,
504/* 0x0686: ctx_xfer_post */
505 0x21f50712,
506/* 0x068a: ctx_xfer_done */
507 0x21f5027f,
508 0x00f80591,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000, 513 0x00000000,
514 0x00000000, 514 0x00000000,
515 0x00000000, 515 0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
index b6da800ee9c2..855b220378f9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
@@ -196,7 +196,7 @@ uint32_t nve0_grgpc_code[] = {
196 0x1fb4f000, 196 0x1fb4f000,
197 0xf410b4b0, 197 0xf410b4b0,
198 0xa7f0f01b, 198 0xa7f0f01b,
199 0xd021f402, 199 0xd021f405,
200/* 0x0223: mmctx_stop */ 200/* 0x0223: mmctx_stop */
201 0xc82b0ef4, 201 0xc82b0ef4,
202 0xb4b600ab, 202 0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nve0_grgpc_code[] = {
304 0x21f440e3, 304 0x21f440e3,
305 0xf8e0fc9d, 305 0xf8e0fc9d,
306/* 0x03a1: init */ 306/* 0x03a1: init */
307 0xfe04bd00, 307 0xf104bd00,
308 0x27f00004, 308 0xf0420017,
309 0x0007f102, 309 0x11cf0013,
310 0x0003f012, 310 0x0911e700,
311 0xbd0002d0, 311 0x0814b601,
312 0x1f17f104, 312 0xf00014fe,
313 0x0010fe05, 313 0x07f10227,
314 0x070007f1, 314 0x03f01200,
315 0x0002d000,
316 0x17f104bd,
317 0x10fe0530,
318 0x0007f100,
319 0x0003f007,
320 0xbd0000d0,
321 0x0427f004,
322 0x040007f1,
315 0xd00003f0, 323 0xd00003f0,
316 0x04bd0000, 324 0x04bd0002,
317 0xf10427f0, 325 0xf11031f4,
318 0xf0040007, 326 0xf0820027,
319 0x02d00003, 327 0x22cf0123,
328 0x0137f000,
329 0xbb1f24f0,
330 0x32b60432,
331 0x05028001,
332 0xf1060380,
333 0xf0860027,
334 0x22cf0123,
335 0x04028000,
336 0x0c30e7f1,
337 0xbd50e3f0,
338 0xbd34bd24,
339/* 0x0421: init_unk_loop */
340 0x6821f444,
341 0xf400f6b0,
342 0xf7f00f0b,
343 0x04f2bb01,
344 0xb6054ffd,
345/* 0x0436: init_unk_next */
346 0x20b60130,
347 0x04e0b601,
348 0xf40126b0,
349/* 0x0442: init_unk_done */
350 0x0380e21b,
351 0x08048007,
352 0x010027f1,
353 0xcf0223f0,
354 0x34bd0022,
355 0xf1082595,
356 0xf0c00007,
357 0x05d00103,
358 0xf104bd00,
359 0xf0c10007,
360 0x05d00103,
361 0x9804bd00,
362 0x0f98000e,
363 0x5021f501,
364 0x002fbb01,
365 0x98003fbb,
366 0x0f98010e,
367 0x5021f502,
368 0x050e9801,
369 0xbb00effd,
370 0x3ebb002e,
371 0x020e9800,
372 0xf5030f98,
373 0x98015021,
374 0xeffd070e,
375 0x002ebb00,
376 0xb6003ebb,
377 0x07f10235,
378 0x03f0d300,
379 0x0003d001,
380 0x25b604bd,
381 0x0635b608,
382 0xb60120b6,
383 0x24b60130,
384 0x0834b608,
385 0xf5022fb9,
386 0xbb02d321,
387 0x07f1003f,
388 0x03f00100,
389 0x0003d002,
390 0x24bd04bd,
391 0xf11f29f0,
392 0xf0080007,
393 0x02d00203,
394/* 0x04f3: main */
320 0xf404bd00, 395 0xf404bd00,
321 0x27f11031, 396 0x28f40031,
322 0x23f08200, 397 0x24d7f000,
323 0x0022cf01, 398 0xf43921f4,
324 0xf00137f0, 399 0xe4b0f401,
325 0x32bb1f24, 400 0x1e18f404,
326 0x0132b604, 401 0xf00181fe,
327 0x80050280, 402 0x20bd0627,
328 0x27f10603, 403 0xb60412fd,
329 0x23f08600, 404 0x1efd01e4,
330 0x0022cf01, 405 0x0018fe05,
331 0xf1040280, 406 0x05e821f5,
332 0xf00c30e7, 407/* 0x0523: main_not_ctx_xfer */
333 0x24bd50e3, 408 0x94d30ef4,
334 0x44bd34bd, 409 0xf5f010ef,
335/* 0x0410: init_unk_loop */ 410 0x7e21f501,
336 0xb06821f4, 411 0xc60ef403,
337 0x0bf400f6, 412/* 0x0530: ih */
338 0x01f7f00f, 413 0x88fe80f9,
339 0xfd04f2bb, 414 0xf980f901,
340 0x30b6054f, 415 0xf9a0f990,
341/* 0x0425: init_unk_next */ 416 0xf9d0f9b0,
342 0x0120b601, 417 0xbdf0f9e0,
343 0xb004e0b6, 418 0x00a7f104,
344 0x1bf40126, 419 0x00a3f002,
345/* 0x0431: init_unk_done */ 420 0xc400aacf,
346 0x070380e2, 421 0x0bf404ab,
347 0xf1080480, 422 0x24d7f02c,
348 0xf0010027, 423 0x1a00e7f1,
349 0x22cf0223, 424 0xcf00e3f0,
350 0x9534bd00, 425 0xf7f100ee,
351 0x07f10825, 426 0xf3f01900,
352 0x03f0c000, 427 0x00ffcf00,
353 0x0005d001, 428 0xf00421f4,
429 0x07f101e7,
430 0x03f01d00,
431 0x000ed000,
432/* 0x057e: ih_no_fifo */
354 0x07f104bd, 433 0x07f104bd,
355 0x03f0c100, 434 0x03f00100,
356 0x0005d001, 435 0x000ad000,
357 0x0e9804bd, 436 0xf0fc04bd,
358 0x010f9800, 437 0xd0fce0fc,
359 0x015021f5, 438 0xa0fcb0fc,
360 0xbb002fbb, 439 0x80fc90fc,
361 0x0e98003f, 440 0xfc0088fe,
362 0x020f9801, 441 0x0032f480,
363 0x015021f5, 442/* 0x05a2: hub_barrier_done */
364 0xfd050e98, 443 0xf7f001f8,
365 0x2ebb00ef, 444 0x040e9801,
366 0x003ebb00, 445 0xb904febb,
367 0x98020e98, 446 0xe7f102ff,
368 0x21f5030f, 447 0xe3f09418,
369 0x0e980150, 448 0x9d21f440,
370 0x00effd07, 449/* 0x05ba: ctx_redswitch */
371 0xbb002ebb, 450 0xf7f000f8,
372 0x35b6003e, 451 0x0007f120,
373 0x0007f102,
374 0x0103f0d3,
375 0xbd0003d0,
376 0x0825b604,
377 0xb60635b6,
378 0x30b60120,
379 0x0824b601,
380 0xb90834b6,
381 0x21f5022f,
382 0x3fbb02d3,
383 0x0007f100,
384 0x0203f001,
385 0xbd0003d0,
386 0xf024bd04,
387 0x07f11f29,
388 0x03f00800,
389 0x0002d002,
390/* 0x04e2: main */
391 0x31f404bd,
392 0x0028f400,
393 0xf424d7f0,
394 0x01f43921,
395 0x04e4b0f4,
396 0xfe1e18f4,
397 0x27f00181,
398 0xfd20bd06,
399 0xe4b60412,
400 0x051efd01,
401 0xf50018fe,
402 0xf405d721,
403/* 0x0512: main_not_ctx_xfer */
404 0xef94d30e,
405 0x01f5f010,
406 0x037e21f5,
407/* 0x051f: ih */
408 0xf9c60ef4,
409 0x0188fe80,
410 0x90f980f9,
411 0xb0f9a0f9,
412 0xe0f9d0f9,
413 0x04bdf0f9,
414 0x0200a7f1,
415 0xcf00a3f0,
416 0xabc400aa,
417 0x2c0bf404,
418 0xf124d7f0,
419 0xf01a00e7,
420 0xeecf00e3,
421 0x00f7f100,
422 0x00f3f019,
423 0xf400ffcf,
424 0xe7f00421,
425 0x0007f101,
426 0x0003f01d,
427 0xbd000ed0,
428/* 0x056d: ih_no_fifo */
429 0x0007f104,
430 0x0003f001,
431 0xbd000ad0,
432 0xfcf0fc04,
433 0xfcd0fce0,
434 0xfca0fcb0,
435 0xfe80fc90,
436 0x80fc0088,
437 0xf80032f4,
438/* 0x0591: hub_barrier_done */
439 0x01f7f001,
440 0xbb040e98,
441 0xffb904fe,
442 0x18e7f102,
443 0x40e3f094,
444 0xf89d21f4,
445/* 0x05a9: ctx_redswitch */
446 0x20f7f000,
447 0x850007f1,
448 0xd00103f0,
449 0x04bd000f,
450/* 0x05bb: ctx_redswitch_delay */
451 0xb608e7f0,
452 0x1bf401e2,
453 0x00f5f1fd,
454 0x00f5f108,
455 0x0007f102,
456 0x0103f085, 452 0x0103f085,
457 0xbd000fd0, 453 0xbd000fd0,
458/* 0x05d7: ctx_xfer */ 454 0x08e7f004,
459 0xf100f804, 455/* 0x05cc: ctx_redswitch_delay */
460 0xf0810007, 456 0xf401e2b6,
461 0x0fd00203, 457 0xf5f1fd1b,
462 0xf404bd00, 458 0xf5f10800,
463 0x21f50711, 459 0x07f10200,
464/* 0x05ea: ctx_xfer_not_load */ 460 0x03f08500,
465 0x21f505a9, 461 0x000fd001,
466 0x24bd026a, 462 0x00f804bd,
467 0x47fc07f1, 463/* 0x05e8: ctx_xfer */
464 0x810007f1,
468 0xd00203f0, 465 0xd00203f0,
469 0x04bd0002, 466 0x04bd000f,
470 0xb6012cf0, 467 0xf50711f4,
471 0x07f10320, 468/* 0x05fb: ctx_xfer_not_load */
472 0x03f04afc, 469 0xf505ba21,
473 0x0002d002, 470 0xbd026a21,
474 0xacf004bd, 471 0xfc07f124,
475 0x02a5f001, 472 0x0203f047,
476 0x0000b7f1, 473 0xbd0002d0,
477 0x9850b3f0, 474 0x012cf004,
478 0xc4b6040c, 475 0xf10320b6,
479 0x00bcbb0f, 476 0xf04afc07,
480 0x98000c98, 477 0x02d00203,
481 0xe7f0010d, 478 0xf004bd00,
482 0x6f21f500, 479 0xa5f001ac,
483 0x01acf001, 480 0x00b7f102,
484 0x4000b7f1, 481 0x50b3f000,
482 0xb6040c98,
483 0xbcbb0fc4,
484 0x000c9800,
485 0xf0010d98,
486 0x21f500e7,
487 0xacf0016f,
488 0x00b7f101,
489 0x50b3f040,
490 0xb6040c98,
491 0xbcbb0fc4,
492 0x010c9800,
493 0x98020d98,
494 0xe7f1060f,
495 0x21f50800,
496 0xacf0016f,
497 0x04a5f001,
498 0x3000b7f1,
485 0x9850b3f0, 499 0x9850b3f0,
486 0xc4b6040c, 500 0xc4b6040c,
487 0x00bcbb0f, 501 0x00bcbb0f,
488 0x98010c98, 502 0x98020c98,
489 0x0f98020d, 503 0x0f98030d,
490 0x00e7f106, 504 0x00e7f108,
491 0x6f21f508, 505 0x6f21f502,
492 0x01acf001, 506 0x5e21f501,
493 0xf104a5f0, 507 0x0601f402,
494 0xf03000b7, 508/* 0x0697: ctx_xfer_post */
495 0x0c9850b3, 509 0xf50712f4,
496 0x0fc4b604, 510/* 0x069b: ctx_xfer_done */
497 0x9800bcbb, 511 0xf5027f21,
498 0x0d98020c, 512 0xf805a221,
499 0x080f9803,
500 0x0200e7f1,
501 0x016f21f5,
502 0x025e21f5,
503 0xf40601f4,
504/* 0x0686: ctx_xfer_post */
505 0x21f50712,
506/* 0x068a: ctx_xfer_done */
507 0x21f5027f,
508 0x00f80591,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000, 513 0x00000000,
514 0x00000000, 514 0x00000000,
515 0x00000000, 515 0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
index 6316ebaf5d9a..1b803197d28b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
@@ -196,7 +196,7 @@ uint32_t nvf0_grgpc_code[] = {
196 0x1fb4f000, 196 0x1fb4f000,
197 0xf410b4b0, 197 0xf410b4b0,
198 0xa7f0f01b, 198 0xa7f0f01b,
199 0xd021f402, 199 0xd021f405,
200/* 0x0223: mmctx_stop */ 200/* 0x0223: mmctx_stop */
201 0xc82b0ef4, 201 0xc82b0ef4,
202 0xb4b600ab, 202 0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nvf0_grgpc_code[] = {
304 0x21f440e3, 304 0x21f440e3,
305 0xf8e0fc9d, 305 0xf8e0fc9d,
306/* 0x03a1: init */ 306/* 0x03a1: init */
307 0xfe04bd00, 307 0xf104bd00,
308 0x27f00004, 308 0xf0420017,
309 0x0007f102, 309 0x11cf0013,
310 0x0003f012, 310 0x0911e700,
311 0xbd0002d0, 311 0x0814b601,
312 0x1f17f104, 312 0xf00014fe,
313 0x0010fe05, 313 0x07f10227,
314 0x070007f1, 314 0x03f01200,
315 0x0002d000,
316 0x17f104bd,
317 0x10fe0530,
318 0x0007f100,
319 0x0003f007,
320 0xbd0000d0,
321 0x0427f004,
322 0x040007f1,
315 0xd00003f0, 323 0xd00003f0,
316 0x04bd0000, 324 0x04bd0002,
317 0xf10427f0, 325 0xf11031f4,
318 0xf0040007, 326 0xf0820027,
319 0x02d00003, 327 0x22cf0123,
328 0x0137f000,
329 0xbb1f24f0,
330 0x32b60432,
331 0x05028001,
332 0xf1060380,
333 0xf0860027,
334 0x22cf0123,
335 0x04028000,
336 0x0c30e7f1,
337 0xbd50e3f0,
338 0xbd34bd24,
339/* 0x0421: init_unk_loop */
340 0x6821f444,
341 0xf400f6b0,
342 0xf7f00f0b,
343 0x04f2bb01,
344 0xb6054ffd,
345/* 0x0436: init_unk_next */
346 0x20b60130,
347 0x04e0b601,
348 0xf40226b0,
349/* 0x0442: init_unk_done */
350 0x0380e21b,
351 0x08048007,
352 0x010027f1,
353 0xcf0223f0,
354 0x34bd0022,
355 0xf1082595,
356 0xf0c00007,
357 0x05d00103,
358 0xf104bd00,
359 0xf0c10007,
360 0x05d00103,
361 0x9804bd00,
362 0x0f98000e,
363 0x5021f501,
364 0x002fbb01,
365 0x98003fbb,
366 0x0f98010e,
367 0x5021f502,
368 0x050e9801,
369 0xbb00effd,
370 0x3ebb002e,
371 0x020e9800,
372 0xf5030f98,
373 0x98015021,
374 0xeffd070e,
375 0x002ebb00,
376 0xb6003ebb,
377 0x07f10235,
378 0x03f0d300,
379 0x0003d001,
380 0x25b604bd,
381 0x0635b608,
382 0xb60120b6,
383 0x24b60130,
384 0x0834b608,
385 0xf5022fb9,
386 0xbb02d321,
387 0x07f1003f,
388 0x03f00100,
389 0x0003d002,
390 0x24bd04bd,
391 0xf11f29f0,
392 0xf0300007,
393 0x02d00203,
394/* 0x04f3: main */
320 0xf404bd00, 395 0xf404bd00,
321 0x27f11031, 396 0x28f40031,
322 0x23f08200, 397 0x24d7f000,
323 0x0022cf01, 398 0xf43921f4,
324 0xf00137f0, 399 0xe4b0f401,
325 0x32bb1f24, 400 0x1e18f404,
326 0x0132b604, 401 0xf00181fe,
327 0x80050280, 402 0x20bd0627,
328 0x27f10603, 403 0xb60412fd,
329 0x23f08600, 404 0x1efd01e4,
330 0x0022cf01, 405 0x0018fe05,
331 0xf1040280, 406 0x05e821f5,
332 0xf00c30e7, 407/* 0x0523: main_not_ctx_xfer */
333 0x24bd50e3, 408 0x94d30ef4,
334 0x44bd34bd, 409 0xf5f010ef,
335/* 0x0410: init_unk_loop */ 410 0x7e21f501,
336 0xb06821f4, 411 0xc60ef403,
337 0x0bf400f6, 412/* 0x0530: ih */
338 0x01f7f00f, 413 0x88fe80f9,
339 0xfd04f2bb, 414 0xf980f901,
340 0x30b6054f, 415 0xf9a0f990,
341/* 0x0425: init_unk_next */ 416 0xf9d0f9b0,
342 0x0120b601, 417 0xbdf0f9e0,
343 0xb004e0b6, 418 0x00a7f104,
344 0x1bf40226, 419 0x00a3f002,
345/* 0x0431: init_unk_done */ 420 0xc400aacf,
346 0x070380e2, 421 0x0bf404ab,
347 0xf1080480, 422 0x24d7f02c,
348 0xf0010027, 423 0x1a00e7f1,
349 0x22cf0223, 424 0xcf00e3f0,
350 0x9534bd00, 425 0xf7f100ee,
351 0x07f10825, 426 0xf3f01900,
352 0x03f0c000, 427 0x00ffcf00,
353 0x0005d001, 428 0xf00421f4,
429 0x07f101e7,
430 0x03f01d00,
431 0x000ed000,
432/* 0x057e: ih_no_fifo */
354 0x07f104bd, 433 0x07f104bd,
355 0x03f0c100, 434 0x03f00100,
356 0x0005d001, 435 0x000ad000,
357 0x0e9804bd, 436 0xf0fc04bd,
358 0x010f9800, 437 0xd0fce0fc,
359 0x015021f5, 438 0xa0fcb0fc,
360 0xbb002fbb, 439 0x80fc90fc,
361 0x0e98003f, 440 0xfc0088fe,
362 0x020f9801, 441 0x0032f480,
363 0x015021f5, 442/* 0x05a2: hub_barrier_done */
364 0xfd050e98, 443 0xf7f001f8,
365 0x2ebb00ef, 444 0x040e9801,
366 0x003ebb00, 445 0xb904febb,
367 0x98020e98, 446 0xe7f102ff,
368 0x21f5030f, 447 0xe3f09418,
369 0x0e980150, 448 0x9d21f440,
370 0x00effd07, 449/* 0x05ba: ctx_redswitch */
371 0xbb002ebb, 450 0xf7f000f8,
372 0x35b6003e, 451 0x0007f120,
373 0x0007f102,
374 0x0103f0d3,
375 0xbd0003d0,
376 0x0825b604,
377 0xb60635b6,
378 0x30b60120,
379 0x0824b601,
380 0xb90834b6,
381 0x21f5022f,
382 0x3fbb02d3,
383 0x0007f100,
384 0x0203f001,
385 0xbd0003d0,
386 0xf024bd04,
387 0x07f11f29,
388 0x03f03000,
389 0x0002d002,
390/* 0x04e2: main */
391 0x31f404bd,
392 0x0028f400,
393 0xf424d7f0,
394 0x01f43921,
395 0x04e4b0f4,
396 0xfe1e18f4,
397 0x27f00181,
398 0xfd20bd06,
399 0xe4b60412,
400 0x051efd01,
401 0xf50018fe,
402 0xf405d721,
403/* 0x0512: main_not_ctx_xfer */
404 0xef94d30e,
405 0x01f5f010,
406 0x037e21f5,
407/* 0x051f: ih */
408 0xf9c60ef4,
409 0x0188fe80,
410 0x90f980f9,
411 0xb0f9a0f9,
412 0xe0f9d0f9,
413 0x04bdf0f9,
414 0x0200a7f1,
415 0xcf00a3f0,
416 0xabc400aa,
417 0x2c0bf404,
418 0xf124d7f0,
419 0xf01a00e7,
420 0xeecf00e3,
421 0x00f7f100,
422 0x00f3f019,
423 0xf400ffcf,
424 0xe7f00421,
425 0x0007f101,
426 0x0003f01d,
427 0xbd000ed0,
428/* 0x056d: ih_no_fifo */
429 0x0007f104,
430 0x0003f001,
431 0xbd000ad0,
432 0xfcf0fc04,
433 0xfcd0fce0,
434 0xfca0fcb0,
435 0xfe80fc90,
436 0x80fc0088,
437 0xf80032f4,
438/* 0x0591: hub_barrier_done */
439 0x01f7f001,
440 0xbb040e98,
441 0xffb904fe,
442 0x18e7f102,
443 0x40e3f094,
444 0xf89d21f4,
445/* 0x05a9: ctx_redswitch */
446 0x20f7f000,
447 0x850007f1,
448 0xd00103f0,
449 0x04bd000f,
450/* 0x05bb: ctx_redswitch_delay */
451 0xb608e7f0,
452 0x1bf401e2,
453 0x00f5f1fd,
454 0x00f5f108,
455 0x0007f102,
456 0x0103f085, 452 0x0103f085,
457 0xbd000fd0, 453 0xbd000fd0,
458/* 0x05d7: ctx_xfer */ 454 0x08e7f004,
459 0xf100f804, 455/* 0x05cc: ctx_redswitch_delay */
460 0xf0810007, 456 0xf401e2b6,
461 0x0fd00203, 457 0xf5f1fd1b,
462 0xf404bd00, 458 0xf5f10800,
463 0x21f50711, 459 0x07f10200,
464/* 0x05ea: ctx_xfer_not_load */ 460 0x03f08500,
465 0x21f505a9, 461 0x000fd001,
466 0x24bd026a, 462 0x00f804bd,
467 0x47fc07f1, 463/* 0x05e8: ctx_xfer */
464 0x810007f1,
468 0xd00203f0, 465 0xd00203f0,
469 0x04bd0002, 466 0x04bd000f,
470 0xb6012cf0, 467 0xf50711f4,
471 0x07f10320, 468/* 0x05fb: ctx_xfer_not_load */
472 0x03f04afc, 469 0xf505ba21,
473 0x0002d002, 470 0xbd026a21,
474 0xacf004bd, 471 0xfc07f124,
475 0x02a5f001, 472 0x0203f047,
476 0x0000b7f1, 473 0xbd0002d0,
477 0x9850b3f0, 474 0x012cf004,
478 0xc4b6040c, 475 0xf10320b6,
479 0x00bcbb0f, 476 0xf04afc07,
480 0x98000c98, 477 0x02d00203,
481 0xe7f0010d, 478 0xf004bd00,
482 0x6f21f500, 479 0xa5f001ac,
483 0x01acf001, 480 0x00b7f102,
484 0x4000b7f1, 481 0x50b3f000,
482 0xb6040c98,
483 0xbcbb0fc4,
484 0x000c9800,
485 0xf0010d98,
486 0x21f500e7,
487 0xacf0016f,
488 0x00b7f101,
489 0x50b3f040,
490 0xb6040c98,
491 0xbcbb0fc4,
492 0x010c9800,
493 0x98020d98,
494 0xe7f1060f,
495 0x21f50800,
496 0xacf0016f,
497 0x04a5f001,
498 0x3000b7f1,
485 0x9850b3f0, 499 0x9850b3f0,
486 0xc4b6040c, 500 0xc4b6040c,
487 0x00bcbb0f, 501 0x00bcbb0f,
488 0x98010c98, 502 0x98020c98,
489 0x0f98020d, 503 0x0f98030d,
490 0x00e7f106, 504 0x00e7f108,
491 0x6f21f508, 505 0x6f21f502,
492 0x01acf001, 506 0x5e21f501,
493 0xf104a5f0, 507 0x0601f402,
494 0xf03000b7, 508/* 0x0697: ctx_xfer_post */
495 0x0c9850b3, 509 0xf50712f4,
496 0x0fc4b604, 510/* 0x069b: ctx_xfer_done */
497 0x9800bcbb, 511 0xf5027f21,
498 0x0d98020c, 512 0xf805a221,
499 0x080f9803,
500 0x0200e7f1,
501 0x016f21f5,
502 0x025e21f5,
503 0xf40601f4,
504/* 0x0686: ctx_xfer_post */
505 0x21f50712,
506/* 0x068a: ctx_xfer_done */
507 0x21f5027f,
508 0x00f80591,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000, 513 0x00000000,
514 0x00000000, 514 0x00000000,
515 0x00000000, 515 0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5
new file mode 100644
index 000000000000..27591b3086a5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5
@@ -0,0 +1,40 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#define CHIPSET GK208
26#include "macros.fuc"
27
28.section #gm107_grhub_data
29#define INCLUDE_DATA
30#include "com.fuc"
31#include "hub.fuc"
32#undef INCLUDE_DATA
33
34.section #gm107_grhub_code
35#define INCLUDE_CODE
36bra #init
37#include "com.fuc"
38#include "hub.fuc"
39.align 256
40#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h
new file mode 100644
index 000000000000..214dd16ec566
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h
@@ -0,0 +1,916 @@
1uint32_t gm107_grhub_data[] = {
2/* 0x0000: hub_mmio_list_head */
3 0x00000300,
4/* 0x0004: hub_mmio_list_tail */
5 0x00000304,
6/* 0x0008: gpc_count */
7 0x00000000,
8/* 0x000c: rop_count */
9 0x00000000,
10/* 0x0010: cmd_queue */
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29/* 0x0058: ctx_current */
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57 0x00000000,
58 0x00000000,
59 0x00000000,
60 0x00000000,
61 0x00000000,
62 0x00000000,
63 0x00000000,
64 0x00000000,
65 0x00000000,
66 0x00000000,
67 0x00000000,
68 0x00000000,
69 0x00000000,
70 0x00000000,
71 0x00000000,
72/* 0x0100: chan_data */
73/* 0x0100: chan_mmio_count */
74 0x00000000,
75/* 0x0104: chan_mmio_address */
76 0x00000000,
77 0x00000000,
78 0x00000000,
79 0x00000000,
80 0x00000000,
81 0x00000000,
82 0x00000000,
83 0x00000000,
84 0x00000000,
85 0x00000000,
86 0x00000000,
87 0x00000000,
88 0x00000000,
89 0x00000000,
90 0x00000000,
91 0x00000000,
92 0x00000000,
93 0x00000000,
94 0x00000000,
95 0x00000000,
96 0x00000000,
97 0x00000000,
98 0x00000000,
99 0x00000000,
100 0x00000000,
101 0x00000000,
102 0x00000000,
103 0x00000000,
104 0x00000000,
105 0x00000000,
106 0x00000000,
107 0x00000000,
108 0x00000000,
109 0x00000000,
110 0x00000000,
111 0x00000000,
112 0x00000000,
113 0x00000000,
114 0x00000000,
115 0x00000000,
116 0x00000000,
117 0x00000000,
118 0x00000000,
119 0x00000000,
120 0x00000000,
121 0x00000000,
122 0x00000000,
123 0x00000000,
124 0x00000000,
125 0x00000000,
126 0x00000000,
127 0x00000000,
128 0x00000000,
129 0x00000000,
130 0x00000000,
131 0x00000000,
132 0x00000000,
133 0x00000000,
134 0x00000000,
135 0x00000000,
136 0x00000000,
137 0x00000000,
138 0x00000000,
139/* 0x0200: xfer_data */
140 0x00000000,
141 0x00000000,
142 0x00000000,
143 0x00000000,
144 0x00000000,
145 0x00000000,
146 0x00000000,
147 0x00000000,
148 0x00000000,
149 0x00000000,
150 0x00000000,
151 0x00000000,
152 0x00000000,
153 0x00000000,
154 0x00000000,
155 0x00000000,
156 0x00000000,
157 0x00000000,
158 0x00000000,
159 0x00000000,
160 0x00000000,
161 0x00000000,
162 0x00000000,
163 0x00000000,
164 0x00000000,
165 0x00000000,
166 0x00000000,
167 0x00000000,
168 0x00000000,
169 0x00000000,
170 0x00000000,
171 0x00000000,
172 0x00000000,
173 0x00000000,
174 0x00000000,
175 0x00000000,
176 0x00000000,
177 0x00000000,
178 0x00000000,
179 0x00000000,
180 0x00000000,
181 0x00000000,
182 0x00000000,
183 0x00000000,
184 0x00000000,
185 0x00000000,
186 0x00000000,
187 0x00000000,
188 0x00000000,
189 0x00000000,
190 0x00000000,
191 0x00000000,
192 0x00000000,
193 0x00000000,
194 0x00000000,
195 0x00000000,
196 0x00000000,
197 0x00000000,
198 0x00000000,
199 0x00000000,
200 0x00000000,
201 0x00000000,
202 0x00000000,
203 0x00000000,
204/* 0x0300: hub_mmio_list_base */
205 0x0417e91c,
206};
207
208uint32_t gm107_grhub_code[] = {
209 0x030e0ef5,
210/* 0x0004: queue_put */
211 0x9800d898,
212 0x86f001d9,
213 0xf489a408,
214 0x020f0b1b,
215 0x0002f87e,
216/* 0x001a: queue_put_next */
217 0x98c400f8,
218 0x0384b607,
219 0xb6008dbb,
220 0x8eb50880,
221 0x018fb500,
222 0xf00190b6,
223 0xd9b50f94,
224/* 0x0037: queue_get */
225 0xf400f801,
226 0xd8980131,
227 0x01d99800,
228 0x0bf489a4,
229 0x0789c421,
230 0xbb0394b6,
231 0x90b6009d,
232 0x009e9808,
233 0xb6019f98,
234 0x84f00180,
235 0x00d8b50f,
236/* 0x0063: queue_get_done */
237 0xf80132f4,
238/* 0x0065: nv_rd32 */
239 0xf0ecb200,
240 0x00801fc9,
241 0x0cf601ca,
242/* 0x0073: nv_rd32_wait */
243 0x8c04bd00,
244 0xcf01ca00,
245 0xccc800cc,
246 0xf61bf41f,
247 0xec7e060a,
248 0x008f0000,
249 0xffcf01cb,
250/* 0x008f: nv_wr32 */
251 0x8000f800,
252 0xf601cc00,
253 0x04bd000f,
254 0xc9f0ecb2,
255 0x1ec9f01f,
256 0x01ca0080,
257 0xbd000cf6,
258/* 0x00a9: nv_wr32_wait */
259 0xca008c04,
260 0x00cccf01,
261 0xf41fccc8,
262 0x00f8f61b,
263/* 0x00b8: wait_donez */
264 0x99f094bd,
265 0x37008000,
266 0x0009f602,
267 0x008004bd,
268 0x0af60206,
269/* 0x00cf: wait_donez_ne */
270 0x8804bd00,
271 0xcf010000,
272 0x8aff0088,
273 0xf61bf488,
274 0x99f094bd,
275 0x17008000,
276 0x0009f602,
277 0x00f804bd,
278/* 0x00ec: wait_doneo */
279 0x99f094bd,
280 0x37008000,
281 0x0009f602,
282 0x008004bd,
283 0x0af60206,
284/* 0x0103: wait_doneo_e */
285 0x8804bd00,
286 0xcf010000,
287 0x8aff0088,
288 0xf60bf488,
289 0x99f094bd,
290 0x17008000,
291 0x0009f602,
292 0x00f804bd,
293/* 0x0120: mmctx_size */
294/* 0x0122: nv_mmctx_size_loop */
295 0xe89894bd,
296 0x1a85b600,
297 0xb60180b6,
298 0x98bb0284,
299 0x04e0b600,
300 0x1bf4efa4,
301 0xf89fb2ec,
302/* 0x013d: mmctx_xfer */
303 0xf094bd00,
304 0x00800199,
305 0x09f60237,
306 0xbd04bd00,
307 0x05bbfd94,
308 0x800f0bf4,
309 0xf601c400,
310 0x04bd000b,
311/* 0x015f: mmctx_base_disabled */
312 0xfd0099f0,
313 0x0bf405ee,
314 0xc6008018,
315 0x000ef601,
316 0x008004bd,
317 0x0ff601c7,
318 0xf004bd00,
319/* 0x017a: mmctx_multi_disabled */
320 0xabc80199,
321 0x10b4b600,
322 0xc80cb9f0,
323 0xe4b601ae,
324 0x05befd11,
325 0x01c50080,
326 0xbd000bf6,
327/* 0x0195: mmctx_exec_loop */
328/* 0x0195: mmctx_wait_free */
329 0xc5008e04,
330 0x00eecf01,
331 0xf41fe4f0,
332 0xce98f60b,
333 0x05e9fd00,
334 0x01c80080,
335 0xbd000ef6,
336 0x04c0b604,
337 0x1bf4cda4,
338 0x02abc8df,
339/* 0x01bf: mmctx_fini_wait */
340 0x8b1c1bf4,
341 0xcf01c500,
342 0xb4f000bb,
343 0x10b4b01f,
344 0x0af31bf4,
345 0x00b87e05,
346 0x250ef400,
347/* 0x01d8: mmctx_stop */
348 0xb600abc8,
349 0xb9f010b4,
350 0x12b9f00c,
351 0x01c50080,
352 0xbd000bf6,
353/* 0x01ed: mmctx_stop_wait */
354 0xc5008b04,
355 0x00bbcf01,
356 0xf412bbc8,
357/* 0x01fa: mmctx_done */
358 0x94bdf61b,
359 0x800199f0,
360 0xf6021700,
361 0x04bd0009,
362/* 0x020a: strand_wait */
363 0xa0f900f8,
364 0xb87e020a,
365 0xa0fc0000,
366/* 0x0216: strand_pre */
367 0x0c0900f8,
368 0x024afc80,
369 0xbd0009f6,
370 0x020a7e04,
371/* 0x0227: strand_post */
372 0x0900f800,
373 0x4afc800d,
374 0x0009f602,
375 0x0a7e04bd,
376 0x00f80002,
377/* 0x0238: strand_set */
378 0xfc800f0c,
379 0x0cf6024f,
380 0x0c04bd00,
381 0x4afc800b,
382 0x000cf602,
383 0xfc8004bd,
384 0x0ef6024f,
385 0x0c04bd00,
386 0x4afc800a,
387 0x000cf602,
388 0x0a7e04bd,
389 0x00f80002,
390/* 0x0268: strand_ctx_init */
391 0x99f094bd,
392 0x37008003,
393 0x0009f602,
394 0x167e04bd,
395 0x030e0002,
396 0x0002387e,
397 0xfc80c4bd,
398 0x0cf60247,
399 0x0c04bd00,
400 0x4afc8001,
401 0x000cf602,
402 0x0a7e04bd,
403 0x0c920002,
404 0x46fc8001,
405 0x000cf602,
406 0x020c04bd,
407 0x024afc80,
408 0xbd000cf6,
409 0x020a7e04,
410 0x02277e00,
411 0x42008800,
412 0x20008902,
413 0x0099cf02,
414/* 0x02c7: ctx_init_strand_loop */
415 0xf608fe95,
416 0x8ef6008e,
417 0x808acf40,
418 0xb606a5b6,
419 0xeabb01a0,
420 0x0480b600,
421 0xf40192b6,
422 0xe4b6e81b,
423 0xf2efbc08,
424 0x99f094bd,
425 0x17008003,
426 0x0009f602,
427 0x00f804bd,
428/* 0x02f8: error */
429 0x02050080,
430 0xbd000ff6,
431 0x80010f04,
432 0xf6030700,
433 0x04bd000f,
434/* 0x030e: init */
435 0x04bd00f8,
436 0x410007fe,
437 0x11cf4200,
438 0x0911e700,
439 0x0814b601,
440 0x020014fe,
441 0x12004002,
442 0xbd0002f6,
443 0x05c94104,
444 0xbd0010fe,
445 0x07004024,
446 0xbd0002f6,
447 0x20034204,
448 0x01010080,
449 0xbd0002f6,
450 0x20044204,
451 0x01010480,
452 0xbd0002f6,
453 0x200b4204,
454 0x01010880,
455 0xbd0002f6,
456 0x200c4204,
457 0x01011c80,
458 0xbd0002f6,
459 0x01039204,
460 0x03090080,
461 0xbd0003f6,
462 0x87044204,
463 0xf6040040,
464 0x04bd0002,
465 0x00400402,
466 0x0002f603,
467 0x31f404bd,
468 0x96048e10,
469 0x00657e40,
470 0xc7feb200,
471 0x01b590f1,
472 0x1ff4f003,
473 0x01020fb5,
474 0x041fbb01,
475 0x800112b6,
476 0xf6010300,
477 0x04bd0001,
478 0x01040080,
479 0xbd0001f6,
480 0x01004104,
481 0x627e020f,
482 0x717e0006,
483 0x100f0006,
484 0x0006b37e,
485 0x98000e98,
486 0x207e010f,
487 0x14950001,
488 0xc0008008,
489 0x0004f601,
490 0x008004bd,
491 0x04f601c1,
492 0xb704bd00,
493 0xbb130030,
494 0xf5b6001f,
495 0xd3008002,
496 0x000ff601,
497 0x15b604bd,
498 0x0110b608,
499 0xb20814b6,
500 0x02687e1f,
501 0x001fbb00,
502 0x84020398,
503/* 0x041f: init_gpc */
504 0xb8502000,
505 0x0008044e,
506 0x8f7e1fb2,
507 0x4eb80000,
508 0xbd00010c,
509 0x008f7ef4,
510 0x044eb800,
511 0x8f7e0001,
512 0x4eb80000,
513 0x0f000100,
514 0x008f7e02,
515 0x004eb800,
516/* 0x044e: init_gpc_wait */
517 0x657e0008,
518 0xffc80000,
519 0xf90bf41f,
520 0x08044eb8,
521 0x00657e00,
522 0x001fbb00,
523 0x800040b7,
524 0xf40132b6,
525 0x000fb41b,
526 0x0006b37e,
527 0x627e000f,
528 0x00800006,
529 0x01f60201,
530 0xbd04bd00,
531 0x1f19f014,
532 0x02300080,
533 0xbd0001f6,
534/* 0x0491: main */
535 0x0031f404,
536 0x0d0028f4,
537 0x00377e10,
538 0xf401f400,
539 0x4001e4b1,
540 0x00c71bf5,
541 0x99f094bd,
542 0x37008004,
543 0x0009f602,
544 0x008104bd,
545 0x11cf02c0,
546 0xc1008200,
547 0x0022cf02,
548 0xf41f13c8,
549 0x23c8770b,
550 0x550bf41f,
551 0x12b220f9,
552 0x99f094bd,
553 0x37008007,
554 0x0009f602,
555 0x32f404bd,
556 0x0231f401,
557 0x0008367e,
558 0x99f094bd,
559 0x17008007,
560 0x0009f602,
561 0x20fc04bd,
562 0x99f094bd,
563 0x37008006,
564 0x0009f602,
565 0x31f404bd,
566 0x08367e01,
567 0xf094bd00,
568 0x00800699,
569 0x09f60217,
570 0xf404bd00,
571/* 0x0522: chsw_prev_no_next */
572 0x20f92f0e,
573 0x32f412b2,
574 0x0232f401,
575 0x0008367e,
576 0x008020fc,
577 0x02f602c0,
578 0xf404bd00,
579/* 0x053e: chsw_no_prev */
580 0x23c8130e,
581 0x0d0bf41f,
582 0xf40131f4,
583 0x367e0232,
584/* 0x054e: chsw_done */
585 0x01020008,
586 0x02c30080,
587 0xbd0002f6,
588 0xf094bd04,
589 0x00800499,
590 0x09f60217,
591 0xf504bd00,
592/* 0x056b: main_not_ctx_switch */
593 0xb0ff2a0e,
594 0x1bf401e4,
595 0x7ef2b20c,
596 0xf40007d6,
597/* 0x057a: main_not_ctx_chan */
598 0xe4b0400e,
599 0x2c1bf402,
600 0x99f094bd,
601 0x37008007,
602 0x0009f602,
603 0x32f404bd,
604 0x0232f401,
605 0x0008367e,
606 0x99f094bd,
607 0x17008007,
608 0x0009f602,
609 0x0ef404bd,
610/* 0x05a9: main_not_ctx_save */
611 0x10ef9411,
612 0x7e01f5f0,
613 0xf50002f8,
614/* 0x05b7: main_done */
615 0xbdfede0e,
616 0x1f29f024,
617 0x02300080,
618 0xbd0002f6,
619 0xcc0ef504,
620/* 0x05c9: ih */
621 0xfe80f9fe,
622 0x80f90188,
623 0xa0f990f9,
624 0xd0f9b0f9,
625 0xf0f9e0f9,
626 0x004a04bd,
627 0x00aacf02,
628 0xf404abc4,
629 0x100d230b,
630 0xcf1a004e,
631 0x004f00ee,
632 0x00ffcf19,
633 0x0000047e,
634 0x0400b0b7,
635 0x0040010e,
636 0x000ef61d,
637/* 0x060a: ih_no_fifo */
638 0xabe404bd,
639 0x0bf40100,
640 0x4e100d0c,
641 0x047e4001,
642/* 0x061a: ih_no_ctxsw */
643 0xabe40000,
644 0x0bf40400,
645 0x01004b10,
646 0x448ebfb2,
647 0x8f7e4001,
648/* 0x062e: ih_no_fwmthd */
649 0x044b0000,
650 0xffb0bd01,
651 0x0bf4b4ab,
652 0x0700800c,
653 0x000bf603,
654/* 0x0642: ih_no_other */
655 0x004004bd,
656 0x000af601,
657 0xf0fc04bd,
658 0xd0fce0fc,
659 0xa0fcb0fc,
660 0x80fc90fc,
661 0xfc0088fe,
662 0x0032f480,
663/* 0x0662: ctx_4170s */
664 0xf5f001f8,
665 0x8effb210,
666 0x7e404170,
667 0xf800008f,
668/* 0x0671: ctx_4170w */
669 0x41708e00,
670 0x00657e40,
671 0xf0ffb200,
672 0x1bf410f4,
673/* 0x0683: ctx_redswitch */
674 0x4e00f8f3,
675 0xe5f00200,
676 0x20e5f040,
677 0x8010e5f0,
678 0xf6018500,
679 0x04bd000e,
680/* 0x069a: ctx_redswitch_delay */
681 0xf2b6080f,
682 0xfd1bf401,
683 0x0400e5f1,
684 0x0100e5f1,
685 0x01850080,
686 0xbd000ef6,
687/* 0x06b3: ctx_86c */
688 0x8000f804,
689 0xf6022300,
690 0x04bd000f,
691 0x148effb2,
692 0x8f7e408a,
693 0xffb20000,
694 0x41a88c8e,
695 0x00008f7e,
696/* 0x06d2: ctx_mem */
697 0x008000f8,
698 0x0ff60284,
699/* 0x06db: ctx_mem_wait */
700 0x8f04bd00,
701 0xcf028400,
702 0xfffd00ff,
703 0xf61bf405,
704/* 0x06ea: ctx_load */
705 0x94bd00f8,
706 0x800599f0,
707 0xf6023700,
708 0x04bd0009,
709 0xb87e0c0a,
710 0xf4bd0000,
711 0x02890080,
712 0xbd000ff6,
713 0xc1008004,
714 0x0002f602,
715 0x008004bd,
716 0x02f60283,
717 0x0f04bd00,
718 0x06d27e07,
719 0xc0008000,
720 0x0002f602,
721 0x0bfe04bd,
722 0x1f2af000,
723 0xb60424b6,
724 0x94bd0220,
725 0x800899f0,
726 0xf6023700,
727 0x04bd0009,
728 0x02810080,
729 0xbd0002f6,
730 0x0000d204,
731 0x25f08000,
732 0x88008002,
733 0x0002f602,
734 0x100104bd,
735 0xf0020042,
736 0x12fa0223,
737 0xbd03f805,
738 0x0899f094,
739 0x02170080,
740 0xbd0009f6,
741 0x81019804,
742 0x981814b6,
743 0x25b68002,
744 0x0512fd08,
745 0xbd1601b5,
746 0x0999f094,
747 0x02370080,
748 0xbd0009f6,
749 0x81008004,
750 0x0001f602,
751 0x010204bd,
752 0x02880080,
753 0xbd0002f6,
754 0x01004104,
755 0xfa0613f0,
756 0x03f80501,
757 0x99f094bd,
758 0x17008009,
759 0x0009f602,
760 0x94bd04bd,
761 0x800599f0,
762 0xf6021700,
763 0x04bd0009,
764/* 0x07d6: ctx_chan */
765 0xea7e00f8,
766 0x0c0a0006,
767 0x0000b87e,
768 0xd27e050f,
769 0x00f80006,
770/* 0x07e8: ctx_mmio_exec */
771 0x80410398,
772 0xf6028100,
773 0x04bd0003,
774/* 0x07f6: ctx_mmio_loop */
775 0x34c434bd,
776 0x0e1bf4ff,
777 0xf0020045,
778 0x35fa0653,
779/* 0x0807: ctx_mmio_pull */
780 0x9803f805,
781 0x4f98804e,
782 0x008f7e81,
783 0x0830b600,
784 0xf40112b6,
785/* 0x081a: ctx_mmio_done */
786 0x0398df1b,
787 0x81008016,
788 0x0003f602,
789 0x00b504bd,
790 0x01004140,
791 0xfa0613f0,
792 0x03f80601,
793/* 0x0836: ctx_xfer */
794 0x040e00f8,
795 0x03020080,
796 0xbd000ef6,
797/* 0x0841: ctx_xfer_idle */
798 0x00008e04,
799 0x00eecf03,
800 0x2000e4f1,
801 0xf4f51bf4,
802 0x02f40611,
803/* 0x0855: ctx_xfer_pre */
804 0x7e100f0c,
805 0xf40006b3,
806/* 0x085e: ctx_xfer_pre_load */
807 0x020f1b11,
808 0x0006627e,
809 0x0006717e,
810 0x0006837e,
811 0x627ef4bd,
812 0xea7e0006,
813/* 0x0876: ctx_xfer_exec */
814 0x01980006,
815 0x8024bd16,
816 0xf6010500,
817 0x04bd0002,
818 0x008e1fb2,
819 0x8f7e41a5,
820 0xfcf00000,
821 0x022cf001,
822 0xfd0124b6,
823 0xffb205f2,
824 0x41a5048e,
825 0x00008f7e,
826 0x0002167e,
827 0xfc8024bd,
828 0x02f60247,
829 0xf004bd00,
830 0x20b6012c,
831 0x4afc8003,
832 0x0002f602,
833 0xacf004bd,
834 0x06a5f001,
835 0x0c98000b,
836 0x010d9800,
837 0x3d7e000e,
838 0x080a0001,
839 0x0000ec7e,
840 0x00020a7e,
841 0x0a1201f4,
842 0x00b87e0c,
843 0x7e050f00,
844 0xf40006d2,
845/* 0x08f2: ctx_xfer_post */
846 0x020f2d02,
847 0x0006627e,
848 0xb37ef4bd,
849 0x277e0006,
850 0x717e0002,
851 0xf4bd0006,
852 0x0006627e,
853 0x981011f4,
854 0x11fd4001,
855 0x070bf405,
856 0x0007e87e,
857/* 0x091c: ctx_xfer_no_post_mmio */
858/* 0x091c: ctx_xfer_done */
859 0x000000f8,
860 0x00000000,
861 0x00000000,
862 0x00000000,
863 0x00000000,
864 0x00000000,
865 0x00000000,
866 0x00000000,
867 0x00000000,
868 0x00000000,
869 0x00000000,
870 0x00000000,
871 0x00000000,
872 0x00000000,
873 0x00000000,
874 0x00000000,
875 0x00000000,
876 0x00000000,
877 0x00000000,
878 0x00000000,
879 0x00000000,
880 0x00000000,
881 0x00000000,
882 0x00000000,
883 0x00000000,
884 0x00000000,
885 0x00000000,
886 0x00000000,
887 0x00000000,
888 0x00000000,
889 0x00000000,
890 0x00000000,
891 0x00000000,
892 0x00000000,
893 0x00000000,
894 0x00000000,
895 0x00000000,
896 0x00000000,
897 0x00000000,
898 0x00000000,
899 0x00000000,
900 0x00000000,
901 0x00000000,
902 0x00000000,
903 0x00000000,
904 0x00000000,
905 0x00000000,
906 0x00000000,
907 0x00000000,
908 0x00000000,
909 0x00000000,
910 0x00000000,
911 0x00000000,
912 0x00000000,
913 0x00000000,
914 0x00000000,
915 0x00000000,
916};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
index 4750984bf380..64dfd75192bf 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
@@ -342,7 +342,7 @@ uint32_t nv108_grhub_code[] = {
342 0xb4f000bb, 342 0xb4f000bb,
343 0x10b4b01f, 343 0x10b4b01f,
344 0x0af31bf4, 344 0x0af31bf4,
345 0x00b87e02, 345 0x00b87e05,
346 0x250ef400, 346 0x250ef400,
347/* 0x01d8: mmctx_stop */ 347/* 0x01d8: mmctx_stop */
348 0xb600abc8, 348 0xb600abc8,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
index 132f684b1946..f8f7b278a13f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
@@ -361,7 +361,7 @@ uint32_t nvc0_grhub_code[] = {
361 0x1fb4f000, 361 0x1fb4f000,
362 0xf410b4b0, 362 0xf410b4b0,
363 0xa7f0f01b, 363 0xa7f0f01b,
364 0xd021f402, 364 0xd021f405,
365/* 0x0223: mmctx_stop */ 365/* 0x0223: mmctx_stop */
366 0xc82b0ef4, 366 0xc82b0ef4,
367 0xb4b600ab, 367 0xb4b600ab,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
index 84af82418987..624215a005b0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
@@ -361,7 +361,7 @@ uint32_t nvd7_grhub_code[] = {
361 0x1fb4f000, 361 0x1fb4f000,
362 0xf410b4b0, 362 0xf410b4b0,
363 0xa7f0f01b, 363 0xa7f0f01b,
364 0xd021f402, 364 0xd021f405,
365/* 0x0223: mmctx_stop */ 365/* 0x0223: mmctx_stop */
366 0xc82b0ef4, 366 0xc82b0ef4,
367 0xb4b600ab, 367 0xb4b600ab,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
index 1c179bdd48cc..6547b3dfc7ed 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
@@ -361,7 +361,7 @@ uint32_t nve0_grhub_code[] = {
361 0x1fb4f000, 361 0x1fb4f000,
362 0xf410b4b0, 362 0xf410b4b0,
363 0xa7f0f01b, 363 0xa7f0f01b,
364 0xd021f402, 364 0xd021f405,
365/* 0x0223: mmctx_stop */ 365/* 0x0223: mmctx_stop */
366 0xc82b0ef4, 366 0xc82b0ef4,
367 0xb4b600ab, 367 0xb4b600ab,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
index 229c0ae37228..a5aee5a4302f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
@@ -361,7 +361,7 @@ uint32_t nvf0_grhub_code[] = {
361 0x1fb4f000, 361 0x1fb4f000,
362 0xf410b4b0, 362 0xf410b4b0,
363 0xa7f0f01b, 363 0xa7f0f01b,
364 0xd021f402, 364 0xd021f405,
365/* 0x0223: mmctx_stop */ 365/* 0x0223: mmctx_stop */
366 0xc82b0ef4, 366 0xc82b0ef4,
367 0xb4b600ab, 367 0xb4b600ab,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
index 6ffe28307dbd..a47d49db5232 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
@@ -132,6 +132,7 @@
132#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD 0x41a068 132#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD 0x41a068
133#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK 0x41a074 133#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK 0x41a074
134#define NV_PGRAPH_GPCX_GPCCS_UNITS 0x41a608 134#define NV_PGRAPH_GPCX_GPCCS_UNITS 0x41a608
135#define NV_PGRAPH_GPCX_GPCCS_CAPS 0x41a108
135#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH 0x41a614 136#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH 0x41a614
136#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11 0x00000800 137#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11 0x00000800
137#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE 0x00000200 138#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE 0x00000200
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
new file mode 100644
index 000000000000..21c5f31d607f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
@@ -0,0 +1,465 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/P0260.h>
27
28#include "nvc0.h"
29#include "ctxnvc0.h"
30
31/*******************************************************************************
32 * Graphics object classes
33 ******************************************************************************/
34
35static struct nouveau_oclass
36gm107_graph_sclass[] = {
37 { 0x902d, &nouveau_object_ofuncs },
38 { 0xa140, &nouveau_object_ofuncs },
39 { 0xb097, &nouveau_object_ofuncs },
40 { 0xb0c0, &nouveau_object_ofuncs },
41 {}
42};
43
44/*******************************************************************************
45 * PGRAPH register lists
46 ******************************************************************************/
47
48static const struct nvc0_graph_init
49gm107_graph_init_main_0[] = {
50 { 0x400080, 1, 0x04, 0x003003c2 },
51 { 0x400088, 1, 0x04, 0x0001bfe7 },
52 { 0x40008c, 1, 0x04, 0x00060000 },
53 { 0x400090, 1, 0x04, 0x00000030 },
54 { 0x40013c, 1, 0x04, 0x003901f3 },
55 { 0x400140, 1, 0x04, 0x00000100 },
56 { 0x400144, 1, 0x04, 0x00000000 },
57 { 0x400148, 1, 0x04, 0x00000110 },
58 { 0x400138, 1, 0x04, 0x00000000 },
59 { 0x400130, 2, 0x04, 0x00000000 },
60 { 0x400124, 1, 0x04, 0x00000002 },
61 {}
62};
63
64static const struct nvc0_graph_init
65gm107_graph_init_ds_0[] = {
66 { 0x405844, 1, 0x04, 0x00ffffff },
67 { 0x405850, 1, 0x04, 0x00000000 },
68 { 0x405900, 1, 0x04, 0x00000000 },
69 { 0x405908, 1, 0x04, 0x00000000 },
70 {}
71};
72
73static const struct nvc0_graph_init
74gm107_graph_init_scc_0[] = {
75 { 0x40803c, 1, 0x04, 0x00000010 },
76 {}
77};
78
79static const struct nvc0_graph_init
80gm107_graph_init_sked_0[] = {
81 { 0x407010, 1, 0x04, 0x00000000 },
82 { 0x407040, 1, 0x04, 0x40440424 },
83 { 0x407048, 1, 0x04, 0x0000000a },
84 {}
85};
86
87static const struct nvc0_graph_init
88gm107_graph_init_prop_0[] = {
89 { 0x418408, 1, 0x04, 0x00000000 },
90 { 0x4184a0, 1, 0x04, 0x00000000 },
91 {}
92};
93
94static const struct nvc0_graph_init
95gm107_graph_init_setup_1[] = {
96 { 0x4188c8, 2, 0x04, 0x00000000 },
97 { 0x4188d0, 1, 0x04, 0x00010000 },
98 { 0x4188d4, 1, 0x04, 0x00010201 },
99 {}
100};
101
102static const struct nvc0_graph_init
103gm107_graph_init_zcull_0[] = {
104 { 0x418910, 1, 0x04, 0x00010001 },
105 { 0x418914, 1, 0x04, 0x00000301 },
106 { 0x418918, 1, 0x04, 0x00800000 },
107 { 0x418930, 2, 0x04, 0x00000000 },
108 { 0x418980, 1, 0x04, 0x77777770 },
109 { 0x418984, 3, 0x04, 0x77777777 },
110 {}
111};
112
113static const struct nvc0_graph_init
114gm107_graph_init_gpc_unk_1[] = {
115 { 0x418d00, 1, 0x04, 0x00000000 },
116 { 0x418f00, 1, 0x04, 0x00000400 },
117 { 0x418f08, 1, 0x04, 0x00000000 },
118 { 0x418e08, 1, 0x04, 0x00000000 },
119 {}
120};
121
122static const struct nvc0_graph_init
123gm107_graph_init_tpccs_0[] = {
124 { 0x419dc4, 1, 0x04, 0x00000000 },
125 { 0x419dc8, 1, 0x04, 0x00000501 },
126 { 0x419dd0, 1, 0x04, 0x00000000 },
127 { 0x419dd4, 1, 0x04, 0x00000100 },
128 { 0x419dd8, 1, 0x04, 0x00000001 },
129 { 0x419ddc, 1, 0x04, 0x00000002 },
130 { 0x419de0, 1, 0x04, 0x00000001 },
131 { 0x419d0c, 1, 0x04, 0x00000000 },
132 { 0x419d10, 1, 0x04, 0x00000014 },
133 {}
134};
135
136static const struct nvc0_graph_init
137gm107_graph_init_tex_0[] = {
138 { 0x419ab0, 1, 0x04, 0x00000000 },
139 { 0x419ab8, 1, 0x04, 0x000000e7 },
140 { 0x419abc, 1, 0x04, 0x00000000 },
141 { 0x419acc, 1, 0x04, 0x000000ff },
142 { 0x419ac0, 1, 0x04, 0x00000000 },
143 { 0x419aa8, 2, 0x04, 0x00000000 },
144 { 0x419ad0, 2, 0x04, 0x00000000 },
145 { 0x419ae0, 2, 0x04, 0x00000000 },
146 { 0x419af0, 4, 0x04, 0x00000000 },
147 {}
148};
149
150static const struct nvc0_graph_init
151gm107_graph_init_pe_0[] = {
152 { 0x419900, 1, 0x04, 0x000000ff },
153 { 0x41980c, 1, 0x04, 0x00000010 },
154 { 0x419844, 1, 0x04, 0x00000000 },
155 { 0x419838, 1, 0x04, 0x000000ff },
156 { 0x419850, 1, 0x04, 0x00000004 },
157 { 0x419854, 2, 0x04, 0x00000000 },
158 { 0x419894, 3, 0x04, 0x00100401 },
159 {}
160};
161
162static const struct nvc0_graph_init
163gm107_graph_init_l1c_0[] = {
164 { 0x419c98, 1, 0x04, 0x00000000 },
165 { 0x419cc0, 2, 0x04, 0x00000000 },
166 {}
167};
168
169static const struct nvc0_graph_init
170gm107_graph_init_sm_0[] = {
171 { 0x419e30, 1, 0x04, 0x000000ff },
172 { 0x419e00, 1, 0x04, 0x00000000 },
173 { 0x419ea0, 1, 0x04, 0x00000000 },
174 { 0x419ee4, 1, 0x04, 0x00000000 },
175 { 0x419ea4, 1, 0x04, 0x00000100 },
176 { 0x419ea8, 1, 0x04, 0x01000000 },
177 { 0x419ee8, 1, 0x04, 0x00000091 },
178 { 0x419eb4, 1, 0x04, 0x00000000 },
179 { 0x419ebc, 2, 0x04, 0x00000000 },
180 { 0x419edc, 1, 0x04, 0x000c1810 },
181 { 0x419ed8, 1, 0x04, 0x00000000 },
182 { 0x419ee0, 1, 0x04, 0x00000000 },
183 { 0x419f74, 1, 0x04, 0x00005155 },
184 { 0x419f80, 4, 0x04, 0x00000000 },
185 {}
186};
187
188static const struct nvc0_graph_init
189gm107_graph_init_l1c_1[] = {
190 { 0x419ccc, 2, 0x04, 0x00000000 },
191 { 0x419c80, 1, 0x04, 0x3f006022 },
192 { 0x419c88, 1, 0x04, 0x00000000 },
193 {}
194};
195
196static const struct nvc0_graph_init
197gm107_graph_init_pes_0[] = {
198 { 0x41be50, 1, 0x04, 0x000000ff },
199 { 0x41be04, 1, 0x04, 0x00000000 },
200 { 0x41be08, 1, 0x04, 0x00000004 },
201 { 0x41be0c, 1, 0x04, 0x00000008 },
202 { 0x41be10, 1, 0x04, 0x0e3b8bc7 },
203 { 0x41be14, 2, 0x04, 0x00000000 },
204 { 0x41be3c, 5, 0x04, 0x00100401 },
205 {}
206};
207
208static const struct nvc0_graph_init
209gm107_graph_init_wwdx_0[] = {
210 { 0x41bfd4, 1, 0x04, 0x00800000 },
211 { 0x41bfdc, 1, 0x04, 0x00000000 },
212 {}
213};
214
215static const struct nvc0_graph_init
216gm107_graph_init_cbm_0[] = {
217 { 0x41becc, 1, 0x04, 0x00000000 },
218 {}
219};
220
221static const struct nvc0_graph_init
222gm107_graph_init_be_0[] = {
223 { 0x408890, 1, 0x04, 0x000000ff },
224 { 0x40880c, 1, 0x04, 0x00000000 },
225 { 0x408850, 1, 0x04, 0x00000004 },
226 { 0x408878, 1, 0x04, 0x00c81603 },
227 { 0x40887c, 1, 0x04, 0x80543432 },
228 { 0x408880, 1, 0x04, 0x0010581e },
229 { 0x408884, 1, 0x04, 0x00001205 },
230 { 0x408974, 1, 0x04, 0x000000ff },
231 { 0x408910, 9, 0x04, 0x00000000 },
232 { 0x408950, 1, 0x04, 0x00000000 },
233 { 0x408954, 1, 0x04, 0x0000ffff },
234 { 0x408958, 1, 0x04, 0x00000034 },
235 { 0x40895c, 1, 0x04, 0x8531a003 },
236 { 0x408960, 1, 0x04, 0x0561985a },
237 { 0x408964, 1, 0x04, 0x04e15c4f },
238 { 0x408968, 1, 0x04, 0x02808833 },
239 { 0x40896c, 1, 0x04, 0x01f02438 },
240 { 0x408970, 1, 0x04, 0x00012c00 },
241 { 0x408984, 1, 0x04, 0x00000000 },
242 { 0x408988, 1, 0x04, 0x08040201 },
243 { 0x40898c, 1, 0x04, 0x80402010 },
244 {}
245};
246
247static const struct nvc0_graph_init
248gm107_graph_init_sm_1[] = {
249 { 0x419e5c, 1, 0x04, 0x00000000 },
250 { 0x419e58, 1, 0x04, 0x00000000 },
251 {}
252};
253
254static const struct nvc0_graph_pack
255gm107_graph_pack_mmio[] = {
256 { gm107_graph_init_main_0 },
257 { nvf0_graph_init_fe_0 },
258 { nvc0_graph_init_pri_0 },
259 { nvc0_graph_init_rstr2d_0 },
260 { nvc0_graph_init_pd_0 },
261 { gm107_graph_init_ds_0 },
262 { gm107_graph_init_scc_0 },
263 { gm107_graph_init_sked_0 },
264 { nvf0_graph_init_cwd_0 },
265 { gm107_graph_init_prop_0 },
266 { nv108_graph_init_gpc_unk_0 },
267 { nvc0_graph_init_setup_0 },
268 { nvc0_graph_init_crstr_0 },
269 { gm107_graph_init_setup_1 },
270 { gm107_graph_init_zcull_0 },
271 { nvc0_graph_init_gpm_0 },
272 { gm107_graph_init_gpc_unk_1 },
273 { nvc0_graph_init_gcc_0 },
274 { gm107_graph_init_tpccs_0 },
275 { gm107_graph_init_tex_0 },
276 { gm107_graph_init_pe_0 },
277 { gm107_graph_init_l1c_0 },
278 { nvc0_graph_init_mpc_0 },
279 { gm107_graph_init_sm_0 },
280 { gm107_graph_init_l1c_1 },
281 { gm107_graph_init_pes_0 },
282 { gm107_graph_init_wwdx_0 },
283 { gm107_graph_init_cbm_0 },
284 { gm107_graph_init_be_0 },
285 { gm107_graph_init_sm_1 },
286 {}
287};
288
289/*******************************************************************************
290 * PGRAPH engine/subdev functions
291 ******************************************************************************/
292
293static void
294gm107_graph_init_bios(struct nvc0_graph_priv *priv)
295{
296 static const struct {
297 u32 ctrl;
298 u32 data;
299 } regs[] = {
300 { 0x419ed8, 0x419ee0 },
301 { 0x419ad0, 0x419ad4 },
302 { 0x419ae0, 0x419ae4 },
303 { 0x419af0, 0x419af4 },
304 { 0x419af8, 0x419afc },
305 };
306 struct nouveau_bios *bios = nouveau_bios(priv);
307 struct nvbios_P0260E infoE;
308 struct nvbios_P0260X infoX;
309 int E = -1, X;
310 u8 ver, hdr;
311
312 while (nvbios_P0260Ep(bios, ++E, &ver, &hdr, &infoE)) {
313 if (X = -1, E < ARRAY_SIZE(regs)) {
314 nv_wr32(priv, regs[E].ctrl, infoE.data);
315 while (nvbios_P0260Xp(bios, ++X, &ver, &hdr, &infoX))
316 nv_wr32(priv, regs[E].data, infoX.data);
317 }
318 }
319}
320
321int
322gm107_graph_init(struct nouveau_object *object)
323{
324 struct nvc0_graph_oclass *oclass = (void *)object->oclass;
325 struct nvc0_graph_priv *priv = (void *)object;
326 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
327 u32 data[TPC_MAX / 8] = {};
328 u8 tpcnr[GPC_MAX];
329 int gpc, tpc, ppc, rop;
330 int ret, i;
331
332 ret = nouveau_graph_init(&priv->base);
333 if (ret)
334 return ret;
335
336 nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
337 nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000);
338 nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000);
339 nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
340 nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
341
342 nvc0_graph_mmio(priv, oclass->mmio);
343
344 gm107_graph_init_bios(priv);
345
346 nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
347
348 memset(data, 0x00, sizeof(data));
349 memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
350 for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
351 do {
352 gpc = (gpc + 1) % priv->gpc_nr;
353 } while (!tpcnr[gpc]);
354 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
355
356 data[i / 8] |= tpc << ((i % 8) * 4);
357 }
358
359 nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
360 nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
361 nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
362 nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
363
364 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
365 nv_wr32(priv, GPC_UNIT(gpc, 0x0914),
366 priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]);
367 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 |
368 priv->tpc_total);
369 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
370 }
371
372 nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
373 nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
374
375 nv_wr32(priv, 0x400500, 0x00010001);
376
377 nv_wr32(priv, 0x400100, 0xffffffff);
378 nv_wr32(priv, 0x40013c, 0xffffffff);
379 nv_wr32(priv, 0x400124, 0x00000002);
380 nv_wr32(priv, 0x409c24, 0x000e0000);
381
382 nv_wr32(priv, 0x404000, 0xc0000000);
383 nv_wr32(priv, 0x404600, 0xc0000000);
384 nv_wr32(priv, 0x408030, 0xc0000000);
385 nv_wr32(priv, 0x404490, 0xc0000000);
386 nv_wr32(priv, 0x406018, 0xc0000000);
387 nv_wr32(priv, 0x407020, 0x40000000);
388 nv_wr32(priv, 0x405840, 0xc0000000);
389 nv_wr32(priv, 0x405844, 0x00ffffff);
390 nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
391
392 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
393 for (ppc = 0; ppc < 2 /* priv->ppc_nr[gpc] */; ppc++)
394 nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
395 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
396 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
397 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
398 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
399 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
400 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
401 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
402 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
403 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
404 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
405 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000);
406 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe);
407 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005);
408 }
409 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
410 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
411 }
412
413 for (rop = 0; rop < priv->rop_nr; rop++) {
414 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000);
415 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000);
416 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
417 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
418 }
419
420 nv_wr32(priv, 0x400108, 0xffffffff);
421 nv_wr32(priv, 0x400138, 0xffffffff);
422 nv_wr32(priv, 0x400118, 0xffffffff);
423 nv_wr32(priv, 0x400130, 0xffffffff);
424 nv_wr32(priv, 0x40011c, 0xffffffff);
425 nv_wr32(priv, 0x400134, 0xffffffff);
426
427 nv_wr32(priv, 0x400054, 0x2c350f63);
428 return nvc0_graph_init_ctxctl(priv);
429}
430
431#include "fuc/hubgm107.fuc5.h"
432
433static struct nvc0_graph_ucode
434gm107_graph_fecs_ucode = {
435 .code.data = gm107_grhub_code,
436 .code.size = sizeof(gm107_grhub_code),
437 .data.data = gm107_grhub_data,
438 .data.size = sizeof(gm107_grhub_data),
439};
440
441#include "fuc/gpcgm107.fuc5.h"
442
443static struct nvc0_graph_ucode
444gm107_graph_gpccs_ucode = {
445 .code.data = gm107_grgpc_code,
446 .code.size = sizeof(gm107_grgpc_code),
447 .data.data = gm107_grgpc_data,
448 .data.size = sizeof(gm107_grgpc_data),
449};
450
451struct nouveau_oclass *
452gm107_graph_oclass = &(struct nvc0_graph_oclass) {
453 .base.handle = NV_ENGINE(GR, 0x07),
454 .base.ofuncs = &(struct nouveau_ofuncs) {
455 .ctor = nvc0_graph_ctor,
456 .dtor = nvc0_graph_dtor,
457 .init = gm107_graph_init,
458 .fini = _nouveau_graph_fini,
459 },
460 .cclass = &gm107_grctx_oclass,
461 .sclass = gm107_graph_sclass,
462 .mmio = gm107_graph_pack_mmio,
463 .fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL,
464 .gpccs.ucode = &gm107_graph_gpccs_ucode,
465}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
index e1af65ead379..00ea1a089822 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -38,11 +39,11 @@ nv108_graph_sclass[] = {
38}; 39};
39 40
40/******************************************************************************* 41/*******************************************************************************
41 * PGRAPH engine/subdev functions 42 * PGRAPH register lists
42 ******************************************************************************/ 43 ******************************************************************************/
43 44
44static struct nvc0_graph_init 45static const struct nvc0_graph_init
45nv108_graph_init_regs[] = { 46nv108_graph_init_main_0[] = {
46 { 0x400080, 1, 0x04, 0x003083c2 }, 47 { 0x400080, 1, 0x04, 0x003083c2 },
47 { 0x400088, 1, 0x04, 0x0001bfe7 }, 48 { 0x400088, 1, 0x04, 0x0001bfe7 },
48 { 0x40008c, 1, 0x04, 0x00000000 }, 49 { 0x40008c, 1, 0x04, 0x00000000 },
@@ -57,66 +58,46 @@ nv108_graph_init_regs[] = {
57 {} 58 {}
58}; 59};
59 60
60struct nvc0_graph_init 61static const struct nvc0_graph_init
61nv108_graph_init_unk58xx[] = { 62nv108_graph_init_ds_0[] = {
62 { 0x405844, 1, 0x04, 0x00ffffff }, 63 { 0x405844, 1, 0x04, 0x00ffffff },
63 { 0x405850, 1, 0x04, 0x00000000 }, 64 { 0x405850, 1, 0x04, 0x00000000 },
64 { 0x405900, 1, 0x04, 0x00000000 }, 65 { 0x405900, 1, 0x04, 0x00000000 },
65 { 0x405908, 1, 0x04, 0x00000000 }, 66 { 0x405908, 1, 0x04, 0x00000000 },
66 { 0x405928, 1, 0x04, 0x00000000 }, 67 { 0x405928, 2, 0x04, 0x00000000 },
67 { 0x40592c, 1, 0x04, 0x00000000 },
68 {} 68 {}
69}; 69};
70 70
71static struct nvc0_graph_init 71const struct nvc0_graph_init
72nv108_graph_init_gpc[] = { 72nv108_graph_init_gpc_unk_0[] = {
73 { 0x418408, 1, 0x04, 0x00000000 },
74 { 0x4184a0, 3, 0x04, 0x00000000 },
75 { 0x418604, 1, 0x04, 0x00000000 }, 73 { 0x418604, 1, 0x04, 0x00000000 },
76 { 0x418680, 1, 0x04, 0x00000000 }, 74 { 0x418680, 1, 0x04, 0x00000000 },
77 { 0x418714, 1, 0x04, 0x00000000 }, 75 { 0x418714, 1, 0x04, 0x00000000 },
78 { 0x418384, 2, 0x04, 0x00000000 }, 76 { 0x418384, 2, 0x04, 0x00000000 },
79 { 0x418814, 3, 0x04, 0x00000000 }, 77 {}
80 { 0x418b04, 1, 0x04, 0x00000000 }, 78};
79
80static const struct nvc0_graph_init
81nv108_graph_init_setup_1[] = {
81 { 0x4188c8, 2, 0x04, 0x00000000 }, 82 { 0x4188c8, 2, 0x04, 0x00000000 },
82 { 0x4188d0, 1, 0x04, 0x00010000 }, 83 { 0x4188d0, 1, 0x04, 0x00010000 },
83 { 0x4188d4, 1, 0x04, 0x00000201 }, 84 { 0x4188d4, 1, 0x04, 0x00000201 },
84 { 0x418910, 1, 0x04, 0x00010001 },
85 { 0x418914, 1, 0x04, 0x00000301 },
86 { 0x418918, 1, 0x04, 0x00800000 },
87 { 0x418980, 1, 0x04, 0x77777770 },
88 { 0x418984, 3, 0x04, 0x77777777 },
89 { 0x418c04, 1, 0x04, 0x00000000 },
90 { 0x418c64, 2, 0x04, 0x00000000 },
91 { 0x418c88, 1, 0x04, 0x00000000 },
92 { 0x418cb4, 2, 0x04, 0x00000000 },
93 { 0x418d00, 1, 0x04, 0x00000000 },
94 { 0x418d28, 2, 0x04, 0x00000000 },
95 { 0x418f00, 1, 0x04, 0x00000400 },
96 { 0x418f08, 1, 0x04, 0x00000000 },
97 { 0x418f20, 2, 0x04, 0x00000000 },
98 { 0x418e00, 1, 0x04, 0x00000000 },
99 { 0x418e08, 1, 0x04, 0x00000000 },
100 { 0x418e1c, 2, 0x04, 0x00000000 },
101 { 0x41900c, 1, 0x04, 0x00000000 },
102 { 0x419018, 1, 0x04, 0x00000000 },
103 {} 85 {}
104}; 86};
105 87
106static struct nvc0_graph_init 88static const struct nvc0_graph_init
107nv108_graph_init_tpc[] = { 89nv108_graph_init_tex_0[] = {
108 { 0x419d0c, 1, 0x04, 0x00000000 },
109 { 0x419d10, 1, 0x04, 0x00000014 },
110 { 0x419ab0, 1, 0x04, 0x00000000 }, 90 { 0x419ab0, 1, 0x04, 0x00000000 },
111 { 0x419ac8, 1, 0x04, 0x00000000 }, 91 { 0x419ac8, 1, 0x04, 0x00000000 },
112 { 0x419ab8, 1, 0x04, 0x000000e7 }, 92 { 0x419ab8, 1, 0x04, 0x000000e7 },
113 { 0x419abc, 2, 0x04, 0x00000000 }, 93 { 0x419abc, 2, 0x04, 0x00000000 },
114 { 0x419ab4, 1, 0x04, 0x00000000 }, 94 { 0x419ab4, 1, 0x04, 0x00000000 },
115 { 0x419aa8, 2, 0x04, 0x00000000 }, 95 { 0x419aa8, 2, 0x04, 0x00000000 },
116 { 0x41980c, 1, 0x04, 0x00000010 }, 96 {}
117 { 0x419844, 1, 0x04, 0x00000000 }, 97};
118 { 0x419850, 1, 0x04, 0x00000004 }, 98
119 { 0x419854, 2, 0x04, 0x00000000 }, 99static const struct nvc0_graph_init
100nv108_graph_init_l1c_0[] = {
120 { 0x419c98, 1, 0x04, 0x00000000 }, 101 { 0x419c98, 1, 0x04, 0x00000000 },
121 { 0x419ca8, 1, 0x04, 0x00000000 }, 102 { 0x419ca8, 1, 0x04, 0x00000000 },
122 { 0x419cb0, 1, 0x04, 0x01000000 }, 103 { 0x419cb0, 1, 0x04, 0x01000000 },
@@ -127,22 +108,47 @@ nv108_graph_init_tpc[] = {
127 { 0x419cc0, 2, 0x04, 0x00000000 }, 108 { 0x419cc0, 2, 0x04, 0x00000000 },
128 { 0x419c80, 1, 0x04, 0x00000230 }, 109 { 0x419c80, 1, 0x04, 0x00000230 },
129 { 0x419ccc, 2, 0x04, 0x00000000 }, 110 { 0x419ccc, 2, 0x04, 0x00000000 },
130 { 0x419c0c, 1, 0x04, 0x00000000 },
131 { 0x419e00, 1, 0x04, 0x00000080 },
132 { 0x419ea0, 1, 0x04, 0x00000000 },
133 { 0x419ee4, 1, 0x04, 0x00000000 },
134 { 0x419ea4, 1, 0x04, 0x00000100 },
135 { 0x419ea8, 1, 0x04, 0x00000000 },
136 { 0x419eb4, 1, 0x04, 0x00000000 },
137 { 0x419ebc, 2, 0x04, 0x00000000 },
138 { 0x419edc, 1, 0x04, 0x00000000 },
139 { 0x419f00, 1, 0x04, 0x00000000 },
140 { 0x419ed0, 1, 0x04, 0x00003234 },
141 { 0x419f74, 1, 0x04, 0x00015555 },
142 { 0x419f80, 4, 0x04, 0x00000000 },
143 {} 111 {}
144}; 112};
145 113
114static const struct nvc0_graph_pack
115nv108_graph_pack_mmio[] = {
116 { nv108_graph_init_main_0 },
117 { nvf0_graph_init_fe_0 },
118 { nvc0_graph_init_pri_0 },
119 { nvc0_graph_init_rstr2d_0 },
120 { nvd9_graph_init_pd_0 },
121 { nv108_graph_init_ds_0 },
122 { nvc0_graph_init_scc_0 },
123 { nvf0_graph_init_sked_0 },
124 { nvf0_graph_init_cwd_0 },
125 { nvd9_graph_init_prop_0 },
126 { nv108_graph_init_gpc_unk_0 },
127 { nvc0_graph_init_setup_0 },
128 { nvc0_graph_init_crstr_0 },
129 { nv108_graph_init_setup_1 },
130 { nvc0_graph_init_zcull_0 },
131 { nvd9_graph_init_gpm_0 },
132 { nvf0_graph_init_gpc_unk_1 },
133 { nvc0_graph_init_gcc_0 },
134 { nve4_graph_init_tpccs_0 },
135 { nv108_graph_init_tex_0 },
136 { nve4_graph_init_pe_0 },
137 { nv108_graph_init_l1c_0 },
138 { nvc0_graph_init_mpc_0 },
139 { nvf0_graph_init_sm_0 },
140 { nvd7_graph_init_pes_0 },
141 { nvd7_graph_init_wwdx_0 },
142 { nvd7_graph_init_cbm_0 },
143 { nve4_graph_init_be_0 },
144 { nvc0_graph_init_fe_1 },
145 {}
146};
147
148/*******************************************************************************
149 * PGRAPH engine/subdev functions
150 ******************************************************************************/
151
146static int 152static int
147nv108_graph_fini(struct nouveau_object *object, bool suspend) 153nv108_graph_fini(struct nouveau_object *object, bool suspend)
148{ 154{
@@ -180,25 +186,6 @@ nv108_graph_fini(struct nouveau_object *object, bool suspend)
180 return nouveau_graph_fini(&priv->base, suspend); 186 return nouveau_graph_fini(&priv->base, suspend);
181} 187}
182 188
183static struct nvc0_graph_init *
184nv108_graph_init_mmio[] = {
185 nv108_graph_init_regs,
186 nvf0_graph_init_unk40xx,
187 nvc0_graph_init_unk44xx,
188 nvc0_graph_init_unk78xx,
189 nvc0_graph_init_unk60xx,
190 nvd9_graph_init_unk64xx,
191 nv108_graph_init_unk58xx,
192 nvc0_graph_init_unk80xx,
193 nvf0_graph_init_unk70xx,
194 nvf0_graph_init_unk5bxx,
195 nv108_graph_init_gpc,
196 nv108_graph_init_tpc,
197 nve4_graph_init_unk,
198 nve4_graph_init_unk88xx,
199 NULL
200};
201
202#include "fuc/hubnv108.fuc5.h" 189#include "fuc/hubnv108.fuc5.h"
203 190
204static struct nvc0_graph_ucode 191static struct nvc0_graph_ucode
@@ -230,7 +217,7 @@ nv108_graph_oclass = &(struct nvc0_graph_oclass) {
230 }, 217 },
231 .cclass = &nv108_grctx_oclass, 218 .cclass = &nv108_grctx_oclass,
232 .sclass = nv108_graph_sclass, 219 .sclass = nv108_graph_sclass,
233 .mmio = nv108_graph_init_mmio, 220 .mmio = nv108_graph_pack_mmio,
234 .fecs.ucode = &nv108_graph_fecs_ucode, 221 .fecs.ucode = &nv108_graph_fecs_ucode,
235 .gpccs.ucode = &nv108_graph_gpccs_ucode, 222 .gpccs.ucode = &nv108_graph_gpccs_ucode,
236}.base; 223}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
index b24559315903..d145e080899a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
@@ -349,7 +349,7 @@ nv20_graph_init(struct nouveau_object *object)
349 nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); 349 nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp);
350 350
351 /* begin RAM config */ 351 /* begin RAM config */
352 vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; 352 vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
353 nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); 353 nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
354 nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); 354 nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204));
355 nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); 355 nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 193a5de1b482..6477fbf6a550 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -484,7 +484,7 @@ nv40_graph_init(struct nouveau_object *object)
484 engine->tile_prog(engine, i); 484 engine->tile_prog(engine, i);
485 485
486 /* begin RAM config */ 486 /* begin RAM config */
487 vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; 487 vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
488 switch (nv_device(priv)->chipset) { 488 switch (nv_device(priv)->chipset) {
489 case 0x40: 489 case 0x40:
490 nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); 490 nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index 7a367c402978..2c7809e1a09b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -197,34 +197,35 @@ static const struct nouveau_bitfield nv50_pgraph_status[] = {
197 { 0x00000080, "UNK7" }, 197 { 0x00000080, "UNK7" },
198 { 0x00000100, "CTXPROG" }, 198 { 0x00000100, "CTXPROG" },
199 { 0x00000200, "VFETCH" }, 199 { 0x00000200, "VFETCH" },
200 { 0x00000400, "CCACHE_UNK4" }, 200 { 0x00000400, "CCACHE_PREGEOM" },
201 { 0x00000800, "STRMOUT_GSCHED_UNK5" }, 201 { 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
202 { 0x00001000, "UNK14XX" }, 202 { 0x00001000, "VCLIP" },
203 { 0x00002000, "UNK24XX_CSCHED" }, 203 { 0x00002000, "RATTR_APLANE" },
204 { 0x00004000, "UNK1CXX" }, 204 { 0x00004000, "TRAST" },
205 { 0x00008000, "CLIPID" }, 205 { 0x00008000, "CLIPID" },
206 { 0x00010000, "ZCULL" }, 206 { 0x00010000, "ZCULL" },
207 { 0x00020000, "ENG2D" }, 207 { 0x00020000, "ENG2D" },
208 { 0x00040000, "UNK34XX" }, 208 { 0x00040000, "RMASK" },
209 { 0x00080000, "TPRAST" }, 209 { 0x00080000, "TPC_RAST" },
210 { 0x00100000, "TPROP" }, 210 { 0x00100000, "TPC_PROP" },
211 { 0x00200000, "TEX" }, 211 { 0x00200000, "TPC_TEX" },
212 { 0x00400000, "TPVP" }, 212 { 0x00400000, "TPC_GEOM" },
213 { 0x00800000, "MP" }, 213 { 0x00800000, "TPC_MP" },
214 { 0x01000000, "ROP" }, 214 { 0x01000000, "ROP" },
215 {} 215 {}
216}; 216};
217 217
218static const char *const nv50_pgraph_vstatus_0[] = { 218static const char *const nv50_pgraph_vstatus_0[] = {
219 "VFETCH", "CCACHE", "UNK4", "UNK5", "GSCHED", "STRMOUT", "UNK14XX", NULL 219 "VFETCH", "CCACHE", "PREGEOM", "POSTGEOM", "VATTR", "STRMOUT", "VCLIP",
220 NULL
220}; 221};
221 222
222static const char *const nv50_pgraph_vstatus_1[] = { 223static const char *const nv50_pgraph_vstatus_1[] = {
223 "TPRAST", "TPROP", "TEXTURE", "TPVP", "MP", NULL 224 "TPC_RAST", "TPC_PROP", "TPC_TEX", "TPC_GEOM", "TPC_MP", NULL
224}; 225};
225 226
226static const char *const nv50_pgraph_vstatus_2[] = { 227static const char *const nv50_pgraph_vstatus_2[] = {
227 "UNK24XX", "CSCHED", "UNK1CXX", "CLIPID", "ZCULL", "ENG2D", "UNK34XX", 228 "RATTR", "APLANE", "TRAST", "CLIPID", "ZCULL", "ENG2D", "RMASK",
228 "ROP", NULL 229 "ROP", NULL
229}; 230};
230 231
@@ -329,6 +330,15 @@ static const struct nouveau_bitfield nv50_mpc_traps[] = {
329 {} 330 {}
330}; 331};
331 332
333static const struct nouveau_bitfield nv50_tex_traps[] = {
334 { 0x00000001, "" }, /* any bit set? */
335 { 0x00000002, "FAULT" },
336 { 0x00000004, "STORAGE_TYPE_MISMATCH" },
337 { 0x00000008, "LINEAR_MISMATCH" },
338 { 0x00000020, "WRONG_MEMTYPE" },
339 {}
340};
341
332static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = { 342static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
333 { 0x00000001, "NOTIFY" }, 343 { 0x00000001, "NOTIFY" },
334 { 0x00000002, "IN" }, 344 { 0x00000002, "IN" },
@@ -531,6 +541,13 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
531 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) 541 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
532 nv_error(priv, "\t0x%08x: 0x%08x\n", r, 542 nv_error(priv, "\t0x%08x: 0x%08x\n", r,
533 nv_rd32(priv, r)); 543 nv_rd32(priv, r));
544 if (ustatus) {
545 nv_error(priv, "%s - TP%d:", name, i);
546 nouveau_bitfield_print(nv50_tex_traps,
547 ustatus);
548 pr_cont("\n");
549 ustatus = 0;
550 }
534 } 551 }
535 break; 552 break;
536 case 7: /* MP error */ 553 case 7: /* MP error */
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index a73ab209ea88..f3c7329da0a0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -146,11 +147,11 @@ nvc0_graph_context_dtor(struct nouveau_object *object)
146} 147}
147 148
148/******************************************************************************* 149/*******************************************************************************
149 * PGRAPH engine/subdev functions 150 * PGRAPH register lists
150 ******************************************************************************/ 151 ******************************************************************************/
151 152
152struct nvc0_graph_init 153const struct nvc0_graph_init
153nvc0_graph_init_regs[] = { 154nvc0_graph_init_main_0[] = {
154 { 0x400080, 1, 0x04, 0x003083c2 }, 155 { 0x400080, 1, 0x04, 0x003083c2 },
155 { 0x400088, 1, 0x04, 0x00006fe7 }, 156 { 0x400088, 1, 0x04, 0x00006fe7 },
156 { 0x40008c, 1, 0x04, 0x00000000 }, 157 { 0x40008c, 1, 0x04, 0x00000000 },
@@ -165,95 +166,170 @@ nvc0_graph_init_regs[] = {
165 {} 166 {}
166}; 167};
167 168
168struct nvc0_graph_init 169const struct nvc0_graph_init
169nvc0_graph_init_unk40xx[] = { 170nvc0_graph_init_fe_0[] = {
170 { 0x40415c, 1, 0x04, 0x00000000 }, 171 { 0x40415c, 1, 0x04, 0x00000000 },
171 { 0x404170, 1, 0x04, 0x00000000 }, 172 { 0x404170, 1, 0x04, 0x00000000 },
172 {} 173 {}
173}; 174};
174 175
175struct nvc0_graph_init 176const struct nvc0_graph_init
176nvc0_graph_init_unk44xx[] = { 177nvc0_graph_init_pri_0[] = {
177 { 0x404488, 2, 0x04, 0x00000000 }, 178 { 0x404488, 2, 0x04, 0x00000000 },
178 {} 179 {}
179}; 180};
180 181
181struct nvc0_graph_init 182const struct nvc0_graph_init
182nvc0_graph_init_unk78xx[] = { 183nvc0_graph_init_rstr2d_0[] = {
183 { 0x407808, 1, 0x04, 0x00000000 }, 184 { 0x407808, 1, 0x04, 0x00000000 },
184 {} 185 {}
185}; 186};
186 187
187struct nvc0_graph_init 188const struct nvc0_graph_init
188nvc0_graph_init_unk60xx[] = { 189nvc0_graph_init_pd_0[] = {
189 { 0x406024, 1, 0x04, 0x00000000 }, 190 { 0x406024, 1, 0x04, 0x00000000 },
190 {} 191 {}
191}; 192};
192 193
193struct nvc0_graph_init 194const struct nvc0_graph_init
194nvc0_graph_init_unk58xx[] = { 195nvc0_graph_init_ds_0[] = {
195 { 0x405844, 1, 0x04, 0x00ffffff }, 196 { 0x405844, 1, 0x04, 0x00ffffff },
196 { 0x405850, 1, 0x04, 0x00000000 }, 197 { 0x405850, 1, 0x04, 0x00000000 },
197 { 0x405908, 1, 0x04, 0x00000000 }, 198 { 0x405908, 1, 0x04, 0x00000000 },
198 {} 199 {}
199}; 200};
200 201
201struct nvc0_graph_init 202const struct nvc0_graph_init
202nvc0_graph_init_unk80xx[] = { 203nvc0_graph_init_scc_0[] = {
203 { 0x40803c, 1, 0x04, 0x00000000 }, 204 { 0x40803c, 1, 0x04, 0x00000000 },
204 {} 205 {}
205}; 206};
206 207
207struct nvc0_graph_init 208const struct nvc0_graph_init
208nvc0_graph_init_gpc[] = { 209nvc0_graph_init_prop_0[] = {
209 { 0x4184a0, 1, 0x04, 0x00000000 }, 210 { 0x4184a0, 1, 0x04, 0x00000000 },
211 {}
212};
213
214const struct nvc0_graph_init
215nvc0_graph_init_gpc_unk_0[] = {
210 { 0x418604, 1, 0x04, 0x00000000 }, 216 { 0x418604, 1, 0x04, 0x00000000 },
211 { 0x418680, 1, 0x04, 0x00000000 }, 217 { 0x418680, 1, 0x04, 0x00000000 },
212 { 0x418714, 1, 0x04, 0x80000000 }, 218 { 0x418714, 1, 0x04, 0x80000000 },
213 { 0x418384, 1, 0x04, 0x00000000 }, 219 { 0x418384, 1, 0x04, 0x00000000 },
220 {}
221};
222
223const struct nvc0_graph_init
224nvc0_graph_init_setup_0[] = {
214 { 0x418814, 3, 0x04, 0x00000000 }, 225 { 0x418814, 3, 0x04, 0x00000000 },
226 {}
227};
228
229const struct nvc0_graph_init
230nvc0_graph_init_crstr_0[] = {
215 { 0x418b04, 1, 0x04, 0x00000000 }, 231 { 0x418b04, 1, 0x04, 0x00000000 },
232 {}
233};
234
235const struct nvc0_graph_init
236nvc0_graph_init_setup_1[] = {
216 { 0x4188c8, 1, 0x04, 0x80000000 }, 237 { 0x4188c8, 1, 0x04, 0x80000000 },
217 { 0x4188cc, 1, 0x04, 0x00000000 }, 238 { 0x4188cc, 1, 0x04, 0x00000000 },
218 { 0x4188d0, 1, 0x04, 0x00010000 }, 239 { 0x4188d0, 1, 0x04, 0x00010000 },
219 { 0x4188d4, 1, 0x04, 0x00000001 }, 240 { 0x4188d4, 1, 0x04, 0x00000001 },
241 {}
242};
243
244const struct nvc0_graph_init
245nvc0_graph_init_zcull_0[] = {
220 { 0x418910, 1, 0x04, 0x00010001 }, 246 { 0x418910, 1, 0x04, 0x00010001 },
221 { 0x418914, 1, 0x04, 0x00000301 }, 247 { 0x418914, 1, 0x04, 0x00000301 },
222 { 0x418918, 1, 0x04, 0x00800000 }, 248 { 0x418918, 1, 0x04, 0x00800000 },
223 { 0x418980, 1, 0x04, 0x77777770 }, 249 { 0x418980, 1, 0x04, 0x77777770 },
224 { 0x418984, 3, 0x04, 0x77777777 }, 250 { 0x418984, 3, 0x04, 0x77777777 },
251 {}
252};
253
254const struct nvc0_graph_init
255nvc0_graph_init_gpm_0[] = {
225 { 0x418c04, 1, 0x04, 0x00000000 }, 256 { 0x418c04, 1, 0x04, 0x00000000 },
226 { 0x418c88, 1, 0x04, 0x00000000 }, 257 { 0x418c88, 1, 0x04, 0x00000000 },
258 {}
259};
260
261const struct nvc0_graph_init
262nvc0_graph_init_gpc_unk_1[] = {
227 { 0x418d00, 1, 0x04, 0x00000000 }, 263 { 0x418d00, 1, 0x04, 0x00000000 },
228 { 0x418f08, 1, 0x04, 0x00000000 }, 264 { 0x418f08, 1, 0x04, 0x00000000 },
229 { 0x418e00, 1, 0x04, 0x00000050 }, 265 { 0x418e00, 1, 0x04, 0x00000050 },
230 { 0x418e08, 1, 0x04, 0x00000000 }, 266 { 0x418e08, 1, 0x04, 0x00000000 },
267 {}
268};
269
270const struct nvc0_graph_init
271nvc0_graph_init_gcc_0[] = {
231 { 0x41900c, 1, 0x04, 0x00000000 }, 272 { 0x41900c, 1, 0x04, 0x00000000 },
232 { 0x419018, 1, 0x04, 0x00000000 }, 273 { 0x419018, 1, 0x04, 0x00000000 },
233 {} 274 {}
234}; 275};
235 276
236static struct nvc0_graph_init 277const struct nvc0_graph_init
237nvc0_graph_init_tpc[] = { 278nvc0_graph_init_tpccs_0[] = {
238 { 0x419d08, 2, 0x04, 0x00000000 }, 279 { 0x419d08, 2, 0x04, 0x00000000 },
239 { 0x419d10, 1, 0x04, 0x00000014 }, 280 { 0x419d10, 1, 0x04, 0x00000014 },
281 {}
282};
283
284const struct nvc0_graph_init
285nvc0_graph_init_tex_0[] = {
240 { 0x419ab0, 1, 0x04, 0x00000000 }, 286 { 0x419ab0, 1, 0x04, 0x00000000 },
241 { 0x419ab8, 1, 0x04, 0x000000e7 }, 287 { 0x419ab8, 1, 0x04, 0x000000e7 },
242 { 0x419abc, 2, 0x04, 0x00000000 }, 288 { 0x419abc, 2, 0x04, 0x00000000 },
289 {}
290};
291
292const struct nvc0_graph_init
293nvc0_graph_init_pe_0[] = {
243 { 0x41980c, 3, 0x04, 0x00000000 }, 294 { 0x41980c, 3, 0x04, 0x00000000 },
244 { 0x419844, 1, 0x04, 0x00000000 }, 295 { 0x419844, 1, 0x04, 0x00000000 },
245 { 0x41984c, 1, 0x04, 0x00005bc5 }, 296 { 0x41984c, 1, 0x04, 0x00005bc5 },
246 { 0x419850, 4, 0x04, 0x00000000 }, 297 { 0x419850, 4, 0x04, 0x00000000 },
298 {}
299};
300
301const struct nvc0_graph_init
302nvc0_graph_init_l1c_0[] = {
247 { 0x419c98, 1, 0x04, 0x00000000 }, 303 { 0x419c98, 1, 0x04, 0x00000000 },
248 { 0x419ca8, 1, 0x04, 0x80000000 }, 304 { 0x419ca8, 1, 0x04, 0x80000000 },
249 { 0x419cb4, 1, 0x04, 0x00000000 }, 305 { 0x419cb4, 1, 0x04, 0x00000000 },
250 { 0x419cb8, 1, 0x04, 0x00008bf4 }, 306 { 0x419cb8, 1, 0x04, 0x00008bf4 },
251 { 0x419cbc, 1, 0x04, 0x28137606 }, 307 { 0x419cbc, 1, 0x04, 0x28137606 },
252 { 0x419cc0, 2, 0x04, 0x00000000 }, 308 { 0x419cc0, 2, 0x04, 0x00000000 },
309 {}
310};
311
312const struct nvc0_graph_init
313nvc0_graph_init_wwdx_0[] = {
253 { 0x419bd4, 1, 0x04, 0x00800000 }, 314 { 0x419bd4, 1, 0x04, 0x00800000 },
254 { 0x419bdc, 1, 0x04, 0x00000000 }, 315 { 0x419bdc, 1, 0x04, 0x00000000 },
316 {}
317};
318
319const struct nvc0_graph_init
320nvc0_graph_init_tpccs_1[] = {
255 { 0x419d2c, 1, 0x04, 0x00000000 }, 321 { 0x419d2c, 1, 0x04, 0x00000000 },
322 {}
323};
324
325const struct nvc0_graph_init
326nvc0_graph_init_mpc_0[] = {
256 { 0x419c0c, 1, 0x04, 0x00000000 }, 327 { 0x419c0c, 1, 0x04, 0x00000000 },
328 {}
329};
330
331static const struct nvc0_graph_init
332nvc0_graph_init_sm_0[] = {
257 { 0x419e00, 1, 0x04, 0x00000000 }, 333 { 0x419e00, 1, 0x04, 0x00000000 },
258 { 0x419ea0, 1, 0x04, 0x00000000 }, 334 { 0x419ea0, 1, 0x04, 0x00000000 },
259 { 0x419ea4, 1, 0x04, 0x00000100 }, 335 { 0x419ea4, 1, 0x04, 0x00000100 },
@@ -270,8 +346,8 @@ nvc0_graph_init_tpc[] = {
270 {} 346 {}
271}; 347};
272 348
273struct nvc0_graph_init 349const struct nvc0_graph_init
274nvc0_graph_init_unk88xx[] = { 350nvc0_graph_init_be_0[] = {
275 { 0x40880c, 1, 0x04, 0x00000000 }, 351 { 0x40880c, 1, 0x04, 0x00000000 },
276 { 0x408910, 9, 0x04, 0x00000000 }, 352 { 0x408910, 9, 0x04, 0x00000000 },
277 { 0x408950, 1, 0x04, 0x00000000 }, 353 { 0x408950, 1, 0x04, 0x00000000 },
@@ -282,18 +358,64 @@ nvc0_graph_init_unk88xx[] = {
282 {} 358 {}
283}; 359};
284 360
285struct nvc0_graph_init 361const struct nvc0_graph_init
286nvc0_graph_tpc_0[] = { 362nvc0_graph_init_fe_1[] = {
287 { 0x50405c, 1, 0x04, 0x00000001 }, 363 { 0x4040f0, 1, 0x04, 0x00000000 },
288 {} 364 {}
289}; 365};
290 366
367const struct nvc0_graph_init
368nvc0_graph_init_pe_1[] = {
369 { 0x419880, 1, 0x04, 0x00000002 },
370 {}
371};
372
373static const struct nvc0_graph_pack
374nvc0_graph_pack_mmio[] = {
375 { nvc0_graph_init_main_0 },
376 { nvc0_graph_init_fe_0 },
377 { nvc0_graph_init_pri_0 },
378 { nvc0_graph_init_rstr2d_0 },
379 { nvc0_graph_init_pd_0 },
380 { nvc0_graph_init_ds_0 },
381 { nvc0_graph_init_scc_0 },
382 { nvc0_graph_init_prop_0 },
383 { nvc0_graph_init_gpc_unk_0 },
384 { nvc0_graph_init_setup_0 },
385 { nvc0_graph_init_crstr_0 },
386 { nvc0_graph_init_setup_1 },
387 { nvc0_graph_init_zcull_0 },
388 { nvc0_graph_init_gpm_0 },
389 { nvc0_graph_init_gpc_unk_1 },
390 { nvc0_graph_init_gcc_0 },
391 { nvc0_graph_init_tpccs_0 },
392 { nvc0_graph_init_tex_0 },
393 { nvc0_graph_init_pe_0 },
394 { nvc0_graph_init_l1c_0 },
395 { nvc0_graph_init_wwdx_0 },
396 { nvc0_graph_init_tpccs_1 },
397 { nvc0_graph_init_mpc_0 },
398 { nvc0_graph_init_sm_0 },
399 { nvc0_graph_init_be_0 },
400 { nvc0_graph_init_fe_1 },
401 { nvc0_graph_init_pe_1 },
402 {}
403};
404
405/*******************************************************************************
406 * PGRAPH engine/subdev functions
407 ******************************************************************************/
408
291void 409void
292nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init) 410nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
293{ 411{
294 for (; init && init->count; init++) { 412 const struct nvc0_graph_pack *pack;
295 u32 addr = init->addr, i; 413 const struct nvc0_graph_init *init;
296 for (i = 0; i < init->count; i++) { 414
415 pack_for_each_init(init, pack, p) {
416 u32 next = init->addr + init->count * init->pitch;
417 u32 addr = init->addr;
418 while (addr < next) {
297 nv_wr32(priv, addr, init->data); 419 nv_wr32(priv, addr, init->data);
298 addr += init->pitch; 420 addr += init->pitch;
299 } 421 }
@@ -301,49 +423,53 @@ nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init)
301} 423}
302 424
303void 425void
304nvc0_graph_icmd(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init) 426nvc0_graph_icmd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
305{ 427{
306 u32 addr, data; 428 const struct nvc0_graph_pack *pack;
307 int i, j; 429 const struct nvc0_graph_init *init;
430 u32 data = 0;
308 431
309 nv_wr32(priv, 0x400208, 0x80000000); 432 nv_wr32(priv, 0x400208, 0x80000000);
310 for (i = 0; init->count; init++, i++) { 433
311 if (!i || data != init->data) { 434 pack_for_each_init(init, pack, p) {
435 u32 next = init->addr + init->count * init->pitch;
436 u32 addr = init->addr;
437
438 if ((pack == p && init == p->init) || data != init->data) {
312 nv_wr32(priv, 0x400204, init->data); 439 nv_wr32(priv, 0x400204, init->data);
313 data = init->data; 440 data = init->data;
314 } 441 }
315 442
316 addr = init->addr; 443 while (addr < next) {
317 for (j = 0; j < init->count; j++) {
318 nv_wr32(priv, 0x400200, addr); 444 nv_wr32(priv, 0x400200, addr);
445 nv_wait(priv, 0x400700, 0x00000002, 0x00000000);
319 addr += init->pitch; 446 addr += init->pitch;
320 while (nv_rd32(priv, 0x400700) & 0x00000002) {}
321 } 447 }
322 } 448 }
449
323 nv_wr32(priv, 0x400208, 0x00000000); 450 nv_wr32(priv, 0x400208, 0x00000000);
324} 451}
325 452
326void 453void
327nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds) 454nvc0_graph_mthd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
328{ 455{
329 struct nvc0_graph_mthd *mthd; 456 const struct nvc0_graph_pack *pack;
330 struct nvc0_graph_init *init; 457 const struct nvc0_graph_init *init;
331 int i = 0, j; 458 u32 data = 0;
332 u32 data;
333
334 while ((mthd = &mthds[i++]) && (init = mthd->init)) {
335 u32 addr = 0x80000000 | mthd->oclass;
336 for (data = 0; init->count; init++) {
337 if (init == mthd->init || data != init->data) {
338 nv_wr32(priv, 0x40448c, init->data);
339 data = init->data;
340 }
341 459
342 addr = (addr & 0x8000ffff) | (init->addr << 14); 460 pack_for_each_init(init, pack, p) {
343 for (j = 0; j < init->count; j++) { 461 u32 ctrl = 0x80000000 | pack->type;
344 nv_wr32(priv, 0x404488, addr); 462 u32 next = init->addr + init->count * init->pitch;
345 addr += init->pitch << 14; 463 u32 addr = init->addr;
346 } 464
465 if ((pack == p && init == p->init) || data != init->data) {
466 nv_wr32(priv, 0x40448c, init->data);
467 data = init->data;
468 }
469
470 while (addr < next) {
471 nv_wr32(priv, 0x404488, ctrl | (addr << 14));
472 addr += init->pitch;
347 } 473 }
348 } 474 }
349} 475}
@@ -772,11 +898,12 @@ nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,
772 898
773static void 899static void
774nvc0_graph_init_csdata(struct nvc0_graph_priv *priv, 900nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,
775 struct nvc0_graph_init *init, 901 const struct nvc0_graph_pack *pack,
776 u32 falcon, u32 starstar, u32 base) 902 u32 falcon, u32 starstar, u32 base)
777{ 903{
778 u32 addr = init->addr; 904 const struct nvc0_graph_pack *iter;
779 u32 next = addr; 905 const struct nvc0_graph_init *init;
906 u32 addr = ~0, prev = ~0, xfer = 0;
780 u32 star, temp; 907 u32 star, temp;
781 908
782 nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar); 909 nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar);
@@ -786,22 +913,28 @@ nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,
786 star = temp; 913 star = temp;
787 nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star); 914 nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star);
788 915
789 do { 916 pack_for_each_init(init, iter, pack) {
790 if (init->addr != next) { 917 u32 head = init->addr - base;
791 while (addr < next) { 918 u32 tail = head + init->count * init->pitch;
792 u32 nr = min((int)(next - addr) / 4, 32); 919 while (head < tail) {
793 nv_wr32(priv, falcon + 0x01c4, 920 if (head != prev + 4 || xfer >= 32) {
794 ((nr - 1) << 26) | (addr - base)); 921 if (xfer) {
795 addr += nr * 4; 922 u32 data = ((--xfer << 26) | addr);
796 star += 4; 923 nv_wr32(priv, falcon + 0x01c4, data);
924 star += 4;
925 }
926 addr = head;
927 xfer = 0;
797 } 928 }
798 addr = next = init->addr; 929 prev = head;
930 xfer = xfer + 1;
931 head = head + init->pitch;
799 } 932 }
800 next += init->count * 4; 933 }
801 } while ((init++)->count);
802 934
935 nv_wr32(priv, falcon + 0x01c4, (--xfer << 26) | addr);
803 nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar); 936 nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar);
804 nv_wr32(priv, falcon + 0x01c4, star); 937 nv_wr32(priv, falcon + 0x01c4, star + 4);
805} 938}
806 939
807int 940int
@@ -809,7 +942,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
809{ 942{
810 struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass; 943 struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
811 struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass; 944 struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
812 struct nvc0_graph_init *init;
813 u32 r000260; 945 u32 r000260;
814 int i; 946 int i;
815 947
@@ -919,10 +1051,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
919 nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]); 1051 nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]);
920 } 1052 }
921 1053
922 for (i = 0; (init = cclass->hub[i]); i++) {
923 nvc0_graph_init_csdata(priv, init, 0x409000, 0x000, 0x000000);
924 }
925
926 /* load GPC microcode */ 1054 /* load GPC microcode */
927 nv_wr32(priv, 0x41a1c0, 0x01000000); 1055 nv_wr32(priv, 0x41a1c0, 0x01000000);
928 for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++) 1056 for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
@@ -936,12 +1064,11 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
936 } 1064 }
937 nv_wr32(priv, 0x000260, r000260); 1065 nv_wr32(priv, 0x000260, r000260);
938 1066
939 if ((init = cclass->gpc[0])) 1067 /* load register lists */
940 nvc0_graph_init_csdata(priv, init, 0x41a000, 0x000, 0x418000); 1068 nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
941 if ((init = cclass->gpc[2])) 1069 nvc0_graph_init_csdata(priv, cclass->gpc, 0x41a000, 0x000, 0x418000);
942 nvc0_graph_init_csdata(priv, init, 0x41a000, 0x004, 0x419800); 1070 nvc0_graph_init_csdata(priv, cclass->tpc, 0x41a000, 0x004, 0x419800);
943 if ((init = cclass->gpc[3])) 1071 nvc0_graph_init_csdata(priv, cclass->ppc, 0x41a000, 0x008, 0x41be00);
944 nvc0_graph_init_csdata(priv, init, 0x41a000, 0x008, 0x41be00);
945 1072
946 /* start HUB ucode running, it'll init the GPCs */ 1073 /* start HUB ucode running, it'll init the GPCs */
947 nv_wr32(priv, 0x40910c, 0x00000000); 1074 nv_wr32(priv, 0x40910c, 0x00000000);
@@ -988,8 +1115,7 @@ nvc0_graph_init(struct nouveau_object *object)
988 nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); 1115 nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
989 nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); 1116 nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
990 1117
991 for (i = 0; oclass->mmio[i]; i++) 1118 nvc0_graph_mmio(priv, oclass->mmio);
992 nvc0_graph_mmio(priv, oclass->mmio[i]);
993 1119
994 memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); 1120 memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
995 for (i = 0, gpc = -1; i < priv->tpc_total; i++) { 1121 for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
@@ -1091,10 +1217,10 @@ nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname,
1091 int ret; 1217 int ret;
1092 1218
1093 snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); 1219 snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
1094 ret = request_firmware(&fw, f, &device->pdev->dev); 1220 ret = request_firmware(&fw, f, nv_device_base(device));
1095 if (ret) { 1221 if (ret) {
1096 snprintf(f, sizeof(f), "nouveau/%s", fwname); 1222 snprintf(f, sizeof(f), "nouveau/%s", fwname);
1097 ret = request_firmware(&fw, f, &device->pdev->dev); 1223 ret = request_firmware(&fw, f, nv_device_base(device));
1098 if (ret) { 1224 if (ret) {
1099 nv_error(priv, "failed to load %s\n", fwname); 1225 nv_error(priv, "failed to load %s\n", fwname);
1100 return ret; 1226 return ret;
@@ -1220,22 +1346,6 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1220 return 0; 1346 return 0;
1221} 1347}
1222 1348
1223struct nvc0_graph_init *
1224nvc0_graph_init_mmio[] = {
1225 nvc0_graph_init_regs,
1226 nvc0_graph_init_unk40xx,
1227 nvc0_graph_init_unk44xx,
1228 nvc0_graph_init_unk78xx,
1229 nvc0_graph_init_unk60xx,
1230 nvc0_graph_init_unk58xx,
1231 nvc0_graph_init_unk80xx,
1232 nvc0_graph_init_gpc,
1233 nvc0_graph_init_tpc,
1234 nvc0_graph_init_unk88xx,
1235 nvc0_graph_tpc_0,
1236 NULL
1237};
1238
1239#include "fuc/hubnvc0.fuc.h" 1349#include "fuc/hubnvc0.fuc.h"
1240 1350
1241struct nvc0_graph_ucode 1351struct nvc0_graph_ucode
@@ -1267,7 +1377,7 @@ nvc0_graph_oclass = &(struct nvc0_graph_oclass) {
1267 }, 1377 },
1268 .cclass = &nvc0_grctx_oclass, 1378 .cclass = &nvc0_grctx_oclass,
1269 .sclass = nvc0_graph_sclass, 1379 .sclass = nvc0_graph_sclass,
1270 .mmio = nvc0_graph_init_mmio, 1380 .mmio = nvc0_graph_pack_mmio,
1271 .fecs.ucode = &nvc0_graph_fecs_ucode, 1381 .fecs.ucode = &nvc0_graph_fecs_ucode,
1272 .gpccs.ucode = &nvc0_graph_gpccs_ucode, 1382 .gpccs.ucode = &nvc0_graph_gpccs_ucode,
1273}.base; 1383}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
index b0ab6de270b2..90d44616c876 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
@@ -45,6 +45,7 @@
45#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) 45#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r))
46#define GPC_BCAST(r) (0x418000 + (r)) 46#define GPC_BCAST(r) (0x418000 + (r))
47#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) 47#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r))
48#define PPC_UNIT(t, m, r) (0x503000 + (t) * 0x8000 + (m) * 0x200 + (r))
48#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) 49#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
49 50
50struct nvc0_graph_data { 51struct nvc0_graph_data {
@@ -102,8 +103,6 @@ struct nvc0_graph_chan {
102 } data[4]; 103 } data[4];
103}; 104};
104 105
105int nvc0_grctx_generate(struct nvc0_graph_priv *);
106
107int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, 106int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *,
108 struct nouveau_oclass *, void *, u32, 107 struct nouveau_oclass *, void *, u32,
109 struct nouveau_object **); 108 struct nouveau_object **);
@@ -130,34 +129,14 @@ struct nvc0_graph_init {
130 u32 data; 129 u32 data;
131}; 130};
132 131
133struct nvc0_graph_mthd { 132struct nvc0_graph_pack {
134 u16 oclass; 133 const struct nvc0_graph_init *init;
135 struct nvc0_graph_init *init; 134 u32 type;
136};
137
138struct nvc0_grctx {
139 struct nvc0_graph_priv *priv;
140 struct nvc0_graph_data *data;
141 struct nvc0_graph_mmio *mmio;
142 int buffer_nr;
143 u64 buffer[4];
144 u64 addr;
145}; 135};
146 136
147struct nvc0_grctx_oclass { 137#define pack_for_each_init(init, pack, head) \
148 struct nouveau_oclass base; 138 for (pack = head; pack && pack->init; pack++) \
149 /* main context generation function */ 139 for (init = pack->init; init && init->count; init++)
150 void (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
151 /* context-specific modify-on-first-load list generation function */
152 void (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
153 void (*unkn)(struct nvc0_graph_priv *);
154 /* mmio context data */
155 struct nvc0_graph_init **hub;
156 struct nvc0_graph_init **gpc;
157 /* indirect context data, generated with icmds/mthds */
158 struct nvc0_graph_init *icmd;
159 struct nvc0_graph_mthd *mthd;
160};
161 140
162struct nvc0_graph_ucode { 141struct nvc0_graph_ucode {
163 struct nvc0_graph_fuc code; 142 struct nvc0_graph_fuc code;
@@ -171,7 +150,7 @@ struct nvc0_graph_oclass {
171 struct nouveau_oclass base; 150 struct nouveau_oclass base;
172 struct nouveau_oclass **cclass; 151 struct nouveau_oclass **cclass;
173 struct nouveau_oclass *sclass; 152 struct nouveau_oclass *sclass;
174 struct nvc0_graph_init **mmio; 153 const struct nvc0_graph_pack *mmio;
175 struct { 154 struct {
176 struct nvc0_graph_ucode *ucode; 155 struct nvc0_graph_ucode *ucode;
177 } fecs; 156 } fecs;
@@ -180,119 +159,72 @@ struct nvc0_graph_oclass {
180 } gpccs; 159 } gpccs;
181}; 160};
182 161
183void nvc0_graph_mmio(struct nvc0_graph_priv *, struct nvc0_graph_init *); 162void nvc0_graph_mmio(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
184void nvc0_graph_icmd(struct nvc0_graph_priv *, struct nvc0_graph_init *); 163void nvc0_graph_icmd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
185void nvc0_graph_mthd(struct nvc0_graph_priv *, struct nvc0_graph_mthd *); 164void nvc0_graph_mthd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
186int nvc0_graph_init_ctxctl(struct nvc0_graph_priv *); 165int nvc0_graph_init_ctxctl(struct nvc0_graph_priv *);
187 166
188extern struct nvc0_graph_init nvc0_graph_init_regs[]; 167/* register init value lists */
189extern struct nvc0_graph_init nvc0_graph_init_unk40xx[]; 168
190extern struct nvc0_graph_init nvc0_graph_init_unk44xx[]; 169extern const struct nvc0_graph_init nvc0_graph_init_main_0[];
191extern struct nvc0_graph_init nvc0_graph_init_unk78xx[]; 170extern const struct nvc0_graph_init nvc0_graph_init_fe_0[];
192extern struct nvc0_graph_init nvc0_graph_init_unk60xx[]; 171extern const struct nvc0_graph_init nvc0_graph_init_pri_0[];
193extern struct nvc0_graph_init nvc0_graph_init_unk58xx[]; 172extern const struct nvc0_graph_init nvc0_graph_init_rstr2d_0[];
194extern struct nvc0_graph_init nvc0_graph_init_unk80xx[]; 173extern const struct nvc0_graph_init nvc0_graph_init_pd_0[];
195extern struct nvc0_graph_init nvc0_graph_init_gpc[]; 174extern const struct nvc0_graph_init nvc0_graph_init_ds_0[];
196extern struct nvc0_graph_init nvc0_graph_init_unk88xx[]; 175extern const struct nvc0_graph_init nvc0_graph_init_scc_0[];
197extern struct nvc0_graph_init nvc0_graph_tpc_0[]; 176extern const struct nvc0_graph_init nvc0_graph_init_prop_0[];
198 177extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_0[];
199extern struct nvc0_graph_init nvc3_graph_init_unk58xx[]; 178extern const struct nvc0_graph_init nvc0_graph_init_setup_0[];
200 179extern const struct nvc0_graph_init nvc0_graph_init_crstr_0[];
201extern struct nvc0_graph_init nvd9_graph_init_unk58xx[]; 180extern const struct nvc0_graph_init nvc0_graph_init_setup_1[];
202extern struct nvc0_graph_init nvd9_graph_init_unk64xx[]; 181extern const struct nvc0_graph_init nvc0_graph_init_zcull_0[];
203 182extern const struct nvc0_graph_init nvc0_graph_init_gpm_0[];
204extern struct nvc0_graph_init nve4_graph_init_regs[]; 183extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_1[];
205extern struct nvc0_graph_init nve4_graph_init_unk[]; 184extern const struct nvc0_graph_init nvc0_graph_init_gcc_0[];
206extern struct nvc0_graph_init nve4_graph_init_unk88xx[]; 185extern const struct nvc0_graph_init nvc0_graph_init_tpccs_0[];
207 186extern const struct nvc0_graph_init nvc0_graph_init_tex_0[];
208extern struct nvc0_graph_init nvf0_graph_init_unk40xx[]; 187extern const struct nvc0_graph_init nvc0_graph_init_pe_0[];
209extern struct nvc0_graph_init nvf0_graph_init_unk70xx[]; 188extern const struct nvc0_graph_init nvc0_graph_init_l1c_0[];
210extern struct nvc0_graph_init nvf0_graph_init_unk5bxx[]; 189extern const struct nvc0_graph_init nvc0_graph_init_wwdx_0[];
211extern struct nvc0_graph_init nvf0_graph_init_tpc[]; 190extern const struct nvc0_graph_init nvc0_graph_init_tpccs_1[];
212 191extern const struct nvc0_graph_init nvc0_graph_init_mpc_0[];
213int nvc0_grctx_generate(struct nvc0_graph_priv *); 192extern const struct nvc0_graph_init nvc0_graph_init_be_0[];
214void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *); 193extern const struct nvc0_graph_init nvc0_graph_init_fe_1[];
215void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); 194extern const struct nvc0_graph_init nvc0_graph_init_pe_1[];
216void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *); 195
217void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *); 196extern const struct nvc0_graph_init nvc4_graph_init_ds_0[];
218void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *); 197extern const struct nvc0_graph_init nvc4_graph_init_tex_0[];
219void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *); 198extern const struct nvc0_graph_init nvc4_graph_init_sm_0[];
220void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *); 199
221void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *); 200extern const struct nvc0_graph_init nvc1_graph_init_gpc_unk_0[];
222void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *); 201extern const struct nvc0_graph_init nvc1_graph_init_setup_1[];
223 202
224extern struct nouveau_oclass *nvc0_grctx_oclass; 203extern const struct nvc0_graph_init nvd9_graph_init_pd_0[];
225extern struct nvc0_graph_init *nvc0_grctx_init_hub[]; 204extern const struct nvc0_graph_init nvd9_graph_init_ds_0[];
226extern struct nvc0_graph_init nvc0_grctx_init_base[]; 205extern const struct nvc0_graph_init nvd9_graph_init_prop_0[];
227extern struct nvc0_graph_init nvc0_grctx_init_unk40xx[]; 206extern const struct nvc0_graph_init nvd9_graph_init_gpm_0[];
228extern struct nvc0_graph_init nvc0_grctx_init_unk44xx[]; 207extern const struct nvc0_graph_init nvd9_graph_init_gpc_unk_1[];
229extern struct nvc0_graph_init nvc0_grctx_init_unk46xx[]; 208extern const struct nvc0_graph_init nvd9_graph_init_tex_0[];
230extern struct nvc0_graph_init nvc0_grctx_init_unk47xx[]; 209extern const struct nvc0_graph_init nvd9_graph_init_sm_0[];
231extern struct nvc0_graph_init nvc0_grctx_init_unk60xx[]; 210extern const struct nvc0_graph_init nvd9_graph_init_fe_1[];
232extern struct nvc0_graph_init nvc0_grctx_init_unk64xx[]; 211
233extern struct nvc0_graph_init nvc0_grctx_init_unk78xx[]; 212extern const struct nvc0_graph_init nvd7_graph_init_pes_0[];
234extern struct nvc0_graph_init nvc0_grctx_init_unk80xx[]; 213extern const struct nvc0_graph_init nvd7_graph_init_wwdx_0[];
235extern struct nvc0_graph_init nvc0_grctx_init_gpc_0[]; 214extern const struct nvc0_graph_init nvd7_graph_init_cbm_0[];
236extern struct nvc0_graph_init nvc0_grctx_init_gpc_1[]; 215
237extern struct nvc0_graph_init nvc0_grctx_init_tpc[]; 216extern const struct nvc0_graph_init nve4_graph_init_main_0[];
238extern struct nvc0_graph_init nvc0_grctx_init_icmd[]; 217extern const struct nvc0_graph_init nve4_graph_init_tpccs_0[];
239extern struct nvc0_graph_init nvd9_grctx_init_icmd[]; // 218extern const struct nvc0_graph_init nve4_graph_init_pe_0[];
240 219extern const struct nvc0_graph_init nve4_graph_init_be_0[];
241extern struct nvc0_graph_mthd nvc0_grctx_init_mthd[]; 220
242extern struct nvc0_graph_init nvc0_grctx_init_902d[]; 221extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
243extern struct nvc0_graph_init nvc0_grctx_init_9039[]; 222extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
244extern struct nvc0_graph_init nvc0_grctx_init_90c0[]; 223extern const struct nvc0_graph_init nvf0_graph_init_cwd_0[];
245extern struct nvc0_graph_init nvc0_grctx_init_mthd_magic[]; 224extern const struct nvc0_graph_init nvf0_graph_init_gpc_unk_1[];
246 225extern const struct nvc0_graph_init nvf0_graph_init_sm_0[];
247void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); 226
248void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *); 227extern const struct nvc0_graph_init nv108_graph_init_gpc_unk_0[];
249extern struct nouveau_oclass *nvc1_grctx_oclass; 228
250extern struct nvc0_graph_init nvc1_grctx_init_9097[];
251
252extern struct nouveau_oclass *nvc3_grctx_oclass;
253
254extern struct nouveau_oclass *nvc8_grctx_oclass;
255extern struct nvc0_graph_init nvc8_grctx_init_9197[];
256extern struct nvc0_graph_init nvc8_grctx_init_9297[];
257
258extern struct nouveau_oclass *nvd7_grctx_oclass;
259
260extern struct nouveau_oclass *nvd9_grctx_oclass;
261extern struct nvc0_graph_init nvd9_grctx_init_rop[];
262extern struct nvc0_graph_mthd nvd9_grctx_init_mthd[];
263
264void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
265void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
266extern struct nouveau_oclass *nve4_grctx_oclass;
267extern struct nvc0_graph_init nve4_grctx_init_unk46xx[];
268extern struct nvc0_graph_init nve4_grctx_init_unk47xx[];
269extern struct nvc0_graph_init nve4_grctx_init_unk58xx[];
270extern struct nvc0_graph_init nve4_grctx_init_unk80xx[];
271extern struct nvc0_graph_init nve4_grctx_init_unk90xx[];
272
273extern struct nouveau_oclass *nvf0_grctx_oclass;
274extern struct nvc0_graph_init nvf0_grctx_init_unk44xx[];
275extern struct nvc0_graph_init nvf0_grctx_init_unk5bxx[];
276extern struct nvc0_graph_init nvf0_grctx_init_unk60xx[];
277
278extern struct nouveau_oclass *nv108_grctx_oclass;
279
280#define mmio_data(s,a,p) do { \
281 info->buffer[info->buffer_nr] = round_up(info->addr, (a)); \
282 info->addr = info->buffer[info->buffer_nr++] + (s); \
283 info->data->size = (s); \
284 info->data->align = (a); \
285 info->data->access = (p); \
286 info->data++; \
287} while(0)
288
289#define mmio_list(r,d,s,b) do { \
290 info->mmio->addr = (r); \
291 info->mmio->data = (d); \
292 info->mmio->shift = (s); \
293 info->mmio->buffer = (b); \
294 info->mmio++; \
295 nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0)); \
296} while(0)
297 229
298#endif 230#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
index bc4a469b86cb..30cab0b2eba1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -39,94 +40,82 @@ nvc1_graph_sclass[] = {
39}; 40};
40 41
41/******************************************************************************* 42/*******************************************************************************
42 * PGRAPH engine/subdev functions 43 * PGRAPH register lists
43 ******************************************************************************/ 44 ******************************************************************************/
44 45
45static struct nvc0_graph_init 46const struct nvc0_graph_init
46nvc1_graph_init_gpc[] = { 47nvc1_graph_init_gpc_unk_0[] = {
47 { 0x4184a0, 1, 0x04, 0x00000000 },
48 { 0x418604, 1, 0x04, 0x00000000 }, 48 { 0x418604, 1, 0x04, 0x00000000 },
49 { 0x418680, 1, 0x04, 0x00000000 }, 49 { 0x418680, 1, 0x04, 0x00000000 },
50 { 0x418714, 1, 0x04, 0x00000000 }, 50 { 0x418714, 1, 0x04, 0x00000000 },
51 { 0x418384, 1, 0x04, 0x00000000 }, 51 { 0x418384, 1, 0x04, 0x00000000 },
52 { 0x418814, 3, 0x04, 0x00000000 }, 52 {}
53 { 0x418b04, 1, 0x04, 0x00000000 }, 53};
54
55const struct nvc0_graph_init
56nvc1_graph_init_setup_1[] = {
54 { 0x4188c8, 2, 0x04, 0x00000000 }, 57 { 0x4188c8, 2, 0x04, 0x00000000 },
55 { 0x4188d0, 1, 0x04, 0x00010000 }, 58 { 0x4188d0, 1, 0x04, 0x00010000 },
56 { 0x4188d4, 1, 0x04, 0x00000001 }, 59 { 0x4188d4, 1, 0x04, 0x00000001 },
57 { 0x418910, 1, 0x04, 0x00010001 }, 60 {}
58 { 0x418914, 1, 0x04, 0x00000301 }, 61};
59 { 0x418918, 1, 0x04, 0x00800000 }, 62
60 { 0x418980, 1, 0x04, 0x77777770 }, 63static const struct nvc0_graph_init
61 { 0x418984, 3, 0x04, 0x77777777 }, 64nvc1_graph_init_gpc_unk_1[] = {
62 { 0x418c04, 1, 0x04, 0x00000000 },
63 { 0x418c88, 1, 0x04, 0x00000000 },
64 { 0x418d00, 1, 0x04, 0x00000000 }, 65 { 0x418d00, 1, 0x04, 0x00000000 },
65 { 0x418f08, 1, 0x04, 0x00000000 }, 66 { 0x418f08, 1, 0x04, 0x00000000 },
66 { 0x418e00, 1, 0x04, 0x00000003 }, 67 { 0x418e00, 1, 0x04, 0x00000003 },
67 { 0x418e08, 1, 0x04, 0x00000000 }, 68 { 0x418e08, 1, 0x04, 0x00000000 },
68 { 0x41900c, 1, 0x04, 0x00000000 },
69 { 0x419018, 1, 0x04, 0x00000000 },
70 {} 69 {}
71}; 70};
72 71
73static struct nvc0_graph_init 72static const struct nvc0_graph_init
74nvc1_graph_init_tpc[] = { 73nvc1_graph_init_pe_0[] = {
75 { 0x419d08, 2, 0x04, 0x00000000 }, 74 { 0x41980c, 1, 0x04, 0x00000010 },
76 { 0x419d10, 1, 0x04, 0x00000014 }, 75 { 0x419810, 1, 0x04, 0x00000000 },
77 { 0x419ab0, 1, 0x04, 0x00000000 },
78 { 0x419ac8, 1, 0x04, 0x00000000 },
79 { 0x419ab8, 1, 0x04, 0x000000e7 },
80 { 0x419abc, 2, 0x04, 0x00000000 },
81 { 0x41980c, 2, 0x04, 0x00000000 },
82 { 0x419814, 1, 0x04, 0x00000004 }, 76 { 0x419814, 1, 0x04, 0x00000004 },
83 { 0x419844, 1, 0x04, 0x00000000 }, 77 { 0x419844, 1, 0x04, 0x00000000 },
84 { 0x41984c, 1, 0x04, 0x00005bc5 }, 78 { 0x41984c, 1, 0x04, 0x00005bc5 },
85 { 0x419850, 4, 0x04, 0x00000000 }, 79 { 0x419850, 4, 0x04, 0x00000000 },
86 { 0x419880, 1, 0x04, 0x00000002 }, 80 { 0x419880, 1, 0x04, 0x00000002 },
87 { 0x419c98, 1, 0x04, 0x00000000 },
88 { 0x419ca8, 1, 0x04, 0x80000000 },
89 { 0x419cb4, 1, 0x04, 0x00000000 },
90 { 0x419cb8, 1, 0x04, 0x00008bf4 },
91 { 0x419cbc, 1, 0x04, 0x28137606 },
92 { 0x419cc0, 2, 0x04, 0x00000000 },
93 { 0x419bd4, 1, 0x04, 0x00800000 },
94 { 0x419bdc, 1, 0x04, 0x00000000 },
95 { 0x419d2c, 1, 0x04, 0x00000000 },
96 { 0x419c0c, 1, 0x04, 0x00000000 },
97 { 0x419e00, 1, 0x04, 0x00000000 },
98 { 0x419ea0, 1, 0x04, 0x00000000 },
99 { 0x419ea4, 1, 0x04, 0x00000100 },
100 { 0x419ea8, 1, 0x04, 0x00001100 },
101 { 0x419eac, 1, 0x04, 0x11100702 },
102 { 0x419eb0, 1, 0x04, 0x00000003 },
103 { 0x419eb4, 4, 0x04, 0x00000000 },
104 { 0x419ec8, 1, 0x04, 0x0e063818 },
105 { 0x419ecc, 1, 0x04, 0x0e060e06 },
106 { 0x419ed0, 1, 0x04, 0x00003818 },
107 { 0x419ed4, 1, 0x04, 0x011104f1 },
108 { 0x419edc, 1, 0x04, 0x00000000 },
109 { 0x419f00, 1, 0x04, 0x00000000 },
110 { 0x419f2c, 1, 0x04, 0x00000000 },
111 {} 81 {}
112}; 82};
113 83
114struct nvc0_graph_init * 84static const struct nvc0_graph_pack
115nvc1_graph_init_mmio[] = { 85nvc1_graph_pack_mmio[] = {
116 nvc0_graph_init_regs, 86 { nvc0_graph_init_main_0 },
117 nvc0_graph_init_unk40xx, 87 { nvc0_graph_init_fe_0 },
118 nvc0_graph_init_unk44xx, 88 { nvc0_graph_init_pri_0 },
119 nvc0_graph_init_unk78xx, 89 { nvc0_graph_init_rstr2d_0 },
120 nvc0_graph_init_unk60xx, 90 { nvc0_graph_init_pd_0 },
121 nvc3_graph_init_unk58xx, 91 { nvc4_graph_init_ds_0 },
122 nvc0_graph_init_unk80xx, 92 { nvc0_graph_init_scc_0 },
123 nvc1_graph_init_gpc, 93 { nvc0_graph_init_prop_0 },
124 nvc1_graph_init_tpc, 94 { nvc1_graph_init_gpc_unk_0 },
125 nvc0_graph_init_unk88xx, 95 { nvc0_graph_init_setup_0 },
126 nvc0_graph_tpc_0, 96 { nvc0_graph_init_crstr_0 },
127 NULL 97 { nvc1_graph_init_setup_1 },
98 { nvc0_graph_init_zcull_0 },
99 { nvc0_graph_init_gpm_0 },
100 { nvc1_graph_init_gpc_unk_1 },
101 { nvc0_graph_init_gcc_0 },
102 { nvc0_graph_init_tpccs_0 },
103 { nvc4_graph_init_tex_0 },
104 { nvc1_graph_init_pe_0 },
105 { nvc0_graph_init_l1c_0 },
106 { nvc0_graph_init_wwdx_0 },
107 { nvc0_graph_init_tpccs_1 },
108 { nvc0_graph_init_mpc_0 },
109 { nvc4_graph_init_sm_0 },
110 { nvc0_graph_init_be_0 },
111 { nvc0_graph_init_fe_1 },
112 {}
128}; 113};
129 114
115/*******************************************************************************
116 * PGRAPH engine/subdev functions
117 ******************************************************************************/
118
130struct nouveau_oclass * 119struct nouveau_oclass *
131nvc1_graph_oclass = &(struct nvc0_graph_oclass) { 120nvc1_graph_oclass = &(struct nvc0_graph_oclass) {
132 .base.handle = NV_ENGINE(GR, 0xc1), 121 .base.handle = NV_ENGINE(GR, 0xc1),
@@ -138,7 +127,7 @@ nvc1_graph_oclass = &(struct nvc0_graph_oclass) {
138 }, 127 },
139 .cclass = &nvc1_grctx_oclass, 128 .cclass = &nvc1_grctx_oclass,
140 .sclass = nvc1_graph_sclass, 129 .sclass = nvc1_graph_sclass,
141 .mmio = nvc1_graph_init_mmio, 130 .mmio = nvc1_graph_pack_mmio,
142 .fecs.ucode = &nvc0_graph_fecs_ucode, 131 .fecs.ucode = &nvc0_graph_fecs_ucode,
143 .gpccs.ucode = &nvc0_graph_gpccs_ucode, 132 .gpccs.ucode = &nvc0_graph_gpccs_ucode,
144}.base; 133}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c
index d44b3b3ee800..e82e70c53132 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c
@@ -23,13 +23,14 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * PGRAPH engine/subdev functions 29 * PGRAPH register lists
29 ******************************************************************************/ 30 ******************************************************************************/
30 31
31struct nvc0_graph_init 32const struct nvc0_graph_init
32nvc3_graph_init_unk58xx[] = { 33nvc4_graph_init_ds_0[] = {
33 { 0x405844, 1, 0x04, 0x00ffffff }, 34 { 0x405844, 1, 0x04, 0x00ffffff },
34 { 0x405850, 1, 0x04, 0x00000000 }, 35 { 0x405850, 1, 0x04, 0x00000000 },
35 { 0x405900, 1, 0x04, 0x00002834 }, 36 { 0x405900, 1, 0x04, 0x00002834 },
@@ -37,29 +38,27 @@ nvc3_graph_init_unk58xx[] = {
37 {} 38 {}
38}; 39};
39 40
40static struct nvc0_graph_init 41const struct nvc0_graph_init
41nvc3_graph_init_tpc[] = { 42nvc4_graph_init_tex_0[] = {
42 { 0x419d08, 2, 0x04, 0x00000000 },
43 { 0x419d10, 1, 0x04, 0x00000014 },
44 { 0x419ab0, 1, 0x04, 0x00000000 }, 43 { 0x419ab0, 1, 0x04, 0x00000000 },
45 { 0x419ac8, 1, 0x04, 0x00000000 }, 44 { 0x419ac8, 1, 0x04, 0x00000000 },
46 { 0x419ab8, 1, 0x04, 0x000000e7 }, 45 { 0x419ab8, 1, 0x04, 0x000000e7 },
47 { 0x419abc, 2, 0x04, 0x00000000 }, 46 { 0x419abc, 2, 0x04, 0x00000000 },
47 {}
48};
49
50static const struct nvc0_graph_init
51nvc4_graph_init_pe_0[] = {
48 { 0x41980c, 3, 0x04, 0x00000000 }, 52 { 0x41980c, 3, 0x04, 0x00000000 },
49 { 0x419844, 1, 0x04, 0x00000000 }, 53 { 0x419844, 1, 0x04, 0x00000000 },
50 { 0x41984c, 1, 0x04, 0x00005bc5 }, 54 { 0x41984c, 1, 0x04, 0x00005bc5 },
51 { 0x419850, 4, 0x04, 0x00000000 }, 55 { 0x419850, 4, 0x04, 0x00000000 },
52 { 0x419880, 1, 0x04, 0x00000002 }, 56 { 0x419880, 1, 0x04, 0x00000002 },
53 { 0x419c98, 1, 0x04, 0x00000000 }, 57 {}
54 { 0x419ca8, 1, 0x04, 0x80000000 }, 58};
55 { 0x419cb4, 1, 0x04, 0x00000000 }, 59
56 { 0x419cb8, 1, 0x04, 0x00008bf4 }, 60const struct nvc0_graph_init
57 { 0x419cbc, 1, 0x04, 0x28137606 }, 61nvc4_graph_init_sm_0[] = {
58 { 0x419cc0, 2, 0x04, 0x00000000 },
59 { 0x419bd4, 1, 0x04, 0x00800000 },
60 { 0x419bdc, 1, 0x04, 0x00000000 },
61 { 0x419d2c, 1, 0x04, 0x00000000 },
62 { 0x419c0c, 1, 0x04, 0x00000000 },
63 { 0x419e00, 1, 0x04, 0x00000000 }, 62 { 0x419e00, 1, 0x04, 0x00000000 },
64 { 0x419ea0, 1, 0x04, 0x00000000 }, 63 { 0x419ea0, 1, 0x04, 0x00000000 },
65 { 0x419ea4, 1, 0x04, 0x00000100 }, 64 { 0x419ea4, 1, 0x04, 0x00000100 },
@@ -77,24 +76,43 @@ nvc3_graph_init_tpc[] = {
77 {} 76 {}
78}; 77};
79 78
80static struct nvc0_graph_init * 79static const struct nvc0_graph_pack
81nvc3_graph_init_mmio[] = { 80nvc4_graph_pack_mmio[] = {
82 nvc0_graph_init_regs, 81 { nvc0_graph_init_main_0 },
83 nvc0_graph_init_unk40xx, 82 { nvc0_graph_init_fe_0 },
84 nvc0_graph_init_unk44xx, 83 { nvc0_graph_init_pri_0 },
85 nvc0_graph_init_unk78xx, 84 { nvc0_graph_init_rstr2d_0 },
86 nvc0_graph_init_unk60xx, 85 { nvc0_graph_init_pd_0 },
87 nvc3_graph_init_unk58xx, 86 { nvc4_graph_init_ds_0 },
88 nvc0_graph_init_unk80xx, 87 { nvc0_graph_init_scc_0 },
89 nvc0_graph_init_gpc, 88 { nvc0_graph_init_prop_0 },
90 nvc3_graph_init_tpc, 89 { nvc0_graph_init_gpc_unk_0 },
91 nvc0_graph_init_unk88xx, 90 { nvc0_graph_init_setup_0 },
92 nvc0_graph_tpc_0, 91 { nvc0_graph_init_crstr_0 },
93 NULL 92 { nvc0_graph_init_setup_1 },
93 { nvc0_graph_init_zcull_0 },
94 { nvc0_graph_init_gpm_0 },
95 { nvc0_graph_init_gpc_unk_1 },
96 { nvc0_graph_init_gcc_0 },
97 { nvc0_graph_init_tpccs_0 },
98 { nvc4_graph_init_tex_0 },
99 { nvc4_graph_init_pe_0 },
100 { nvc0_graph_init_l1c_0 },
101 { nvc0_graph_init_wwdx_0 },
102 { nvc0_graph_init_tpccs_1 },
103 { nvc0_graph_init_mpc_0 },
104 { nvc4_graph_init_sm_0 },
105 { nvc0_graph_init_be_0 },
106 { nvc0_graph_init_fe_1 },
107 {}
94}; 108};
95 109
110/*******************************************************************************
111 * PGRAPH engine/subdev functions
112 ******************************************************************************/
113
96struct nouveau_oclass * 114struct nouveau_oclass *
97nvc3_graph_oclass = &(struct nvc0_graph_oclass) { 115nvc4_graph_oclass = &(struct nvc0_graph_oclass) {
98 .base.handle = NV_ENGINE(GR, 0xc3), 116 .base.handle = NV_ENGINE(GR, 0xc3),
99 .base.ofuncs = &(struct nouveau_ofuncs) { 117 .base.ofuncs = &(struct nouveau_ofuncs) {
100 .ctor = nvc0_graph_ctor, 118 .ctor = nvc0_graph_ctor,
@@ -102,9 +120,9 @@ nvc3_graph_oclass = &(struct nvc0_graph_oclass) {
102 .init = nvc0_graph_init, 120 .init = nvc0_graph_init,
103 .fini = _nouveau_graph_fini, 121 .fini = _nouveau_graph_fini,
104 }, 122 },
105 .cclass = &nvc3_grctx_oclass, 123 .cclass = &nvc4_grctx_oclass,
106 .sclass = nvc0_graph_sclass, 124 .sclass = nvc0_graph_sclass,
107 .mmio = nvc3_graph_init_mmio, 125 .mmio = nvc4_graph_pack_mmio,
108 .fecs.ucode = &nvc0_graph_fecs_ucode, 126 .fecs.ucode = &nvc0_graph_fecs_ucode,
109 .gpccs.ucode = &nvc0_graph_gpccs_ucode, 127 .gpccs.ucode = &nvc0_graph_gpccs_ucode,
110}.base; 128}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
index 02845e567314..a6bf783e1256 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -40,58 +41,11 @@ nvc8_graph_sclass[] = {
40}; 41};
41 42
42/******************************************************************************* 43/*******************************************************************************
43 * PGRAPH engine/subdev functions 44 * PGRAPH register lists
44 ******************************************************************************/ 45 ******************************************************************************/
45 46
46static struct nvc0_graph_init 47static const struct nvc0_graph_init
47nvc8_graph_init_gpc[] = { 48nvc8_graph_init_sm_0[] = {
48 { 0x4184a0, 1, 0x04, 0x00000000 },
49 { 0x418604, 1, 0x04, 0x00000000 },
50 { 0x418680, 1, 0x04, 0x00000000 },
51 { 0x418714, 1, 0x04, 0x80000000 },
52 { 0x418384, 1, 0x04, 0x00000000 },
53 { 0x418814, 3, 0x04, 0x00000000 },
54 { 0x418b04, 1, 0x04, 0x00000000 },
55 { 0x4188c8, 2, 0x04, 0x00000000 },
56 { 0x4188d0, 1, 0x04, 0x00010000 },
57 { 0x4188d4, 1, 0x04, 0x00000001 },
58 { 0x418910, 1, 0x04, 0x00010001 },
59 { 0x418914, 1, 0x04, 0x00000301 },
60 { 0x418918, 1, 0x04, 0x00800000 },
61 { 0x418980, 1, 0x04, 0x77777770 },
62 { 0x418984, 3, 0x04, 0x77777777 },
63 { 0x418c04, 1, 0x04, 0x00000000 },
64 { 0x418c88, 1, 0x04, 0x00000000 },
65 { 0x418d00, 1, 0x04, 0x00000000 },
66 { 0x418f08, 1, 0x04, 0x00000000 },
67 { 0x418e00, 1, 0x04, 0x00000050 },
68 { 0x418e08, 1, 0x04, 0x00000000 },
69 { 0x41900c, 1, 0x04, 0x00000000 },
70 { 0x419018, 1, 0x04, 0x00000000 },
71 {}
72};
73
74static struct nvc0_graph_init
75nvc8_graph_init_tpc[] = {
76 { 0x419d08, 2, 0x04, 0x00000000 },
77 { 0x419d10, 1, 0x04, 0x00000014 },
78 { 0x419ab0, 1, 0x04, 0x00000000 },
79 { 0x419ab8, 1, 0x04, 0x000000e7 },
80 { 0x419abc, 2, 0x04, 0x00000000 },
81 { 0x41980c, 3, 0x04, 0x00000000 },
82 { 0x419844, 1, 0x04, 0x00000000 },
83 { 0x41984c, 1, 0x04, 0x00005bc5 },
84 { 0x419850, 4, 0x04, 0x00000000 },
85 { 0x419c98, 1, 0x04, 0x00000000 },
86 { 0x419ca8, 1, 0x04, 0x80000000 },
87 { 0x419cb4, 1, 0x04, 0x00000000 },
88 { 0x419cb8, 1, 0x04, 0x00008bf4 },
89 { 0x419cbc, 1, 0x04, 0x28137606 },
90 { 0x419cc0, 2, 0x04, 0x00000000 },
91 { 0x419bd4, 1, 0x04, 0x00800000 },
92 { 0x419bdc, 1, 0x04, 0x00000000 },
93 { 0x419d2c, 1, 0x04, 0x00000000 },
94 { 0x419c0c, 1, 0x04, 0x00000000 },
95 { 0x419e00, 1, 0x04, 0x00000000 }, 49 { 0x419e00, 1, 0x04, 0x00000000 },
96 { 0x419ea0, 1, 0x04, 0x00000000 }, 50 { 0x419ea0, 1, 0x04, 0x00000000 },
97 { 0x419ea4, 1, 0x04, 0x00000100 }, 51 { 0x419ea4, 1, 0x04, 0x00000100 },
@@ -108,22 +62,42 @@ nvc8_graph_init_tpc[] = {
108 {} 62 {}
109}; 63};
110 64
111static struct nvc0_graph_init * 65static const struct nvc0_graph_pack
112nvc8_graph_init_mmio[] = { 66nvc8_graph_pack_mmio[] = {
113 nvc0_graph_init_regs, 67 { nvc0_graph_init_main_0 },
114 nvc0_graph_init_unk40xx, 68 { nvc0_graph_init_fe_0 },
115 nvc0_graph_init_unk44xx, 69 { nvc0_graph_init_pri_0 },
116 nvc0_graph_init_unk78xx, 70 { nvc0_graph_init_rstr2d_0 },
117 nvc0_graph_init_unk60xx, 71 { nvc0_graph_init_pd_0 },
118 nvc0_graph_init_unk58xx, 72 { nvc0_graph_init_ds_0 },
119 nvc0_graph_init_unk80xx, 73 { nvc0_graph_init_scc_0 },
120 nvc8_graph_init_gpc, 74 { nvc0_graph_init_prop_0 },
121 nvc8_graph_init_tpc, 75 { nvc0_graph_init_gpc_unk_0 },
122 nvc0_graph_init_unk88xx, 76 { nvc0_graph_init_setup_0 },
123 nvc0_graph_tpc_0, 77 { nvc0_graph_init_crstr_0 },
124 NULL 78 { nvc1_graph_init_setup_1 },
79 { nvc0_graph_init_zcull_0 },
80 { nvc0_graph_init_gpm_0 },
81 { nvc0_graph_init_gpc_unk_1 },
82 { nvc0_graph_init_gcc_0 },
83 { nvc0_graph_init_tpccs_0 },
84 { nvc0_graph_init_tex_0 },
85 { nvc0_graph_init_pe_0 },
86 { nvc0_graph_init_l1c_0 },
87 { nvc0_graph_init_wwdx_0 },
88 { nvc0_graph_init_tpccs_1 },
89 { nvc0_graph_init_mpc_0 },
90 { nvc8_graph_init_sm_0 },
91 { nvc0_graph_init_be_0 },
92 { nvc0_graph_init_fe_1 },
93 { nvc0_graph_init_pe_1 },
94 {}
125}; 95};
126 96
97/*******************************************************************************
98 * PGRAPH engine/subdev functions
99 ******************************************************************************/
100
127struct nouveau_oclass * 101struct nouveau_oclass *
128nvc8_graph_oclass = &(struct nvc0_graph_oclass) { 102nvc8_graph_oclass = &(struct nvc0_graph_oclass) {
129 .base.handle = NV_ENGINE(GR, 0xc8), 103 .base.handle = NV_ENGINE(GR, 0xc8),
@@ -135,7 +109,7 @@ nvc8_graph_oclass = &(struct nvc0_graph_oclass) {
135 }, 109 },
136 .cclass = &nvc8_grctx_oclass, 110 .cclass = &nvc8_grctx_oclass,
137 .sclass = nvc8_graph_sclass, 111 .sclass = nvc8_graph_sclass,
138 .mmio = nvc8_graph_init_mmio, 112 .mmio = nvc8_graph_pack_mmio,
139 .fecs.ucode = &nvc0_graph_fecs_ucode, 113 .fecs.ucode = &nvc0_graph_fecs_ucode,
140 .gpccs.ucode = &nvc0_graph_gpccs_ucode, 114 .gpccs.ucode = &nvc0_graph_gpccs_ucode,
141}.base; 115}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
index 5052d7ab4d72..2a6a94e2a041 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
@@ -23,6 +23,77 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
27
28/*******************************************************************************
29 * PGRAPH register lists
30 ******************************************************************************/
31
32static const struct nvc0_graph_init
33nvd7_graph_init_pe_0[] = {
34 { 0x41980c, 1, 0x04, 0x00000010 },
35 { 0x419844, 1, 0x04, 0x00000000 },
36 { 0x41984c, 1, 0x04, 0x00005bc8 },
37 { 0x419850, 3, 0x04, 0x00000000 },
38 {}
39};
40
41const struct nvc0_graph_init
42nvd7_graph_init_pes_0[] = {
43 { 0x41be04, 1, 0x04, 0x00000000 },
44 { 0x41be08, 1, 0x04, 0x00000004 },
45 { 0x41be0c, 1, 0x04, 0x00000000 },
46 { 0x41be10, 1, 0x04, 0x003b8bc7 },
47 { 0x41be14, 2, 0x04, 0x00000000 },
48 {}
49};
50
51const struct nvc0_graph_init
52nvd7_graph_init_wwdx_0[] = {
53 { 0x41bfd4, 1, 0x04, 0x00800000 },
54 { 0x41bfdc, 1, 0x04, 0x00000000 },
55 { 0x41bff8, 2, 0x04, 0x00000000 },
56 {}
57};
58
59const struct nvc0_graph_init
60nvd7_graph_init_cbm_0[] = {
61 { 0x41becc, 1, 0x04, 0x00000000 },
62 { 0x41bee8, 2, 0x04, 0x00000000 },
63 {}
64};
65
66static const struct nvc0_graph_pack
67nvd7_graph_pack_mmio[] = {
68 { nvc0_graph_init_main_0 },
69 { nvc0_graph_init_fe_0 },
70 { nvc0_graph_init_pri_0 },
71 { nvc0_graph_init_rstr2d_0 },
72 { nvd9_graph_init_pd_0 },
73 { nvd9_graph_init_ds_0 },
74 { nvc0_graph_init_scc_0 },
75 { nvd9_graph_init_prop_0 },
76 { nvc1_graph_init_gpc_unk_0 },
77 { nvc0_graph_init_setup_0 },
78 { nvc0_graph_init_crstr_0 },
79 { nvc1_graph_init_setup_1 },
80 { nvc0_graph_init_zcull_0 },
81 { nvd9_graph_init_gpm_0 },
82 { nvd9_graph_init_gpc_unk_1 },
83 { nvc0_graph_init_gcc_0 },
84 { nvc0_graph_init_tpccs_0 },
85 { nvd9_graph_init_tex_0 },
86 { nvd7_graph_init_pe_0 },
87 { nvc0_graph_init_l1c_0 },
88 { nvc0_graph_init_mpc_0 },
89 { nvd9_graph_init_sm_0 },
90 { nvd7_graph_init_pes_0 },
91 { nvd7_graph_init_wwdx_0 },
92 { nvd7_graph_init_cbm_0 },
93 { nvc0_graph_init_be_0 },
94 { nvd9_graph_init_fe_1 },
95 {}
96};
26 97
27/******************************************************************************* 98/*******************************************************************************
28 * PGRAPH engine/subdev functions 99 * PGRAPH engine/subdev functions
@@ -48,108 +119,6 @@ nvd7_graph_gpccs_ucode = {
48 .data.size = sizeof(nvd7_grgpc_data), 119 .data.size = sizeof(nvd7_grgpc_data),
49}; 120};
50 121
51static struct nvc0_graph_init
52nvd7_graph_init_gpc[] = {
53 { 0x418408, 1, 0x04, 0x00000000 },
54 { 0x4184a0, 1, 0x04, 0x00000000 },
55 { 0x4184a4, 2, 0x04, 0x00000000 },
56 { 0x418604, 1, 0x04, 0x00000000 },
57 { 0x418680, 1, 0x04, 0x00000000 },
58 { 0x418714, 1, 0x04, 0x00000000 },
59 { 0x418384, 1, 0x04, 0x00000000 },
60 { 0x418814, 3, 0x04, 0x00000000 },
61 { 0x418b04, 1, 0x04, 0x00000000 },
62 { 0x4188c8, 2, 0x04, 0x00000000 },
63 { 0x4188d0, 1, 0x04, 0x00010000 },
64 { 0x4188d4, 1, 0x04, 0x00000001 },
65 { 0x418910, 1, 0x04, 0x00010001 },
66 { 0x418914, 1, 0x04, 0x00000301 },
67 { 0x418918, 1, 0x04, 0x00800000 },
68 { 0x418980, 1, 0x04, 0x77777770 },
69 { 0x418984, 3, 0x04, 0x77777777 },
70 { 0x418c04, 1, 0x04, 0x00000000 },
71 { 0x418c64, 1, 0x04, 0x00000000 },
72 { 0x418c68, 1, 0x04, 0x00000000 },
73 { 0x418c88, 1, 0x04, 0x00000000 },
74 { 0x418cb4, 2, 0x04, 0x00000000 },
75 { 0x418d00, 1, 0x04, 0x00000000 },
76 { 0x418d28, 1, 0x04, 0x00000000 },
77 { 0x418f00, 1, 0x04, 0x00000000 },
78 { 0x418f08, 1, 0x04, 0x00000000 },
79 { 0x418f20, 2, 0x04, 0x00000000 },
80 { 0x418e00, 1, 0x04, 0x00000003 },
81 { 0x418e08, 1, 0x04, 0x00000000 },
82 { 0x418e1c, 1, 0x04, 0x00000000 },
83 { 0x418e20, 1, 0x04, 0x00000000 },
84 { 0x41900c, 1, 0x04, 0x00000000 },
85 { 0x419018, 1, 0x04, 0x00000000 },
86 {}
87};
88
89static struct nvc0_graph_init
90nvd7_graph_init_tpc[] = {
91 { 0x419d08, 2, 0x04, 0x00000000 },
92 { 0x419d10, 1, 0x04, 0x00000014 },
93 { 0x419ab0, 1, 0x04, 0x00000000 },
94 { 0x419ac8, 1, 0x04, 0x00000000 },
95 { 0x419ab8, 1, 0x04, 0x000000e7 },
96 { 0x419abc, 2, 0x04, 0x00000000 },
97 { 0x419ab4, 1, 0x04, 0x00000000 },
98 { 0x41980c, 1, 0x04, 0x00000010 },
99 { 0x419844, 1, 0x04, 0x00000000 },
100 { 0x41984c, 1, 0x04, 0x00005bc8 },
101 { 0x419850, 2, 0x04, 0x00000000 },
102 { 0x419c98, 1, 0x04, 0x00000000 },
103 { 0x419ca8, 1, 0x04, 0x80000000 },
104 { 0x419cb4, 1, 0x04, 0x00000000 },
105 { 0x419cb8, 1, 0x04, 0x00008bf4 },
106 { 0x419cbc, 1, 0x04, 0x28137606 },
107 { 0x419cc0, 2, 0x04, 0x00000000 },
108 { 0x419c0c, 1, 0x04, 0x00000000 },
109 { 0x419e00, 1, 0x04, 0x00000000 },
110 { 0x419ea0, 1, 0x04, 0x00000000 },
111 { 0x419ea4, 1, 0x04, 0x00000100 },
112 { 0x419ea8, 1, 0x04, 0x02001100 },
113 { 0x419eac, 1, 0x04, 0x11100702 },
114 { 0x419eb0, 1, 0x04, 0x00000003 },
115 { 0x419eb4, 4, 0x04, 0x00000000 },
116 { 0x419ec8, 1, 0x04, 0x0e063818 },
117 { 0x419ecc, 1, 0x04, 0x0e060e06 },
118 { 0x419ed0, 1, 0x04, 0x00003818 },
119 { 0x419ed4, 1, 0x04, 0x011104f1 },
120 { 0x419edc, 1, 0x04, 0x00000000 },
121 { 0x419f00, 1, 0x04, 0x00000000 },
122 { 0x419f2c, 1, 0x04, 0x00000000 },
123 {}
124};
125
126static struct nvc0_graph_init
127nvd7_graph_init_tpc_0[] = {
128 { 0x40402c, 1, 0x04, 0x00000000 },
129 { 0x4040f0, 1, 0x04, 0x00000000 },
130 { 0x404174, 1, 0x04, 0x00000000 },
131 { 0x503018, 1, 0x04, 0x00000001 },
132 {}
133};
134
135static struct nvc0_graph_init *
136nvd7_graph_init_mmio[] = {
137 nvc0_graph_init_regs,
138 nvc0_graph_init_unk40xx,
139 nvc0_graph_init_unk44xx,
140 nvc0_graph_init_unk78xx,
141 nvc0_graph_init_unk60xx,
142 nvd9_graph_init_unk64xx,
143 nvd9_graph_init_unk58xx,
144 nvc0_graph_init_unk80xx,
145 nvd7_graph_init_gpc,
146 nvd7_graph_init_tpc,
147 nve4_graph_init_unk,
148 nvc0_graph_init_unk88xx,
149 nvd7_graph_init_tpc_0,
150 NULL
151};
152
153struct nouveau_oclass * 122struct nouveau_oclass *
154nvd7_graph_oclass = &(struct nvc0_graph_oclass) { 123nvd7_graph_oclass = &(struct nvc0_graph_oclass) {
155 .base.handle = NV_ENGINE(GR, 0xd7), 124 .base.handle = NV_ENGINE(GR, 0xd7),
@@ -161,7 +130,7 @@ nvd7_graph_oclass = &(struct nvc0_graph_oclass) {
161 }, 130 },
162 .cclass = &nvd7_grctx_oclass, 131 .cclass = &nvd7_grctx_oclass,
163 .sclass = nvc8_graph_sclass, 132 .sclass = nvc8_graph_sclass,
164 .mmio = nvd7_graph_init_mmio, 133 .mmio = nvd7_graph_pack_mmio,
165 .fecs.ucode = &nvd7_graph_fecs_ucode, 134 .fecs.ucode = &nvd7_graph_fecs_ucode,
166 .gpccs.ucode = &nvd7_graph_gpccs_ucode, 135 .gpccs.ucode = &nvd7_graph_gpccs_ucode,
167}.base; 136}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c
index 652098e0df3f..00fdf202fb92 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c
@@ -23,76 +23,70 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * PGRAPH engine/subdev functions 29 * PGRAPH register lists
29 ******************************************************************************/ 30 ******************************************************************************/
30 31
31struct nvc0_graph_init 32const struct nvc0_graph_init
32nvd9_graph_init_unk64xx[] = { 33nvd9_graph_init_pd_0[] = {
34 { 0x406024, 1, 0x04, 0x00000000 },
33 { 0x4064f0, 3, 0x04, 0x00000000 }, 35 { 0x4064f0, 3, 0x04, 0x00000000 },
34 {} 36 {}
35}; 37};
36 38
37struct nvc0_graph_init 39const struct nvc0_graph_init
38nvd9_graph_init_unk58xx[] = { 40nvd9_graph_init_ds_0[] = {
39 { 0x405844, 1, 0x04, 0x00ffffff }, 41 { 0x405844, 1, 0x04, 0x00ffffff },
40 { 0x405850, 1, 0x04, 0x00000000 }, 42 { 0x405850, 1, 0x04, 0x00000000 },
41 { 0x405900, 1, 0x04, 0x00002834 }, 43 { 0x405900, 1, 0x04, 0x00002834 },
42 { 0x405908, 1, 0x04, 0x00000000 }, 44 { 0x405908, 1, 0x04, 0x00000000 },
43 { 0x405928, 1, 0x04, 0x00000000 }, 45 { 0x405928, 2, 0x04, 0x00000000 },
44 { 0x40592c, 1, 0x04, 0x00000000 },
45 {} 46 {}
46}; 47};
47 48
48static struct nvc0_graph_init 49const struct nvc0_graph_init
49nvd9_graph_init_gpc[] = { 50nvd9_graph_init_prop_0[] = {
50 { 0x418408, 1, 0x04, 0x00000000 }, 51 { 0x418408, 1, 0x04, 0x00000000 },
51 { 0x4184a0, 1, 0x04, 0x00000000 }, 52 { 0x4184a0, 3, 0x04, 0x00000000 },
52 { 0x4184a4, 2, 0x04, 0x00000000 }, 53 {}
53 { 0x418604, 1, 0x04, 0x00000000 }, 54};
54 { 0x418680, 1, 0x04, 0x00000000 }, 55
55 { 0x418714, 1, 0x04, 0x00000000 }, 56const struct nvc0_graph_init
56 { 0x418384, 1, 0x04, 0x00000000 }, 57nvd9_graph_init_gpm_0[] = {
57 { 0x418814, 3, 0x04, 0x00000000 },
58 { 0x418b04, 1, 0x04, 0x00000000 },
59 { 0x4188c8, 2, 0x04, 0x00000000 },
60 { 0x4188d0, 1, 0x04, 0x00010000 },
61 { 0x4188d4, 1, 0x04, 0x00000001 },
62 { 0x418910, 1, 0x04, 0x00010001 },
63 { 0x418914, 1, 0x04, 0x00000301 },
64 { 0x418918, 1, 0x04, 0x00800000 },
65 { 0x418980, 1, 0x04, 0x77777770 },
66 { 0x418984, 3, 0x04, 0x77777777 },
67 { 0x418c04, 1, 0x04, 0x00000000 }, 58 { 0x418c04, 1, 0x04, 0x00000000 },
68 { 0x418c64, 1, 0x04, 0x00000000 }, 59 { 0x418c64, 2, 0x04, 0x00000000 },
69 { 0x418c68, 1, 0x04, 0x00000000 },
70 { 0x418c88, 1, 0x04, 0x00000000 }, 60 { 0x418c88, 1, 0x04, 0x00000000 },
71 { 0x418cb4, 2, 0x04, 0x00000000 }, 61 { 0x418cb4, 2, 0x04, 0x00000000 },
62 {}
63};
64
65const struct nvc0_graph_init
66nvd9_graph_init_gpc_unk_1[] = {
72 { 0x418d00, 1, 0x04, 0x00000000 }, 67 { 0x418d00, 1, 0x04, 0x00000000 },
73 { 0x418d28, 1, 0x04, 0x00000000 }, 68 { 0x418d28, 2, 0x04, 0x00000000 },
74 { 0x418d2c, 1, 0x04, 0x00000000 },
75 { 0x418f00, 1, 0x04, 0x00000000 }, 69 { 0x418f00, 1, 0x04, 0x00000000 },
76 { 0x418f08, 1, 0x04, 0x00000000 }, 70 { 0x418f08, 1, 0x04, 0x00000000 },
77 { 0x418f20, 2, 0x04, 0x00000000 }, 71 { 0x418f20, 2, 0x04, 0x00000000 },
78 { 0x418e00, 1, 0x04, 0x00000003 }, 72 { 0x418e00, 1, 0x04, 0x00000003 },
79 { 0x418e08, 1, 0x04, 0x00000000 }, 73 { 0x418e08, 1, 0x04, 0x00000000 },
80 { 0x418e1c, 1, 0x04, 0x00000000 }, 74 { 0x418e1c, 2, 0x04, 0x00000000 },
81 { 0x418e20, 1, 0x04, 0x00000000 },
82 { 0x41900c, 1, 0x04, 0x00000000 },
83 { 0x419018, 1, 0x04, 0x00000000 },
84 {} 75 {}
85}; 76};
86 77
87static struct nvc0_graph_init 78const struct nvc0_graph_init
88nvd9_graph_init_tpc[] = { 79nvd9_graph_init_tex_0[] = {
89 { 0x419d08, 2, 0x04, 0x00000000 },
90 { 0x419d10, 1, 0x04, 0x00000014 },
91 { 0x419ab0, 1, 0x04, 0x00000000 }, 80 { 0x419ab0, 1, 0x04, 0x00000000 },
92 { 0x419ac8, 1, 0x04, 0x00000000 }, 81 { 0x419ac8, 1, 0x04, 0x00000000 },
93 { 0x419ab8, 1, 0x04, 0x000000e7 }, 82 { 0x419ab8, 1, 0x04, 0x000000e7 },
94 { 0x419abc, 2, 0x04, 0x00000000 }, 83 { 0x419abc, 2, 0x04, 0x00000000 },
95 { 0x419ab4, 1, 0x04, 0x00000000 }, 84 { 0x419ab4, 1, 0x04, 0x00000000 },
85 {}
86};
87
88static const struct nvc0_graph_init
89nvd9_graph_init_pe_0[] = {
96 { 0x41980c, 1, 0x04, 0x00000010 }, 90 { 0x41980c, 1, 0x04, 0x00000010 },
97 { 0x419810, 1, 0x04, 0x00000000 }, 91 { 0x419810, 1, 0x04, 0x00000000 },
98 { 0x419814, 1, 0x04, 0x00000004 }, 92 { 0x419814, 1, 0x04, 0x00000004 },
@@ -100,20 +94,26 @@ nvd9_graph_init_tpc[] = {
100 { 0x41984c, 1, 0x04, 0x0000a918 }, 94 { 0x41984c, 1, 0x04, 0x0000a918 },
101 { 0x419850, 4, 0x04, 0x00000000 }, 95 { 0x419850, 4, 0x04, 0x00000000 },
102 { 0x419880, 1, 0x04, 0x00000002 }, 96 { 0x419880, 1, 0x04, 0x00000002 },
103 { 0x419c98, 1, 0x04, 0x00000000 }, 97 {}
104 { 0x419ca8, 1, 0x04, 0x80000000 }, 98};
105 { 0x419cb4, 1, 0x04, 0x00000000 }, 99
106 { 0x419cb8, 1, 0x04, 0x00008bf4 }, 100static const struct nvc0_graph_init
107 { 0x419cbc, 1, 0x04, 0x28137606 }, 101nvd9_graph_init_wwdx_0[] = {
108 { 0x419cc0, 2, 0x04, 0x00000000 },
109 { 0x419bd4, 1, 0x04, 0x00800000 }, 102 { 0x419bd4, 1, 0x04, 0x00800000 },
110 { 0x419bdc, 1, 0x04, 0x00000000 }, 103 { 0x419bdc, 1, 0x04, 0x00000000 },
111 { 0x419bf8, 1, 0x04, 0x00000000 }, 104 { 0x419bf8, 2, 0x04, 0x00000000 },
112 { 0x419bfc, 1, 0x04, 0x00000000 }, 105 {}
106};
107
108static const struct nvc0_graph_init
109nvd9_graph_init_tpccs_1[] = {
113 { 0x419d2c, 1, 0x04, 0x00000000 }, 110 { 0x419d2c, 1, 0x04, 0x00000000 },
114 { 0x419d48, 1, 0x04, 0x00000000 }, 111 { 0x419d48, 2, 0x04, 0x00000000 },
115 { 0x419d4c, 1, 0x04, 0x00000000 }, 112 {}
116 { 0x419c0c, 1, 0x04, 0x00000000 }, 113};
114
115const struct nvc0_graph_init
116nvd9_graph_init_sm_0[] = {
117 { 0x419e00, 1, 0x04, 0x00000000 }, 117 { 0x419e00, 1, 0x04, 0x00000000 },
118 { 0x419ea0, 1, 0x04, 0x00000000 }, 118 { 0x419ea0, 1, 0x04, 0x00000000 },
119 { 0x419ea4, 1, 0x04, 0x00000100 }, 119 { 0x419ea4, 1, 0x04, 0x00000100 },
@@ -131,23 +131,49 @@ nvd9_graph_init_tpc[] = {
131 {} 131 {}
132}; 132};
133 133
134static struct nvc0_graph_init * 134const struct nvc0_graph_init
135nvd9_graph_init_mmio[] = { 135nvd9_graph_init_fe_1[] = {
136 nvc0_graph_init_regs, 136 { 0x40402c, 1, 0x04, 0x00000000 },
137 nvc0_graph_init_unk40xx, 137 { 0x4040f0, 1, 0x04, 0x00000000 },
138 nvc0_graph_init_unk44xx, 138 { 0x404174, 1, 0x04, 0x00000000 },
139 nvc0_graph_init_unk78xx, 139 {}
140 nvc0_graph_init_unk60xx,
141 nvd9_graph_init_unk64xx,
142 nvd9_graph_init_unk58xx,
143 nvc0_graph_init_unk80xx,
144 nvd9_graph_init_gpc,
145 nvd9_graph_init_tpc,
146 nvc0_graph_init_unk88xx,
147 nvc0_graph_tpc_0,
148 NULL
149}; 140};
150 141
142static const struct nvc0_graph_pack
143nvd9_graph_pack_mmio[] = {
144 { nvc0_graph_init_main_0 },
145 { nvc0_graph_init_fe_0 },
146 { nvc0_graph_init_pri_0 },
147 { nvc0_graph_init_rstr2d_0 },
148 { nvd9_graph_init_pd_0 },
149 { nvd9_graph_init_ds_0 },
150 { nvc0_graph_init_scc_0 },
151 { nvd9_graph_init_prop_0 },
152 { nvc1_graph_init_gpc_unk_0 },
153 { nvc0_graph_init_setup_0 },
154 { nvc0_graph_init_crstr_0 },
155 { nvc1_graph_init_setup_1 },
156 { nvc0_graph_init_zcull_0 },
157 { nvd9_graph_init_gpm_0 },
158 { nvd9_graph_init_gpc_unk_1 },
159 { nvc0_graph_init_gcc_0 },
160 { nvc0_graph_init_tpccs_0 },
161 { nvd9_graph_init_tex_0 },
162 { nvd9_graph_init_pe_0 },
163 { nvc0_graph_init_l1c_0 },
164 { nvd9_graph_init_wwdx_0 },
165 { nvd9_graph_init_tpccs_1 },
166 { nvc0_graph_init_mpc_0 },
167 { nvd9_graph_init_sm_0 },
168 { nvc0_graph_init_be_0 },
169 { nvd9_graph_init_fe_1 },
170 {}
171};
172
173/*******************************************************************************
174 * PGRAPH engine/subdev functions
175 ******************************************************************************/
176
151struct nouveau_oclass * 177struct nouveau_oclass *
152nvd9_graph_oclass = &(struct nvc0_graph_oclass) { 178nvd9_graph_oclass = &(struct nvc0_graph_oclass) {
153 .base.handle = NV_ENGINE(GR, 0xd9), 179 .base.handle = NV_ENGINE(GR, 0xd9),
@@ -159,7 +185,7 @@ nvd9_graph_oclass = &(struct nvc0_graph_oclass) {
159 }, 185 },
160 .cclass = &nvd9_grctx_oclass, 186 .cclass = &nvd9_grctx_oclass,
161 .sclass = nvc8_graph_sclass, 187 .sclass = nvc8_graph_sclass,
162 .mmio = nvd9_graph_init_mmio, 188 .mmio = nvd9_graph_pack_mmio,
163 .fecs.ucode = &nvc0_graph_fecs_ucode, 189 .fecs.ucode = &nvc0_graph_fecs_ucode,
164 .gpccs.ucode = &nvc0_graph_gpccs_ucode, 190 .gpccs.ucode = &nvc0_graph_gpccs_ucode,
165}.base; 191}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
index 05ec09c88517..f7c011217175 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -38,11 +39,11 @@ nve4_graph_sclass[] = {
38}; 39};
39 40
40/******************************************************************************* 41/*******************************************************************************
41 * PGRAPH engine/subdev functions 42 * PGRAPH register lists
42 ******************************************************************************/ 43 ******************************************************************************/
43 44
44struct nvc0_graph_init 45const struct nvc0_graph_init
45nve4_graph_init_regs[] = { 46nve4_graph_init_main_0[] = {
46 { 0x400080, 1, 0x04, 0x003083c2 }, 47 { 0x400080, 1, 0x04, 0x003083c2 },
47 { 0x400088, 1, 0x04, 0x0001ffe7 }, 48 { 0x400088, 1, 0x04, 0x0001ffe7 },
48 { 0x40008c, 1, 0x04, 0x00000000 }, 49 { 0x40008c, 1, 0x04, 0x00000000 },
@@ -57,81 +58,59 @@ nve4_graph_init_regs[] = {
57 {} 58 {}
58}; 59};
59 60
60static struct nvc0_graph_init 61static const struct nvc0_graph_init
61nve4_graph_init_unk58xx[] = { 62nve4_graph_init_ds_0[] = {
62 { 0x405844, 1, 0x04, 0x00ffffff }, 63 { 0x405844, 1, 0x04, 0x00ffffff },
63 { 0x405850, 1, 0x04, 0x00000000 }, 64 { 0x405850, 1, 0x04, 0x00000000 },
64 { 0x405900, 1, 0x04, 0x0000ff34 }, 65 { 0x405900, 1, 0x04, 0x0000ff34 },
65 { 0x405908, 1, 0x04, 0x00000000 }, 66 { 0x405908, 1, 0x04, 0x00000000 },
66 { 0x405928, 1, 0x04, 0x00000000 }, 67 { 0x405928, 2, 0x04, 0x00000000 },
67 { 0x40592c, 1, 0x04, 0x00000000 },
68 {} 68 {}
69}; 69};
70 70
71static struct nvc0_graph_init 71static const struct nvc0_graph_init
72nve4_graph_init_unk70xx[] = { 72nve4_graph_init_sked_0[] = {
73 { 0x407010, 1, 0x04, 0x00000000 }, 73 { 0x407010, 1, 0x04, 0x00000000 },
74 {} 74 {}
75}; 75};
76 76
77struct nvc0_graph_init 77static const struct nvc0_graph_init
78nve4_graph_init_unk5bxx[] = { 78nve4_graph_init_cwd_0[] = {
79 { 0x405b50, 1, 0x04, 0x00000000 }, 79 { 0x405b50, 1, 0x04, 0x00000000 },
80 {} 80 {}
81}; 81};
82 82
83static struct nvc0_graph_init 83static const struct nvc0_graph_init
84nve4_graph_init_gpc[] = { 84nve4_graph_init_gpc_unk_1[] = {
85 { 0x418408, 1, 0x04, 0x00000000 },
86 { 0x4184a0, 1, 0x04, 0x00000000 },
87 { 0x4184a4, 2, 0x04, 0x00000000 },
88 { 0x418604, 1, 0x04, 0x00000000 },
89 { 0x418680, 1, 0x04, 0x00000000 },
90 { 0x418714, 1, 0x04, 0x00000000 },
91 { 0x418384, 1, 0x04, 0x00000000 },
92 { 0x418814, 3, 0x04, 0x00000000 },
93 { 0x418b04, 1, 0x04, 0x00000000 },
94 { 0x4188c8, 2, 0x04, 0x00000000 },
95 { 0x4188d0, 1, 0x04, 0x00010000 },
96 { 0x4188d4, 1, 0x04, 0x00000001 },
97 { 0x418910, 1, 0x04, 0x00010001 },
98 { 0x418914, 1, 0x04, 0x00000301 },
99 { 0x418918, 1, 0x04, 0x00800000 },
100 { 0x418980, 1, 0x04, 0x77777770 },
101 { 0x418984, 3, 0x04, 0x77777777 },
102 { 0x418c04, 1, 0x04, 0x00000000 },
103 { 0x418c64, 1, 0x04, 0x00000000 },
104 { 0x418c68, 1, 0x04, 0x00000000 },
105 { 0x418c88, 1, 0x04, 0x00000000 },
106 { 0x418cb4, 2, 0x04, 0x00000000 },
107 { 0x418d00, 1, 0x04, 0x00000000 }, 85 { 0x418d00, 1, 0x04, 0x00000000 },
108 { 0x418d28, 1, 0x04, 0x00000000 }, 86 { 0x418d28, 2, 0x04, 0x00000000 },
109 { 0x418d2c, 1, 0x04, 0x00000000 },
110 { 0x418f00, 1, 0x04, 0x00000000 }, 87 { 0x418f00, 1, 0x04, 0x00000000 },
111 { 0x418f08, 1, 0x04, 0x00000000 }, 88 { 0x418f08, 1, 0x04, 0x00000000 },
112 { 0x418f20, 2, 0x04, 0x00000000 }, 89 { 0x418f20, 2, 0x04, 0x00000000 },
113 { 0x418e00, 1, 0x04, 0x00000060 }, 90 { 0x418e00, 1, 0x04, 0x00000060 },
114 { 0x418e08, 1, 0x04, 0x00000000 }, 91 { 0x418e08, 1, 0x04, 0x00000000 },
115 { 0x418e1c, 1, 0x04, 0x00000000 }, 92 { 0x418e1c, 2, 0x04, 0x00000000 },
116 { 0x418e20, 1, 0x04, 0x00000000 },
117 { 0x41900c, 1, 0x04, 0x00000000 },
118 { 0x419018, 1, 0x04, 0x00000000 },
119 {} 93 {}
120}; 94};
121 95
122static struct nvc0_graph_init 96const struct nvc0_graph_init
123nve4_graph_init_tpc[] = { 97nve4_graph_init_tpccs_0[] = {
124 { 0x419d0c, 1, 0x04, 0x00000000 }, 98 { 0x419d0c, 1, 0x04, 0x00000000 },
125 { 0x419d10, 1, 0x04, 0x00000014 }, 99 { 0x419d10, 1, 0x04, 0x00000014 },
126 { 0x419ab0, 1, 0x04, 0x00000000 }, 100 {}
127 { 0x419ac8, 1, 0x04, 0x00000000 }, 101};
128 { 0x419ab8, 1, 0x04, 0x000000e7 }, 102
129 { 0x419abc, 2, 0x04, 0x00000000 }, 103const struct nvc0_graph_init
130 { 0x419ab4, 1, 0x04, 0x00000000 }, 104nve4_graph_init_pe_0[] = {
131 { 0x41980c, 1, 0x04, 0x00000010 }, 105 { 0x41980c, 1, 0x04, 0x00000010 },
132 { 0x419844, 1, 0x04, 0x00000000 }, 106 { 0x419844, 1, 0x04, 0x00000000 },
133 { 0x419850, 1, 0x04, 0x00000004 }, 107 { 0x419850, 1, 0x04, 0x00000004 },
134 { 0x419854, 2, 0x04, 0x00000000 }, 108 { 0x419854, 2, 0x04, 0x00000000 },
109 {}
110};
111
112static const struct nvc0_graph_init
113nve4_graph_init_l1c_0[] = {
135 { 0x419c98, 1, 0x04, 0x00000000 }, 114 { 0x419c98, 1, 0x04, 0x00000000 },
136 { 0x419ca8, 1, 0x04, 0x00000000 }, 115 { 0x419ca8, 1, 0x04, 0x00000000 },
137 { 0x419cb0, 1, 0x04, 0x01000000 }, 116 { 0x419cb0, 1, 0x04, 0x01000000 },
@@ -141,39 +120,25 @@ nve4_graph_init_tpc[] = {
141 { 0x419cbc, 1, 0x04, 0x28137646 }, 120 { 0x419cbc, 1, 0x04, 0x28137646 },
142 { 0x419cc0, 2, 0x04, 0x00000000 }, 121 { 0x419cc0, 2, 0x04, 0x00000000 },
143 { 0x419c80, 1, 0x04, 0x00020232 }, 122 { 0x419c80, 1, 0x04, 0x00020232 },
144 { 0x419c0c, 1, 0x04, 0x00000000 }, 123 {}
124};
125
126static const struct nvc0_graph_init
127nve4_graph_init_sm_0[] = {
145 { 0x419e00, 1, 0x04, 0x00000000 }, 128 { 0x419e00, 1, 0x04, 0x00000000 },
146 { 0x419ea0, 1, 0x04, 0x00000000 }, 129 { 0x419ea0, 1, 0x04, 0x00000000 },
147 { 0x419ee4, 1, 0x04, 0x00000000 }, 130 { 0x419ee4, 1, 0x04, 0x00000000 },
148 { 0x419ea4, 1, 0x04, 0x00000100 }, 131 { 0x419ea4, 1, 0x04, 0x00000100 },
149 { 0x419ea8, 1, 0x04, 0x00000000 }, 132 { 0x419ea8, 1, 0x04, 0x00000000 },
150 { 0x419eb4, 1, 0x04, 0x00000000 }, 133 { 0x419eb4, 4, 0x04, 0x00000000 },
151 { 0x419eb8, 3, 0x04, 0x00000000 },
152 { 0x419edc, 1, 0x04, 0x00000000 }, 134 { 0x419edc, 1, 0x04, 0x00000000 },
153 { 0x419f00, 1, 0x04, 0x00000000 }, 135 { 0x419f00, 1, 0x04, 0x00000000 },
154 { 0x419f74, 1, 0x04, 0x00000555 }, 136 { 0x419f74, 1, 0x04, 0x00000555 },
155 {} 137 {}
156}; 138};
157 139
158struct nvc0_graph_init 140const struct nvc0_graph_init
159nve4_graph_init_unk[] = { 141nve4_graph_init_be_0[] = {
160 { 0x41be04, 1, 0x04, 0x00000000 },
161 { 0x41be08, 1, 0x04, 0x00000004 },
162 { 0x41be0c, 1, 0x04, 0x00000000 },
163 { 0x41be10, 1, 0x04, 0x003b8bc7 },
164 { 0x41be14, 2, 0x04, 0x00000000 },
165 { 0x41bfd4, 1, 0x04, 0x00800000 },
166 { 0x41bfdc, 1, 0x04, 0x00000000 },
167 { 0x41bff8, 1, 0x04, 0x00000000 },
168 { 0x41bffc, 1, 0x04, 0x00000000 },
169 { 0x41becc, 1, 0x04, 0x00000000 },
170 { 0x41bee8, 1, 0x04, 0x00000000 },
171 { 0x41beec, 1, 0x04, 0x00000000 },
172 {}
173};
174
175struct nvc0_graph_init
176nve4_graph_init_unk88xx[] = {
177 { 0x40880c, 1, 0x04, 0x00000000 }, 142 { 0x40880c, 1, 0x04, 0x00000000 },
178 { 0x408850, 1, 0x04, 0x00000004 }, 143 { 0x408850, 1, 0x04, 0x00000004 },
179 { 0x408910, 9, 0x04, 0x00000000 }, 144 { 0x408910, 9, 0x04, 0x00000000 },
@@ -186,6 +151,67 @@ nve4_graph_init_unk88xx[] = {
186 {} 151 {}
187}; 152};
188 153
154static const struct nvc0_graph_pack
155nve4_graph_pack_mmio[] = {
156 { nve4_graph_init_main_0 },
157 { nvc0_graph_init_fe_0 },
158 { nvc0_graph_init_pri_0 },
159 { nvc0_graph_init_rstr2d_0 },
160 { nvd9_graph_init_pd_0 },
161 { nve4_graph_init_ds_0 },
162 { nvc0_graph_init_scc_0 },
163 { nve4_graph_init_sked_0 },
164 { nve4_graph_init_cwd_0 },
165 { nvd9_graph_init_prop_0 },
166 { nvc1_graph_init_gpc_unk_0 },
167 { nvc0_graph_init_setup_0 },
168 { nvc0_graph_init_crstr_0 },
169 { nvc1_graph_init_setup_1 },
170 { nvc0_graph_init_zcull_0 },
171 { nvd9_graph_init_gpm_0 },
172 { nve4_graph_init_gpc_unk_1 },
173 { nvc0_graph_init_gcc_0 },
174 { nve4_graph_init_tpccs_0 },
175 { nvd9_graph_init_tex_0 },
176 { nve4_graph_init_pe_0 },
177 { nve4_graph_init_l1c_0 },
178 { nvc0_graph_init_mpc_0 },
179 { nve4_graph_init_sm_0 },
180 { nvd7_graph_init_pes_0 },
181 { nvd7_graph_init_wwdx_0 },
182 { nvd7_graph_init_cbm_0 },
183 { nve4_graph_init_be_0 },
184 { nvc0_graph_init_fe_1 },
185 {}
186};
187
188/*******************************************************************************
189 * PGRAPH engine/subdev functions
190 ******************************************************************************/
191
192static int
193nve4_graph_fini(struct nouveau_object *object, bool suspend)
194{
195 struct nvc0_graph_priv *priv = (void *)object;
196
197 /*XXX: this is a nasty hack to power on gr on certain boards
198 * where it's disabled by therm, somehow. ideally it'd
199 * be nice to know when we should be doing this, and why,
200 * but, it's yet to be determined. for now we test for
201 * the particular mmio error that occurs in the situation,
202 * and then bash therm in the way nvidia do.
203 */
204 nv_mask(priv, 0x000200, 0x08001000, 0x08001000);
205 nv_rd32(priv, 0x000200);
206 if (nv_rd32(priv, 0x400700) == 0xbadf1000) {
207 nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
208 nv_rd32(priv, 0x000200);
209 nv_mask(priv, 0x020004, 0xc0000000, 0x40000000);
210 }
211
212 return nouveau_graph_fini(&priv->base, suspend);
213}
214
189int 215int
190nve4_graph_init(struct nouveau_object *object) 216nve4_graph_init(struct nouveau_object *object)
191{ 217{
@@ -210,8 +236,7 @@ nve4_graph_init(struct nouveau_object *object)
210 nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); 236 nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
211 nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); 237 nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
212 238
213 for (i = 0; oclass->mmio[i]; i++) 239 nvc0_graph_mmio(priv, oclass->mmio);
214 nvc0_graph_mmio(priv, oclass->mmio[i]);
215 240
216 nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); 241 nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
217 242
@@ -298,25 +323,6 @@ nve4_graph_init(struct nouveau_object *object)
298 return nvc0_graph_init_ctxctl(priv); 323 return nvc0_graph_init_ctxctl(priv);
299} 324}
300 325
301static struct nvc0_graph_init *
302nve4_graph_init_mmio[] = {
303 nve4_graph_init_regs,
304 nvc0_graph_init_unk40xx,
305 nvc0_graph_init_unk44xx,
306 nvc0_graph_init_unk78xx,
307 nvc0_graph_init_unk60xx,
308 nvd9_graph_init_unk64xx,
309 nve4_graph_init_unk58xx,
310 nvc0_graph_init_unk80xx,
311 nve4_graph_init_unk70xx,
312 nve4_graph_init_unk5bxx,
313 nve4_graph_init_gpc,
314 nve4_graph_init_tpc,
315 nve4_graph_init_unk,
316 nve4_graph_init_unk88xx,
317 NULL
318};
319
320#include "fuc/hubnve0.fuc.h" 326#include "fuc/hubnve0.fuc.h"
321 327
322static struct nvc0_graph_ucode 328static struct nvc0_graph_ucode
@@ -344,11 +350,11 @@ nve4_graph_oclass = &(struct nvc0_graph_oclass) {
344 .ctor = nvc0_graph_ctor, 350 .ctor = nvc0_graph_ctor,
345 .dtor = nvc0_graph_dtor, 351 .dtor = nvc0_graph_dtor,
346 .init = nve4_graph_init, 352 .init = nve4_graph_init,
347 .fini = _nouveau_graph_fini, 353 .fini = nve4_graph_fini,
348 }, 354 },
349 .cclass = &nve4_grctx_oclass, 355 .cclass = &nve4_grctx_oclass,
350 .sclass = nve4_graph_sclass, 356 .sclass = nve4_graph_sclass,
351 .mmio = nve4_graph_init_mmio, 357 .mmio = nve4_graph_pack_mmio,
352 .fecs.ucode = &nve4_graph_fecs_ucode, 358 .fecs.ucode = &nve4_graph_fecs_ucode,
353 .gpccs.ucode = &nve4_graph_gpccs_ucode, 359 .gpccs.ucode = &nve4_graph_gpccs_ucode,
354}.base; 360}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
index b1acb9939d95..c96762122b9b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include "nvc0.h" 25#include "nvc0.h"
26#include "ctxnvc0.h"
26 27
27/******************************************************************************* 28/*******************************************************************************
28 * Graphics object classes 29 * Graphics object classes
@@ -38,86 +39,57 @@ nvf0_graph_sclass[] = {
38}; 39};
39 40
40/******************************************************************************* 41/*******************************************************************************
41 * PGRAPH engine/subdev functions 42 * PGRAPH register lists
42 ******************************************************************************/ 43 ******************************************************************************/
43 44
44struct nvc0_graph_init 45const struct nvc0_graph_init
45nvf0_graph_init_unk40xx[] = { 46nvf0_graph_init_fe_0[] = {
46 { 0x40415c, 1, 0x04, 0x00000000 }, 47 { 0x40415c, 1, 0x04, 0x00000000 },
47 { 0x404170, 1, 0x04, 0x00000000 }, 48 { 0x404170, 1, 0x04, 0x00000000 },
48 { 0x4041b4, 1, 0x04, 0x00000000 }, 49 { 0x4041b4, 1, 0x04, 0x00000000 },
49 {} 50 {}
50}; 51};
51 52
52static struct nvc0_graph_init 53static const struct nvc0_graph_init
53nvf0_graph_init_unk58xx[] = { 54nvf0_graph_init_ds_0[] = {
54 { 0x405844, 1, 0x04, 0x00ffffff }, 55 { 0x405844, 1, 0x04, 0x00ffffff },
55 { 0x405850, 1, 0x04, 0x00000000 }, 56 { 0x405850, 1, 0x04, 0x00000000 },
56 { 0x405900, 1, 0x04, 0x0000ff00 }, 57 { 0x405900, 1, 0x04, 0x0000ff00 },
57 { 0x405908, 1, 0x04, 0x00000000 }, 58 { 0x405908, 1, 0x04, 0x00000000 },
58 { 0x405928, 1, 0x04, 0x00000000 }, 59 { 0x405928, 2, 0x04, 0x00000000 },
59 { 0x40592c, 1, 0x04, 0x00000000 },
60 {} 60 {}
61}; 61};
62 62
63struct nvc0_graph_init 63const struct nvc0_graph_init
64nvf0_graph_init_unk70xx[] = { 64nvf0_graph_init_sked_0[] = {
65 { 0x407010, 1, 0x04, 0x00000000 }, 65 { 0x407010, 1, 0x04, 0x00000000 },
66 { 0x407040, 1, 0x04, 0x80440424 }, 66 { 0x407040, 1, 0x04, 0x80440424 },
67 { 0x407048, 1, 0x04, 0x0000000a }, 67 { 0x407048, 1, 0x04, 0x0000000a },
68 {} 68 {}
69}; 69};
70 70
71struct nvc0_graph_init 71const struct nvc0_graph_init
72nvf0_graph_init_unk5bxx[] = { 72nvf0_graph_init_cwd_0[] = {
73 { 0x405b44, 1, 0x04, 0x00000000 }, 73 { 0x405b44, 1, 0x04, 0x00000000 },
74 { 0x405b50, 1, 0x04, 0x00000000 }, 74 { 0x405b50, 1, 0x04, 0x00000000 },
75 {} 75 {}
76}; 76};
77 77
78static struct nvc0_graph_init 78const struct nvc0_graph_init
79nvf0_graph_init_gpc[] = { 79nvf0_graph_init_gpc_unk_1[] = {
80 { 0x418408, 1, 0x04, 0x00000000 },
81 { 0x4184a0, 1, 0x04, 0x00000000 },
82 { 0x4184a4, 2, 0x04, 0x00000000 },
83 { 0x418604, 1, 0x04, 0x00000000 },
84 { 0x418680, 1, 0x04, 0x00000000 },
85 { 0x418714, 1, 0x04, 0x00000000 },
86 { 0x418384, 1, 0x04, 0x00000000 },
87 { 0x418814, 3, 0x04, 0x00000000 },
88 { 0x418b04, 1, 0x04, 0x00000000 },
89 { 0x4188c8, 2, 0x04, 0x00000000 },
90 { 0x4188d0, 1, 0x04, 0x00010000 },
91 { 0x4188d4, 1, 0x04, 0x00000001 },
92 { 0x418910, 1, 0x04, 0x00010001 },
93 { 0x418914, 1, 0x04, 0x00000301 },
94 { 0x418918, 1, 0x04, 0x00800000 },
95 { 0x418980, 1, 0x04, 0x77777770 },
96 { 0x418984, 3, 0x04, 0x77777777 },
97 { 0x418c04, 1, 0x04, 0x00000000 },
98 { 0x418c64, 1, 0x04, 0x00000000 },
99 { 0x418c68, 1, 0x04, 0x00000000 },
100 { 0x418c88, 1, 0x04, 0x00000000 },
101 { 0x418cb4, 2, 0x04, 0x00000000 },
102 { 0x418d00, 1, 0x04, 0x00000000 }, 80 { 0x418d00, 1, 0x04, 0x00000000 },
103 { 0x418d28, 1, 0x04, 0x00000000 }, 81 { 0x418d28, 2, 0x04, 0x00000000 },
104 { 0x418d2c, 1, 0x04, 0x00000000 },
105 { 0x418f00, 1, 0x04, 0x00000400 }, 82 { 0x418f00, 1, 0x04, 0x00000400 },
106 { 0x418f08, 1, 0x04, 0x00000000 }, 83 { 0x418f08, 1, 0x04, 0x00000000 },
107 { 0x418f20, 1, 0x04, 0x00000000 }, 84 { 0x418f20, 2, 0x04, 0x00000000 },
108 { 0x418f24, 1, 0x04, 0x00000000 },
109 { 0x418e00, 1, 0x04, 0x00000000 }, 85 { 0x418e00, 1, 0x04, 0x00000000 },
110 { 0x418e08, 1, 0x04, 0x00000000 }, 86 { 0x418e08, 1, 0x04, 0x00000000 },
111 { 0x418e1c, 2, 0x04, 0x00000000 }, 87 { 0x418e1c, 2, 0x04, 0x00000000 },
112 { 0x41900c, 1, 0x04, 0x00000000 },
113 { 0x419018, 1, 0x04, 0x00000000 },
114 {} 88 {}
115}; 89};
116 90
117struct nvc0_graph_init 91static const struct nvc0_graph_init
118nvf0_graph_init_tpc[] = { 92nvf0_graph_init_tex_0[] = {
119 { 0x419d0c, 1, 0x04, 0x00000000 },
120 { 0x419d10, 1, 0x04, 0x00000014 },
121 { 0x419ab0, 1, 0x04, 0x00000000 }, 93 { 0x419ab0, 1, 0x04, 0x00000000 },
122 { 0x419ac8, 1, 0x04, 0x00000000 }, 94 { 0x419ac8, 1, 0x04, 0x00000000 },
123 { 0x419ab8, 1, 0x04, 0x000000e7 }, 95 { 0x419ab8, 1, 0x04, 0x000000e7 },
@@ -125,10 +97,11 @@ nvf0_graph_init_tpc[] = {
125 { 0x419abc, 2, 0x04, 0x00000000 }, 97 { 0x419abc, 2, 0x04, 0x00000000 },
126 { 0x419ab4, 1, 0x04, 0x00000000 }, 98 { 0x419ab4, 1, 0x04, 0x00000000 },
127 { 0x419aa8, 2, 0x04, 0x00000000 }, 99 { 0x419aa8, 2, 0x04, 0x00000000 },
128 { 0x41980c, 1, 0x04, 0x00000010 }, 100 {}
129 { 0x419844, 1, 0x04, 0x00000000 }, 101};
130 { 0x419850, 1, 0x04, 0x00000004 }, 102
131 { 0x419854, 2, 0x04, 0x00000000 }, 103static const struct nvc0_graph_init
104nvf0_graph_init_l1c_0[] = {
132 { 0x419c98, 1, 0x04, 0x00000000 }, 105 { 0x419c98, 1, 0x04, 0x00000000 },
133 { 0x419ca8, 1, 0x04, 0x00000000 }, 106 { 0x419ca8, 1, 0x04, 0x00000000 },
134 { 0x419cb0, 1, 0x04, 0x01000000 }, 107 { 0x419cb0, 1, 0x04, 0x01000000 },
@@ -139,7 +112,11 @@ nvf0_graph_init_tpc[] = {
139 { 0x419cc0, 2, 0x04, 0x00000000 }, 112 { 0x419cc0, 2, 0x04, 0x00000000 },
140 { 0x419c80, 1, 0x04, 0x00020230 }, 113 { 0x419c80, 1, 0x04, 0x00020230 },
141 { 0x419ccc, 2, 0x04, 0x00000000 }, 114 { 0x419ccc, 2, 0x04, 0x00000000 },
142 { 0x419c0c, 1, 0x04, 0x00000000 }, 115 {}
116};
117
118const struct nvc0_graph_init
119nvf0_graph_init_sm_0[] = {
143 { 0x419e00, 1, 0x04, 0x00000080 }, 120 { 0x419e00, 1, 0x04, 0x00000080 },
144 { 0x419ea0, 1, 0x04, 0x00000000 }, 121 { 0x419ea0, 1, 0x04, 0x00000000 },
145 { 0x419ee4, 1, 0x04, 0x00000000 }, 122 { 0x419ee4, 1, 0x04, 0x00000000 },
@@ -155,6 +132,44 @@ nvf0_graph_init_tpc[] = {
155 {} 132 {}
156}; 133};
157 134
135static const struct nvc0_graph_pack
136nvf0_graph_pack_mmio[] = {
137 { nve4_graph_init_main_0 },
138 { nvf0_graph_init_fe_0 },
139 { nvc0_graph_init_pri_0 },
140 { nvc0_graph_init_rstr2d_0 },
141 { nvd9_graph_init_pd_0 },
142 { nvf0_graph_init_ds_0 },
143 { nvc0_graph_init_scc_0 },
144 { nvf0_graph_init_sked_0 },
145 { nvf0_graph_init_cwd_0 },
146 { nvd9_graph_init_prop_0 },
147 { nvc1_graph_init_gpc_unk_0 },
148 { nvc0_graph_init_setup_0 },
149 { nvc0_graph_init_crstr_0 },
150 { nvc1_graph_init_setup_1 },
151 { nvc0_graph_init_zcull_0 },
152 { nvd9_graph_init_gpm_0 },
153 { nvf0_graph_init_gpc_unk_1 },
154 { nvc0_graph_init_gcc_0 },
155 { nve4_graph_init_tpccs_0 },
156 { nvf0_graph_init_tex_0 },
157 { nve4_graph_init_pe_0 },
158 { nvf0_graph_init_l1c_0 },
159 { nvc0_graph_init_mpc_0 },
160 { nvf0_graph_init_sm_0 },
161 { nvd7_graph_init_pes_0 },
162 { nvd7_graph_init_wwdx_0 },
163 { nvd7_graph_init_cbm_0 },
164 { nve4_graph_init_be_0 },
165 { nvc0_graph_init_fe_1 },
166 {}
167};
168
169/*******************************************************************************
170 * PGRAPH engine/subdev functions
171 ******************************************************************************/
172
158static int 173static int
159nvf0_graph_fini(struct nouveau_object *object, bool suspend) 174nvf0_graph_fini(struct nouveau_object *object, bool suspend)
160{ 175{
@@ -192,25 +207,6 @@ nvf0_graph_fini(struct nouveau_object *object, bool suspend)
192 return nouveau_graph_fini(&priv->base, suspend); 207 return nouveau_graph_fini(&priv->base, suspend);
193} 208}
194 209
195static struct nvc0_graph_init *
196nvf0_graph_init_mmio[] = {
197 nve4_graph_init_regs,
198 nvf0_graph_init_unk40xx,
199 nvc0_graph_init_unk44xx,
200 nvc0_graph_init_unk78xx,
201 nvc0_graph_init_unk60xx,
202 nvd9_graph_init_unk64xx,
203 nvf0_graph_init_unk58xx,
204 nvc0_graph_init_unk80xx,
205 nvf0_graph_init_unk70xx,
206 nvf0_graph_init_unk5bxx,
207 nvf0_graph_init_gpc,
208 nvf0_graph_init_tpc,
209 nve4_graph_init_unk,
210 nve4_graph_init_unk88xx,
211 NULL
212};
213
214#include "fuc/hubnvf0.fuc.h" 210#include "fuc/hubnvf0.fuc.h"
215 211
216static struct nvc0_graph_ucode 212static struct nvc0_graph_ucode
@@ -242,7 +238,7 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
242 }, 238 },
243 .cclass = &nvf0_grctx_oclass, 239 .cclass = &nvf0_grctx_oclass,
244 .sclass = nvf0_graph_sclass, 240 .sclass = nvf0_graph_sclass,
245 .mmio = nvf0_graph_init_mmio, 241 .mmio = nvf0_graph_pack_mmio,
246 .fecs.ucode = &nvf0_graph_fecs_ucode, 242 .fecs.ucode = &nvf0_graph_fecs_ucode,
247 .gpccs.ucode = &nvf0_graph_gpccs_ucode, 243 .gpccs.ucode = &nvf0_graph_gpccs_ucode,
248}.base; 244}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
index 5f6ede7c4892..92384759d2f5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
@@ -112,7 +112,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)
112 snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x", 112 snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
113 xtensa->addr >> 12); 113 xtensa->addr >> 12);
114 114
115 ret = request_firmware(&fw, name, &device->pdev->dev); 115 ret = request_firmware(&fw, name, nv_device_base(device));
116 if (ret) { 116 if (ret) {
117 nv_warn(xtensa, "unable to load firmware %s\n", name); 117 nv_warn(xtensa, "unable to load firmware %s\n", name);
118 return ret; 118 return ret;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index e71a4325e670..9c0cd73462d9 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -258,6 +258,7 @@ struct nv04_display_scanoutpos {
258 * 9070: NVD0_DISP 258 * 9070: NVD0_DISP
259 * 9170: NVE0_DISP 259 * 9170: NVE0_DISP
260 * 9270: NVF0_DISP 260 * 9270: NVF0_DISP
261 * 9470: GM107_DISP
261 */ 262 */
262 263
263#define NV50_DISP_CLASS 0x00005070 264#define NV50_DISP_CLASS 0x00005070
@@ -268,6 +269,7 @@ struct nv04_display_scanoutpos {
268#define NVD0_DISP_CLASS 0x00009070 269#define NVD0_DISP_CLASS 0x00009070
269#define NVE0_DISP_CLASS 0x00009170 270#define NVE0_DISP_CLASS 0x00009170
270#define NVF0_DISP_CLASS 0x00009270 271#define NVF0_DISP_CLASS 0x00009270
272#define GM107_DISP_CLASS 0x00009470
271 273
272#define NV50_DISP_MTHD 0x00000000 274#define NV50_DISP_MTHD 0x00000000
273#define NV50_DISP_MTHD_HEAD 0x00000003 275#define NV50_DISP_MTHD_HEAD 0x00000003
@@ -342,6 +344,7 @@ struct nv50_display_class {
342 * 907a: NVD0_DISP_CURS 344 * 907a: NVD0_DISP_CURS
343 * 917a: NVE0_DISP_CURS 345 * 917a: NVE0_DISP_CURS
344 * 927a: NVF0_DISP_CURS 346 * 927a: NVF0_DISP_CURS
347 * 947a: GM107_DISP_CURS
345 */ 348 */
346 349
347#define NV50_DISP_CURS_CLASS 0x0000507a 350#define NV50_DISP_CURS_CLASS 0x0000507a
@@ -352,6 +355,7 @@ struct nv50_display_class {
352#define NVD0_DISP_CURS_CLASS 0x0000907a 355#define NVD0_DISP_CURS_CLASS 0x0000907a
353#define NVE0_DISP_CURS_CLASS 0x0000917a 356#define NVE0_DISP_CURS_CLASS 0x0000917a
354#define NVF0_DISP_CURS_CLASS 0x0000927a 357#define NVF0_DISP_CURS_CLASS 0x0000927a
358#define GM107_DISP_CURS_CLASS 0x0000947a
355 359
356struct nv50_display_curs_class { 360struct nv50_display_curs_class {
357 u32 head; 361 u32 head;
@@ -365,6 +369,7 @@ struct nv50_display_curs_class {
365 * 907b: NVD0_DISP_OIMM 369 * 907b: NVD0_DISP_OIMM
366 * 917b: NVE0_DISP_OIMM 370 * 917b: NVE0_DISP_OIMM
367 * 927b: NVE0_DISP_OIMM 371 * 927b: NVE0_DISP_OIMM
372 * 947b: GM107_DISP_OIMM
368 */ 373 */
369 374
370#define NV50_DISP_OIMM_CLASS 0x0000507b 375#define NV50_DISP_OIMM_CLASS 0x0000507b
@@ -375,6 +380,7 @@ struct nv50_display_curs_class {
375#define NVD0_DISP_OIMM_CLASS 0x0000907b 380#define NVD0_DISP_OIMM_CLASS 0x0000907b
376#define NVE0_DISP_OIMM_CLASS 0x0000917b 381#define NVE0_DISP_OIMM_CLASS 0x0000917b
377#define NVF0_DISP_OIMM_CLASS 0x0000927b 382#define NVF0_DISP_OIMM_CLASS 0x0000927b
383#define GM107_DISP_OIMM_CLASS 0x0000947b
378 384
379struct nv50_display_oimm_class { 385struct nv50_display_oimm_class {
380 u32 head; 386 u32 head;
@@ -388,6 +394,7 @@ struct nv50_display_oimm_class {
388 * 907c: NVD0_DISP_SYNC 394 * 907c: NVD0_DISP_SYNC
389 * 917c: NVE0_DISP_SYNC 395 * 917c: NVE0_DISP_SYNC
390 * 927c: NVF0_DISP_SYNC 396 * 927c: NVF0_DISP_SYNC
397 * 947c: GM107_DISP_SYNC
391 */ 398 */
392 399
393#define NV50_DISP_SYNC_CLASS 0x0000507c 400#define NV50_DISP_SYNC_CLASS 0x0000507c
@@ -398,6 +405,7 @@ struct nv50_display_oimm_class {
398#define NVD0_DISP_SYNC_CLASS 0x0000907c 405#define NVD0_DISP_SYNC_CLASS 0x0000907c
399#define NVE0_DISP_SYNC_CLASS 0x0000917c 406#define NVE0_DISP_SYNC_CLASS 0x0000917c
400#define NVF0_DISP_SYNC_CLASS 0x0000927c 407#define NVF0_DISP_SYNC_CLASS 0x0000927c
408#define GM107_DISP_SYNC_CLASS 0x0000947c
401 409
402struct nv50_display_sync_class { 410struct nv50_display_sync_class {
403 u32 pushbuf; 411 u32 pushbuf;
@@ -412,6 +420,7 @@ struct nv50_display_sync_class {
412 * 907d: NVD0_DISP_MAST 420 * 907d: NVD0_DISP_MAST
413 * 917d: NVE0_DISP_MAST 421 * 917d: NVE0_DISP_MAST
414 * 927d: NVF0_DISP_MAST 422 * 927d: NVF0_DISP_MAST
423 * 947d: GM107_DISP_MAST
415 */ 424 */
416 425
417#define NV50_DISP_MAST_CLASS 0x0000507d 426#define NV50_DISP_MAST_CLASS 0x0000507d
@@ -422,6 +431,7 @@ struct nv50_display_sync_class {
422#define NVD0_DISP_MAST_CLASS 0x0000907d 431#define NVD0_DISP_MAST_CLASS 0x0000907d
423#define NVE0_DISP_MAST_CLASS 0x0000917d 432#define NVE0_DISP_MAST_CLASS 0x0000917d
424#define NVF0_DISP_MAST_CLASS 0x0000927d 433#define NVF0_DISP_MAST_CLASS 0x0000927d
434#define GM107_DISP_MAST_CLASS 0x0000947d
425 435
426struct nv50_display_mast_class { 436struct nv50_display_mast_class {
427 u32 pushbuf; 437 u32 pushbuf;
@@ -435,6 +445,7 @@ struct nv50_display_mast_class {
435 * 907e: NVD0_DISP_OVLY 445 * 907e: NVD0_DISP_OVLY
436 * 917e: NVE0_DISP_OVLY 446 * 917e: NVE0_DISP_OVLY
437 * 927e: NVF0_DISP_OVLY 447 * 927e: NVF0_DISP_OVLY
448 * 947e: GM107_DISP_OVLY
438 */ 449 */
439 450
440#define NV50_DISP_OVLY_CLASS 0x0000507e 451#define NV50_DISP_OVLY_CLASS 0x0000507e
@@ -445,6 +456,7 @@ struct nv50_display_mast_class {
445#define NVD0_DISP_OVLY_CLASS 0x0000907e 456#define NVD0_DISP_OVLY_CLASS 0x0000907e
446#define NVE0_DISP_OVLY_CLASS 0x0000917e 457#define NVE0_DISP_OVLY_CLASS 0x0000917e
447#define NVF0_DISP_OVLY_CLASS 0x0000927e 458#define NVF0_DISP_OVLY_CLASS 0x0000927e
459#define GM107_DISP_OVLY_CLASS 0x0000947e
448 460
449struct nv50_display_ovly_class { 461struct nv50_display_ovly_class {
450 u32 pushbuf; 462 u32 pushbuf;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index 7b8ea221b00d..a8a9a9cf16cb 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -40,6 +40,7 @@ enum nv_subdev_type {
40 40
41 NVDEV_ENGINE_FIRST, 41 NVDEV_ENGINE_FIRST,
42 NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST, 42 NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
43 NVDEV_ENGINE_IFB,
43 NVDEV_ENGINE_FIFO, 44 NVDEV_ENGINE_FIFO,
44 NVDEV_ENGINE_SW, 45 NVDEV_ENGINE_SW,
45 NVDEV_ENGINE_GR, 46 NVDEV_ENGINE_GR,
@@ -65,6 +66,7 @@ struct nouveau_device {
65 struct list_head head; 66 struct list_head head;
66 67
67 struct pci_dev *pdev; 68 struct pci_dev *pdev;
69 struct platform_device *platformdev;
68 u64 handle; 70 u64 handle;
69 71
70 const char *cfgopt; 72 const char *cfgopt;
@@ -84,6 +86,7 @@ struct nouveau_device {
84 NV_C0 = 0xc0, 86 NV_C0 = 0xc0,
85 NV_D0 = 0xd0, 87 NV_D0 = 0xd0,
86 NV_E0 = 0xe0, 88 NV_E0 = 0xe0,
89 GM100 = 0x110,
87 } card_type; 90 } card_type;
88 u32 chipset; 91 u32 chipset;
89 u32 crystal; 92 u32 crystal;
@@ -140,4 +143,32 @@ nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub)
140 device->pdev->subsystem_device == sub; 143 device->pdev->subsystem_device == sub;
141} 144}
142 145
146static inline bool
147nv_device_is_pci(struct nouveau_device *device)
148{
149 return device->pdev != NULL;
150}
151
152static inline struct device *
153nv_device_base(struct nouveau_device *device)
154{
155 return nv_device_is_pci(device) ? &device->pdev->dev :
156 &device->platformdev->dev;
157}
158
159resource_size_t
160nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
161
162resource_size_t
163nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
164
165dma_addr_t
166nv_device_map_page(struct nouveau_device *device, struct page *page);
167
168void
169nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);
170
171int
172nv_device_get_irq(struct nouveau_device *device, bool stall);
173
143#endif 174#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/namedb.h b/drivers/gpu/drm/nouveau/core/include/core/namedb.h
index 8897e0886085..f5b5fd8e1fc9 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/namedb.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/namedb.h
@@ -33,7 +33,7 @@ nv_namedb(void *obj)
33 33
34int nouveau_namedb_create_(struct nouveau_object *, struct nouveau_object *, 34int nouveau_namedb_create_(struct nouveau_object *, struct nouveau_object *,
35 struct nouveau_oclass *, u32 pclass, 35 struct nouveau_oclass *, u32 pclass,
36 struct nouveau_oclass *, u32 engcls, 36 struct nouveau_oclass *, u64 engcls,
37 int size, void **); 37 int size, void **);
38 38
39int _nouveau_namedb_ctor(struct nouveau_object *, struct nouveau_object *, 39int _nouveau_namedb_ctor(struct nouveau_object *, struct nouveau_object *,
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/device.h b/drivers/gpu/drm/nouveau/core/include/engine/device.h
index b3dd2c4c2f1e..672d3c8f4145 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/device.h
@@ -3,11 +3,20 @@
3 3
4#include <core/device.h> 4#include <core/device.h>
5 5
6#define nouveau_device_create(p,n,s,c,d,u) \ 6struct platform_device;
7 nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u)
8 7
9int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, 8enum nv_bus_type {
10 const char *cfg, const char *dbg, int, void **); 9 NOUVEAU_BUS_PCI,
10 NOUVEAU_BUS_PLATFORM,
11};
12
13#define nouveau_device_create(p,t,n,s,c,d,u) \
14 nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d), \
15 sizeof(**u), (void **)u)
16
17int nouveau_device_create_(void *, enum nv_bus_type type, u64 name,
18 const char *sname, const char *cfg, const char *dbg,
19 int, void **);
11 20
12int nv04_identify(struct nouveau_device *); 21int nv04_identify(struct nouveau_device *);
13int nv10_identify(struct nouveau_device *); 22int nv10_identify(struct nouveau_device *);
@@ -17,6 +26,7 @@ int nv40_identify(struct nouveau_device *);
17int nv50_identify(struct nouveau_device *); 26int nv50_identify(struct nouveau_device *);
18int nvc0_identify(struct nouveau_device *); 27int nvc0_identify(struct nouveau_device *);
19int nve0_identify(struct nouveau_device *); 28int nve0_identify(struct nouveau_device *);
29int gm100_identify(struct nouveau_device *);
20 30
21struct nouveau_device *nouveau_device_find(u64 name); 31struct nouveau_device *nouveau_device_find(u64 name);
22 32
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
index 4b21fabfbddb..fd0c68804de3 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
@@ -36,14 +36,15 @@ void _nouveau_disp_dtor(struct nouveau_object *);
36#define _nouveau_disp_init _nouveau_engine_init 36#define _nouveau_disp_init _nouveau_engine_init
37#define _nouveau_disp_fini _nouveau_engine_fini 37#define _nouveau_disp_fini _nouveau_engine_fini
38 38
39extern struct nouveau_oclass nv04_disp_oclass; 39extern struct nouveau_oclass *nv04_disp_oclass;
40extern struct nouveau_oclass nv50_disp_oclass; 40extern struct nouveau_oclass *nv50_disp_oclass;
41extern struct nouveau_oclass nv84_disp_oclass; 41extern struct nouveau_oclass *nv84_disp_oclass;
42extern struct nouveau_oclass nva0_disp_oclass; 42extern struct nouveau_oclass *nva0_disp_oclass;
43extern struct nouveau_oclass nv94_disp_oclass; 43extern struct nouveau_oclass *nv94_disp_oclass;
44extern struct nouveau_oclass nva3_disp_oclass; 44extern struct nouveau_oclass *nva3_disp_oclass;
45extern struct nouveau_oclass nvd0_disp_oclass; 45extern struct nouveau_oclass *nvd0_disp_oclass;
46extern struct nouveau_oclass nve0_disp_oclass; 46extern struct nouveau_oclass *nve0_disp_oclass;
47extern struct nouveau_oclass nvf0_disp_oclass; 47extern struct nouveau_oclass *nvf0_disp_oclass;
48extern struct nouveau_oclass *gm107_disp_oclass;
48 49
49#endif 50#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
index 97705618de97..871edfdf3d5b 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
@@ -63,13 +63,14 @@ extern struct nouveau_oclass nv40_graph_oclass;
63extern struct nouveau_oclass nv50_graph_oclass; 63extern struct nouveau_oclass nv50_graph_oclass;
64extern struct nouveau_oclass *nvc0_graph_oclass; 64extern struct nouveau_oclass *nvc0_graph_oclass;
65extern struct nouveau_oclass *nvc1_graph_oclass; 65extern struct nouveau_oclass *nvc1_graph_oclass;
66extern struct nouveau_oclass *nvc3_graph_oclass; 66extern struct nouveau_oclass *nvc4_graph_oclass;
67extern struct nouveau_oclass *nvc8_graph_oclass; 67extern struct nouveau_oclass *nvc8_graph_oclass;
68extern struct nouveau_oclass *nvd7_graph_oclass; 68extern struct nouveau_oclass *nvd7_graph_oclass;
69extern struct nouveau_oclass *nvd9_graph_oclass; 69extern struct nouveau_oclass *nvd9_graph_oclass;
70extern struct nouveau_oclass *nve4_graph_oclass; 70extern struct nouveau_oclass *nve4_graph_oclass;
71extern struct nouveau_oclass *nvf0_graph_oclass; 71extern struct nouveau_oclass *nvf0_graph_oclass;
72extern struct nouveau_oclass *nv108_graph_oclass; 72extern struct nouveau_oclass *nv108_graph_oclass;
73extern struct nouveau_oclass *gm107_graph_oclass;
73 74
74extern const struct nouveau_bitfield nv04_graph_nsource[]; 75extern const struct nouveau_bitfield nv04_graph_nsource[];
75extern struct nouveau_ofuncs nv04_graph_ofuncs; 76extern struct nouveau_ofuncs nv04_graph_ofuncs;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h
new file mode 100644
index 000000000000..bba01ab1e049
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h
@@ -0,0 +1,23 @@
1#ifndef __NVBIOS_P0260_H__
2#define __NVBIOS_P0260_H__
3
4u32 nvbios_P0260Te(struct nouveau_bios *,
5 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz);
6
7struct nvbios_P0260E {
8 u32 data;
9};
10
11u32 nvbios_P0260Ee(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
12u32 nvbios_P0260Ep(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
13 struct nvbios_P0260E *);
14
15struct nvbios_P0260X {
16 u32 data;
17};
18
19u32 nvbios_P0260Xe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
20u32 nvbios_P0260Xp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
21 struct nvbios_P0260X *);
22
23#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
index c1270548fd0d..a32feb3f3fb6 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
@@ -16,6 +16,7 @@ enum dcb_connector_type {
16 DCB_CONNECTOR_eDP = 0x47, 16 DCB_CONNECTOR_eDP = 0x47,
17 DCB_CONNECTOR_HDMI_0 = 0x60, 17 DCB_CONNECTOR_HDMI_0 = 0x60,
18 DCB_CONNECTOR_HDMI_1 = 0x61, 18 DCB_CONNECTOR_HDMI_1 = 0x61,
19 DCB_CONNECTOR_HDMI_C = 0x63,
19 DCB_CONNECTOR_DMS59_DP0 = 0x64, 20 DCB_CONNECTOR_DMS59_DP0 = 0x64,
20 DCB_CONNECTOR_DMS59_DP1 = 0x65, 21 DCB_CONNECTOR_DMS59_DP1 = 0x65,
21 DCB_CONNECTOR_NONE = 0xff 22 DCB_CONNECTOR_NONE = 0xff
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
index c5e6d1e6ac1d..c086ac6d677d 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
@@ -61,6 +61,6 @@ struct nvbios_ramcfg {
61}; 61};
62 62
63u8 nvbios_ramcfg_count(struct nouveau_bios *); 63u8 nvbios_ramcfg_count(struct nouveau_bios *);
64u8 nvbios_ramcfg_index(struct nouveau_bios *); 64u8 nvbios_ramcfg_index(struct nouveau_subdev *);
65 65
66#endif 66#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
index 083541dbe9c8..8dc5051df55d 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
@@ -31,6 +31,12 @@ struct nouveau_therm_trip_point {
31 int hysteresis; 31 int hysteresis;
32}; 32};
33 33
34enum nvbios_therm_fan_mode {
35 NVBIOS_THERM_FAN_TRIP = 0,
36 NVBIOS_THERM_FAN_LINEAR = 1,
37 NVBIOS_THERM_FAN_OTHER = 2,
38};
39
34struct nvbios_therm_fan { 40struct nvbios_therm_fan {
35 u16 pwm_freq; 41 u16 pwm_freq;
36 42
@@ -40,6 +46,7 @@ struct nvbios_therm_fan {
40 u16 bump_period; 46 u16 bump_period;
41 u16 slow_down_period; 47 u16 slow_down_period;
42 48
49 enum nvbios_therm_fan_mode fan_mode;
43 struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX]; 50 struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX];
44 u8 nr_fan_trip; 51 u8 nr_fan_trip;
45 u8 linear_min_temp; 52 u8 linear_min_temp;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
index ed1ac68c38b3..e292271a84e4 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
@@ -9,6 +9,7 @@ struct nouveau_devinit {
9 bool post; 9 bool post;
10 void (*meminit)(struct nouveau_devinit *); 10 void (*meminit)(struct nouveau_devinit *);
11 int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq); 11 int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
12 u32 (*mmio)(struct nouveau_devinit *, u32 addr);
12}; 13};
13 14
14static inline struct nouveau_devinit * 15static inline struct nouveau_devinit *
@@ -28,5 +29,6 @@ extern struct nouveau_oclass *nv98_devinit_oclass;
28extern struct nouveau_oclass *nva3_devinit_oclass; 29extern struct nouveau_oclass *nva3_devinit_oclass;
29extern struct nouveau_oclass *nvaf_devinit_oclass; 30extern struct nouveau_oclass *nvaf_devinit_oclass;
30extern struct nouveau_oclass *nvc0_devinit_oclass; 31extern struct nouveau_oclass *nvc0_devinit_oclass;
32extern struct nouveau_oclass *gm107_devinit_oclass;
31 33
32#endif 34#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
index d7ecafbae1ca..58c7ccdebb01 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
@@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass;
105extern struct nouveau_oclass *nvaf_fb_oclass; 105extern struct nouveau_oclass *nvaf_fb_oclass;
106extern struct nouveau_oclass *nvc0_fb_oclass; 106extern struct nouveau_oclass *nvc0_fb_oclass;
107extern struct nouveau_oclass *nve0_fb_oclass; 107extern struct nouveau_oclass *nve0_fb_oclass;
108extern struct nouveau_oclass *gm107_fb_oclass;
108 109
109#include <subdev/bios/ramcfg.h> 110#include <subdev/bios/ramcfg.h>
110 111
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
index a1985ed3d58d..c9c1950b7743 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
@@ -35,6 +35,7 @@ nouveau_ltcg(void *obj)
35#define _nouveau_ltcg_init _nouveau_subdev_init 35#define _nouveau_ltcg_init _nouveau_subdev_init
36#define _nouveau_ltcg_fini _nouveau_subdev_fini 36#define _nouveau_ltcg_fini _nouveau_subdev_fini
37 37
38extern struct nouveau_oclass nvc0_ltcg_oclass; 38extern struct nouveau_oclass *gf100_ltcg_oclass;
39extern struct nouveau_oclass *gm107_ltcg_oclass;
39 40
40#endif 41#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
index 3c6738edd127..72b176831be6 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
@@ -12,6 +12,7 @@ struct nouveau_mc_intr {
12struct nouveau_mc { 12struct nouveau_mc {
13 struct nouveau_subdev base; 13 struct nouveau_subdev base;
14 bool use_msi; 14 bool use_msi;
15 unsigned int irq;
15}; 16};
16 17
17static inline struct nouveau_mc * 18static inline struct nouveau_mc *
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
index 69891d4a3fe7..d4a68179e586 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
@@ -31,7 +31,7 @@ struct nouveau_therm {
31 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool); 31 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
32 int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *); 32 int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *);
33 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 33 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
34 int (*pwm_clock)(struct nouveau_therm *); 34 int (*pwm_clock)(struct nouveau_therm *, int line);
35 35
36 int (*fan_get)(struct nouveau_therm *); 36 int (*fan_get)(struct nouveau_therm *);
37 int (*fan_set)(struct nouveau_therm *, int); 37 int (*fan_set)(struct nouveau_therm *, int);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
index 9ab70dfe5b02..db9be803a874 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
@@ -59,5 +59,6 @@ int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *,
59 struct nouveau_oclass *, int size, void **); 59 struct nouveau_oclass *, int size, void **);
60 60
61extern struct nouveau_oclass nv04_timer_oclass; 61extern struct nouveau_oclass nv04_timer_oclass;
62extern struct nouveau_oclass gk20a_timer_oclass;
62 63
63#endif 64#endif
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h
index 191e739f30d1..d0ced94ca54c 100644
--- a/drivers/gpu/drm/nouveau/core/os.h
+++ b/drivers/gpu/drm/nouveau/core/os.h
@@ -5,6 +5,7 @@
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/mutex.h> 6#include <linux/mutex.h>
7#include <linux/pci.h> 7#include <linux/pci.h>
8#include <linux/platform_device.h>
8#include <linux/printk.h> 9#include <linux/printk.h>
9#include <linux/bitops.h> 10#include <linux/bitops.h>
10#include <linux/firmware.h> 11#include <linux/firmware.h>
@@ -23,17 +24,6 @@
23 24
24#include <asm/unaligned.h> 25#include <asm/unaligned.h>
25 26
26static inline int
27ffsll(u64 mask)
28{
29 int i;
30 for (i = 0; i < 64; i++) {
31 if (mask & (1ULL << i))
32 return i + 1;
33 }
34 return 0;
35}
36
37#ifndef ioread32_native 27#ifndef ioread32_native
38#ifdef __BIG_ENDIAN 28#ifdef __BIG_ENDIAN
39#define ioread16_native ioread16be 29#define ioread16_native ioread16be
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
index 7098ddd54678..bdf594116f3f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
@@ -118,8 +118,8 @@ nouveau_bar_create_(struct nouveau_object *parent,
118 if (ret) 118 if (ret)
119 return ret; 119 return ret;
120 120
121 bar->iomem = ioremap(pci_resource_start(device->pdev, 3), 121 bar->iomem = ioremap(nv_device_resource_start(device, 3),
122 pci_resource_len(device->pdev, 3)); 122 nv_device_resource_len(device, 3));
123 return 0; 123 return 0;
124} 124}
125 125
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
index 090d594a21b3..f748ba49dfc8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
@@ -139,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
139 139
140 /* BAR3 */ 140 /* BAR3 */
141 start = 0x0100000000ULL; 141 start = 0x0100000000ULL;
142 limit = start + pci_resource_len(device->pdev, 3); 142 limit = start + nv_device_resource_len(device, 3);
143 143
144 ret = nouveau_vm_new(device, start, limit, start, &vm); 144 ret = nouveau_vm_new(device, start, limit, start, &vm);
145 if (ret) 145 if (ret)
@@ -173,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
173 173
174 /* BAR1 */ 174 /* BAR1 */
175 start = 0x0000000000ULL; 175 start = 0x0000000000ULL;
176 limit = start + pci_resource_len(device->pdev, 1); 176 limit = start + nv_device_resource_len(device, 1);
177 177
178 ret = nouveau_vm_new(device, start, limit--, start, &vm); 178 ret = nouveau_vm_new(device, start, limit--, start, &vm);
179 if (ret) 179 if (ret)
@@ -231,7 +231,7 @@ static int
231nv50_bar_init(struct nouveau_object *object) 231nv50_bar_init(struct nouveau_object *object)
232{ 232{
233 struct nv50_bar_priv *priv = (void *)object; 233 struct nv50_bar_priv *priv = (void *)object;
234 int ret; 234 int ret, i;
235 235
236 ret = nouveau_bar_init(&priv->base); 236 ret = nouveau_bar_init(&priv->base);
237 if (ret) 237 if (ret)
@@ -249,6 +249,8 @@ nv50_bar_init(struct nouveau_object *object)
249 nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12); 249 nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12);
250 nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4); 250 nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4);
251 nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4); 251 nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4);
252 for (i = 0; i < 8; i++)
253 nv_wr32(priv, 0x001900 + (i * 4), 0x00000000);
252 return 0; 254 return 0;
253} 255}
254 256
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index bac5e754de35..3f30db62e656 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -84,7 +84,6 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
84 struct nouveau_object **pobject) 84 struct nouveau_object **pobject)
85{ 85{
86 struct nouveau_device *device = nv_device(parent); 86 struct nouveau_device *device = nv_device(parent);
87 struct pci_dev *pdev = device->pdev;
88 struct nvc0_bar_priv *priv; 87 struct nvc0_bar_priv *priv;
89 struct nouveau_gpuobj *mem; 88 struct nouveau_gpuobj *mem;
90 struct nouveau_vm *vm; 89 struct nouveau_vm *vm;
@@ -107,14 +106,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
107 if (ret) 106 if (ret)
108 return ret; 107 return ret;
109 108
110 ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm); 109 ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
111 if (ret) 110 if (ret)
112 return ret; 111 return ret;
113 112
114 atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); 113 atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
115 114
116 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 115 ret = nouveau_gpuobj_new(nv_object(priv), NULL,
117 (pci_resource_len(pdev, 3) >> 12) * 8, 116 (nv_device_resource_len(device, 3) >> 12) * 8,
118 0x1000, NVOBJ_FLAG_ZERO_ALLOC, 117 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
119 &vm->pgt[0].obj[0]); 118 &vm->pgt[0].obj[0]);
120 vm->pgt[0].refcount[0] = 1; 119 vm->pgt[0].refcount[0] = 1;
@@ -128,8 +127,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
128 127
129 nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); 128 nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
130 nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); 129 nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
131 nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1)); 130 nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
132 nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); 131 nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));
133 132
134 /* BAR1 */ 133 /* BAR1 */
135 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, 134 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
@@ -143,7 +142,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
143 if (ret) 142 if (ret)
144 return ret; 143 return ret;
145 144
146 ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm); 145 ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
147 if (ret) 146 if (ret)
148 return ret; 147 return ret;
149 148
@@ -156,8 +155,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
156 155
157 nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); 156 nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
158 nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); 157 nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
159 nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1)); 158 nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
160 nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1)); 159 nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));
161 160
162 priv->base.alloc = nouveau_bar_alloc; 161 priv->base.alloc = nouveau_bar_alloc;
163 priv->base.kmap = nvc0_bar_kmap; 162 priv->base.kmap = nvc0_bar_kmap;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c
new file mode 100644
index 000000000000..199f4e5f7488
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/ramcfg.h>
28#include <subdev/bios/P0260.h>
29
30u32
31nvbios_P0260Te(struct nouveau_bios *bios,
32 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
33{
34 struct bit_entry bit_P;
35 u32 data = 0x00000000;
36
37 if (!bit_entry(bios, 'P', &bit_P)) {
38 if (bit_P.version == 2 && bit_P.length > 0x63)
39 data = nv_ro32(bios, bit_P.offset + 0x60);
40 if (data) {
41 *ver = nv_ro08(bios, data + 0);
42 switch (*ver) {
43 case 0x10:
44 *hdr = nv_ro08(bios, data + 1);
45 *cnt = nv_ro08(bios, data + 2);
46 *len = 4;
47 *xnr = nv_ro08(bios, data + 3);
48 *xsz = 4;
49 return data;
50 default:
51 break;
52 }
53 }
54 }
55
56 return 0x00000000;
57}
58
59u32
60nvbios_P0260Ee(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
61{
62 u8 hdr, cnt, xnr, xsz;
63 u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, len, &xnr, &xsz);
64 if (data && idx < cnt)
65 return data + hdr + (idx * *len);
66 return 0x00000000;
67}
68
69u32
70nvbios_P0260Ep(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,
71 struct nvbios_P0260E *info)
72{
73 u32 data = nvbios_P0260Ee(bios, idx, ver, len);
74 memset(info, 0x00, sizeof(*info));
75 switch (!!data * *ver) {
76 case 0x10:
77 info->data = nv_ro32(bios, data);
78 return data;
79 default:
80 break;
81 }
82 return 0x00000000;
83}
84
85u32
86nvbios_P0260Xe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *xsz)
87{
88 u8 hdr, cnt, len, xnr;
89 u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, &len, &xnr, xsz);
90 if (data && idx < xnr)
91 return data + hdr + (cnt * len) + (idx * *xsz);
92 return 0x00000000;
93}
94
95u32
96nvbios_P0260Xp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr,
97 struct nvbios_P0260X *info)
98{
99 u32 data = nvbios_P0260Xe(bios, idx, ver, hdr);
100 memset(info, 0x00, sizeof(*info));
101 switch (!!data * *ver) {
102 case 0x10:
103 info->data = nv_ro32(bios, data);
104 return data;
105 default:
106 break;
107 }
108 return 0x00000000;
109}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index ef0c9c4a8cc3..e9df94f96d78 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -90,10 +90,26 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
90 int i; 90 int i;
91 91
92 if (device->card_type >= NV_50) { 92 if (device->card_type >= NV_50) {
93 if ( device->card_type < NV_C0 || 93 if (device->card_type >= NV_C0 && device->card_type < GM100) {
94 !(nv_rd32(bios, 0x022500) & 0x00000001)) 94 if (nv_rd32(bios, 0x022500) & 0x00000001)
95 addr = (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8; 95 return;
96 } else
97 if (device->card_type >= GM100) {
98 if (nv_rd32(bios, 0x021c04) & 0x00000001)
99 return;
100 }
101
102 addr = nv_rd32(bios, 0x619f04);
103 if (!(addr & 0x00000008)) {
104 nv_debug(bios, "... not enabled\n");
105 return;
106 }
107 if ( (addr & 0x00000003) != 1) {
108 nv_debug(bios, "... not in vram\n");
109 return;
110 }
96 111
112 addr = (u64)(addr >> 8) << 8;
97 if (!addr) { 113 if (!addr) {
98 addr = (u64)nv_rd32(bios, 0x001700) << 16; 114 addr = (u64)nv_rd32(bios, 0x001700) << 16;
99 addr += 0xf0000; 115 addr += 0xf0000;
@@ -141,6 +157,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
141 pcireg = 0x001850; 157 pcireg = 0x001850;
142 access = nv_mask(bios, pcireg, 0x00000001, 0x00000000); 158 access = nv_mask(bios, pcireg, 0x00000001, 0x00000000);
143 159
160 /* WARNING: PROM accesses should always be 32-bits aligned. Other
161 * accesses work on most chipset but do not on Kepler chipsets
162 */
163
144 /* bail if no rom signature, with a workaround for a PROM reading 164 /* bail if no rom signature, with a workaround for a PROM reading
145 * issue on some chipsets. the first read after a period of 165 * issue on some chipsets. the first read after a period of
146 * inactivity returns the wrong result, so retry the first header 166 * inactivity returns the wrong result, so retry the first header
@@ -148,31 +168,32 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
148 */ 168 */
149 i = 16; 169 i = 16;
150 do { 170 do {
151 if (nv_rd08(bios, 0x300000) == 0x55) 171 if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55)
152 break; 172 break;
153 } while (i--); 173 } while (i--);
154 174
155 if (!i || nv_rd08(bios, 0x300001) != 0xaa) 175 if (!i)
156 goto out;
157
158 /* additional check (see note below) - read PCI record header */
159 pcir = nv_rd08(bios, 0x300018) |
160 nv_rd08(bios, 0x300019) << 8;
161 if (nv_rd08(bios, 0x300000 + pcir) != 'P' ||
162 nv_rd08(bios, 0x300001 + pcir) != 'C' ||
163 nv_rd08(bios, 0x300002 + pcir) != 'I' ||
164 nv_rd08(bios, 0x300003 + pcir) != 'R')
165 goto out; 176 goto out;
166 177
167 /* read entire bios image to system memory */ 178 /* read entire bios image to system memory */
168 bios->size = nv_rd08(bios, 0x300002) * 512; 179 bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512;
169 if (!bios->size) 180 if (!bios->size)
170 goto out; 181 goto out;
171 182
172 bios->data = kmalloc(bios->size, GFP_KERNEL); 183 bios->data = kmalloc(bios->size, GFP_KERNEL);
173 if (bios->data) { 184 if (bios->data) {
174 for (i = 0; i < bios->size; i++) 185 for (i = 0; i < bios->size; i+=4)
175 nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i)); 186 nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i));
187 }
188
189 /* check the PCI record header */
190 pcir = nv_ro16(bios, 0x0018);
191 if (bios->data[pcir + 0] != 'P' ||
192 bios->data[pcir + 1] != 'C' ||
193 bios->data[pcir + 2] != 'I' ||
194 bios->data[pcir + 3] != 'R') {
195 bios->size = 0;
196 kfree(bios->data);
176 } 197 }
177 198
178out: 199out:
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
index 2d9b9d7a7992..88606bfaf847 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
@@ -142,9 +142,36 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
142 if (*ver >= 0x40) { 142 if (*ver >= 0x40) {
143 u32 conf = nv_ro32(bios, dcb + 0x04); 143 u32 conf = nv_ro32(bios, dcb + 0x04);
144 switch (outp->type) { 144 switch (outp->type) {
145 case DCB_OUTPUT_DP:
146 switch (conf & 0x00e00000) {
147 case 0x00000000:
148 outp->dpconf.link_bw = 0x06;
149 break;
150 case 0x00200000:
151 outp->dpconf.link_bw = 0x0a;
152 break;
153 case 0x00400000:
154 default:
155 outp->dpconf.link_bw = 0x14;
156 break;
157 }
158
159 switch (conf & 0x0f000000) {
160 case 0x0f000000:
161 outp->dpconf.link_nr = 4;
162 break;
163 case 0x03000000:
164 outp->dpconf.link_nr = 2;
165 break;
166 case 0x01000000:
167 default:
168 outp->dpconf.link_nr = 1;
169 break;
170 }
171
172 /* fall-through... */
145 case DCB_OUTPUT_TMDS: 173 case DCB_OUTPUT_TMDS:
146 case DCB_OUTPUT_LVDS: 174 case DCB_OUTPUT_LVDS:
147 case DCB_OUTPUT_DP:
148 outp->link = (conf & 0x00000030) >> 4; 175 outp->link = (conf & 0x00000030) >> 4;
149 outp->sorconf.link = outp->link; /*XXX*/ 176 outp->sorconf.link = outp->link; /*XXX*/
150 outp->extdev = 0x00; 177 outp->extdev = 0x00;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index de201baeb053..acaeaf79e3f0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -118,6 +118,8 @@ init_conn(struct nvbios_init *init)
118static inline u32 118static inline u32
119init_nvreg(struct nvbios_init *init, u32 reg) 119init_nvreg(struct nvbios_init *init, u32 reg)
120{ 120{
121 struct nouveau_devinit *devinit = nouveau_devinit(init->bios);
122
121 /* C51 (at least) sometimes has the lower bits set which the VBIOS 123 /* C51 (at least) sometimes has the lower bits set which the VBIOS
122 * interprets to mean that access needs to go through certain IO 124 * interprets to mean that access needs to go through certain IO
123 * ports instead. The NVIDIA binary driver has been seen to access 125 * ports instead. The NVIDIA binary driver has been seen to access
@@ -147,6 +149,9 @@ init_nvreg(struct nvbios_init *init, u32 reg)
147 149
148 if (reg & ~0x00fffffc) 150 if (reg & ~0x00fffffc)
149 warn("unknown bits in register 0x%08x\n", reg); 151 warn("unknown bits in register 0x%08x\n", reg);
152
153 if (devinit->mmio)
154 reg = devinit->mmio(devinit, reg);
150 return reg; 155 return reg;
151} 156}
152 157
@@ -154,7 +159,7 @@ static u32
154init_rd32(struct nvbios_init *init, u32 reg) 159init_rd32(struct nvbios_init *init, u32 reg)
155{ 160{
156 reg = init_nvreg(init, reg); 161 reg = init_nvreg(init, reg);
157 if (init_exec(init)) 162 if (reg != ~0 && init_exec(init))
158 return nv_rd32(init->subdev, reg); 163 return nv_rd32(init->subdev, reg);
159 return 0x00000000; 164 return 0x00000000;
160} 165}
@@ -163,7 +168,7 @@ static void
163init_wr32(struct nvbios_init *init, u32 reg, u32 val) 168init_wr32(struct nvbios_init *init, u32 reg, u32 val)
164{ 169{
165 reg = init_nvreg(init, reg); 170 reg = init_nvreg(init, reg);
166 if (init_exec(init)) 171 if (reg != ~0 && init_exec(init))
167 nv_wr32(init->subdev, reg, val); 172 nv_wr32(init->subdev, reg, val);
168} 173}
169 174
@@ -171,7 +176,7 @@ static u32
171init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val) 176init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val)
172{ 177{
173 reg = init_nvreg(init, reg); 178 reg = init_nvreg(init, reg);
174 if (init_exec(init)) { 179 if (reg != ~0 && init_exec(init)) {
175 u32 tmp = nv_rd32(init->subdev, reg); 180 u32 tmp = nv_rd32(init->subdev, reg);
176 nv_wr32(init->subdev, reg, (tmp & ~mask) | val); 181 nv_wr32(init->subdev, reg, (tmp & ~mask) | val);
177 return tmp; 182 return tmp;
@@ -410,7 +415,7 @@ init_ram_restrict(struct nvbios_init *init)
410 * in case *not* re-reading the strap causes similar breakage. 415 * in case *not* re-reading the strap causes similar breakage.
411 */ 416 */
412 if (!init->ramcfg || init->bios->version.major < 0x70) 417 if (!init->ramcfg || init->bios->version.major < 0x70)
413 init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios); 418 init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->subdev);
414 return (init->ramcfg & 0x7fffffff); 419 return (init->ramcfg & 0x7fffffff);
415} 420}
416 421
@@ -845,9 +850,8 @@ init_idx_addr_latched(struct nvbios_init *init)
845 u32 data = nv_ro32(bios, init->offset + 13); 850 u32 data = nv_ro32(bios, init->offset + 13);
846 u8 count = nv_ro08(bios, init->offset + 17); 851 u8 count = nv_ro08(bios, init->offset + 17);
847 852
848 trace("INDEX_ADDRESS_LATCHED\t" 853 trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg);
849 "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n", 854 trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data);
850 creg, dreg, mask, data);
851 init->offset += 18; 855 init->offset += 18;
852 856
853 while (count--) { 857 while (count--) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
index 991aedda999b..6c401f70ab99 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
@@ -27,9 +27,9 @@
27#include <subdev/bios/ramcfg.h> 27#include <subdev/bios/ramcfg.h>
28 28
29static u8 29static u8
30nvbios_ramcfg_strap(struct nouveau_bios *bios) 30nvbios_ramcfg_strap(struct nouveau_subdev *subdev)
31{ 31{
32 return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; 32 return (nv_rd32(subdev, 0x101000) & 0x0000003c) >> 2;
33} 33}
34 34
35u8 35u8
@@ -48,9 +48,10 @@ nvbios_ramcfg_count(struct nouveau_bios *bios)
48} 48}
49 49
50u8 50u8
51nvbios_ramcfg_index(struct nouveau_bios *bios) 51nvbios_ramcfg_index(struct nouveau_subdev *subdev)
52{ 52{
53 u8 strap = nvbios_ramcfg_strap(bios); 53 struct nouveau_bios *bios = nouveau_bios(subdev);
54 u8 strap = nvbios_ramcfg_strap(subdev);
54 u32 xlat = 0x00000000; 55 u32 xlat = 0x00000000;
55 struct bit_entry bit_M; 56 struct bit_entry bit_M;
56 57
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
index 22ac6dbd6c8f..d15854094078 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
@@ -164,6 +164,7 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
164 164
165 i = 0; 165 i = 0;
166 fan->nr_fan_trip = 0; 166 fan->nr_fan_trip = 0;
167 fan->fan_mode = NVBIOS_THERM_FAN_OTHER;
167 while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { 168 while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) {
168 s16 value = nv_ro16(bios, entry + 1); 169 s16 value = nv_ro16(bios, entry + 1);
169 170
@@ -174,6 +175,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
174 break; 175 break;
175 case 0x24: 176 case 0x24:
176 fan->nr_fan_trip++; 177 fan->nr_fan_trip++;
178 if (fan->fan_mode > NVBIOS_THERM_FAN_TRIP)
179 fan->fan_mode = NVBIOS_THERM_FAN_TRIP;
177 cur_trip = &fan->trip[fan->nr_fan_trip - 1]; 180 cur_trip = &fan->trip[fan->nr_fan_trip - 1];
178 cur_trip->hysteresis = value & 0xf; 181 cur_trip->hysteresis = value & 0xf;
179 cur_trip->temp = (value & 0xff0) >> 4; 182 cur_trip->temp = (value & 0xff0) >> 4;
@@ -194,11 +197,19 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
194 fan->slow_down_period = value; 197 fan->slow_down_period = value;
195 break; 198 break;
196 case 0x46: 199 case 0x46:
200 if (fan->fan_mode > NVBIOS_THERM_FAN_LINEAR)
201 fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
197 fan->linear_min_temp = nv_ro08(bios, entry + 1); 202 fan->linear_min_temp = nv_ro08(bios, entry + 1);
198 fan->linear_max_temp = nv_ro08(bios, entry + 2); 203 fan->linear_max_temp = nv_ro08(bios, entry + 2);
199 break; 204 break;
200 } 205 }
201 } 206 }
202 207
208 /* starting from fermi, fan management is always linear */
209 if (nv_device(bios)->card_type >= NV_C0 &&
210 fan->fan_mode == NVBIOS_THERM_FAN_OTHER) {
211 fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
212 }
213
203 return 0; 214 return 0;
204} 215}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
index 8fa34e8152c2..239acfe876c3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
@@ -96,5 +96,6 @@ nouveau_devinit_create_(struct nouveau_object *parent,
96 devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false); 96 devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
97 devinit->meminit = impl->meminit; 97 devinit->meminit = impl->meminit;
98 devinit->pll_set = impl->pll_set; 98 devinit->pll_set = impl->pll_set;
99 devinit->mmio = impl->mmio;
99 return 0; 100 return 0;
100} 101}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
index 6b56a0f4cb40..4fe49cf4c99a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
@@ -24,6 +24,8 @@
24 * 24 *
25 */ 25 */
26 26
27#include <core/device.h>
28
27#define NV04_PFB_BOOT_0 0x00100000 29#define NV04_PFB_BOOT_0 0x00100000
28# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 30# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
29# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 31# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
@@ -60,10 +62,10 @@
60# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) 62# define NV10_PFB_REFCTRL_VALID_1 (1 << 31)
61 63
62static inline struct io_mapping * 64static inline struct io_mapping *
63fbmem_init(struct pci_dev *pdev) 65fbmem_init(struct nouveau_device *dev)
64{ 66{
65 return io_mapping_create_wc(pci_resource_start(pdev, 1), 67 return io_mapping_create_wc(nv_device_resource_start(dev, 1),
66 pci_resource_len(pdev, 1)); 68 nv_device_resource_len(dev, 1));
67} 69}
68 70
69static inline void 71static inline void
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c
new file mode 100644
index 000000000000..c69bc7f54e37
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c
@@ -0,0 +1,56 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv50.h"
26
27static u64
28gm107_devinit_disable(struct nouveau_devinit *devinit)
29{
30 struct nv50_devinit_priv *priv = (void *)devinit;
31 u32 r021c00 = nv_rd32(priv, 0x021c00);
32 u32 r021c04 = nv_rd32(priv, 0x021c04);
33 u64 disable = 0ULL;
34
35 if (r021c00 & 0x00000001)
36 disable |= (1ULL << NVDEV_ENGINE_COPY0);
37 if (r021c00 & 0x00000004)
38 disable |= (1ULL << NVDEV_ENGINE_COPY2);
39 if (r021c04 & 0x00000001)
40 disable |= (1ULL << NVDEV_ENGINE_DISP);
41
42 return disable;
43}
44
45struct nouveau_oclass *
46gm107_devinit_oclass = &(struct nouveau_devinit_impl) {
47 .base.handle = NV_SUBDEV(DEVINIT, 0x07),
48 .base.ofuncs = &(struct nouveau_ofuncs) {
49 .ctor = nv50_devinit_ctor,
50 .dtor = _nouveau_devinit_dtor,
51 .init = nv50_devinit_init,
52 .fini = _nouveau_devinit_fini,
53 },
54 .pll_set = nvc0_devinit_pll_set,
55 .disable = gm107_devinit_disable,
56}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
index 7037eae46e44..052ad690b468 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
@@ -38,7 +38,7 @@ nv04_devinit_meminit(struct nouveau_devinit *devinit)
38 int i; 38 int i;
39 39
40 /* Map the framebuffer aperture */ 40 /* Map the framebuffer aperture */
41 fb = fbmem_init(nv_device(priv)->pdev); 41 fb = fbmem_init(nv_device(priv));
42 if (!fb) { 42 if (!fb) {
43 nv_error(priv, "failed to map fb\n"); 43 nv_error(priv, "failed to map fb\n");
44 return; 44 return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
index 98b7e6780dc7..4a19c10e5178 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
@@ -53,7 +53,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
53 int i, v; 53 int i, v;
54 54
55 /* Map the framebuffer aperture */ 55 /* Map the framebuffer aperture */
56 fb = fbmem_init(nv_device(priv)->pdev); 56 fb = fbmem_init(nv_device(priv));
57 if (!fb) { 57 if (!fb) {
58 nv_error(priv, "failed to map fb\n"); 58 nv_error(priv, "failed to map fb\n");
59 return; 59 return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
index 32b3d2131a7f..3b8d657da279 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
@@ -46,7 +46,7 @@ nv10_devinit_meminit(struct nouveau_devinit *devinit)
46 mem_width_count = 2; 46 mem_width_count = 2;
47 47
48 /* Map the framebuffer aperture */ 48 /* Map the framebuffer aperture */
49 fb = fbmem_init(nv_device(priv)->pdev); 49 fb = fbmem_init(nv_device(priv));
50 if (!fb) { 50 if (!fb) {
51 nv_error(priv, "failed to map fb\n"); 51 nv_error(priv, "failed to map fb\n");
52 return; 52 return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
index 4689ba303b0b..04bc9732644c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
@@ -37,7 +37,7 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
37 struct io_mapping *fb; 37 struct io_mapping *fb;
38 38
39 /* Map the framebuffer aperture */ 39 /* Map the framebuffer aperture */
40 fb = fbmem_init(nv_device(priv)->pdev); 40 fb = fbmem_init(nv_device(priv));
41 if (!fb) { 41 if (!fb) {
42 nv_error(priv, "failed to map fb\n"); 42 nv_error(priv, "failed to map fb\n");
43 return; 43 return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
index 141c27e9f182..51d5076333ec 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
@@ -5,6 +5,7 @@
5 5
6struct nv50_devinit_priv { 6struct nv50_devinit_priv {
7 struct nouveau_devinit base; 7 struct nouveau_devinit base;
8 u32 r001540;
8}; 9};
9 10
10int nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *, 11int nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
@@ -15,4 +16,6 @@ int nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
15 16
16int nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32); 17int nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
17 18
19int nvc0_devinit_pll_set(struct nouveau_devinit *, u32, u32);
20
18#endif 21#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
index 6dedf1dad7f7..006cf348bda7 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
@@ -81,6 +81,55 @@ nva3_devinit_disable(struct nouveau_devinit *devinit)
81 return disable; 81 return disable;
82} 82}
83 83
84static u32
85nva3_devinit_mmio_part[] = {
86 0x100720, 0x1008bc, 4,
87 0x100a20, 0x100adc, 4,
88 0x100d80, 0x100ddc, 4,
89 0x110000, 0x110f9c, 4,
90 0x111000, 0x11103c, 8,
91 0x111080, 0x1110fc, 4,
92 0x111120, 0x1111fc, 4,
93 0x111300, 0x1114bc, 4,
94 0,
95};
96
97static u32
98nva3_devinit_mmio(struct nouveau_devinit *devinit, u32 addr)
99{
100 struct nv50_devinit_priv *priv = (void *)devinit;
101 u32 *mmio = nva3_devinit_mmio_part;
102
103 /* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP
104 * instructions which touch registers that may not even exist on
105 * some configurations (Quadro 400), which causes the register
106 * interface to screw up for some amount of time after attempting to
107 * write to one of these, and results in all sorts of things going
108 * horribly wrong.
109 *
110 * the binary driver avoids touching these registers at all, however,
111 * the video bios doesn't care and does what the scripts say. it's
112 * presumed that the io-port access to priv registers isn't effected
113 * by the screw-up bug mentioned above.
114 *
115 * really, a new opcode should've been invented to handle these
116 * requirements, but whatever, it's too late for that now.
117 */
118 while (mmio[0]) {
119 if (addr >= mmio[0] && addr <= mmio[1]) {
120 u32 part = (addr / mmio[2]) & 7;
121 if (!priv->r001540)
122 priv->r001540 = nv_rd32(priv, 0x001540);
123 if (part >= hweight8((priv->r001540 >> 16) & 0xff))
124 return ~0;
125 return addr;
126 }
127 mmio += 3;
128 }
129
130 return addr;
131}
132
84struct nouveau_oclass * 133struct nouveau_oclass *
85nva3_devinit_oclass = &(struct nouveau_devinit_impl) { 134nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
86 .base.handle = NV_SUBDEV(DEVINIT, 0xa3), 135 .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
@@ -92,4 +141,5 @@ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
92 }, 141 },
93 .pll_set = nva3_devinit_pll_set, 142 .pll_set = nva3_devinit_pll_set,
94 .disable = nva3_devinit_disable, 143 .disable = nva3_devinit_disable,
144 .mmio = nva3_devinit_mmio,
95}.base; 145}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
index fa7e63766b1b..30c765747eea 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
@@ -24,7 +24,7 @@
24 24
25#include "nv50.h" 25#include "nv50.h"
26 26
27static int 27int
28nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) 28nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
29{ 29{
30 struct nv50_devinit_priv *priv = (void *)devinit; 30 struct nv50_devinit_priv *priv = (void *)devinit;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
index 822a2fbf44a5..f0e8683ad840 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
@@ -11,6 +11,7 @@ struct nouveau_devinit_impl {
11 void (*meminit)(struct nouveau_devinit *); 11 void (*meminit)(struct nouveau_devinit *);
12 int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq); 12 int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
13 u64 (*disable)(struct nouveau_devinit *); 13 u64 (*disable)(struct nouveau_devinit *);
14 u32 (*mmio)(struct nouveau_devinit *, u32);
14}; 15};
15 16
16#define nouveau_devinit_create(p,e,o,d) \ 17#define nouveau_devinit_create(p,e,o,d) \
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c
new file mode 100644
index 000000000000..c4840aedc2dc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c
@@ -0,0 +1,38 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nvc0.h"
26
27struct nouveau_oclass *
28gm107_fb_oclass = &(struct nouveau_fb_impl) {
29 .base.handle = NV_SUBDEV(FB, 0x07),
30 .base.ofuncs = &(struct nouveau_ofuncs) {
31 .ctor = nvc0_fb_ctor,
32 .dtor = nvc0_fb_dtor,
33 .init = nvc0_fb_init,
34 .fini = _nouveau_fb_fini,
35 },
36 .memtype = nvc0_fb_memtype_valid,
37 .ram = &gm107_ram_oclass,
38}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index cbc7f00c1278..1fc55c1e91a1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -250,10 +250,8 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
250 250
251 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 251 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
252 if (priv->r100c08_page) { 252 if (priv->r100c08_page) {
253 priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, 253 priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
254 0, PAGE_SIZE, 254 if (!priv->r100c08)
255 PCI_DMA_BIDIRECTIONAL);
256 if (pci_dma_mapping_error(device->pdev, priv->r100c08))
257 nv_warn(priv, "failed 0x100c08 page map\n"); 255 nv_warn(priv, "failed 0x100c08 page map\n");
258 } else { 256 } else {
259 nv_warn(priv, "failed 0x100c08 page alloc\n"); 257 nv_warn(priv, "failed 0x100c08 page alloc\n");
@@ -270,8 +268,7 @@ nv50_fb_dtor(struct nouveau_object *object)
270 struct nv50_fb_priv *priv = (void *)object; 268 struct nv50_fb_priv *priv = (void *)object;
271 269
272 if (priv->r100c08_page) { 270 if (priv->r100c08_page) {
273 pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE, 271 nv_device_unmap_page(device, priv->r100c08);
274 PCI_DMA_BIDIRECTIONAL);
275 __free_page(priv->r100c08_page); 272 __free_page(priv->r100c08_page);
276 } 273 }
277 274
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 45470e1f0385..0670ae33ee45 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -70,8 +70,7 @@ nvc0_fb_dtor(struct nouveau_object *object)
70 struct nvc0_fb_priv *priv = (void *)object; 70 struct nvc0_fb_priv *priv = (void *)object;
71 71
72 if (priv->r100c10_page) { 72 if (priv->r100c10_page) {
73 pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, 73 nv_device_unmap_page(device, priv->r100c10);
74 PCI_DMA_BIDIRECTIONAL);
75 __free_page(priv->r100c10_page); 74 __free_page(priv->r100c10_page);
76 } 75 }
77 76
@@ -94,10 +93,8 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
94 93
95 priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 94 priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
96 if (priv->r100c10_page) { 95 if (priv->r100c10_page) {
97 priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 96 priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
98 0, PAGE_SIZE, 97 if (!priv->r100c10)
99 PCI_DMA_BIDIRECTIONAL);
100 if (pci_dma_mapping_error(device->pdev, priv->r100c10))
101 return -EFAULT; 98 return -EFAULT;
102 } 99 }
103 100
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
index 9e1931eb746f..705a06d755ad 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
@@ -18,12 +18,14 @@ int nvc0_fb_init(struct nouveau_object *);
18bool nvc0_fb_memtype_valid(struct nouveau_fb *, u32); 18bool nvc0_fb_memtype_valid(struct nouveau_fb *, u32);
19 19
20 20
21#define nvc0_ram_create(p,e,o,d) \ 21#define nvc0_ram_create(p,e,o,m,d) \
22 nvc0_ram_create_((p), (e), (o), sizeof(**d), (void **)d) 22 nvc0_ram_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
23int nvc0_ram_create_(struct nouveau_object *, struct nouveau_object *, 23int nvc0_ram_create_(struct nouveau_object *, struct nouveau_object *,
24 struct nouveau_oclass *, int, void **); 24 struct nouveau_oclass *, u32, int, void **);
25int nvc0_ram_get(struct nouveau_fb *, u64, u32, u32, u32, 25int nvc0_ram_get(struct nouveau_fb *, u64, u32, u32, u32,
26 struct nouveau_mem **); 26 struct nouveau_mem **);
27void nvc0_ram_put(struct nouveau_fb *, struct nouveau_mem **); 27void nvc0_ram_put(struct nouveau_fb *, struct nouveau_mem **);
28 28
29int nve0_ram_init(struct nouveau_object*);
30
29#endif 31#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
index edaf95dee612..da74c889aed4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
@@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass;
32extern struct nouveau_oclass nvaa_ram_oclass; 32extern struct nouveau_oclass nvaa_ram_oclass;
33extern struct nouveau_oclass nvc0_ram_oclass; 33extern struct nouveau_oclass nvc0_ram_oclass;
34extern struct nouveau_oclass nve0_ram_oclass; 34extern struct nouveau_oclass nve0_ram_oclass;
35extern struct nouveau_oclass gm107_ram_oclass;
35 36
36int nouveau_sddr3_calc(struct nouveau_ram *ram); 37int nouveau_sddr3_calc(struct nouveau_ram *ram);
37int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts); 38int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c
new file mode 100644
index 000000000000..4c6363595c79
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c
@@ -0,0 +1,56 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nvc0.h"
26
27struct gm107_ram {
28 struct nouveau_ram base;
29};
30
31static int
32gm107_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
33 struct nouveau_oclass *oclass, void *data, u32 size,
34 struct nouveau_object **pobject)
35{
36 struct gm107_ram *ram;
37 int ret;
38
39 ret = nvc0_ram_create(parent, engine, oclass, 0x021c14, &ram);
40 *pobject = nv_object(ram);
41 if (ret)
42 return ret;
43
44 return 0;
45}
46
47struct nouveau_oclass
48gm107_ram_oclass = {
49 .handle = 0,
50 .ofuncs = &(struct nouveau_ofuncs) {
51 .ctor = gm107_ram_ctor,
52 .dtor = _nouveau_ram_dtor,
53 .init = nve0_ram_init,
54 .fini = _nouveau_ram_fini,
55 }
56};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
index c7fdb3a9e88b..ef91b6e893af 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
@@ -91,7 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
91 } while (perfE.memory < freq); 91 } while (perfE.memory < freq);
92 92
93 /* locate specific data set for the attached memory */ 93 /* locate specific data set for the attached memory */
94 strap = nvbios_ramcfg_index(bios); 94 strap = nvbios_ramcfg_index(nv_subdev(pfb));
95 if (strap >= cnt) { 95 if (strap >= cnt) {
96 nv_error(pfb, "invalid ramcfg strap\n"); 96 nv_error(pfb, "invalid ramcfg strap\n");
97 return -EINVAL; 97 return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
index f4ae8aa46a25..6eb97f16fbda 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
@@ -98,7 +98,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
98 } 98 }
99 99
100 /* locate specific data set for the attached memory */ 100 /* locate specific data set for the attached memory */
101 strap = nvbios_ramcfg_index(bios); 101 strap = nvbios_ramcfg_index(nv_subdev(pfb));
102 if (strap >= cnt) { 102 if (strap >= cnt) {
103 nv_error(pfb, "invalid ramcfg strap\n"); 103 nv_error(pfb, "invalid ramcfg strap\n");
104 return -EINVAL; 104 return -EINVAL;
@@ -335,21 +335,23 @@ nva3_ram_init(struct nouveau_object *object)
335 /* prepare for ddr link training, and load training patterns */ 335 /* prepare for ddr link training, and load training patterns */
336 switch (ram->base.type) { 336 switch (ram->base.type) {
337 case NV_MEM_TYPE_DDR3: { 337 case NV_MEM_TYPE_DDR3: {
338 static const u32 pattern[16] = { 338 if (nv_device(pfb)->chipset == 0xa8) {
339 0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee, 339 static const u32 pattern[16] = {
340 0x00000000, 0x11111111, 0x44444444, 0xdddddddd, 340 0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
341 0x33333333, 0x55555555, 0x77777777, 0x66666666, 341 0x00000000, 0x11111111, 0x44444444, 0xdddddddd,
342 0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb, 342 0x33333333, 0x55555555, 0x77777777, 0x66666666,
343 }; 343 0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb,
344 344 };
345 nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/ 345
346 nv_wr32(pfb, 0x1005a8, 0x0000ffff); 346 nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/
347 nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001); 347 nv_wr32(pfb, 0x1005a8, 0x0000ffff);
348 for (i = 0; i < 0x30; i++) { 348 nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001);
349 nv_wr32(pfb, 0x10f8c0, (i << 8) | i); 349 for (i = 0; i < 0x30; i++) {
350 nv_wr32(pfb, 0x10f8e0, (i << 8) | i); 350 nv_wr32(pfb, 0x10f8c0, (i << 8) | i);
351 nv_wr32(pfb, 0x10f900, pattern[i % 16]); 351 nv_wr32(pfb, 0x10f8e0, (i << 8) | i);
352 nv_wr32(pfb, 0x10f920, pattern[i % 16]); 352 nv_wr32(pfb, 0x10f900, pattern[i % 16]);
353 nv_wr32(pfb, 0x10f920, pattern[i % 16]);
354 }
353 } 355 }
354 } 356 }
355 break; 357 break;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index 0391b824ee76..8edc92224c84 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -152,7 +152,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
152 } 152 }
153 153
154 /* locate specific data set for the attached memory */ 154 /* locate specific data set for the attached memory */
155 strap = nvbios_ramcfg_index(bios); 155 strap = nvbios_ramcfg_index(nv_subdev(pfb));
156 if (strap >= cnt) { 156 if (strap >= cnt) {
157 nv_error(pfb, "invalid ramcfg strap\n"); 157 nv_error(pfb, "invalid ramcfg strap\n");
158 return -EINVAL; 158 return -EINVAL;
@@ -505,7 +505,8 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
505 505
506int 506int
507nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine, 507nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
508 struct nouveau_oclass *oclass, int size, void **pobject) 508 struct nouveau_oclass *oclass, u32 maskaddr, int size,
509 void **pobject)
509{ 510{
510 struct nouveau_fb *pfb = nouveau_fb(parent); 511 struct nouveau_fb *pfb = nouveau_fb(parent);
511 struct nouveau_bios *bios = nouveau_bios(pfb); 512 struct nouveau_bios *bios = nouveau_bios(pfb);
@@ -513,7 +514,7 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
513 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ 514 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
514 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ 515 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
515 u32 parts = nv_rd32(pfb, 0x022438); 516 u32 parts = nv_rd32(pfb, 0x022438);
516 u32 pmask = nv_rd32(pfb, 0x022554); 517 u32 pmask = nv_rd32(pfb, maskaddr);
517 u32 bsize = nv_rd32(pfb, 0x10f20c); 518 u32 bsize = nv_rd32(pfb, 0x10f20c);
518 u32 offset, length; 519 u32 offset, length;
519 bool uniform = true; 520 bool uniform = true;
@@ -630,7 +631,7 @@ nvc0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
630 struct nvc0_ram *ram; 631 struct nvc0_ram *ram;
631 int ret; 632 int ret;
632 633
633 ret = nvc0_ram_create(parent, engine, oclass, &ram); 634 ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
634 *pobject = nv_object(ram); 635 *pobject = nv_object(ram);
635 if (ret) 636 if (ret)
636 return ret; 637 return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
index 3257c522a021..16752192cf87 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
@@ -950,10 +950,11 @@ nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
950 } 950 }
951 951
952 /* locate specific data set for the attached memory */ 952 /* locate specific data set for the attached memory */
953 strap = nvbios_ramcfg_index(nv_subdev(pfb));
953 ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data, 954 ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
954 ram->base.rammap.version, 955 ram->base.rammap.version,
955 ram->base.rammap.size, cnt, len, 956 ram->base.rammap.size,
956 nvbios_ramcfg_index(bios), 957 cnt, len, strap,
957 &ram->base.ramcfg.version, 958 &ram->base.ramcfg.version,
958 &ram->base.ramcfg.size, 959 &ram->base.ramcfg.size,
959 &data->bios); 960 &data->bios);
@@ -1123,7 +1124,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
1123 ram_exec(fuc, false); 1124 ram_exec(fuc, false);
1124} 1125}
1125 1126
1126static int 1127int
1127nve0_ram_init(struct nouveau_object *object) 1128nve0_ram_init(struct nouveau_object *object)
1128{ 1129{
1129 struct nouveau_fb *pfb = (void *)object->parent; 1130 struct nouveau_fb *pfb = (void *)object->parent;
@@ -1226,7 +1227,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1226 int ret, i; 1227 int ret, i;
1227 u32 tmp; 1228 u32 tmp;
1228 1229
1229 ret = nvc0_ram_create(parent, engine, oclass, &ram); 1230 ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
1230 *pobject = nv_object(ram); 1231 *pobject = nv_object(ram);
1231 if (ret) 1232 if (ret)
1232 return ret; 1233 return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
index c4c1d415e7fe..2ef774731629 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
@@ -46,7 +46,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
46 u8 unk0 = !!(data & 0x02000000); 46 u8 unk0 = !!(data & 0x02000000);
47 u8 unk1 = !!(data & 0x04000000); 47 u8 unk1 = !!(data & 0x04000000);
48 u32 val = (unk1 << 16) | unk0; 48 u32 val = (unk1 << 16) | unk0;
49 u32 reg = regs[line >> 4]; line &= 0x0f; 49 u32 reg = regs[line >> 4];
50 u32 lsh = line & 0x0f;
50 51
51 if ( func == DCB_GPIO_UNUSED || 52 if ( func == DCB_GPIO_UNUSED ||
52 (match != DCB_GPIO_UNUSED && match != func)) 53 (match != DCB_GPIO_UNUSED && match != func))
@@ -54,7 +55,7 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
54 55
55 gpio->set(gpio, 0, func, line, defs); 56 gpio->set(gpio, 0, func, line, defs);
56 57
57 nv_mask(priv, reg, 0x00010001 << line, val << line); 58 nv_mask(priv, reg, 0x00010001 << lsh, val << lsh);
58 } 59 }
59} 60}
60 61
@@ -79,7 +80,7 @@ nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
79 if (nv50_gpio_location(line, &reg, &shift)) 80 if (nv50_gpio_location(line, &reg, &shift))
80 return -EINVAL; 81 return -EINVAL;
81 82
82 nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); 83 nv_mask(gpio, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift);
83 return 0; 84 return 0;
84} 85}
85 86
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index c33c03d2f4af..378e05b88e6f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -111,7 +111,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
111 snprintf(port->adapter.name, sizeof(port->adapter.name), 111 snprintf(port->adapter.name, sizeof(port->adapter.name),
112 "nouveau-%s-%d", device->name, index); 112 "nouveau-%s-%d", device->name, index);
113 port->adapter.owner = THIS_MODULE; 113 port->adapter.owner = THIS_MODULE;
114 port->adapter.dev.parent = &device->pdev->dev; 114 port->adapter.dev.parent = nv_device_base(device);
115 port->index = index; 115 port->index = index;
116 port->func = func; 116 port->func = func;
117 i2c_set_adapdata(&port->adapter, i2c); 117 i2c_set_adapdata(&port->adapter, i2c);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
index ec0b9661d614..8803809f9fc5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
@@ -50,7 +50,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
50 struct nouveau_object **pobject) 50 struct nouveau_object **pobject)
51{ 51{
52 struct nouveau_device *device = nv_device(parent); 52 struct nouveau_device *device = nv_device(parent);
53 struct pci_dev *pdev = device->pdev;
54 struct nv04_instmem_priv *priv; 53 struct nv04_instmem_priv *priv;
55 int ret, bar, vs; 54 int ret, bar, vs;
56 55
@@ -60,13 +59,13 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
60 return ret; 59 return ret;
61 60
62 /* map bar */ 61 /* map bar */
63 if (pci_resource_len(pdev, 2)) 62 if (nv_device_resource_len(device, 2))
64 bar = 2; 63 bar = 2;
65 else 64 else
66 bar = 3; 65 bar = 3;
67 66
68 priv->iomem = ioremap(pci_resource_start(pdev, bar), 67 priv->iomem = ioremap(nv_device_resource_start(device, bar),
69 pci_resource_len(pdev, bar)); 68 nv_device_resource_len(device, bar));
70 if (!priv->iomem) { 69 if (!priv->iomem) {
71 nv_error(priv, "unable to map PRAMIN BAR\n"); 70 nv_error(priv, "unable to map PRAMIN BAR\n");
72 return -EFAULT; 71 return -EFAULT;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
index cce65cc56514..f2f3338a967a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
@@ -22,44 +22,35 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <subdev/ltcg.h>
26#include <subdev/fb.h> 25#include <subdev/fb.h>
27#include <subdev/timer.h> 26#include <subdev/timer.h>
28 27
29struct nvc0_ltcg_priv { 28#include "gf100.h"
30 struct nouveau_ltcg base;
31 u32 part_nr;
32 u32 subp_nr;
33 u32 num_tags;
34 u32 tag_base;
35 struct nouveau_mm tags;
36 struct nouveau_mm_node *tag_ram;
37};
38 29
39static void 30static void
40nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp) 31gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
41{ 32{
42 u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); 33 u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
43 u32 stat = nv_rd32(priv, subp_base + 0x020); 34 u32 stat = nv_rd32(priv, base + 0x020);
44 35
45 if (stat) { 36 if (stat) {
46 nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat); 37 nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
47 nv_wr32(priv, subp_base + 0x020, stat); 38 nv_wr32(priv, base + 0x020, stat);
48 } 39 }
49} 40}
50 41
51static void 42static void
52nvc0_ltcg_intr(struct nouveau_subdev *subdev) 43gf100_ltcg_intr(struct nouveau_subdev *subdev)
53{ 44{
54 struct nvc0_ltcg_priv *priv = (void *)subdev; 45 struct gf100_ltcg_priv *priv = (void *)subdev;
55 u32 units; 46 u32 mask;
56 47
57 units = nv_rd32(priv, 0x00017c); 48 mask = nv_rd32(priv, 0x00017c);
58 while (units) { 49 while (mask) {
59 u32 subp, unit = ffs(units) - 1; 50 u32 lts, ltc = __ffs(mask);
60 for (subp = 0; subp < priv->subp_nr; subp++) 51 for (lts = 0; lts < priv->lts_nr; lts++)
61 nvc0_ltcg_subp_isr(priv, unit, subp); 52 gf100_ltcg_lts_isr(priv, ltc, lts);
62 units &= ~(1 << unit); 53 mask &= ~(1 << ltc);
63 } 54 }
64 55
65 /* we do something horribly wrong and upset PMFB a lot, so mask off 56 /* we do something horribly wrong and upset PMFB a lot, so mask off
@@ -68,11 +59,11 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev)
68 nv_mask(priv, 0x000640, 0x02000000, 0x00000000); 59 nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
69} 60}
70 61
71static int 62int
72nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n, 63gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
73 struct nouveau_mm_node **pnode) 64 struct nouveau_mm_node **pnode)
74{ 65{
75 struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; 66 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
76 int ret; 67 int ret;
77 68
78 ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode); 69 ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
@@ -82,18 +73,18 @@ nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
82 return ret; 73 return ret;
83} 74}
84 75
85static void 76void
86nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode) 77gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
87{ 78{
88 struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; 79 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
89 80
90 nouveau_mm_free(&priv->tags, pnode); 81 nouveau_mm_free(&priv->tags, pnode);
91} 82}
92 83
93static void 84static void
94nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count) 85gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
95{ 86{
96 struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; 87 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
97 u32 last = first + count - 1; 88 u32 last = first + count - 1;
98 int p, i; 89 int p, i;
99 90
@@ -104,16 +95,16 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
104 nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */ 95 nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
105 96
106 /* wait until it's finished with clearing */ 97 /* wait until it's finished with clearing */
107 for (p = 0; p < priv->part_nr; ++p) { 98 for (p = 0; p < priv->ltc_nr; ++p) {
108 for (i = 0; i < priv->subp_nr; ++i) 99 for (i = 0; i < priv->lts_nr; ++i)
109 nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0); 100 nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
110 } 101 }
111} 102}
112 103
113/* TODO: Figure out tag memory details and drop the over-cautious allocation. 104/* TODO: Figure out tag memory details and drop the over-cautious allocation.
114 */ 105 */
115static int 106int
116nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) 107gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
117{ 108{
118 u32 tag_size, tag_margin, tag_align; 109 u32 tag_size, tag_margin, tag_align;
119 int ret; 110 int ret;
@@ -124,7 +115,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
124 priv->num_tags = 1 << 17; /* we have 17 bits in PTE */ 115 priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
125 priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */ 116 priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
126 117
127 tag_align = priv->part_nr * 0x800; 118 tag_align = priv->ltc_nr * 0x800;
128 tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align; 119 tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
129 120
130 /* 4 part 4 sub: 0x2000 bytes for 56 tags */ 121 /* 4 part 4 sub: 0x2000 bytes for 56 tags */
@@ -157,11 +148,11 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
157} 148}
158 149
159static int 150static int
160nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 151gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
161 struct nouveau_oclass *oclass, void *data, u32 size, 152 struct nouveau_oclass *oclass, void *data, u32 size,
162 struct nouveau_object **pobject) 153 struct nouveau_object **pobject)
163{ 154{
164 struct nvc0_ltcg_priv *priv; 155 struct gf100_ltcg_priv *priv;
165 struct nouveau_fb *pfb = nouveau_fb(parent); 156 struct nouveau_fb *pfb = nouveau_fb(parent);
166 u32 parts, mask; 157 u32 parts, mask;
167 int ret, i; 158 int ret, i;
@@ -175,27 +166,27 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
175 mask = nv_rd32(priv, 0x022554); 166 mask = nv_rd32(priv, 0x022554);
176 for (i = 0; i < parts; i++) { 167 for (i = 0; i < parts; i++) {
177 if (!(mask & (1 << i))) 168 if (!(mask & (1 << i)))
178 priv->part_nr++; 169 priv->ltc_nr++;
179 } 170 }
180 priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; 171 priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
181 172
182 ret = nvc0_ltcg_init_tag_ram(pfb, priv); 173 ret = gf100_ltcg_init_tag_ram(pfb, priv);
183 if (ret) 174 if (ret)
184 return ret; 175 return ret;
185 176
186 priv->base.tags_alloc = nvc0_ltcg_tags_alloc; 177 priv->base.tags_alloc = gf100_ltcg_tags_alloc;
187 priv->base.tags_free = nvc0_ltcg_tags_free; 178 priv->base.tags_free = gf100_ltcg_tags_free;
188 priv->base.tags_clear = nvc0_ltcg_tags_clear; 179 priv->base.tags_clear = gf100_ltcg_tags_clear;
189 180
190 nv_subdev(priv)->intr = nvc0_ltcg_intr; 181 nv_subdev(priv)->intr = gf100_ltcg_intr;
191 return 0; 182 return 0;
192} 183}
193 184
194static void 185void
195nvc0_ltcg_dtor(struct nouveau_object *object) 186gf100_ltcg_dtor(struct nouveau_object *object)
196{ 187{
197 struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; 188 struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
198 struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; 189 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
199 struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent); 190 struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
200 191
201 nouveau_mm_fini(&priv->tags); 192 nouveau_mm_fini(&priv->tags);
@@ -205,10 +196,10 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
205} 196}
206 197
207static int 198static int
208nvc0_ltcg_init(struct nouveau_object *object) 199gf100_ltcg_init(struct nouveau_object *object)
209{ 200{
210 struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; 201 struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
211 struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; 202 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
212 int ret; 203 int ret;
213 204
214 ret = nouveau_ltcg_init(ltcg); 205 ret = nouveau_ltcg_init(ltcg);
@@ -216,20 +207,20 @@ nvc0_ltcg_init(struct nouveau_object *object)
216 return ret; 207 return ret;
217 208
218 nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ 209 nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
219 nv_wr32(priv, 0x17e8d8, priv->part_nr); 210 nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
220 if (nv_device(ltcg)->card_type >= NV_E0) 211 if (nv_device(ltcg)->card_type >= NV_E0)
221 nv_wr32(priv, 0x17e000, priv->part_nr); 212 nv_wr32(priv, 0x17e000, priv->ltc_nr);
222 nv_wr32(priv, 0x17e8d4, priv->tag_base); 213 nv_wr32(priv, 0x17e8d4, priv->tag_base);
223 return 0; 214 return 0;
224} 215}
225 216
226struct nouveau_oclass 217struct nouveau_oclass *
227nvc0_ltcg_oclass = { 218gf100_ltcg_oclass = &(struct nouveau_oclass) {
228 .handle = NV_SUBDEV(LTCG, 0xc0), 219 .handle = NV_SUBDEV(LTCG, 0xc0),
229 .ofuncs = &(struct nouveau_ofuncs) { 220 .ofuncs = &(struct nouveau_ofuncs) {
230 .ctor = nvc0_ltcg_ctor, 221 .ctor = gf100_ltcg_ctor,
231 .dtor = nvc0_ltcg_dtor, 222 .dtor = gf100_ltcg_dtor,
232 .init = nvc0_ltcg_init, 223 .init = gf100_ltcg_init,
233 .fini = _nouveau_ltcg_fini, 224 .fini = _nouveau_ltcg_fini,
234 }, 225 },
235}; 226};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
new file mode 100644
index 000000000000..87b10b8412ea
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
@@ -0,0 +1,21 @@
1#ifndef __NVKM_LTCG_PRIV_GF100_H__
2#define __NVKM_LTCG_PRIV_GF100_H__
3
4#include <subdev/ltcg.h>
5
6struct gf100_ltcg_priv {
7 struct nouveau_ltcg base;
8 u32 ltc_nr;
9 u32 lts_nr;
10 u32 num_tags;
11 u32 tag_base;
12 struct nouveau_mm tags;
13 struct nouveau_mm_node *tag_ram;
14};
15
16void gf100_ltcg_dtor(struct nouveau_object *);
17int gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *);
18int gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **);
19void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **);
20
21#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
new file mode 100644
index 000000000000..e79d0e81de40
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
@@ -0,0 +1,142 @@
1/*
2 * Copyright 2014 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/fb.h>
26#include <subdev/timer.h>
27
28#include "gf100.h"
29
30static void
31gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
32{
33 u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
34 u32 stat = nv_rd32(priv, base + 0x00c);
35
36 if (stat) {
37 nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
38 nv_wr32(priv, base + 0x00c, stat);
39 }
40}
41
42static void
43gm107_ltcg_intr(struct nouveau_subdev *subdev)
44{
45 struct gf100_ltcg_priv *priv = (void *)subdev;
46 u32 mask;
47
48 mask = nv_rd32(priv, 0x00017c);
49 while (mask) {
50 u32 lts, ltc = __ffs(mask);
51 for (lts = 0; lts < priv->lts_nr; lts++)
52 gm107_ltcg_lts_isr(priv, ltc, lts);
53 mask &= ~(1 << ltc);
54 }
55
56 /* we do something horribly wrong and upset PMFB a lot, so mask off
57 * interrupts from it after the first one until it's fixed
58 */
59 nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
60}
61
62static void
63gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
64{
65 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
66 u32 last = first + count - 1;
67 int p, i;
68
69 BUG_ON((first > last) || (last >= priv->num_tags));
70
71 nv_wr32(priv, 0x17e270, first);
72 nv_wr32(priv, 0x17e274, last);
73 nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */
74
75 /* wait until it's finished with clearing */
76 for (p = 0; p < priv->ltc_nr; ++p) {
77 for (i = 0; i < priv->lts_nr; ++i)
78 nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0);
79 }
80}
81
82static int
83gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
84 struct nouveau_oclass *oclass, void *data, u32 size,
85 struct nouveau_object **pobject)
86{
87 struct gf100_ltcg_priv *priv;
88 struct nouveau_fb *pfb = nouveau_fb(parent);
89 u32 parts, mask;
90 int ret, i;
91
92 ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
93 *pobject = nv_object(priv);
94 if (ret)
95 return ret;
96
97 parts = nv_rd32(priv, 0x022438);
98 mask = nv_rd32(priv, 0x021c14);
99 for (i = 0; i < parts; i++) {
100 if (!(mask & (1 << i)))
101 priv->ltc_nr++;
102 }
103 priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
104
105 ret = gf100_ltcg_init_tag_ram(pfb, priv);
106 if (ret)
107 return ret;
108
109 priv->base.tags_alloc = gf100_ltcg_tags_alloc;
110 priv->base.tags_free = gf100_ltcg_tags_free;
111 priv->base.tags_clear = gm107_ltcg_tags_clear;
112
113 nv_subdev(priv)->intr = gm107_ltcg_intr;
114 return 0;
115}
116
117static int
118gm107_ltcg_init(struct nouveau_object *object)
119{
120 struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
121 struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
122 int ret;
123
124 ret = nouveau_ltcg_init(ltcg);
125 if (ret)
126 return ret;
127
128 nv_wr32(priv, 0x17e27c, priv->ltc_nr);
129 nv_wr32(priv, 0x17e278, priv->tag_base);
130 return 0;
131}
132
133struct nouveau_oclass *
134gm107_ltcg_oclass = &(struct nouveau_oclass) {
135 .handle = NV_SUBDEV(LTCG, 0xff),
136 .ofuncs = &(struct nouveau_ofuncs) {
137 .ctor = gm107_ltcg_ctor,
138 .dtor = gf100_ltcg_dtor,
139 .init = gm107_ltcg_init,
140 .fini = _nouveau_ltcg_fini,
141 },
142};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
index b4b9943773bc..8a5555192fa5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
@@ -93,7 +93,7 @@ _nouveau_mc_dtor(struct nouveau_object *object)
93{ 93{
94 struct nouveau_device *device = nv_device(object); 94 struct nouveau_device *device = nv_device(object);
95 struct nouveau_mc *pmc = (void *)object; 95 struct nouveau_mc *pmc = (void *)object;
96 free_irq(device->pdev->irq, pmc); 96 free_irq(pmc->irq, pmc);
97 if (pmc->use_msi) 97 if (pmc->use_msi)
98 pci_disable_msi(device->pdev); 98 pci_disable_msi(device->pdev);
99 nouveau_subdev_destroy(&pmc->base); 99 nouveau_subdev_destroy(&pmc->base);
@@ -114,33 +114,44 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
114 if (ret) 114 if (ret)
115 return ret; 115 return ret;
116 116
117 switch (device->pdev->device & 0x0ff0) { 117 if (nv_device_is_pci(device))
118 case 0x00f0: 118 switch (device->pdev->device & 0x0ff0) {
119 case 0x02e0: 119 case 0x00f0:
120 /* BR02? NFI how these would be handled yet exactly */ 120 case 0x02e0:
121 break; 121 /* BR02? NFI how these would be handled yet exactly */
122 default:
123 switch (device->chipset) {
124 case 0xaa: break; /* reported broken, nv also disable it */
125 default:
126 pmc->use_msi = true;
127 break; 122 break;
123 default:
124 switch (device->chipset) {
125 case 0xaa:
126 /* reported broken, nv also disable it */
127 break;
128 default:
129 pmc->use_msi = true;
130 break;
128 } 131 }
129 }
130 132
131 pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", pmc->use_msi); 133 pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI",
132 if (pmc->use_msi && oclass->msi_rearm) { 134 pmc->use_msi);
133 pmc->use_msi = pci_enable_msi(device->pdev) == 0; 135
134 if (pmc->use_msi) { 136 if (pmc->use_msi && oclass->msi_rearm) {
135 nv_info(pmc, "MSI interrupts enabled\n"); 137 pmc->use_msi = pci_enable_msi(device->pdev) == 0;
136 oclass->msi_rearm(pmc); 138 if (pmc->use_msi) {
139 nv_info(pmc, "MSI interrupts enabled\n");
140 oclass->msi_rearm(pmc);
141 }
142 } else {
143 pmc->use_msi = false;
137 } 144 }
138 } else {
139 pmc->use_msi = false;
140 } 145 }
141 146
142 ret = request_irq(device->pdev->irq, nouveau_mc_intr, 147 ret = nv_device_get_irq(device, true);
143 IRQF_SHARED, "nouveau", pmc); 148 if (ret < 0)
149 return ret;
150 pmc->irq = ret;
151
152 ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau",
153 pmc);
154
144 if (ret < 0) 155 if (ret < 0)
145 return ret; 156 return ret;
146 157
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
index 13c5af88a601..51fcf7960417 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
@@ -96,7 +96,7 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version)
96 acpi_handle handle; 96 acpi_handle handle;
97 int rev; 97 int rev;
98 98
99 handle = ACPI_HANDLE(&device->pdev->dev); 99 handle = ACPI_HANDLE(nv_device_base(device));
100 if (!handle) 100 if (!handle)
101 return false; 101 return false;
102 102
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
index 80e584a1bd1c..9ad01da6eacb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
@@ -110,16 +110,18 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
110 poll = false; 110 poll = false;
111 break; 111 break;
112 case NOUVEAU_THERM_CTRL_AUTO: 112 case NOUVEAU_THERM_CTRL_AUTO:
113 if (priv->fan->bios.nr_fan_trip) { 113 switch(priv->fan->bios.fan_mode) {
114 case NVBIOS_THERM_FAN_TRIP:
114 duty = nouveau_therm_update_trip(therm); 115 duty = nouveau_therm_update_trip(therm);
115 } else 116 break;
116 if (priv->fan->bios.linear_min_temp || 117 case NVBIOS_THERM_FAN_LINEAR:
117 priv->fan->bios.linear_max_temp) {
118 duty = nouveau_therm_update_linear(therm); 118 duty = nouveau_therm_update_linear(therm);
119 } else { 119 break;
120 case NVBIOS_THERM_FAN_OTHER:
120 if (priv->cstate) 121 if (priv->cstate)
121 duty = priv->cstate; 122 duty = priv->cstate;
122 poll = false; 123 poll = false;
124 break;
123 } 125 }
124 immd = false; 126 immd = false;
125 break; 127 break;
@@ -179,7 +181,7 @@ nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
179 181
180 /* do not allow automatic fan management if the thermal sensor is 182 /* do not allow automatic fan management if the thermal sensor is
181 * not available */ 183 * not available */
182 if (priv->mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0) 184 if (mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
183 return -EINVAL; 185 return -EINVAL;
184 186
185 if (priv->mode == mode) 187 if (priv->mode == mode)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 95f6129eeede..016990a8252c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -54,8 +54,10 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
54 54
55 /* check that we're not already at the target duty cycle */ 55 /* check that we're not already at the target duty cycle */
56 duty = fan->get(therm); 56 duty = fan->get(therm);
57 if (duty == target) 57 if (duty == target) {
58 goto done; 58 spin_unlock_irqrestore(&fan->lock, flags);
59 return 0;
60 }
59 61
60 /* smooth out the fanspeed increase/decrease */ 62 /* smooth out the fanspeed increase/decrease */
61 if (!immediate && duty >= 0) { 63 if (!immediate && duty >= 0) {
@@ -73,8 +75,15 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
73 75
74 nv_debug(therm, "FAN update: %d\n", duty); 76 nv_debug(therm, "FAN update: %d\n", duty);
75 ret = fan->set(therm, duty); 77 ret = fan->set(therm, duty);
76 if (ret) 78 if (ret) {
77 goto done; 79 spin_unlock_irqrestore(&fan->lock, flags);
80 return ret;
81 }
82
83 /* fan speed updated, drop the fan lock before grabbing the
84 * alarm-scheduling lock and risking a deadlock
85 */
86 spin_unlock_irqrestore(&fan->lock, flags);
78 87
79 /* schedule next fan update, if not at target speed already */ 88 /* schedule next fan update, if not at target speed already */
80 if (list_empty(&fan->alarm.head) && target != duty) { 89 if (list_empty(&fan->alarm.head) && target != duty) {
@@ -92,8 +101,6 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
92 ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm); 101 ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);
93 } 102 }
94 103
95done:
96 spin_unlock_irqrestore(&fan->lock, flags);
97 return ret; 104 return ret;
98} 105}
99 106
@@ -185,11 +192,8 @@ nouveau_therm_fan_set_defaults(struct nouveau_therm *therm)
185 priv->fan->bios.max_duty = 100; 192 priv->fan->bios.max_duty = 100;
186 priv->fan->bios.bump_period = 500; 193 priv->fan->bios.bump_period = 500;
187 priv->fan->bios.slow_down_period = 2000; 194 priv->fan->bios.slow_down_period = 2000;
188/*XXX: talk to mupuf */
189#if 0
190 priv->fan->bios.linear_min_temp = 40; 195 priv->fan->bios.linear_min_temp = 40;
191 priv->fan->bios.linear_max_temp = 85; 196 priv->fan->bios.linear_max_temp = 85;
192#endif
193} 197}
194 198
195static void 199static void
@@ -235,7 +239,8 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)
235 /* attempt to locate a drivable fan, and determine control method */ 239 /* attempt to locate a drivable fan, and determine control method */
236 ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); 240 ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
237 if (ret == 0) { 241 if (ret == 0) {
238 if (func.log[0] & DCB_GPIO_LOG_DIR_IN) { 242 /* FIXME: is this really the place to perform such checks ? */
243 if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
239 nv_debug(therm, "GPIO_FAN is in input mode\n"); 244 nv_debug(therm, "GPIO_FAN is in input mode\n");
240 ret = -EINVAL; 245 ret = -EINVAL;
241 } else { 246 } else {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
index 5f71db8e8992..9a5c07340263 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
@@ -67,7 +67,7 @@ nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)
67 if (priv->base.bios.pwm_freq) { 67 if (priv->base.bios.pwm_freq) {
68 divs = 1; 68 divs = 1;
69 if (therm->pwm_clock) 69 if (therm->pwm_clock)
70 divs = therm->pwm_clock(therm); 70 divs = therm->pwm_clock(therm, priv->func.line);
71 divs /= priv->base.bios.pwm_freq; 71 divs /= priv->base.bios.pwm_freq;
72 } 72 }
73 73
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index 8cf7597a2182..321db927d638 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -93,7 +93,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
93} 93}
94 94
95int 95int
96nv50_fan_pwm_clock(struct nouveau_therm *therm) 96nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)
97{ 97{
98 int chipset = nv_device(therm)->chipset; 98 int chipset = nv_device(therm)->chipset;
99 int crystal = nv_device(therm)->crystal; 99 int crystal = nv_device(therm)->crystal;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index 4dd4f81ae873..43fec17ea540 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -32,10 +32,12 @@ static int
32pwm_info(struct nouveau_therm *therm, int line) 32pwm_info(struct nouveau_therm *therm, int line)
33{ 33{
34 u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); 34 u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
35
35 switch (gpio & 0x000000c0) { 36 switch (gpio & 0x000000c0) {
36 case 0x00000000: /* normal mode, possibly pwm forced off by us */ 37 case 0x00000000: /* normal mode, possibly pwm forced off by us */
37 case 0x00000040: /* nvio special */ 38 case 0x00000040: /* nvio special */
38 switch (gpio & 0x0000001f) { 39 switch (gpio & 0x0000001f) {
40 case 0x00: return 2;
39 case 0x19: return 1; 41 case 0x19: return 1;
40 case 0x1c: return 0; 42 case 0x1c: return 0;
41 default: 43 default:
@@ -56,8 +58,9 @@ nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
56 int indx = pwm_info(therm, line); 58 int indx = pwm_info(therm, line);
57 if (indx < 0) 59 if (indx < 0)
58 return indx; 60 return indx;
59 61 else if (indx < 2)
60 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); 62 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
63 /* nothing to do for indx == 2, it seems hardwired to PTHERM */
61 return 0; 64 return 0;
62} 65}
63 66
@@ -67,10 +70,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
67 int indx = pwm_info(therm, line); 70 int indx = pwm_info(therm, line);
68 if (indx < 0) 71 if (indx < 0)
69 return indx; 72 return indx;
70 73 else if (indx < 2) {
71 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { 74 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
72 *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); 75 *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
73 *duty = nv_rd32(therm, 0x00e118 + (indx * 8)); 76 *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
77 return 0;
78 }
79 } else if (indx == 2) {
80 *divs = nv_rd32(therm, 0x0200d8) & 0x1fff;
81 *duty = nv_rd32(therm, 0x0200dc) & 0x1fff;
74 return 0; 82 return 0;
75 } 83 }
76 84
@@ -83,16 +91,26 @@ nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
83 int indx = pwm_info(therm, line); 91 int indx = pwm_info(therm, line);
84 if (indx < 0) 92 if (indx < 0)
85 return indx; 93 return indx;
86 94 else if (indx < 2) {
87 nv_wr32(therm, 0x00e114 + (indx * 8), divs); 95 nv_wr32(therm, 0x00e114 + (indx * 8), divs);
88 nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); 96 nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
97 } else if (indx == 2) {
98 nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */
99 nv_wr32(therm, 0x0200dc, duty | 0x40000000);
100 }
89 return 0; 101 return 0;
90} 102}
91 103
92static int 104static int
93nvd0_fan_pwm_clock(struct nouveau_therm *therm) 105nvd0_fan_pwm_clock(struct nouveau_therm *therm, int line)
94{ 106{
95 return (nv_device(therm)->crystal * 1000) / 20; 107 int indx = pwm_info(therm, line);
108 if (indx < 0)
109 return 0;
110 else if (indx < 2)
111 return (nv_device(therm)->crystal * 1000) / 20;
112 else
113 return nv_device(therm)->crystal * 1000 / 10;
96} 114}
97 115
98static int 116static int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 96f8f95693ce..916fca5c7816 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -143,7 +143,7 @@ void nv40_therm_intr(struct nouveau_subdev *);
143int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool); 143int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
144int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *); 144int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);
145int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32); 145int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
146int nv50_fan_pwm_clock(struct nouveau_therm *); 146int nv50_fan_pwm_clock(struct nouveau_therm *, int);
147int nv84_temp_get(struct nouveau_therm *therm); 147int nv84_temp_get(struct nouveau_therm *therm);
148int nv84_therm_fini(struct nouveau_object *object, bool suspend); 148int nv84_therm_fini(struct nouveau_object *object, bool suspend);
149 149
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c
new file mode 100644
index 000000000000..37484db1f7fc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c
@@ -0,0 +1,57 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv04.h"
26
27static int
28gk20a_timer_init(struct nouveau_object *object)
29{
30 struct nv04_timer_priv *priv = (void *)object;
31 u32 hi = upper_32_bits(priv->suspend_time);
32 u32 lo = lower_32_bits(priv->suspend_time);
33 int ret;
34
35 ret = nouveau_timer_init(&priv->base);
36 if (ret)
37 return ret;
38
39 nv_debug(priv, "time low : 0x%08x\n", lo);
40 nv_debug(priv, "time high : 0x%08x\n", hi);
41
42 /* restore the time before suspend */
43 nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
44 nv_wr32(priv, NV04_PTIMER_TIME_0, lo);
45 return 0;
46}
47
48struct nouveau_oclass
49gk20a_timer_oclass = {
50 .handle = NV_SUBDEV(TIMER, 0xff),
51 .ofuncs = &(struct nouveau_ofuncs) {
52 .ctor = nv04_timer_ctor,
53 .dtor = nv04_timer_dtor,
54 .init = gk20a_timer_init,
55 .fini = nv04_timer_fini,
56 }
57};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
index c0bdd10358d7..240ed0b983a9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
@@ -22,22 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <subdev/timer.h> 25#include "nv04.h"
26
27#define NV04_PTIMER_INTR_0 0x009100
28#define NV04_PTIMER_INTR_EN_0 0x009140
29#define NV04_PTIMER_NUMERATOR 0x009200
30#define NV04_PTIMER_DENOMINATOR 0x009210
31#define NV04_PTIMER_TIME_0 0x009400
32#define NV04_PTIMER_TIME_1 0x009410
33#define NV04_PTIMER_ALARM_0 0x009420
34
35struct nv04_timer_priv {
36 struct nouveau_timer base;
37 struct list_head alarms;
38 spinlock_t lock;
39 u64 suspend_time;
40};
41 26
42static u64 27static u64
43nv04_timer_read(struct nouveau_timer *ptimer) 28nv04_timer_read(struct nouveau_timer *ptimer)
@@ -142,35 +127,14 @@ nv04_timer_intr(struct nouveau_subdev *subdev)
142 } 127 }
143} 128}
144 129
145static int 130int
146nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 131nv04_timer_fini(struct nouveau_object *object, bool suspend)
147 struct nouveau_oclass *oclass, void *data, u32 size,
148 struct nouveau_object **pobject)
149{
150 struct nv04_timer_priv *priv;
151 int ret;
152
153 ret = nouveau_timer_create(parent, engine, oclass, &priv);
154 *pobject = nv_object(priv);
155 if (ret)
156 return ret;
157
158 priv->base.base.intr = nv04_timer_intr;
159 priv->base.read = nv04_timer_read;
160 priv->base.alarm = nv04_timer_alarm;
161 priv->base.alarm_cancel = nv04_timer_alarm_cancel;
162 priv->suspend_time = 0;
163
164 INIT_LIST_HEAD(&priv->alarms);
165 spin_lock_init(&priv->lock);
166 return 0;
167}
168
169static void
170nv04_timer_dtor(struct nouveau_object *object)
171{ 132{
172 struct nv04_timer_priv *priv = (void *)object; 133 struct nv04_timer_priv *priv = (void *)object;
173 return nouveau_timer_destroy(&priv->base); 134 if (suspend)
135 priv->suspend_time = nv04_timer_read(&priv->base);
136 nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
137 return nouveau_timer_fini(&priv->base, suspend);
174} 138}
175 139
176static int 140static int
@@ -257,14 +221,35 @@ nv04_timer_init(struct nouveau_object *object)
257 return 0; 221 return 0;
258} 222}
259 223
260static int 224void
261nv04_timer_fini(struct nouveau_object *object, bool suspend) 225nv04_timer_dtor(struct nouveau_object *object)
262{ 226{
263 struct nv04_timer_priv *priv = (void *)object; 227 struct nv04_timer_priv *priv = (void *)object;
264 if (suspend) 228 return nouveau_timer_destroy(&priv->base);
265 priv->suspend_time = nv04_timer_read(&priv->base); 229}
266 nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); 230
267 return nouveau_timer_fini(&priv->base, suspend); 231int
232nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
233 struct nouveau_oclass *oclass, void *data, u32 size,
234 struct nouveau_object **pobject)
235{
236 struct nv04_timer_priv *priv;
237 int ret;
238
239 ret = nouveau_timer_create(parent, engine, oclass, &priv);
240 *pobject = nv_object(priv);
241 if (ret)
242 return ret;
243
244 priv->base.base.intr = nv04_timer_intr;
245 priv->base.read = nv04_timer_read;
246 priv->base.alarm = nv04_timer_alarm;
247 priv->base.alarm_cancel = nv04_timer_alarm_cancel;
248 priv->suspend_time = 0;
249
250 INIT_LIST_HEAD(&priv->alarms);
251 spin_lock_init(&priv->lock);
252 return 0;
268} 253}
269 254
270struct nouveau_oclass 255struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h
new file mode 100644
index 000000000000..4bc152697c37
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h
@@ -0,0 +1,27 @@
1#ifndef __NVKM_TIMER_NV04_H__
2#define __NVKM_TIMER_NV04_H__
3
4#include "priv.h"
5
6#define NV04_PTIMER_INTR_0 0x009100
7#define NV04_PTIMER_INTR_EN_0 0x009140
8#define NV04_PTIMER_NUMERATOR 0x009200
9#define NV04_PTIMER_DENOMINATOR 0x009210
10#define NV04_PTIMER_TIME_0 0x009400
11#define NV04_PTIMER_TIME_1 0x009410
12#define NV04_PTIMER_ALARM_0 0x009420
13
14struct nv04_timer_priv {
15 struct nouveau_timer base;
16 struct list_head alarms;
17 spinlock_t lock;
18 u64 suspend_time;
19};
20
21int nv04_timer_ctor(struct nouveau_object *, struct nouveau_object *,
22 struct nouveau_oclass *, void *, u32,
23 struct nouveau_object **);
24void nv04_timer_dtor(struct nouveau_object *);
25int nv04_timer_fini(struct nouveau_object *, bool);
26
27#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h
new file mode 100644
index 000000000000..799dae3f2300
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h
@@ -0,0 +1,6 @@
1#ifndef __NVKM_TIMER_PRIV_H__
2#define __NVKM_TIMER_PRIV_H__
3
4#include <subdev/timer.h>
5
6#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 0e3270c3ffd2..41be3424c906 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
239 struct drm_device *dev = crtc->dev; 239 struct drm_device *dev = crtc->dev;
240 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 240 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
241 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; 241 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
242 struct drm_framebuffer *fb = crtc->fb; 242 struct drm_framebuffer *fb = crtc->primary->fb;
243 243
244 /* Calculate our timings */ 244 /* Calculate our timings */
245 int horizDisplay = (mode->crtc_hdisplay >> 3) - 1; 245 int horizDisplay = (mode->crtc_hdisplay >> 3) - 1;
@@ -574,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
574 regp->CRTC[NV_CIO_CRE_86] = 0x1; 574 regp->CRTC[NV_CIO_CRE_86] = 0x1;
575 } 575 }
576 576
577 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8; 577 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
578 /* Enable slaved mode (called MODE_TV in nv4ref.h) */ 578 /* Enable slaved mode (called MODE_TV in nv4ref.h) */
579 if (lvds_output || tmds_output || tv_output) 579 if (lvds_output || tmds_output || tv_output)
580 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); 580 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
@@ -588,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
588 regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | 588 regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
589 NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL | 589 NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
590 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; 590 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
591 if (crtc->fb->depth == 16) 591 if (crtc->primary->fb->depth == 16)
592 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; 592 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
593 if (nv_device(drm->device)->chipset >= 0x11) 593 if (nv_device(drm->device)->chipset >= 0x11)
594 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; 594 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
@@ -609,7 +609,7 @@ static int
609nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) 609nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
610{ 610{
611 struct nv04_display *disp = nv04_display(crtc->dev); 611 struct nv04_display *disp = nv04_display(crtc->dev);
612 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); 612 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
613 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 613 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
614 int ret; 614 int ret;
615 615
@@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
808 * mark the lut values as dirty by setting depth==0, and it'll be 808 * mark the lut values as dirty by setting depth==0, and it'll be
809 * uploaded on the first mode_set_base() 809 * uploaded on the first mode_set_base()
810 */ 810 */
811 if (!nv_crtc->base.fb) { 811 if (!nv_crtc->base.primary->fb) {
812 nv_crtc->lut.depth = 0; 812 nv_crtc->lut.depth = 0;
813 return; 813 return;
814 } 814 }
@@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
832 NV_DEBUG(drm, "index %d\n", nv_crtc->index); 832 NV_DEBUG(drm, "index %d\n", nv_crtc->index);
833 833
834 /* no fb bound */ 834 /* no fb bound */
835 if (!atomic && !crtc->fb) { 835 if (!atomic && !crtc->primary->fb) {
836 NV_DEBUG(drm, "No FB bound\n"); 836 NV_DEBUG(drm, "No FB bound\n");
837 return 0; 837 return 0;
838 } 838 }
@@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
844 drm_fb = passed_fb; 844 drm_fb = passed_fb;
845 fb = nouveau_framebuffer(passed_fb); 845 fb = nouveau_framebuffer(passed_fb);
846 } else { 846 } else {
847 drm_fb = crtc->fb; 847 drm_fb = crtc->primary->fb;
848 fb = nouveau_framebuffer(crtc->fb); 848 fb = nouveau_framebuffer(crtc->primary->fb);
849 } 849 }
850 850
851 nv_crtc->fb.offset = fb->nvbo->bo.offset; 851 nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
857 857
858 /* Update the framebuffer format. */ 858 /* Update the framebuffer format. */
859 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3; 859 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
860 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8; 860 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
861 regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; 861 regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
862 if (crtc->fb->depth == 16) 862 if (crtc->primary->fb->depth == 16)
863 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; 863 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
864 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX); 864 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
865 NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, 865 NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
@@ -1048,7 +1048,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set)
1048 1048
1049 /* get a pm reference here */ 1049 /* get a pm reference here */
1050 ret = pm_runtime_get_sync(dev->dev); 1050 ret = pm_runtime_get_sync(dev->dev);
1051 if (ret < 0) 1051 if (ret < 0 && ret != -EACCES)
1052 return ret; 1052 return ret;
1053 1053
1054 ret = drm_crtc_helper_set_config(set); 1054 ret = drm_crtc_helper_set_config(set);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 7fdc51e2a571..a2d669b4acf2 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
415 /* Output property. */ 415 /* Output property. */
416 if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || 416 if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
417 (nv_connector->dithering_mode == DITHERING_MODE_AUTO && 417 (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
418 encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { 418 encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
419 if (nv_device(drm->device)->chipset == 0x11) 419 if (nv_device(drm->device)->chipset == 0x11)
420 regp->dither = savep->dither | 0x00010000; 420 regp->dither = savep->dither | 0x00010000;
421 else { 421 else {
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 900fae01793e..b13f441c6431 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -97,6 +97,7 @@ nouveau_abi16_swclass(struct nouveau_drm *drm)
97 case NV_C0: 97 case NV_C0:
98 case NV_D0: 98 case NV_D0:
99 case NV_E0: 99 case NV_E0:
100 case GM100:
100 return 0x906e; 101 return 0x906e;
101 } 102 }
102 103
@@ -139,7 +140,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
139 140
140 /* destroy channel object, all children will be killed too */ 141 /* destroy channel object, all children will be killed too */
141 if (chan->chan) { 142 if (chan->chan) {
142 abi16->handles &= ~(1 << (chan->chan->handle & 0xffff)); 143 abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));
143 nouveau_channel_del(&chan->chan); 144 nouveau_channel_del(&chan->chan);
144 } 145 }
145 146
@@ -179,12 +180,21 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
179 getparam->value = device->chipset; 180 getparam->value = device->chipset;
180 break; 181 break;
181 case NOUVEAU_GETPARAM_PCI_VENDOR: 182 case NOUVEAU_GETPARAM_PCI_VENDOR:
182 getparam->value = dev->pdev->vendor; 183 if (nv_device_is_pci(device))
184 getparam->value = dev->pdev->vendor;
185 else
186 getparam->value = 0;
183 break; 187 break;
184 case NOUVEAU_GETPARAM_PCI_DEVICE: 188 case NOUVEAU_GETPARAM_PCI_DEVICE:
185 getparam->value = dev->pdev->device; 189 if (nv_device_is_pci(device))
190 getparam->value = dev->pdev->device;
191 else
192 getparam->value = 0;
186 break; 193 break;
187 case NOUVEAU_GETPARAM_BUS_TYPE: 194 case NOUVEAU_GETPARAM_BUS_TYPE:
195 if (!nv_device_is_pci(device))
196 getparam->value = 3;
197 else
188 if (drm_pci_device_is_agp(dev)) 198 if (drm_pci_device_is_agp(dev))
189 getparam->value = 0; 199 getparam->value = 0;
190 else 200 else
@@ -270,8 +280,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
270 return nouveau_abi16_put(abi16, -EINVAL); 280 return nouveau_abi16_put(abi16, -EINVAL);
271 281
272 /* allocate "abi16 channel" data and make up a handle for it */ 282 /* allocate "abi16 channel" data and make up a handle for it */
273 init->channel = ffsll(~abi16->handles); 283 init->channel = __ffs64(~abi16->handles);
274 if (!init->channel--) 284 if (~abi16->handles == 0)
275 return nouveau_abi16_put(abi16, -ENOSPC); 285 return nouveau_abi16_put(abi16, -ENOSPC);
276 286
277 chan = kzalloc(sizeof(*chan), GFP_KERNEL); 287 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
@@ -280,7 +290,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
280 290
281 INIT_LIST_HEAD(&chan->notifiers); 291 INIT_LIST_HEAD(&chan->notifiers);
282 list_add(&chan->head, &abi16->channels); 292 list_add(&chan->head, &abi16->channels);
283 abi16->handles |= (1 << init->channel); 293 abi16->handles |= (1ULL << init->channel);
284 294
285 /* create channel object and initialise dma and fence management */ 295 /* create channel object and initialise dma and fence management */
286 ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | 296 ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN |
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c
index 2953c4e91e1a..51666daddb94 100644
--- a/drivers/gpu/drm/nouveau/nouveau_agp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_agp.c
@@ -75,7 +75,7 @@ nouveau_agp_enabled(struct nouveau_drm *drm)
75{ 75{
76 struct drm_device *dev = drm->dev; 76 struct drm_device *dev = drm->dev;
77 77
78 if (!drm_pci_device_is_agp(dev) || !dev->agp) 78 if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp)
79 return false; 79 return false;
80 80
81 if (drm->agp.stat == UNKNOWN) { 81 if (drm->agp.stat == UNKNOWN) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 4c3feaaa1037..8268a4ccac15 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -1474,9 +1474,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1474 case 0: 1474 case 0:
1475 entry->dpconf.link_bw = 162000; 1475 entry->dpconf.link_bw = 162000;
1476 break; 1476 break;
1477 default: 1477 case 1:
1478 entry->dpconf.link_bw = 270000; 1478 entry->dpconf.link_bw = 270000;
1479 break; 1479 break;
1480 default:
1481 entry->dpconf.link_bw = 540000;
1482 break;
1480 } 1483 }
1481 switch ((conf & 0x0f000000) >> 24) { 1484 switch ((conf & 0x0f000000) >> 24) {
1482 case 0xf: 1485 case 0xf:
@@ -2069,6 +2072,10 @@ nouveau_bios_init(struct drm_device *dev)
2069 struct nvbios *bios = &drm->vbios; 2072 struct nvbios *bios = &drm->vbios;
2070 int ret; 2073 int ret;
2071 2074
2075 /* only relevant for PCI devices */
2076 if (!dev->pdev)
2077 return 0;
2078
2072 if (!NVInitVBIOS(dev)) 2079 if (!NVInitVBIOS(dev))
2073 return -ENODEV; 2080 return -ENODEV;
2074 2081
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 4aed1714b9ab..b6dc85c614be 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1255,7 +1255,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
1255 /* fallthrough, tiled memory */ 1255 /* fallthrough, tiled memory */
1256 case TTM_PL_VRAM: 1256 case TTM_PL_VRAM:
1257 mem->bus.offset = mem->start << PAGE_SHIFT; 1257 mem->bus.offset = mem->start << PAGE_SHIFT;
1258 mem->bus.base = pci_resource_start(dev->pdev, 1); 1258 mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);
1259 mem->bus.is_iomem = true; 1259 mem->bus.is_iomem = true;
1260 if (nv_device(drm->device)->card_type >= NV_50) { 1260 if (nv_device(drm->device)->card_type >= NV_50) {
1261 struct nouveau_bar *bar = nouveau_bar(drm->device); 1261 struct nouveau_bar *bar = nouveau_bar(drm->device);
@@ -1293,7 +1293,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
1293 struct nouveau_drm *drm = nouveau_bdev(bo->bdev); 1293 struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1294 struct nouveau_bo *nvbo = nouveau_bo(bo); 1294 struct nouveau_bo *nvbo = nouveau_bo(bo);
1295 struct nouveau_device *device = nv_device(drm->device); 1295 struct nouveau_device *device = nv_device(drm->device);
1296 u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT; 1296 u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT;
1297 int ret; 1297 int ret;
1298 1298
1299 /* as long as the bo isn't in vram, and isn't tiled, we've got 1299 /* as long as the bo isn't in vram, and isn't tiled, we've got
@@ -1331,6 +1331,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1331{ 1331{
1332 struct ttm_dma_tt *ttm_dma = (void *)ttm; 1332 struct ttm_dma_tt *ttm_dma = (void *)ttm;
1333 struct nouveau_drm *drm; 1333 struct nouveau_drm *drm;
1334 struct nouveau_device *device;
1334 struct drm_device *dev; 1335 struct drm_device *dev;
1335 unsigned i; 1336 unsigned i;
1336 int r; 1337 int r;
@@ -1348,6 +1349,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1348 } 1349 }
1349 1350
1350 drm = nouveau_bdev(ttm->bdev); 1351 drm = nouveau_bdev(ttm->bdev);
1352 device = nv_device(drm->device);
1351 dev = drm->dev; 1353 dev = drm->dev;
1352 1354
1353#if __OS_HAS_AGP 1355#if __OS_HAS_AGP
@@ -1368,13 +1370,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1368 } 1370 }
1369 1371
1370 for (i = 0; i < ttm->num_pages; i++) { 1372 for (i = 0; i < ttm->num_pages; i++) {
1371 ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], 1373 ttm_dma->dma_address[i] = nv_device_map_page(device,
1372 0, PAGE_SIZE, 1374 ttm->pages[i]);
1373 PCI_DMA_BIDIRECTIONAL); 1375 if (!ttm_dma->dma_address[i]) {
1374 if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) {
1375 while (--i) { 1376 while (--i) {
1376 pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], 1377 nv_device_unmap_page(device,
1377 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 1378 ttm_dma->dma_address[i]);
1378 ttm_dma->dma_address[i] = 0; 1379 ttm_dma->dma_address[i] = 0;
1379 } 1380 }
1380 ttm_pool_unpopulate(ttm); 1381 ttm_pool_unpopulate(ttm);
@@ -1389,6 +1390,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1389{ 1390{
1390 struct ttm_dma_tt *ttm_dma = (void *)ttm; 1391 struct ttm_dma_tt *ttm_dma = (void *)ttm;
1391 struct nouveau_drm *drm; 1392 struct nouveau_drm *drm;
1393 struct nouveau_device *device;
1392 struct drm_device *dev; 1394 struct drm_device *dev;
1393 unsigned i; 1395 unsigned i;
1394 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); 1396 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1397,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1397 return; 1399 return;
1398 1400
1399 drm = nouveau_bdev(ttm->bdev); 1401 drm = nouveau_bdev(ttm->bdev);
1402 device = nv_device(drm->device);
1400 dev = drm->dev; 1403 dev = drm->dev;
1401 1404
1402#if __OS_HAS_AGP 1405#if __OS_HAS_AGP
@@ -1415,8 +1418,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1415 1418
1416 for (i = 0; i < ttm->num_pages; i++) { 1419 for (i = 0; i < ttm->num_pages; i++) {
1417 if (ttm_dma->dma_address[i]) { 1420 if (ttm_dma->dma_address[i]) {
1418 pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], 1421 nv_device_unmap_page(device, ttm_dma->dma_address[i]);
1419 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
1420 } 1422 }
1421 } 1423 }
1422 1424
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index cc5152be2cf1..ccb6b452d6d0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -154,7 +154,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
154 * nfi why this exists, it came from the -nv ddx. 154 * nfi why this exists, it came from the -nv ddx.
155 */ 155 */
156 args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR; 156 args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR;
157 args.start = pci_resource_start(device->pdev, 1); 157 args.start = nv_device_resource_start(device, 1);
158 args.limit = args.start + limit; 158 args.limit = args.start + limit;
159 } else { 159 } else {
160 args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR; 160 args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 1674882d60d5..d07ce028af51 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -255,7 +255,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
255 } 255 }
256 256
257 ret = pm_runtime_get_sync(connector->dev->dev); 257 ret = pm_runtime_get_sync(connector->dev->dev);
258 if (ret < 0) 258 if (ret < 0 && ret != -EACCES)
259 return conn_status; 259 return conn_status;
260 260
261 i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); 261 i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
@@ -960,7 +960,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
960 case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; 960 case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort;
961 case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; 961 case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP;
962 case DCB_CONNECTOR_HDMI_0 : 962 case DCB_CONNECTOR_HDMI_0 :
963 case DCB_CONNECTOR_HDMI_1 : return DRM_MODE_CONNECTOR_HDMIA; 963 case DCB_CONNECTOR_HDMI_1 :
964 case DCB_CONNECTOR_HDMI_C : return DRM_MODE_CONNECTOR_HDMIA;
964 default: 965 default:
965 break; 966 break;
966 } 967 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 24011596af43..3ff030dc1ee3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -105,7 +105,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
105 if (retry) ndelay(crtc->linedur_ns); 105 if (retry) ndelay(crtc->linedur_ns);
106 } while (retry--); 106 } while (retry--);
107 107
108 *hpos = calc(args.hblanks, args.hblanke, args.htotal, args.hline); 108 *hpos = args.hline;
109 *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline); 109 *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
110 if (stime) *stime = ns_to_ktime(args.time[0]); 110 if (stime) *stime = ns_to_ktime(args.time[0]);
111 if (etime) *etime = ns_to_ktime(args.time[1]); 111 if (etime) *etime = ns_to_ktime(args.time[1]);
@@ -419,6 +419,7 @@ int
419nouveau_display_create(struct drm_device *dev) 419nouveau_display_create(struct drm_device *dev)
420{ 420{
421 struct nouveau_drm *drm = nouveau_drm(dev); 421 struct nouveau_drm *drm = nouveau_drm(dev);
422 struct nouveau_device *device = nouveau_dev(dev);
422 struct nouveau_display *disp; 423 struct nouveau_display *disp;
423 int ret, gen; 424 int ret, gen;
424 425
@@ -459,7 +460,7 @@ nouveau_display_create(struct drm_device *dev)
459 } 460 }
460 461
461 dev->mode_config.funcs = &nouveau_mode_config_funcs; 462 dev->mode_config.funcs = &nouveau_mode_config_funcs;
462 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); 463 dev->mode_config.fb_base = nv_device_resource_start(device, 1);
463 464
464 dev->mode_config.min_width = 0; 465 dev->mode_config.min_width = 0;
465 dev->mode_config.min_height = 0; 466 dev->mode_config.min_height = 0;
@@ -488,6 +489,7 @@ nouveau_display_create(struct drm_device *dev)
488 489
489 if (drm->vbios.dcb.entries) { 490 if (drm->vbios.dcb.entries) {
490 static const u16 oclass[] = { 491 static const u16 oclass[] = {
492 GM107_DISP_CLASS,
491 NVF0_DISP_CLASS, 493 NVF0_DISP_CLASS,
492 NVE0_DISP_CLASS, 494 NVE0_DISP_CLASS,
493 NVD0_DISP_CLASS, 495 NVD0_DISP_CLASS,
@@ -569,7 +571,7 @@ nouveau_display_suspend(struct drm_device *dev)
569 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 571 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
570 struct nouveau_framebuffer *nouveau_fb; 572 struct nouveau_framebuffer *nouveau_fb;
571 573
572 nouveau_fb = nouveau_framebuffer(crtc->fb); 574 nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
573 if (!nouveau_fb || !nouveau_fb->nvbo) 575 if (!nouveau_fb || !nouveau_fb->nvbo)
574 continue; 576 continue;
575 577
@@ -596,7 +598,7 @@ nouveau_display_repin(struct drm_device *dev)
596 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 598 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
597 struct nouveau_framebuffer *nouveau_fb; 599 struct nouveau_framebuffer *nouveau_fb;
598 600
599 nouveau_fb = nouveau_framebuffer(crtc->fb); 601 nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
600 if (!nouveau_fb || !nouveau_fb->nvbo) 602 if (!nouveau_fb || !nouveau_fb->nvbo)
601 continue; 603 continue;
602 604
@@ -693,7 +695,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
693 const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; 695 const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
694 struct drm_device *dev = crtc->dev; 696 struct drm_device *dev = crtc->dev;
695 struct nouveau_drm *drm = nouveau_drm(dev); 697 struct nouveau_drm *drm = nouveau_drm(dev);
696 struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; 698 struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
697 struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; 699 struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
698 struct nouveau_page_flip_state *s; 700 struct nouveau_page_flip_state *s;
699 struct nouveau_channel *chan = drm->channel; 701 struct nouveau_channel *chan = drm->channel;
@@ -767,7 +769,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
767 goto fail_unreserve; 769 goto fail_unreserve;
768 770
769 /* Update the crtc struct and cleanup */ 771 /* Update the crtc struct and cleanup */
770 crtc->fb = fb; 772 crtc->primary->fb = fb;
771 773
772 nouveau_bo_fence(old_bo, fence); 774 nouveau_bo_fence(old_bo, fence);
773 ttm_bo_unreserve(&old_bo->bo); 775 ttm_bo_unreserve(&old_bo->bo);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 4ee702ac8907..ddd83756b9a2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -33,6 +33,7 @@
33#include <core/client.h> 33#include <core/client.h>
34#include <core/gpuobj.h> 34#include <core/gpuobj.h>
35#include <core/class.h> 35#include <core/class.h>
36#include <core/option.h>
36 37
37#include <engine/device.h> 38#include <engine/device.h>
38#include <engine/disp.h> 39#include <engine/disp.h>
@@ -81,7 +82,7 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400);
81static struct drm_driver driver; 82static struct drm_driver driver;
82 83
83static u64 84static u64
84nouveau_name(struct pci_dev *pdev) 85nouveau_pci_name(struct pci_dev *pdev)
85{ 86{
86 u64 name = (u64)pci_domain_nr(pdev->bus) << 32; 87 u64 name = (u64)pci_domain_nr(pdev->bus) << 32;
87 name |= pdev->bus->number << 16; 88 name |= pdev->bus->number << 16;
@@ -89,15 +90,30 @@ nouveau_name(struct pci_dev *pdev)
89 return name | PCI_FUNC(pdev->devfn); 90 return name | PCI_FUNC(pdev->devfn);
90} 91}
91 92
93static u64
94nouveau_platform_name(struct platform_device *platformdev)
95{
96 return platformdev->id;
97}
98
99static u64
100nouveau_name(struct drm_device *dev)
101{
102 if (dev->pdev)
103 return nouveau_pci_name(dev->pdev);
104 else
105 return nouveau_platform_name(dev->platformdev);
106}
107
92static int 108static int
93nouveau_cli_create(struct pci_dev *pdev, const char *name, 109nouveau_cli_create(u64 name, const char *sname,
94 int size, void **pcli) 110 int size, void **pcli)
95{ 111{
96 struct nouveau_cli *cli; 112 struct nouveau_cli *cli;
97 int ret; 113 int ret;
98 114
99 *pcli = NULL; 115 *pcli = NULL;
100 ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, 116 ret = nouveau_client_create_(sname, name, nouveau_config,
101 nouveau_debug, size, pcli); 117 nouveau_debug, size, pcli);
102 cli = *pcli; 118 cli = *pcli;
103 if (ret) { 119 if (ret) {
@@ -281,7 +297,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
281 remove_conflicting_framebuffers(aper, "nouveaufb", boot); 297 remove_conflicting_framebuffers(aper, "nouveaufb", boot);
282 kfree(aper); 298 kfree(aper);
283 299
284 ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), 300 ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
301 nouveau_pci_name(pdev), pci_name(pdev),
285 nouveau_config, nouveau_debug, &device); 302 nouveau_config, nouveau_debug, &device);
286 if (ret) 303 if (ret)
287 return ret; 304 return ret;
@@ -300,22 +317,27 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
300#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 317#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
301 318
302static void 319static void
303nouveau_get_hdmi_dev(struct drm_device *dev) 320nouveau_get_hdmi_dev(struct nouveau_drm *drm)
304{ 321{
305 struct nouveau_drm *drm = dev->dev_private; 322 struct pci_dev *pdev = drm->dev->pdev;
306 struct pci_dev *pdev = dev->pdev; 323
324 if (!pdev) {
325 DRM_INFO("not a PCI device; no HDMI\n");
326 drm->hdmi_device = NULL;
327 return;
328 }
307 329
308 /* subfunction one is a hdmi audio device? */ 330 /* subfunction one is a hdmi audio device? */
309 drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number, 331 drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
310 PCI_DEVFN(PCI_SLOT(pdev->devfn), 1)); 332 PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
311 333
312 if (!drm->hdmi_device) { 334 if (!drm->hdmi_device) {
313 DRM_INFO("hdmi device not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1); 335 NV_DEBUG(drm, "hdmi device not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);
314 return; 336 return;
315 } 337 }
316 338
317 if ((drm->hdmi_device->class >> 8) != PCI_CLASS_MULTIMEDIA_HD_AUDIO) { 339 if ((drm->hdmi_device->class >> 8) != PCI_CLASS_MULTIMEDIA_HD_AUDIO) {
318 DRM_INFO("possible hdmi device not audio %d\n", drm->hdmi_device->class); 340 NV_DEBUG(drm, "possible hdmi device not audio %d\n", drm->hdmi_device->class);
319 pci_dev_put(drm->hdmi_device); 341 pci_dev_put(drm->hdmi_device);
320 drm->hdmi_device = NULL; 342 drm->hdmi_device = NULL;
321 return; 343 return;
@@ -330,22 +352,24 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
330 struct nouveau_drm *drm; 352 struct nouveau_drm *drm;
331 int ret; 353 int ret;
332 354
333 ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); 355 ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
356 (void **)&drm);
334 if (ret) 357 if (ret)
335 return ret; 358 return ret;
336 359
337 dev->dev_private = drm; 360 dev->dev_private = drm;
338 drm->dev = dev; 361 drm->dev = dev;
362 nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");
339 363
340 INIT_LIST_HEAD(&drm->clients); 364 INIT_LIST_HEAD(&drm->clients);
341 spin_lock_init(&drm->tile.lock); 365 spin_lock_init(&drm->tile.lock);
342 366
343 nouveau_get_hdmi_dev(dev); 367 nouveau_get_hdmi_dev(drm);
344 368
345 /* make sure AGP controller is in a consistent state before we 369 /* make sure AGP controller is in a consistent state before we
346 * (possibly) execute vbios init tables (see nouveau_agp.h) 370 * (possibly) execute vbios init tables (see nouveau_agp.h)
347 */ 371 */
348 if (drm_pci_device_is_agp(dev) && dev->agp) { 372 if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
349 /* dummy device object, doesn't init anything, but allows 373 /* dummy device object, doesn't init anything, but allows
350 * agp code access to registers 374 * agp code access to registers
351 */ 375 */
@@ -486,13 +510,13 @@ nouveau_drm_remove(struct pci_dev *pdev)
486} 510}
487 511
488static int 512static int
489nouveau_do_suspend(struct drm_device *dev) 513nouveau_do_suspend(struct drm_device *dev, bool runtime)
490{ 514{
491 struct nouveau_drm *drm = nouveau_drm(dev); 515 struct nouveau_drm *drm = nouveau_drm(dev);
492 struct nouveau_cli *cli; 516 struct nouveau_cli *cli;
493 int ret; 517 int ret;
494 518
495 if (dev->mode_config.num_crtc) { 519 if (dev->mode_config.num_crtc && !runtime) {
496 NV_INFO(drm, "suspending display...\n"); 520 NV_INFO(drm, "suspending display...\n");
497 ret = nouveau_display_suspend(dev); 521 ret = nouveau_display_suspend(dev);
498 if (ret) 522 if (ret)
@@ -566,7 +590,7 @@ int nouveau_pmops_suspend(struct device *dev)
566 if (drm_dev->mode_config.num_crtc) 590 if (drm_dev->mode_config.num_crtc)
567 nouveau_fbcon_set_suspend(drm_dev, 1); 591 nouveau_fbcon_set_suspend(drm_dev, 1);
568 592
569 ret = nouveau_do_suspend(drm_dev); 593 ret = nouveau_do_suspend(drm_dev, false);
570 if (ret) 594 if (ret)
571 return ret; 595 return ret;
572 596
@@ -646,7 +670,7 @@ static int nouveau_pmops_freeze(struct device *dev)
646 if (drm_dev->mode_config.num_crtc) 670 if (drm_dev->mode_config.num_crtc)
647 nouveau_fbcon_set_suspend(drm_dev, 1); 671 nouveau_fbcon_set_suspend(drm_dev, 1);
648 672
649 ret = nouveau_do_suspend(drm_dev); 673 ret = nouveau_do_suspend(drm_dev, false);
650 return ret; 674 return ret;
651} 675}
652 676
@@ -671,7 +695,6 @@ static int nouveau_pmops_thaw(struct device *dev)
671static int 695static int
672nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) 696nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
673{ 697{
674 struct pci_dev *pdev = dev->pdev;
675 struct nouveau_drm *drm = nouveau_drm(dev); 698 struct nouveau_drm *drm = nouveau_drm(dev);
676 struct nouveau_cli *cli; 699 struct nouveau_cli *cli;
677 char name[32], tmpname[TASK_COMM_LEN]; 700 char name[32], tmpname[TASK_COMM_LEN];
@@ -679,13 +702,15 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
679 702
680 /* need to bring up power immediately if opening device */ 703 /* need to bring up power immediately if opening device */
681 ret = pm_runtime_get_sync(dev->dev); 704 ret = pm_runtime_get_sync(dev->dev);
682 if (ret < 0) 705 if (ret < 0 && ret != -EACCES)
683 return ret; 706 return ret;
684 707
685 get_task_comm(tmpname, current); 708 get_task_comm(tmpname, current);
686 snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); 709 snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
687 710
688 ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); 711 ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli),
712 (void **)&cli);
713
689 if (ret) 714 if (ret)
690 goto out_suspend; 715 goto out_suspend;
691 716
@@ -762,7 +787,7 @@ long nouveau_drm_ioctl(struct file *filp,
762 dev = file_priv->minor->dev; 787 dev = file_priv->minor->dev;
763 788
764 ret = pm_runtime_get_sync(dev->dev); 789 ret = pm_runtime_get_sync(dev->dev);
765 if (ret < 0) 790 if (ret < 0 && ret != -EACCES)
766 return ret; 791 return ret;
767 792
768 ret = drm_ioctl(filp, cmd, arg); 793 ret = drm_ioctl(filp, cmd, arg);
@@ -882,7 +907,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
882 drm_kms_helper_poll_disable(drm_dev); 907 drm_kms_helper_poll_disable(drm_dev);
883 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); 908 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
884 nouveau_switcheroo_optimus_dsm(); 909 nouveau_switcheroo_optimus_dsm();
885 ret = nouveau_do_suspend(drm_dev); 910 ret = nouveau_do_suspend(drm_dev, true);
886 pci_save_state(pdev); 911 pci_save_state(pdev);
887 pci_disable_device(pdev); 912 pci_disable_device(pdev);
888 pci_set_power_state(pdev, PCI_D3cold); 913 pci_set_power_state(pdev, PCI_D3cold);
@@ -908,8 +933,6 @@ static int nouveau_pmops_runtime_resume(struct device *dev)
908 pci_set_master(pdev); 933 pci_set_master(pdev);
909 934
910 ret = nouveau_do_resume(drm_dev); 935 ret = nouveau_do_resume(drm_dev);
911 if (drm_dev->mode_config.num_crtc)
912 nouveau_display_resume(drm_dev);
913 drm_kms_helper_poll_enable(drm_dev); 936 drm_kms_helper_poll_enable(drm_dev);
914 /* do magic */ 937 /* do magic */
915 nv_mask(device, 0x88488, (1 << 25), (1 << 25)); 938 nv_mask(device, 0x88488, (1 << 25), (1 << 25));
@@ -980,6 +1003,25 @@ nouveau_drm_pci_driver = {
980 .driver.pm = &nouveau_pm_ops, 1003 .driver.pm = &nouveau_pm_ops,
981}; 1004};
982 1005
1006int nouveau_drm_platform_probe(struct platform_device *pdev)
1007{
1008 struct nouveau_device *device;
1009 int ret;
1010
1011 ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
1012 nouveau_platform_name(pdev),
1013 dev_name(&pdev->dev), nouveau_config,
1014 nouveau_debug, &device);
1015
1016 ret = drm_platform_init(&driver, pdev);
1017 if (ret) {
1018 nouveau_object_ref(NULL, (struct nouveau_object **)&device);
1019 return ret;
1020 }
1021
1022 return ret;
1023}
1024
983static int __init 1025static int __init
984nouveau_drm_init(void) 1026nouveau_drm_init(void)
985{ 1027{
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 23ca7a517246..7efbafaf7c1d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -161,10 +161,7 @@ int nouveau_pmops_resume(struct device *);
161#define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args) 161#define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
162#define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args) 162#define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)
163#define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args) 163#define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args)
164#define NV_DEBUG(cli, fmt, args...) do { \ 164#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)
165 if (drm_debug & DRM_UT_DRIVER) \
166 nv_info((cli), fmt, ##args); \
167} while (0)
168 165
169extern int nouveau_modeset; 166extern int nouveau_modeset;
170 167
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 7903e0ed3c75..64a42cfd3717 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -528,10 +528,10 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
528 struct nouveau_drm *drm = nouveau_drm(dev); 528 struct nouveau_drm *drm = nouveau_drm(dev);
529 if (drm->fbcon) { 529 if (drm->fbcon) {
530 console_lock(); 530 console_lock();
531 if (state == 0) 531 if (state == 1)
532 nouveau_fbcon_save_disable_accel(dev); 532 nouveau_fbcon_save_disable_accel(dev);
533 fb_set_suspend(drm->fbcon->helper.fbdev, state); 533 fb_set_suspend(drm->fbcon->helper.fbdev, state);
534 if (state == 1) 534 if (state == 0)
535 nouveau_fbcon_restore_accel(dev); 535 nouveau_fbcon_restore_accel(dev);
536 console_unlock(); 536 console_unlock();
537 } 537 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
index 4aff04fa483c..19fd767bab10 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
@@ -383,8 +383,9 @@ nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
383 long value; 383 long value;
384 int ret; 384 int ret;
385 385
386 if (strict_strtol(buf, 10, &value) == -EINVAL) 386 ret = kstrtol(buf, 10, &value);
387 return -EINVAL; 387 if (ret)
388 return ret;
388 389
389 ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value); 390 ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value);
390 if (ret) 391 if (ret)
@@ -587,18 +588,14 @@ nouveau_hwmon_init(struct drm_device *dev)
587 588
588 /* set the default attributes */ 589 /* set the default attributes */
589 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup); 590 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
590 if (ret) { 591 if (ret)
591 if (ret) 592 goto error;
592 goto error;
593 }
594 593
595 /* if the card has a working thermal sensor */ 594 /* if the card has a working thermal sensor */
596 if (therm->temp_get(therm) >= 0) { 595 if (therm->temp_get(therm) >= 0) {
597 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup); 596 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
598 if (ret) { 597 if (ret)
599 if (ret) 598 goto error;
600 goto error;
601 }
602 } 599 }
603 600
604 /* if the card has a pwm fan */ 601 /* if the card has a pwm fan */
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
index 89201a17ce75..75dda2b07176 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
@@ -30,7 +30,7 @@
30static inline struct drm_device * 30static inline struct drm_device *
31drm_device(struct device *d) 31drm_device(struct device *d)
32{ 32{
33 return pci_get_drvdata(to_pci_dev(d)); 33 return dev_get_drvdata(d);
34} 34}
35 35
36#define snappendf(p,r,f,a...) do { \ 36#define snappendf(p,r,f,a...) do { \
@@ -132,9 +132,10 @@ nouveau_sysfs_fini(struct drm_device *dev)
132{ 132{
133 struct nouveau_sysfs *sysfs = nouveau_sysfs(dev); 133 struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
134 struct nouveau_drm *drm = nouveau_drm(dev); 134 struct nouveau_drm *drm = nouveau_drm(dev);
135 struct nouveau_device *device = nv_device(drm->device);
135 136
136 if (sysfs->ctrl) { 137 if (sysfs->ctrl) {
137 device_remove_file(&dev->pdev->dev, &dev_attr_pstate); 138 device_remove_file(nv_device_base(device), &dev_attr_pstate);
138 nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL); 139 nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL);
139 } 140 }
140 141
@@ -146,6 +147,7 @@ int
146nouveau_sysfs_init(struct drm_device *dev) 147nouveau_sysfs_init(struct drm_device *dev)
147{ 148{
148 struct nouveau_drm *drm = nouveau_drm(dev); 149 struct nouveau_drm *drm = nouveau_drm(dev);
150 struct nouveau_device *device = nv_device(drm->device);
149 struct nouveau_sysfs *sysfs; 151 struct nouveau_sysfs *sysfs;
150 int ret; 152 int ret;
151 153
@@ -156,7 +158,7 @@ nouveau_sysfs_init(struct drm_device *dev)
156 ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL, 158 ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL,
157 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl); 159 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl);
158 if (ret == 0) 160 if (ret == 0)
159 device_create_file(&dev->pdev->dev, &dev_attr_pstate); 161 device_create_file(nv_device_base(device), &dev_attr_pstate);
160 162
161 return 0; 163 return 0;
162} 164}
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index be3a3c9feafa..ab0228f640a5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -354,21 +354,26 @@ int
354nouveau_ttm_init(struct nouveau_drm *drm) 354nouveau_ttm_init(struct nouveau_drm *drm)
355{ 355{
356 struct drm_device *dev = drm->dev; 356 struct drm_device *dev = drm->dev;
357 struct nouveau_device *device = nv_device(drm->device);
357 u32 bits; 358 u32 bits;
358 int ret; 359 int ret;
359 360
360 bits = nouveau_vmmgr(drm->device)->dma_bits; 361 bits = nouveau_vmmgr(drm->device)->dma_bits;
361 if ( drm->agp.stat == ENABLED || 362 if (nv_device_is_pci(device)) {
362 !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) 363 if (drm->agp.stat == ENABLED ||
363 bits = 32; 364 !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
364 365 bits = 32;
365 ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); 366
366 if (ret) 367 ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
367 return ret; 368 if (ret)
368 369 return ret;
369 ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); 370
370 if (ret) 371 ret = pci_set_consistent_dma_mask(dev->pdev,
371 pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); 372 DMA_BIT_MASK(bits));
373 if (ret)
374 pci_set_consistent_dma_mask(dev->pdev,
375 DMA_BIT_MASK(32));
376 }
372 377
373 ret = nouveau_ttm_global_init(drm); 378 ret = nouveau_ttm_global_init(drm);
374 if (ret) 379 if (ret)
@@ -396,8 +401,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
396 return ret; 401 return ret;
397 } 402 }
398 403
399 drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1), 404 drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1),
400 pci_resource_len(dev->pdev, 1)); 405 nv_device_resource_len(device, 1));
401 406
402 /* GART init */ 407 /* GART init */
403 if (drm->agp.stat != ENABLED) { 408 if (drm->agp.stat != ENABLED) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 471347edc27e..fb84da3cb50d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -84,6 +84,11 @@ nouveau_vga_init(struct nouveau_drm *drm)
84{ 84{
85 struct drm_device *dev = drm->dev; 85 struct drm_device *dev = drm->dev;
86 bool runtime = false; 86 bool runtime = false;
87
88 /* only relevant for PCI devices */
89 if (!dev->pdev)
90 return;
91
87 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); 92 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
88 93
89 if (nouveau_runtime_pm == 1) 94 if (nouveau_runtime_pm == 1)
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 2dccafc6e9db..58af547b0b93 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
651 nv_connector = nouveau_crtc_connector_get(nv_crtc); 651 nv_connector = nouveau_crtc_connector_get(nv_crtc);
652 connector = &nv_connector->base; 652 connector = &nv_connector->base;
653 if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { 653 if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
654 if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) 654 if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
655 mode = DITHERING_MODE_DYNAMIC2X2; 655 mode = DITHERING_MODE_DYNAMIC2X2;
656 } else { 656 } else {
657 mode = nv_connector->dithering_mode; 657 mode = nv_connector->dithering_mode;
@@ -785,7 +785,8 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
785 785
786 if (update) { 786 if (update) {
787 nv50_display_flip_stop(crtc); 787 nv50_display_flip_stop(crtc);
788 nv50_display_flip_next(crtc, crtc->fb, NULL, 1); 788 nv50_display_flip_next(crtc, crtc->primary->fb,
789 NULL, 1);
789 } 790 }
790 } 791 }
791 792
@@ -1028,7 +1029,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
1028 } 1029 }
1029 1030
1030 nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true); 1031 nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
1031 nv50_display_flip_next(crtc, crtc->fb, NULL, 1); 1032 nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
1032} 1033}
1033 1034
1034static bool 1035static bool
@@ -1042,7 +1043,7 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
1042static int 1043static int
1043nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) 1044nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
1044{ 1045{
1045 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); 1046 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
1046 struct nv50_head *head = nv50_head(crtc); 1047 struct nv50_head *head = nv50_head(crtc);
1047 int ret; 1048 int ret;
1048 1049
@@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
1139 nv50_crtc_set_dither(nv_crtc, false); 1140 nv50_crtc_set_dither(nv_crtc, false);
1140 nv50_crtc_set_scale(nv_crtc, false); 1141 nv50_crtc_set_scale(nv_crtc, false);
1141 nv50_crtc_set_color_vibrance(nv_crtc, false); 1142 nv50_crtc_set_color_vibrance(nv_crtc, false);
1142 nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false); 1143 nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
1143 return 0; 1144 return 0;
1144} 1145}
1145 1146
@@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
1151 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 1152 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
1152 int ret; 1153 int ret;
1153 1154
1154 if (!crtc->fb) { 1155 if (!crtc->primary->fb) {
1155 NV_DEBUG(drm, "No FB bound\n"); 1156 NV_DEBUG(drm, "No FB bound\n");
1156 return 0; 1157 return 0;
1157 } 1158 }
@@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
1161 return ret; 1162 return ret;
1162 1163
1163 nv50_display_flip_stop(crtc); 1164 nv50_display_flip_stop(crtc);
1164 nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true); 1165 nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
1165 nv50_display_flip_next(crtc, crtc->fb, NULL, 1); 1166 nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
1166 return 0; 1167 return 0;
1167} 1168}
1168 1169
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 4313bb0a49a6..355157e4f78d 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -245,7 +245,7 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc,
245 copy_timings_drm_to_omap(&omap_crtc->timings, mode); 245 copy_timings_drm_to_omap(&omap_crtc->timings, mode);
246 omap_crtc->full_update = true; 246 omap_crtc->full_update = true;
247 247
248 return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, 248 return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
249 0, 0, mode->hdisplay, mode->vdisplay, 249 0, 0, mode->hdisplay, mode->vdisplay,
250 x << 16, y << 16, 250 x << 16, y << 16,
251 mode->hdisplay << 16, mode->vdisplay << 16, 251 mode->hdisplay << 16, mode->vdisplay << 16,
@@ -273,7 +273,7 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
273 struct drm_plane *plane = omap_crtc->plane; 273 struct drm_plane *plane = omap_crtc->plane;
274 struct drm_display_mode *mode = &crtc->mode; 274 struct drm_display_mode *mode = &crtc->mode;
275 275
276 return omap_plane_mode_set(plane, crtc, crtc->fb, 276 return omap_plane_mode_set(plane, crtc, crtc->primary->fb,
277 0, 0, mode->hdisplay, mode->vdisplay, 277 0, 0, mode->hdisplay, mode->vdisplay,
278 x << 16, y << 16, 278 x << 16, y << 16,
279 mode->hdisplay << 16, mode->vdisplay << 16, 279 mode->hdisplay << 16, mode->vdisplay << 16,
@@ -308,14 +308,14 @@ static void page_flip_worker(struct work_struct *work)
308 struct drm_gem_object *bo; 308 struct drm_gem_object *bo;
309 309
310 mutex_lock(&crtc->mutex); 310 mutex_lock(&crtc->mutex);
311 omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, 311 omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
312 0, 0, mode->hdisplay, mode->vdisplay, 312 0, 0, mode->hdisplay, mode->vdisplay,
313 crtc->x << 16, crtc->y << 16, 313 crtc->x << 16, crtc->y << 16,
314 mode->hdisplay << 16, mode->vdisplay << 16, 314 mode->hdisplay << 16, mode->vdisplay << 16,
315 vblank_cb, crtc); 315 vblank_cb, crtc);
316 mutex_unlock(&crtc->mutex); 316 mutex_unlock(&crtc->mutex);
317 317
318 bo = omap_framebuffer_bo(crtc->fb, 0); 318 bo = omap_framebuffer_bo(crtc->primary->fb, 0);
319 drm_gem_object_unreference_unlocked(bo); 319 drm_gem_object_unreference_unlocked(bo);
320} 320}
321 321
@@ -336,9 +336,10 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
336{ 336{
337 struct drm_device *dev = crtc->dev; 337 struct drm_device *dev = crtc->dev;
338 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 338 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
339 struct drm_plane *primary = crtc->primary;
339 struct drm_gem_object *bo; 340 struct drm_gem_object *bo;
340 341
341 DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1, 342 DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
342 fb->base.id, event); 343 fb->base.id, event);
343 344
344 if (omap_crtc->old_fb) { 345 if (omap_crtc->old_fb) {
@@ -347,7 +348,7 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
347 } 348 }
348 349
349 omap_crtc->event = event; 350 omap_crtc->event = event;
350 crtc->fb = fb; 351 primary->fb = fb;
351 352
352 /* 353 /*
353 * Hold a reference temporarily until the crtc is updated 354 * Hold a reference temporarily until the crtc is updated
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index f466c4aaee94..d2b8c49bfb4a 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -306,13 +306,14 @@ struct drm_connector *omap_framebuffer_get_next_connector(
306 struct drm_connector *connector = from; 306 struct drm_connector *connector = from;
307 307
308 if (!from) 308 if (!from)
309 return list_first_entry(connector_list, typeof(*from), head); 309 return list_first_entry_or_null(connector_list, typeof(*from),
310 head);
310 311
311 list_for_each_entry_from(connector, connector_list, head) { 312 list_for_each_entry_from(connector, connector_list, head) {
312 if (connector != from) { 313 if (connector != from) {
313 struct drm_encoder *encoder = connector->encoder; 314 struct drm_encoder *encoder = connector->encoder;
314 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; 315 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
315 if (crtc && crtc->fb == fb) 316 if (crtc && crtc->primary->fb == fb)
316 return connector; 317 return connector;
317 318
318 } 319 }
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 3e0f13d1bc84..4ec874da5668 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -16,4 +16,18 @@ config DRM_PANEL_SIMPLE
16 that it can be automatically turned off when the panel goes into a 16 that it can be automatically turned off when the panel goes into a
17 low power state. 17 low power state.
18 18
19config DRM_PANEL_LD9040
20 tristate "LD9040 RGB/SPI panel"
21 depends on DRM && DRM_PANEL
22 depends on OF
23 select SPI
24 select VIDEOMODE_HELPERS
25
26config DRM_PANEL_S6E8AA0
27 tristate "S6E8AA0 DSI video mode panel"
28 depends on DRM && DRM_PANEL
29 depends on OF
30 select DRM_MIPI_DSI
31 select VIDEOMODE_HELPERS
32
19endmenu 33endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index af9dfa235b94..8b929212fad7 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1 +1,3 @@
1obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o 1obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
2obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
3obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
diff --git a/drivers/gpu/drm/panel/panel-ld9040.c b/drivers/gpu/drm/panel/panel-ld9040.c
new file mode 100644
index 000000000000..1f1f8371a199
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ld9040.c
@@ -0,0 +1,376 @@
1/*
2 * ld9040 AMOLED LCD drm_panel driver.
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 * Derived from drivers/video/backlight/ld9040.c
6 *
7 * Andrzej Hajda <a.hajda@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <drm/drmP.h>
15#include <drm/drm_panel.h>
16
17#include <linux/gpio/consumer.h>
18#include <linux/regulator/consumer.h>
19#include <linux/spi/spi.h>
20
21#include <video/mipi_display.h>
22#include <video/of_videomode.h>
23#include <video/videomode.h>
24
25/* Manufacturer Command Set */
26#define MCS_MANPWR 0xb0
27#define MCS_ELVSS_ON 0xb1
28#define MCS_USER_SETTING 0xf0
29#define MCS_DISPCTL 0xf2
30#define MCS_GTCON 0xf7
31#define MCS_PANEL_CONDITION 0xf8
32#define MCS_GAMMA_SET1 0xf9
33#define MCS_GAMMA_CTRL 0xfb
34
35/* array of gamma tables for gamma value 2.2 */
36static u8 const ld9040_gammas[25][22] = {
37 { 0xf9, 0x00, 0x13, 0xb2, 0xba, 0xd2, 0x00, 0x30, 0x00, 0xaf, 0xc0,
38 0xb8, 0xcd, 0x00, 0x3d, 0x00, 0xa8, 0xb8, 0xb7, 0xcd, 0x00, 0x44 },
39 { 0xf9, 0x00, 0x13, 0xb9, 0xb9, 0xd0, 0x00, 0x3c, 0x00, 0xaf, 0xbf,
40 0xb6, 0xcb, 0x00, 0x4b, 0x00, 0xa8, 0xb9, 0xb5, 0xcc, 0x00, 0x52 },
41 { 0xf9, 0x00, 0x13, 0xba, 0xb9, 0xcd, 0x00, 0x41, 0x00, 0xb0, 0xbe,
42 0xb5, 0xc9, 0x00, 0x51, 0x00, 0xa9, 0xb9, 0xb5, 0xca, 0x00, 0x57 },
43 { 0xf9, 0x00, 0x13, 0xb9, 0xb8, 0xcd, 0x00, 0x46, 0x00, 0xb1, 0xbc,
44 0xb5, 0xc8, 0x00, 0x56, 0x00, 0xaa, 0xb8, 0xb4, 0xc9, 0x00, 0x5d },
45 { 0xf9, 0x00, 0x13, 0xba, 0xb8, 0xcb, 0x00, 0x4b, 0x00, 0xb3, 0xbc,
46 0xb4, 0xc7, 0x00, 0x5c, 0x00, 0xac, 0xb8, 0xb4, 0xc8, 0x00, 0x62 },
47 { 0xf9, 0x00, 0x13, 0xbb, 0xb7, 0xca, 0x00, 0x4f, 0x00, 0xb4, 0xbb,
48 0xb3, 0xc7, 0x00, 0x60, 0x00, 0xad, 0xb8, 0xb4, 0xc7, 0x00, 0x67 },
49 { 0xf9, 0x00, 0x47, 0xba, 0xb6, 0xca, 0x00, 0x53, 0x00, 0xb5, 0xbb,
50 0xb3, 0xc6, 0x00, 0x65, 0x00, 0xae, 0xb8, 0xb3, 0xc7, 0x00, 0x6c },
51 { 0xf9, 0x00, 0x71, 0xbb, 0xb5, 0xc8, 0x00, 0x57, 0x00, 0xb5, 0xbb,
52 0xb0, 0xc5, 0x00, 0x6a, 0x00, 0xae, 0xb9, 0xb1, 0xc6, 0x00, 0x70 },
53 { 0xf9, 0x00, 0x7b, 0xbb, 0xb4, 0xc8, 0x00, 0x5b, 0x00, 0xb5, 0xba,
54 0xb1, 0xc4, 0x00, 0x6e, 0x00, 0xae, 0xb9, 0xb0, 0xc5, 0x00, 0x75 },
55 { 0xf9, 0x00, 0x82, 0xba, 0xb4, 0xc7, 0x00, 0x5f, 0x00, 0xb5, 0xba,
56 0xb0, 0xc3, 0x00, 0x72, 0x00, 0xae, 0xb8, 0xb0, 0xc3, 0x00, 0x7a },
57 { 0xf9, 0x00, 0x89, 0xba, 0xb3, 0xc8, 0x00, 0x62, 0x00, 0xb6, 0xba,
58 0xaf, 0xc3, 0x00, 0x76, 0x00, 0xaf, 0xb7, 0xae, 0xc4, 0x00, 0x7e },
59 { 0xf9, 0x00, 0x8b, 0xb9, 0xb3, 0xc7, 0x00, 0x65, 0x00, 0xb7, 0xb8,
60 0xaf, 0xc3, 0x00, 0x7a, 0x00, 0x80, 0xb6, 0xae, 0xc4, 0x00, 0x81 },
61 { 0xf9, 0x00, 0x93, 0xba, 0xb3, 0xc5, 0x00, 0x69, 0x00, 0xb8, 0xb9,
62 0xae, 0xc1, 0x00, 0x7f, 0x00, 0xb0, 0xb6, 0xae, 0xc3, 0x00, 0x85 },
63 { 0xf9, 0x00, 0x97, 0xba, 0xb2, 0xc5, 0x00, 0x6c, 0x00, 0xb8, 0xb8,
64 0xae, 0xc1, 0x00, 0x82, 0x00, 0xb0, 0xb6, 0xae, 0xc2, 0x00, 0x89 },
65 { 0xf9, 0x00, 0x9a, 0xba, 0xb1, 0xc4, 0x00, 0x6f, 0x00, 0xb8, 0xb8,
66 0xad, 0xc0, 0x00, 0x86, 0x00, 0xb0, 0xb7, 0xad, 0xc0, 0x00, 0x8d },
67 { 0xf9, 0x00, 0x9c, 0xb9, 0xb0, 0xc4, 0x00, 0x72, 0x00, 0xb8, 0xb8,
68 0xac, 0xbf, 0x00, 0x8a, 0x00, 0xb0, 0xb6, 0xac, 0xc0, 0x00, 0x91 },
69 { 0xf9, 0x00, 0x9e, 0xba, 0xb0, 0xc2, 0x00, 0x75, 0x00, 0xb9, 0xb8,
70 0xab, 0xbe, 0x00, 0x8e, 0x00, 0xb0, 0xb6, 0xac, 0xbf, 0x00, 0x94 },
71 { 0xf9, 0x00, 0xa0, 0xb9, 0xaf, 0xc3, 0x00, 0x77, 0x00, 0xb9, 0xb7,
72 0xab, 0xbe, 0x00, 0x90, 0x00, 0xb0, 0xb6, 0xab, 0xbf, 0x00, 0x97 },
73 { 0xf9, 0x00, 0xa2, 0xb9, 0xaf, 0xc2, 0x00, 0x7a, 0x00, 0xb9, 0xb7,
74 0xaa, 0xbd, 0x00, 0x94, 0x00, 0xb0, 0xb5, 0xab, 0xbf, 0x00, 0x9a },
75 { 0xf9, 0x00, 0xa4, 0xb9, 0xaf, 0xc1, 0x00, 0x7d, 0x00, 0xb9, 0xb6,
76 0xaa, 0xbb, 0x00, 0x97, 0x00, 0xb1, 0xb5, 0xaa, 0xbf, 0x00, 0x9d },
77 { 0xf9, 0x00, 0xa4, 0xb8, 0xb0, 0xbf, 0x00, 0x80, 0x00, 0xb8, 0xb6,
78 0xaa, 0xbc, 0x00, 0x9a, 0x00, 0xb0, 0xb5, 0xab, 0xbd, 0x00, 0xa0 },
79 { 0xf9, 0x00, 0xa8, 0xb8, 0xae, 0xbe, 0x00, 0x84, 0x00, 0xb9, 0xb7,
80 0xa8, 0xbc, 0x00, 0x9d, 0x00, 0xb2, 0xb5, 0xaa, 0xbc, 0x00, 0xa4 },
81 { 0xf9, 0x00, 0xa9, 0xb6, 0xad, 0xbf, 0x00, 0x86, 0x00, 0xb8, 0xb5,
82 0xa8, 0xbc, 0x00, 0xa0, 0x00, 0xb3, 0xb3, 0xa9, 0xbc, 0x00, 0xa7 },
83 { 0xf9, 0x00, 0xa9, 0xb7, 0xae, 0xbd, 0x00, 0x89, 0x00, 0xb7, 0xb6,
84 0xa8, 0xba, 0x00, 0xa4, 0x00, 0xb1, 0xb4, 0xaa, 0xbb, 0x00, 0xaa },
85 { 0xf9, 0x00, 0xa7, 0xb4, 0xae, 0xbf, 0x00, 0x91, 0x00, 0xb2, 0xb4,
86 0xaa, 0xbb, 0x00, 0xac, 0x00, 0xb3, 0xb1, 0xaa, 0xbc, 0x00, 0xb3 },
87};
88
89struct ld9040 {
90 struct device *dev;
91 struct drm_panel panel;
92
93 struct regulator_bulk_data supplies[2];
94 struct gpio_desc *reset_gpio;
95 u32 power_on_delay;
96 u32 reset_delay;
97 struct videomode vm;
98 u32 width_mm;
99 u32 height_mm;
100
101 int brightness;
102
103 /* This field is tested by functions directly accessing bus before
104 * transfer, transfer is skipped if it is set. In case of transfer
105 * failure or unexpected response the field is set to error value.
106 * Such construct allows to eliminate many checks in higher level
107 * functions.
108 */
109 int error;
110};
111
112#define panel_to_ld9040(p) container_of(p, struct ld9040, panel)
113
114static int ld9040_clear_error(struct ld9040 *ctx)
115{
116 int ret = ctx->error;
117
118 ctx->error = 0;
119 return ret;
120}
121
122static int ld9040_spi_write_word(struct ld9040 *ctx, u16 data)
123{
124 struct spi_device *spi = to_spi_device(ctx->dev);
125 struct spi_transfer xfer = {
126 .len = 2,
127 .tx_buf = &data,
128 };
129 struct spi_message msg;
130
131 spi_message_init(&msg);
132 spi_message_add_tail(&xfer, &msg);
133
134 return spi_sync(spi, &msg);
135}
136
137static void ld9040_dcs_write(struct ld9040 *ctx, const u8 *data, size_t len)
138{
139 int ret = 0;
140
141 if (ctx->error < 0 || len == 0)
142 return;
143
144 dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", len, data);
145 ret = ld9040_spi_write_word(ctx, *data);
146
147 while (!ret && --len) {
148 ++data;
149 ret = ld9040_spi_write_word(ctx, *data | 0x100);
150 }
151
152 if (ret) {
153 dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len,
154 data);
155 ctx->error = ret;
156 }
157
158 usleep_range(300, 310);
159}
160
161#define ld9040_dcs_write_seq_static(ctx, seq...) \
162({\
163 static const u8 d[] = { seq };\
164 ld9040_dcs_write(ctx, d, ARRAY_SIZE(d));\
165})
166
167static void ld9040_brightness_set(struct ld9040 *ctx)
168{
169 ld9040_dcs_write(ctx, ld9040_gammas[ctx->brightness],
170 ARRAY_SIZE(ld9040_gammas[ctx->brightness]));
171
172 ld9040_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL, 0x02, 0x5a);
173}
174
175static void ld9040_init(struct ld9040 *ctx)
176{
177 ld9040_dcs_write_seq_static(ctx, MCS_USER_SETTING, 0x5a, 0x5a);
178 ld9040_dcs_write_seq_static(ctx, MCS_PANEL_CONDITION,
179 0x05, 0x65, 0x96, 0x71, 0x7d, 0x19, 0x3b, 0x0d,
180 0x19, 0x7e, 0x0d, 0xe2, 0x00, 0x00, 0x7e, 0x7d,
181 0x07, 0x07, 0x20, 0x20, 0x20, 0x02, 0x02);
182 ld9040_dcs_write_seq_static(ctx, MCS_DISPCTL,
183 0x02, 0x08, 0x08, 0x10, 0x10);
184 ld9040_dcs_write_seq_static(ctx, MCS_MANPWR, 0x04);
185 ld9040_dcs_write_seq_static(ctx, MCS_ELVSS_ON, 0x0d, 0x00, 0x16);
186 ld9040_dcs_write_seq_static(ctx, MCS_GTCON, 0x09, 0x00, 0x00);
187 ld9040_brightness_set(ctx);
188 ld9040_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
189 ld9040_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
190}
191
192static int ld9040_power_on(struct ld9040 *ctx)
193{
194 int ret;
195
196 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
197 if (ret < 0)
198 return ret;
199
200 msleep(ctx->power_on_delay);
201 gpiod_set_value(ctx->reset_gpio, 0);
202 msleep(ctx->reset_delay);
203 gpiod_set_value(ctx->reset_gpio, 1);
204 msleep(ctx->reset_delay);
205
206 return 0;
207}
208
209static int ld9040_power_off(struct ld9040 *ctx)
210{
211 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
212}
213
214static int ld9040_disable(struct drm_panel *panel)
215{
216 struct ld9040 *ctx = panel_to_ld9040(panel);
217
218 msleep(120);
219 ld9040_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
220 ld9040_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
221 msleep(40);
222
223 ld9040_clear_error(ctx);
224
225 return ld9040_power_off(ctx);
226}
227
228static int ld9040_enable(struct drm_panel *panel)
229{
230 struct ld9040 *ctx = panel_to_ld9040(panel);
231 int ret;
232
233 ret = ld9040_power_on(ctx);
234 if (ret < 0)
235 return ret;
236
237 ld9040_init(ctx);
238
239 ret = ld9040_clear_error(ctx);
240
241 if (ret < 0)
242 ld9040_disable(panel);
243
244 return ret;
245}
246
247static int ld9040_get_modes(struct drm_panel *panel)
248{
249 struct drm_connector *connector = panel->connector;
250 struct ld9040 *ctx = panel_to_ld9040(panel);
251 struct drm_display_mode *mode;
252
253 mode = drm_mode_create(connector->dev);
254 if (!mode) {
255 DRM_ERROR("failed to create a new display mode\n");
256 return 0;
257 }
258
259 drm_display_mode_from_videomode(&ctx->vm, mode);
260 mode->width_mm = ctx->width_mm;
261 mode->height_mm = ctx->height_mm;
262 connector->display_info.width_mm = mode->width_mm;
263 connector->display_info.height_mm = mode->height_mm;
264
265 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
266 drm_mode_probed_add(connector, mode);
267
268 return 1;
269}
270
271static const struct drm_panel_funcs ld9040_drm_funcs = {
272 .disable = ld9040_disable,
273 .enable = ld9040_enable,
274 .get_modes = ld9040_get_modes,
275};
276
277static int ld9040_parse_dt(struct ld9040 *ctx)
278{
279 struct device *dev = ctx->dev;
280 struct device_node *np = dev->of_node;
281 int ret;
282
283 ret = of_get_videomode(np, &ctx->vm, 0);
284 if (ret < 0)
285 return ret;
286
287 of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
288 of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
289 of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
290 of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
291
292 return 0;
293}
294
295static int ld9040_probe(struct spi_device *spi)
296{
297 struct device *dev = &spi->dev;
298 struct ld9040 *ctx;
299 int ret;
300
301 ctx = devm_kzalloc(dev, sizeof(struct ld9040), GFP_KERNEL);
302 if (!ctx)
303 return -ENOMEM;
304
305 spi_set_drvdata(spi, ctx);
306
307 ctx->dev = dev;
308 ctx->brightness = ARRAY_SIZE(ld9040_gammas) - 1;
309
310 ret = ld9040_parse_dt(ctx);
311 if (ret < 0)
312 return ret;
313
314 ctx->supplies[0].supply = "vdd3";
315 ctx->supplies[1].supply = "vci";
316 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
317 ctx->supplies);
318 if (ret < 0)
319 return ret;
320
321 ctx->reset_gpio = devm_gpiod_get(dev, "reset");
322 if (IS_ERR(ctx->reset_gpio)) {
323 dev_err(dev, "cannot get reset-gpios %ld\n",
324 PTR_ERR(ctx->reset_gpio));
325 return PTR_ERR(ctx->reset_gpio);
326 }
327 ret = gpiod_direction_output(ctx->reset_gpio, 1);
328 if (ret < 0) {
329 dev_err(dev, "cannot configure reset-gpios %d\n", ret);
330 return ret;
331 }
332
333 spi->bits_per_word = 9;
334 ret = spi_setup(spi);
335 if (ret < 0) {
336 dev_err(dev, "spi setup failed.\n");
337 return ret;
338 }
339
340 drm_panel_init(&ctx->panel);
341 ctx->panel.dev = dev;
342 ctx->panel.funcs = &ld9040_drm_funcs;
343
344 return drm_panel_add(&ctx->panel);
345}
346
347static int ld9040_remove(struct spi_device *spi)
348{
349 struct ld9040 *ctx = spi_get_drvdata(spi);
350
351 ld9040_power_off(ctx);
352 drm_panel_remove(&ctx->panel);
353
354 return 0;
355}
356
357static struct of_device_id ld9040_of_match[] = {
358 { .compatible = "samsung,ld9040" },
359 { }
360};
361MODULE_DEVICE_TABLE(of, ld9040_of_match);
362
363static struct spi_driver ld9040_driver = {
364 .probe = ld9040_probe,
365 .remove = ld9040_remove,
366 .driver = {
367 .name = "ld9040",
368 .owner = THIS_MODULE,
369 .of_match_table = ld9040_of_match,
370 },
371};
372module_spi_driver(ld9040_driver);
373
374MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
375MODULE_DESCRIPTION("ld9040 LCD Driver");
376MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-s6e8aa0.c b/drivers/gpu/drm/panel/panel-s6e8aa0.c
new file mode 100644
index 000000000000..35941d2412b8
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-s6e8aa0.c
@@ -0,0 +1,1069 @@
1/*
2 * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver.
3 *
4 * Copyright (c) 2013 Samsung Electronics Co., Ltd
5 *
6 * Inki Dae, <inki.dae@samsung.com>
7 * Donghwa Lee, <dh09.lee@samsung.com>
8 * Joongmock Shin <jmock.shin@samsung.com>
9 * Eunchul Kim <chulspro.kim@samsung.com>
10 * Tomasz Figa <t.figa@samsung.com>
11 * Andrzej Hajda <a.hajda@samsung.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16*/
17
18#include <drm/drmP.h>
19#include <drm/drm_mipi_dsi.h>
20#include <drm/drm_panel.h>
21
22#include <linux/gpio/consumer.h>
23#include <linux/regulator/consumer.h>
24
25#include <video/mipi_display.h>
26#include <video/of_videomode.h>
27#include <video/videomode.h>
28
29#define LDI_MTP_LENGTH 24
30#define GAMMA_LEVEL_NUM 25
31#define GAMMA_TABLE_LEN 26
32
33#define PANELCTL_SS_MASK (1 << 5)
34#define PANELCTL_SS_1_800 (0 << 5)
35#define PANELCTL_SS_800_1 (1 << 5)
36#define PANELCTL_GTCON_MASK (7 << 2)
37#define PANELCTL_GTCON_110 (6 << 2)
38#define PANELCTL_GTCON_111 (7 << 2)
39
40#define PANELCTL_CLK1_CON_MASK (7 << 3)
41#define PANELCTL_CLK1_000 (0 << 3)
42#define PANELCTL_CLK1_001 (1 << 3)
43#define PANELCTL_CLK2_CON_MASK (7 << 0)
44#define PANELCTL_CLK2_000 (0 << 0)
45#define PANELCTL_CLK2_001 (1 << 0)
46
47#define PANELCTL_INT1_CON_MASK (7 << 3)
48#define PANELCTL_INT1_000 (0 << 3)
49#define PANELCTL_INT1_001 (1 << 3)
50#define PANELCTL_INT2_CON_MASK (7 << 0)
51#define PANELCTL_INT2_000 (0 << 0)
52#define PANELCTL_INT2_001 (1 << 0)
53
54#define PANELCTL_BICTL_CON_MASK (7 << 3)
55#define PANELCTL_BICTL_000 (0 << 3)
56#define PANELCTL_BICTL_001 (1 << 3)
57#define PANELCTL_BICTLB_CON_MASK (7 << 0)
58#define PANELCTL_BICTLB_000 (0 << 0)
59#define PANELCTL_BICTLB_001 (1 << 0)
60
61#define PANELCTL_EM_CLK1_CON_MASK (7 << 3)
62#define PANELCTL_EM_CLK1_110 (6 << 3)
63#define PANELCTL_EM_CLK1_111 (7 << 3)
64#define PANELCTL_EM_CLK1B_CON_MASK (7 << 0)
65#define PANELCTL_EM_CLK1B_110 (6 << 0)
66#define PANELCTL_EM_CLK1B_111 (7 << 0)
67
68#define PANELCTL_EM_CLK2_CON_MASK (7 << 3)
69#define PANELCTL_EM_CLK2_110 (6 << 3)
70#define PANELCTL_EM_CLK2_111 (7 << 3)
71#define PANELCTL_EM_CLK2B_CON_MASK (7 << 0)
72#define PANELCTL_EM_CLK2B_110 (6 << 0)
73#define PANELCTL_EM_CLK2B_111 (7 << 0)
74
75#define PANELCTL_EM_INT1_CON_MASK (7 << 3)
76#define PANELCTL_EM_INT1_000 (0 << 3)
77#define PANELCTL_EM_INT1_001 (1 << 3)
78#define PANELCTL_EM_INT2_CON_MASK (7 << 0)
79#define PANELCTL_EM_INT2_000 (0 << 0)
80#define PANELCTL_EM_INT2_001 (1 << 0)
81
82#define AID_DISABLE (0x4)
83#define AID_1 (0x5)
84#define AID_2 (0x6)
85#define AID_3 (0x7)
86
87typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
88
89struct s6e8aa0_variant {
90 u8 version;
91 const s6e8aa0_gamma_table *gamma_tables;
92};
93
94struct s6e8aa0 {
95 struct device *dev;
96 struct drm_panel panel;
97
98 struct regulator_bulk_data supplies[2];
99 struct gpio_desc *reset_gpio;
100 u32 power_on_delay;
101 u32 reset_delay;
102 u32 init_delay;
103 bool flip_horizontal;
104 bool flip_vertical;
105 struct videomode vm;
106 u32 width_mm;
107 u32 height_mm;
108
109 u8 version;
110 u8 id;
111 const struct s6e8aa0_variant *variant;
112 int brightness;
113
114 /* This field is tested by functions directly accessing DSI bus before
115 * transfer, transfer is skipped if it is set. In case of transfer
116 * failure or unexpected response the field is set to error value.
117 * Such construct allows to eliminate many checks in higher level
118 * functions.
119 */
120 int error;
121};
122
123#define panel_to_s6e8aa0(p) container_of(p, struct s6e8aa0, panel)
124
125static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
126{
127 int ret = ctx->error;
128
129 ctx->error = 0;
130 return ret;
131}
132
133static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
134{
135 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
136 int ret;
137
138 if (ctx->error < 0)
139 return;
140
141 ret = mipi_dsi_dcs_write(dsi, dsi->channel, data, len);
142 if (ret < 0) {
143 dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len,
144 data);
145 ctx->error = ret;
146 }
147}
148
149static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len)
150{
151 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
152 int ret;
153
154 if (ctx->error < 0)
155 return ctx->error;
156
157 ret = mipi_dsi_dcs_read(dsi, dsi->channel, cmd, data, len);
158 if (ret < 0) {
159 dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
160 ctx->error = ret;
161 }
162
163 return ret;
164}
165
166#define s6e8aa0_dcs_write_seq(ctx, seq...) \
167({\
168 const u8 d[] = { seq };\
169 BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\
170 s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
171})
172
173#define s6e8aa0_dcs_write_seq_static(ctx, seq...) \
174({\
175 static const u8 d[] = { seq };\
176 s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
177})
178
179static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
180{
181 s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
182}
183
184static void s6e8aa0_panel_cond_set_v142(struct s6e8aa0 *ctx)
185{
186 static const u8 aids[] = {
187 0x04, 0x04, 0x04, 0x04, 0x04, 0x60, 0x80, 0xA0
188 };
189 u8 aid = aids[ctx->id >> 5];
190 u8 cfg = 0x3d;
191 u8 clk_con = 0xc8;
192 u8 int_con = 0x08;
193 u8 bictl_con = 0x48;
194 u8 em_clk1_con = 0xff;
195 u8 em_clk2_con = 0xff;
196 u8 em_int_con = 0xc8;
197
198 if (ctx->flip_vertical) {
199 /* GTCON */
200 cfg &= ~(PANELCTL_GTCON_MASK);
201 cfg |= (PANELCTL_GTCON_110);
202 }
203
204 if (ctx->flip_horizontal) {
205 /* SS */
206 cfg &= ~(PANELCTL_SS_MASK);
207 cfg |= (PANELCTL_SS_1_800);
208 }
209
210 if (ctx->flip_horizontal || ctx->flip_vertical) {
211 /* CLK1,2_CON */
212 clk_con &= ~(PANELCTL_CLK1_CON_MASK |
213 PANELCTL_CLK2_CON_MASK);
214 clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001);
215
216 /* INT1,2_CON */
217 int_con &= ~(PANELCTL_INT1_CON_MASK |
218 PANELCTL_INT2_CON_MASK);
219 int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001);
220
221 /* BICTL,B_CON */
222 bictl_con &= ~(PANELCTL_BICTL_CON_MASK |
223 PANELCTL_BICTLB_CON_MASK);
224 bictl_con |= (PANELCTL_BICTL_000 |
225 PANELCTL_BICTLB_001);
226
227 /* EM_CLK1,1B_CON */
228 em_clk1_con &= ~(PANELCTL_EM_CLK1_CON_MASK |
229 PANELCTL_EM_CLK1B_CON_MASK);
230 em_clk1_con |= (PANELCTL_EM_CLK1_110 |
231 PANELCTL_EM_CLK1B_110);
232
233 /* EM_CLK2,2B_CON */
234 em_clk2_con &= ~(PANELCTL_EM_CLK2_CON_MASK |
235 PANELCTL_EM_CLK2B_CON_MASK);
236 em_clk2_con |= (PANELCTL_EM_CLK2_110 |
237 PANELCTL_EM_CLK2B_110);
238
239 /* EM_INT1,2_CON */
240 em_int_con &= ~(PANELCTL_EM_INT1_CON_MASK |
241 PANELCTL_EM_INT2_CON_MASK);
242 em_int_con |= (PANELCTL_EM_INT1_000 |
243 PANELCTL_EM_INT2_001);
244 }
245
246 s6e8aa0_dcs_write_seq(ctx,
247 0xf8, cfg, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00,
248 0x3c, 0x78, 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00,
249 0x00, 0x20, aid, 0x08, 0x6e, 0x00, 0x00, 0x00,
250 0x02, 0x07, 0x07, 0x23, 0x23, 0xc0, clk_con, int_con,
251 bictl_con, 0xc1, 0x00, 0xc1, em_clk1_con, em_clk2_con,
252 em_int_con);
253}
254
255static void s6e8aa0_panel_cond_set(struct s6e8aa0 *ctx)
256{
257 if (ctx->version < 142)
258 s6e8aa0_dcs_write_seq_static(ctx,
259 0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00,
260 0x3c, 0x78, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00,
261 0x00, 0x00, 0x04, 0x08, 0x6e, 0x00, 0x00, 0x00,
262 0x00, 0x07, 0x07, 0x23, 0x6e, 0xc0, 0xc1, 0x01,
263 0x81, 0xc1, 0x00, 0xc3, 0xf6, 0xf6, 0xc1
264 );
265 else
266 s6e8aa0_panel_cond_set_v142(ctx);
267}
268
269static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
270{
271 s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
272}
273
274static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
275{
276 s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
277}
278
279static void s6e8aa0_etc_pentile_control(struct s6e8aa0 *ctx)
280{
281 static const u8 pent32[] = {
282 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xc0, 0x44, 0x44, 0xc0, 0x00
283 };
284
285 static const u8 pent142[] = {
286 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, 0x00
287 };
288
289 if (ctx->version < 142)
290 s6e8aa0_dcs_write(ctx, pent32, ARRAY_SIZE(pent32));
291 else
292 s6e8aa0_dcs_write(ctx, pent142, ARRAY_SIZE(pent142));
293}
294
295static void s6e8aa0_etc_power_control(struct s6e8aa0 *ctx)
296{
297 static const u8 pwr142[] = {
298 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x1e, 0x33, 0x02
299 };
300
301 static const u8 pwr32[] = {
302 0xf4, 0xcf, 0x0a, 0x15, 0x10, 0x19, 0x33, 0x02
303 };
304
305 if (ctx->version < 142)
306 s6e8aa0_dcs_write(ctx, pwr32, ARRAY_SIZE(pwr32));
307 else
308 s6e8aa0_dcs_write(ctx, pwr142, ARRAY_SIZE(pwr142));
309}
310
311static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx)
312{
313 u8 id = ctx->id ? 0 : 0x95;
314
315 s6e8aa0_dcs_write_seq(ctx, 0xb1, 0x04, id);
316}
317
318static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx)
319{
320 u8 br;
321
322 switch (ctx->brightness) {
323 case 0 ... 6: /* 30cd ~ 100cd */
324 br = 0xdf;
325 break;
326 case 7 ... 11: /* 120cd ~ 150cd */
327 br = 0xdd;
328 break;
329 case 12 ... 15: /* 180cd ~ 210cd */
330 default:
331 br = 0xd9;
332 break;
333 case 16 ... 24: /* 240cd ~ 300cd */
334 br = 0xd0;
335 break;
336 }
337
338 s6e8aa0_dcs_write_seq(ctx, 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e,
339 0xc4, 0x0f, 0x40, 0x41, br, 0x00, 0x60, 0x19);
340}
341
342static void s6e8aa0_elvss_nvm_set(struct s6e8aa0 *ctx)
343{
344 if (ctx->version < 142)
345 s6e8aa0_dcs_write_seq_static(ctx,
346 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 0xc4, 0x07,
347 0x40, 0x41, 0xc1, 0x00, 0x60, 0x19);
348 else
349 s6e8aa0_elvss_nvm_set_v142(ctx);
350};
351
352static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
353{
354 s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
355}
356
357static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v142[GAMMA_LEVEL_NUM] = {
358 {
359 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x62, 0x55, 0x55,
360 0xaf, 0xb1, 0xb1, 0xbd, 0xce, 0xb7, 0x9a, 0xb1,
361 0x90, 0xb2, 0xc4, 0xae, 0x00, 0x60, 0x00, 0x40,
362 0x00, 0x70,
363 }, {
364 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x74, 0x68, 0x69,
365 0xb8, 0xc1, 0xb7, 0xbd, 0xcd, 0xb8, 0x93, 0xab,
366 0x88, 0xb4, 0xc4, 0xb1, 0x00, 0x6b, 0x00, 0x4d,
367 0x00, 0x7d,
368 }, {
369 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x95, 0x8a, 0x89,
370 0xb4, 0xc6, 0xb2, 0xc5, 0xd2, 0xbf, 0x90, 0xa8,
371 0x85, 0xb5, 0xc4, 0xb3, 0x00, 0x7b, 0x00, 0x5d,
372 0x00, 0x8f,
373 }, {
374 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9f, 0x98, 0x92,
375 0xb3, 0xc4, 0xb0, 0xbc, 0xcc, 0xb4, 0x91, 0xa6,
376 0x87, 0xb5, 0xc5, 0xb4, 0x00, 0x87, 0x00, 0x6a,
377 0x00, 0x9e,
378 }, {
379 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x99, 0x93, 0x8b,
380 0xb2, 0xc2, 0xb0, 0xbd, 0xce, 0xb4, 0x90, 0xa6,
381 0x87, 0xb3, 0xc3, 0xb2, 0x00, 0x8d, 0x00, 0x70,
382 0x00, 0xa4,
383 }, {
384 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xa5, 0x99,
385 0xb2, 0xc2, 0xb0, 0xbb, 0xcd, 0xb1, 0x93, 0xa7,
386 0x8a, 0xb2, 0xc1, 0xb0, 0x00, 0x92, 0x00, 0x75,
387 0x00, 0xaa,
388 }, {
389 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xa0, 0x93,
390 0xb6, 0xc4, 0xb4, 0xb5, 0xc8, 0xaa, 0x94, 0xa9,
391 0x8c, 0xb2, 0xc0, 0xb0, 0x00, 0x97, 0x00, 0x7a,
392 0x00, 0xaf,
393 }, {
394 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xa7, 0x96,
395 0xb3, 0xc2, 0xb0, 0xba, 0xcb, 0xb0, 0x94, 0xa8,
396 0x8c, 0xb0, 0xbf, 0xaf, 0x00, 0x9f, 0x00, 0x83,
397 0x00, 0xb9,
398 }, {
399 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9d, 0xa2, 0x90,
400 0xb6, 0xc5, 0xb3, 0xb8, 0xc9, 0xae, 0x94, 0xa8,
401 0x8d, 0xaf, 0xbd, 0xad, 0x00, 0xa4, 0x00, 0x88,
402 0x00, 0xbf,
403 }, {
404 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xac, 0x97,
405 0xb4, 0xc4, 0xb1, 0xbb, 0xcb, 0xb2, 0x93, 0xa7,
406 0x8d, 0xae, 0xbc, 0xad, 0x00, 0xa7, 0x00, 0x8c,
407 0x00, 0xc3,
408 }, {
409 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa2, 0xa9, 0x93,
410 0xb6, 0xc5, 0xb2, 0xba, 0xc9, 0xb0, 0x93, 0xa7,
411 0x8d, 0xae, 0xbb, 0xac, 0x00, 0xab, 0x00, 0x90,
412 0x00, 0xc8,
413 }, {
414 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9e, 0xa6, 0x8f,
415 0xb7, 0xc6, 0xb3, 0xb8, 0xc8, 0xb0, 0x93, 0xa6,
416 0x8c, 0xae, 0xbb, 0xad, 0x00, 0xae, 0x00, 0x93,
417 0x00, 0xcc,
418 }, {
419 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb4, 0x9c,
420 0xb3, 0xc3, 0xaf, 0xb7, 0xc7, 0xaf, 0x93, 0xa6,
421 0x8c, 0xaf, 0xbc, 0xad, 0x00, 0xb1, 0x00, 0x97,
422 0x00, 0xcf,
423 }, {
424 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xb1, 0x98,
425 0xb1, 0xc2, 0xab, 0xba, 0xc9, 0xb2, 0x93, 0xa6,
426 0x8d, 0xae, 0xba, 0xab, 0x00, 0xb5, 0x00, 0x9b,
427 0x00, 0xd4,
428 }, {
429 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xae, 0x94,
430 0xb2, 0xc3, 0xac, 0xbb, 0xca, 0xb4, 0x91, 0xa4,
431 0x8a, 0xae, 0xba, 0xac, 0x00, 0xb8, 0x00, 0x9e,
432 0x00, 0xd8,
433 }, {
434 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb7, 0x9c,
435 0xae, 0xc0, 0xa9, 0xba, 0xc9, 0xb3, 0x92, 0xa5,
436 0x8b, 0xad, 0xb9, 0xab, 0x00, 0xbb, 0x00, 0xa1,
437 0x00, 0xdc,
438 }, {
439 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb4, 0x97,
440 0xb0, 0xc1, 0xaa, 0xb9, 0xc8, 0xb2, 0x92, 0xa5,
441 0x8c, 0xae, 0xb9, 0xab, 0x00, 0xbe, 0x00, 0xa4,
442 0x00, 0xdf,
443 }, {
444 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
445 0xb0, 0xc2, 0xab, 0xbb, 0xc9, 0xb3, 0x91, 0xa4,
446 0x8b, 0xad, 0xb8, 0xaa, 0x00, 0xc1, 0x00, 0xa8,
447 0x00, 0xe2,
448 }, {
449 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
450 0xae, 0xbf, 0xa8, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
451 0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xc4, 0x00, 0xab,
452 0x00, 0xe6,
453 }, {
454 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb6, 0x98,
455 0xaf, 0xc0, 0xa8, 0xb8, 0xc7, 0xb2, 0x93, 0xa5,
456 0x8d, 0xad, 0xb7, 0xa9, 0x00, 0xc7, 0x00, 0xae,
457 0x00, 0xe9,
458 }, {
459 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
460 0xaf, 0xc1, 0xa9, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
461 0x8b, 0xad, 0xb7, 0xaa, 0x00, 0xc9, 0x00, 0xb0,
462 0x00, 0xec,
463 }, {
464 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
465 0xac, 0xbe, 0xa6, 0xbb, 0xc9, 0xb4, 0x90, 0xa3,
466 0x8a, 0xad, 0xb7, 0xa9, 0x00, 0xcc, 0x00, 0xb4,
467 0x00, 0xf0,
468 }, {
469 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xb0, 0x91,
470 0xae, 0xc0, 0xa6, 0xba, 0xc8, 0xb4, 0x91, 0xa4,
471 0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xcf, 0x00, 0xb7,
472 0x00, 0xf3,
473 }, {
474 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb8, 0x98,
475 0xab, 0xbd, 0xa4, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
476 0x8b, 0xac, 0xb6, 0xa8, 0x00, 0xd1, 0x00, 0xb9,
477 0x00, 0xf6,
478 }, {
479 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb5, 0x95,
480 0xa9, 0xbc, 0xa1, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
481 0x8a, 0xad, 0xb6, 0xa8, 0x00, 0xd6, 0x00, 0xbf,
482 0x00, 0xfc,
483 },
484};
485
486static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v96[GAMMA_LEVEL_NUM] = {
487 {
488 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
489 0xdf, 0x1f, 0xd7, 0xdc, 0xb7, 0xe1, 0xc0, 0xaf,
490 0xc4, 0xd2, 0xd0, 0xcf, 0x00, 0x4d, 0x00, 0x40,
491 0x00, 0x5f,
492 }, {
493 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
494 0xd5, 0x35, 0xcf, 0xdc, 0xc1, 0xe1, 0xbf, 0xb3,
495 0xc1, 0xd2, 0xd1, 0xce, 0x00, 0x53, 0x00, 0x46,
496 0x00, 0x67,
497 }, {
498 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
499 0xd2, 0x64, 0xcf, 0xdb, 0xc6, 0xe1, 0xbd, 0xb3,
500 0xbd, 0xd2, 0xd2, 0xce, 0x00, 0x59, 0x00, 0x4b,
501 0x00, 0x6e,
502 }, {
503 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
504 0xd0, 0x7c, 0xcf, 0xdb, 0xc9, 0xe0, 0xbc, 0xb4,
505 0xbb, 0xcf, 0xd1, 0xcc, 0x00, 0x5f, 0x00, 0x50,
506 0x00, 0x75,
507 }, {
508 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
509 0xd0, 0x8e, 0xd1, 0xdb, 0xcc, 0xdf, 0xbb, 0xb6,
510 0xb9, 0xd0, 0xd1, 0xcd, 0x00, 0x63, 0x00, 0x54,
511 0x00, 0x7a,
512 }, {
513 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
514 0xd1, 0x9e, 0xd5, 0xda, 0xcd, 0xdd, 0xbb, 0xb7,
515 0xb9, 0xce, 0xce, 0xc9, 0x00, 0x68, 0x00, 0x59,
516 0x00, 0x81,
517 }, {
518 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
519 0xd0, 0xa5, 0xd6, 0xda, 0xcf, 0xdd, 0xbb, 0xb7,
520 0xb8, 0xcc, 0xcd, 0xc7, 0x00, 0x6c, 0x00, 0x5c,
521 0x00, 0x86,
522 }, {
523 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xfe,
524 0xd0, 0xae, 0xd7, 0xd9, 0xd0, 0xdb, 0xb9, 0xb6,
525 0xb5, 0xca, 0xcc, 0xc5, 0x00, 0x74, 0x00, 0x63,
526 0x00, 0x90,
527 }, {
528 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf9,
529 0xcf, 0xb0, 0xd6, 0xd9, 0xd1, 0xdb, 0xb9, 0xb6,
530 0xb4, 0xca, 0xcb, 0xc5, 0x00, 0x77, 0x00, 0x66,
531 0x00, 0x94,
532 }, {
533 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf7,
534 0xcf, 0xb3, 0xd7, 0xd8, 0xd1, 0xd9, 0xb7, 0xb6,
535 0xb3, 0xc9, 0xca, 0xc3, 0x00, 0x7b, 0x00, 0x69,
536 0x00, 0x99,
537
538 }, {
539 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfd, 0x2f, 0xf7,
540 0xdf, 0xb5, 0xd6, 0xd8, 0xd1, 0xd8, 0xb6, 0xb5,
541 0xb2, 0xca, 0xcb, 0xc4, 0x00, 0x7e, 0x00, 0x6c,
542 0x00, 0x9d,
543 }, {
544 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfa, 0x2f, 0xf5,
545 0xce, 0xb6, 0xd5, 0xd7, 0xd2, 0xd8, 0xb6, 0xb4,
546 0xb0, 0xc7, 0xc9, 0xc1, 0x00, 0x84, 0x00, 0x71,
547 0x00, 0xa5,
548 }, {
549 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf7, 0x2f, 0xf2,
550 0xce, 0xb9, 0xd5, 0xd8, 0xd2, 0xd8, 0xb4, 0xb4,
551 0xaf, 0xc7, 0xc9, 0xc1, 0x00, 0x87, 0x00, 0x73,
552 0x00, 0xa8,
553 }, {
554 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf5, 0x2f, 0xf0,
555 0xdf, 0xba, 0xd5, 0xd7, 0xd2, 0xd7, 0xb4, 0xb4,
556 0xaf, 0xc5, 0xc7, 0xbf, 0x00, 0x8a, 0x00, 0x76,
557 0x00, 0xac,
558 }, {
559 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf2, 0x2f, 0xed,
560 0xcE, 0xbb, 0xd4, 0xd6, 0xd2, 0xd6, 0xb5, 0xb4,
561 0xaF, 0xc5, 0xc7, 0xbf, 0x00, 0x8c, 0x00, 0x78,
562 0x00, 0xaf,
563 }, {
564 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x2f, 0xeb,
565 0xcd, 0xbb, 0xd2, 0xd7, 0xd3, 0xd6, 0xb3, 0xb4,
566 0xae, 0xc5, 0xc6, 0xbe, 0x00, 0x91, 0x00, 0x7d,
567 0x00, 0xb6,
568 }, {
569 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xee, 0x2f, 0xea,
570 0xce, 0xbd, 0xd4, 0xd6, 0xd2, 0xd5, 0xb2, 0xb3,
571 0xad, 0xc3, 0xc4, 0xbb, 0x00, 0x94, 0x00, 0x7f,
572 0x00, 0xba,
573 }, {
574 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xec, 0x2f, 0xe8,
575 0xce, 0xbe, 0xd3, 0xd6, 0xd3, 0xd5, 0xb2, 0xb2,
576 0xac, 0xc3, 0xc5, 0xbc, 0x00, 0x96, 0x00, 0x81,
577 0x00, 0xbd,
578 }, {
579 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xeb, 0x2f, 0xe7,
580 0xce, 0xbf, 0xd3, 0xd6, 0xd2, 0xd5, 0xb1, 0xb2,
581 0xab, 0xc2, 0xc4, 0xbb, 0x00, 0x99, 0x00, 0x83,
582 0x00, 0xc0,
583 }, {
584 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x5f, 0xe9,
585 0xca, 0xbf, 0xd3, 0xd5, 0xd2, 0xd4, 0xb2, 0xb2,
586 0xab, 0xc1, 0xc4, 0xba, 0x00, 0x9b, 0x00, 0x85,
587 0x00, 0xc3,
588 }, {
589 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xea, 0x5f, 0xe8,
590 0xee, 0xbf, 0xd2, 0xd5, 0xd2, 0xd4, 0xb1, 0xb2,
591 0xab, 0xc1, 0xc2, 0xb9, 0x00, 0x9D, 0x00, 0x87,
592 0x00, 0xc6,
593 }, {
594 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe9, 0x5f, 0xe7,
595 0xcd, 0xbf, 0xd2, 0xd6, 0xd2, 0xd4, 0xb1, 0xb2,
596 0xab, 0xbe, 0xc0, 0xb7, 0x00, 0xa1, 0x00, 0x8a,
597 0x00, 0xca,
598 }, {
599 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x61, 0xe6,
600 0xcd, 0xbf, 0xd1, 0xd6, 0xd3, 0xd4, 0xaf, 0xb0,
601 0xa9, 0xbe, 0xc1, 0xb7, 0x00, 0xa3, 0x00, 0x8b,
602 0x00, 0xce,
603 }, {
604 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x62, 0xe5,
605 0xcc, 0xc0, 0xd0, 0xd6, 0xd2, 0xd4, 0xaf, 0xb1,
606 0xa9, 0xbd, 0xc0, 0xb6, 0x00, 0xa5, 0x00, 0x8d,
607 0x00, 0xd0,
608 }, {
609 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe7, 0x7f, 0xe3,
610 0xcc, 0xc1, 0xd0, 0xd5, 0xd3, 0xd3, 0xae, 0xaf,
611 0xa8, 0xbe, 0xc0, 0xb7, 0x00, 0xa8, 0x00, 0x90,
612 0x00, 0xd3,
613 }
614};
615
616static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v32[GAMMA_LEVEL_NUM] = {
617 {
618 0xfa, 0x01, 0x43, 0x14, 0x45, 0x72, 0x5e, 0x6b,
619 0xa1, 0xa7, 0x9a, 0xb4, 0xcb, 0xb8, 0x92, 0xac,
620 0x97, 0xb4, 0xc3, 0xb5, 0x00, 0x4e, 0x00, 0x37,
621 0x00, 0x58,
622 }, {
623 0xfa, 0x01, 0x43, 0x14, 0x45, 0x85, 0x71, 0x7d,
624 0xa6, 0xb6, 0xa1, 0xb5, 0xca, 0xba, 0x93, 0xac,
625 0x98, 0xb2, 0xc0, 0xaf, 0x00, 0x59, 0x00, 0x43,
626 0x00, 0x64,
627 }, {
628 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa4, 0x94, 0x9e,
629 0xa0, 0xbb, 0x9c, 0xc3, 0xd2, 0xc6, 0x93, 0xaa,
630 0x95, 0xb7, 0xc2, 0xb4, 0x00, 0x65, 0x00, 0x50,
631 0x00, 0x74,
632 }, {
633 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa1, 0xa6,
634 0xa0, 0xb9, 0x9b, 0xc3, 0xd1, 0xc8, 0x90, 0xa6,
635 0x90, 0xbb, 0xc3, 0xb7, 0x00, 0x6f, 0x00, 0x5b,
636 0x00, 0x80,
637 }, {
638 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa6, 0x9d, 0x9f,
639 0x9f, 0xb8, 0x9a, 0xc7, 0xd5, 0xcc, 0x90, 0xa5,
640 0x8f, 0xb8, 0xc1, 0xb6, 0x00, 0x74, 0x00, 0x60,
641 0x00, 0x85,
642 }, {
643 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb3, 0xae, 0xae,
644 0x9e, 0xb7, 0x9a, 0xc8, 0xd6, 0xce, 0x91, 0xa6,
645 0x90, 0xb6, 0xc0, 0xb3, 0x00, 0x78, 0x00, 0x65,
646 0x00, 0x8a,
647 }, {
648 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa9, 0xa8,
649 0xa3, 0xb9, 0x9e, 0xc4, 0xd3, 0xcb, 0x94, 0xa6,
650 0x90, 0xb6, 0xbf, 0xb3, 0x00, 0x7c, 0x00, 0x69,
651 0x00, 0x8e,
652 }, {
653 0xfa, 0x01, 0x43, 0x14, 0x45, 0xaf, 0xaf, 0xa9,
654 0xa5, 0xbc, 0xa2, 0xc7, 0xd5, 0xcd, 0x93, 0xa5,
655 0x8f, 0xb4, 0xbd, 0xb1, 0x00, 0x83, 0x00, 0x70,
656 0x00, 0x96,
657 }, {
658 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xab, 0xa3,
659 0xaa, 0xbf, 0xa7, 0xc5, 0xd3, 0xcb, 0x93, 0xa5,
660 0x8f, 0xb2, 0xbb, 0xb0, 0x00, 0x86, 0x00, 0x74,
661 0x00, 0x9b,
662 }, {
663 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xb5, 0xab,
664 0xab, 0xc0, 0xa9, 0xc7, 0xd4, 0xcc, 0x94, 0xa4,
665 0x8f, 0xb1, 0xbb, 0xaf, 0x00, 0x8a, 0x00, 0x77,
666 0x00, 0x9e,
667 }, {
668 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb2, 0xa7,
669 0xae, 0xc2, 0xab, 0xc5, 0xd3, 0xca, 0x93, 0xa4,
670 0x8f, 0xb1, 0xba, 0xae, 0x00, 0x8d, 0x00, 0x7b,
671 0x00, 0xa2,
672 }, {
673 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xaf, 0xa3,
674 0xb0, 0xc3, 0xae, 0xc4, 0xd1, 0xc8, 0x93, 0xa4,
675 0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x8f, 0x00, 0x7d,
676 0x00, 0xa5,
677 }, {
678 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbd, 0xaf,
679 0xae, 0xc1, 0xab, 0xc2, 0xd0, 0xc6, 0x94, 0xa4,
680 0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x92, 0x00, 0x80,
681 0x00, 0xa8,
682 }, {
683 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xb9, 0xac,
684 0xad, 0xc1, 0xab, 0xc4, 0xd1, 0xc7, 0x95, 0xa4,
685 0x90, 0xb0, 0xb9, 0xad, 0x00, 0x95, 0x00, 0x84,
686 0x00, 0xac,
687 }, {
688 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb6, 0xa7,
689 0xaf, 0xc2, 0xae, 0xc5, 0xd1, 0xc7, 0x93, 0xa3,
690 0x8e, 0xb0, 0xb9, 0xad, 0x00, 0x98, 0x00, 0x86,
691 0x00, 0xaf,
692 }, {
693 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbf, 0xaf,
694 0xad, 0xc1, 0xab, 0xc3, 0xd0, 0xc6, 0x94, 0xa3,
695 0x8f, 0xaf, 0xb8, 0xac, 0x00, 0x9a, 0x00, 0x89,
696 0x00, 0xb2,
697 }, {
698 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xbc, 0xac,
699 0xaf, 0xc2, 0xad, 0xc2, 0xcf, 0xc4, 0x94, 0xa3,
700 0x90, 0xaf, 0xb8, 0xad, 0x00, 0x9c, 0x00, 0x8b,
701 0x00, 0xb5,
702 }, {
703 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
704 0xb1, 0xc4, 0xaf, 0xc3, 0xcf, 0xc5, 0x94, 0xa3,
705 0x8f, 0xae, 0xb7, 0xac, 0x00, 0x9f, 0x00, 0x8e,
706 0x00, 0xb8,
707 }, {
708 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
709 0xaf, 0xc2, 0xad, 0xc1, 0xce, 0xc3, 0x95, 0xa3,
710 0x90, 0xad, 0xb6, 0xab, 0x00, 0xa2, 0x00, 0x91,
711 0x00, 0xbb,
712 }, {
713 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xbe, 0xac,
714 0xb1, 0xc4, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa4,
715 0x91, 0xad, 0xb6, 0xab, 0x00, 0xa4, 0x00, 0x93,
716 0x00, 0xbd,
717 }, {
718 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
719 0xb3, 0xc5, 0xb2, 0xc1, 0xcd, 0xc2, 0x95, 0xa3,
720 0x90, 0xad, 0xb6, 0xab, 0x00, 0xa6, 0x00, 0x95,
721 0x00, 0xc0,
722 }, {
723 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
724 0xb0, 0xc3, 0xaf, 0xc2, 0xce, 0xc2, 0x94, 0xa2,
725 0x90, 0xac, 0xb6, 0xab, 0x00, 0xa8, 0x00, 0x98,
726 0x00, 0xc3,
727 }, {
728 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xb8, 0xa5,
729 0xb3, 0xc5, 0xb2, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
730 0x90, 0xad, 0xb6, 0xab, 0x00, 0xaa, 0x00, 0x9a,
731 0x00, 0xc5,
732 }, {
733 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xc0, 0xac,
734 0xb0, 0xc3, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa2,
735 0x90, 0xac, 0xb5, 0xa9, 0x00, 0xac, 0x00, 0x9c,
736 0x00, 0xc8,
737 }, {
738 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbd, 0xa8,
739 0xaf, 0xc2, 0xaf, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
740 0x90, 0xac, 0xb5, 0xaa, 0x00, 0xb1, 0x00, 0xa1,
741 0x00, 0xcc,
742 },
743};
744
745static const struct s6e8aa0_variant s6e8aa0_variants[] = {
746 {
747 .version = 32,
748 .gamma_tables = s6e8aa0_gamma_tables_v32,
749 }, {
750 .version = 96,
751 .gamma_tables = s6e8aa0_gamma_tables_v96,
752 }, {
753 .version = 142,
754 .gamma_tables = s6e8aa0_gamma_tables_v142,
755 }, {
756 .version = 210,
757 .gamma_tables = s6e8aa0_gamma_tables_v142,
758 }
759};
760
761static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx)
762{
763 const u8 *gamma;
764
765 if (ctx->error)
766 return;
767
768 gamma = ctx->variant->gamma_tables[ctx->brightness];
769
770 if (ctx->version >= 142)
771 s6e8aa0_elvss_nvm_set(ctx);
772
773 s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN);
774
775 /* update gamma table. */
776 s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03);
777}
778
779static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
780{
781 s6e8aa0_apply_level_1_key(ctx);
782 s6e8aa0_apply_level_2_key(ctx);
783 msleep(20);
784
785 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
786 msleep(40);
787
788 s6e8aa0_panel_cond_set(ctx);
789 s6e8aa0_display_condition_set(ctx);
790 s6e8aa0_brightness_set(ctx);
791 s6e8aa0_etc_source_control(ctx);
792 s6e8aa0_etc_pentile_control(ctx);
793 s6e8aa0_elvss_nvm_set(ctx);
794 s6e8aa0_etc_power_control(ctx);
795 s6e8aa0_etc_elvss_control(ctx);
796 msleep(ctx->init_delay);
797}
798
799static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
800 int size)
801{
802 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
803 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
804 u8 buf[] = {size, 0};
805 struct mipi_dsi_msg msg = {
806 .channel = dsi->channel,
807 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
808 .tx_len = sizeof(buf),
809 .tx_buf = buf
810 };
811 int ret;
812
813 if (ctx->error < 0)
814 return;
815
816 if (!ops || !ops->transfer)
817 ret = -EIO;
818 else
819 ret = ops->transfer(dsi->host, &msg);
820
821 if (ret < 0) {
822 dev_err(ctx->dev,
823 "error %d setting maximum return packet size to %d\n",
824 ret, size);
825 ctx->error = ret;
826 }
827}
828
829static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
830{
831 u8 id[3];
832 int ret, i;
833
834 ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
835 if (ret < ARRAY_SIZE(id) || id[0] == 0x00) {
836 dev_err(ctx->dev, "read id failed\n");
837 ctx->error = -EIO;
838 return;
839 }
840
841 dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
842
843 for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
844 if (id[1] == s6e8aa0_variants[i].version)
845 break;
846 }
847 if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
848 dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
849 ctx->error = -EINVAL;
850 }
851
852 ctx->variant = &s6e8aa0_variants[i];
853 ctx->version = id[1];
854 ctx->id = id[2];
855}
856
857static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
858{
859 s6e8aa0_set_maximum_return_packet_size(ctx, 3);
860 s6e8aa0_read_mtp_id(ctx);
861 s6e8aa0_panel_init(ctx);
862 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
863}
864
865static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
866{
867 int ret;
868
869 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
870 if (ret < 0)
871 return ret;
872
873 msleep(ctx->power_on_delay);
874
875 gpiod_set_value(ctx->reset_gpio, 0);
876 usleep_range(10000, 11000);
877 gpiod_set_value(ctx->reset_gpio, 1);
878
879 msleep(ctx->reset_delay);
880
881 return 0;
882}
883
884static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
885{
886 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
887}
888
889static int s6e8aa0_disable(struct drm_panel *panel)
890{
891 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
892
893 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
894 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
895 msleep(40);
896
897 s6e8aa0_clear_error(ctx);
898
899 return s6e8aa0_power_off(ctx);
900}
901
902static int s6e8aa0_enable(struct drm_panel *panel)
903{
904 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
905 int ret;
906
907 ret = s6e8aa0_power_on(ctx);
908 if (ret < 0)
909 return ret;
910
911 s6e8aa0_set_sequence(ctx);
912 ret = ctx->error;
913
914 if (ret < 0)
915 s6e8aa0_disable(panel);
916
917 return ret;
918}
919
920static int s6e8aa0_get_modes(struct drm_panel *panel)
921{
922 struct drm_connector *connector = panel->connector;
923 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
924 struct drm_display_mode *mode;
925
926 mode = drm_mode_create(connector->dev);
927 if (!mode) {
928 DRM_ERROR("failed to create a new display mode\n");
929 return 0;
930 }
931
932 drm_display_mode_from_videomode(&ctx->vm, mode);
933 mode->width_mm = ctx->width_mm;
934 mode->height_mm = ctx->height_mm;
935 connector->display_info.width_mm = mode->width_mm;
936 connector->display_info.height_mm = mode->height_mm;
937
938 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
939 drm_mode_probed_add(connector, mode);
940
941 return 1;
942}
943
944static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
945 .disable = s6e8aa0_disable,
946 .enable = s6e8aa0_enable,
947 .get_modes = s6e8aa0_get_modes,
948};
949
950static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
951{
952 struct device *dev = ctx->dev;
953 struct device_node *np = dev->of_node;
954 int ret;
955
956 ret = of_get_videomode(np, &ctx->vm, 0);
957 if (ret < 0)
958 return ret;
959
960 of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
961 of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
962 of_property_read_u32(np, "init-delay", &ctx->init_delay);
963 of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
964 of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
965
966 ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
967 ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
968
969 return 0;
970}
971
972static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
973{
974 struct device *dev = &dsi->dev;
975 struct s6e8aa0 *ctx;
976 int ret;
977
978 ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
979 if (!ctx)
980 return -ENOMEM;
981
982 mipi_dsi_set_drvdata(dsi, ctx);
983
984 ctx->dev = dev;
985
986 dsi->lanes = 4;
987 dsi->format = MIPI_DSI_FMT_RGB888;
988 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
989 | MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
990 | MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
991 | MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
992
993 ret = s6e8aa0_parse_dt(ctx);
994 if (ret < 0)
995 return ret;
996
997 ctx->supplies[0].supply = "vdd3";
998 ctx->supplies[1].supply = "vci";
999 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
1000 ctx->supplies);
1001 if (ret < 0) {
1002 dev_err(dev, "failed to get regulators: %d\n", ret);
1003 return ret;
1004 }
1005
1006 ctx->reset_gpio = devm_gpiod_get(dev, "reset");
1007 if (IS_ERR(ctx->reset_gpio)) {
1008 dev_err(dev, "cannot get reset-gpios %ld\n",
1009 PTR_ERR(ctx->reset_gpio));
1010 return PTR_ERR(ctx->reset_gpio);
1011 }
1012 ret = gpiod_direction_output(ctx->reset_gpio, 1);
1013 if (ret < 0) {
1014 dev_err(dev, "cannot configure reset-gpios %d\n", ret);
1015 return ret;
1016 }
1017
1018 ctx->brightness = GAMMA_LEVEL_NUM - 1;
1019
1020 drm_panel_init(&ctx->panel);
1021 ctx->panel.dev = dev;
1022 ctx->panel.funcs = &s6e8aa0_drm_funcs;
1023
1024 ret = drm_panel_add(&ctx->panel);
1025 if (ret < 0)
1026 return ret;
1027
1028 ret = mipi_dsi_attach(dsi);
1029 if (ret < 0)
1030 drm_panel_remove(&ctx->panel);
1031
1032 return ret;
1033}
1034
1035static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
1036{
1037 struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
1038
1039 mipi_dsi_detach(dsi);
1040 drm_panel_remove(&ctx->panel);
1041
1042 return 0;
1043}
1044
1045static struct of_device_id s6e8aa0_of_match[] = {
1046 { .compatible = "samsung,s6e8aa0" },
1047 { }
1048};
1049MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1050
1051static struct mipi_dsi_driver s6e8aa0_driver = {
1052 .probe = s6e8aa0_probe,
1053 .remove = s6e8aa0_remove,
1054 .driver = {
1055 .name = "panel_s6e8aa0",
1056 .owner = THIS_MODULE,
1057 .of_match_table = s6e8aa0_of_match,
1058 },
1059};
1060module_mipi_dsi_driver(s6e8aa0_driver);
1061
1062MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1063MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1064MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1065MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1066MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1067MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1068MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1069MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 59d52ca2c67f..309f29e9234a 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -22,9 +22,8 @@
22 */ 22 */
23 23
24#include <linux/backlight.h> 24#include <linux/backlight.h>
25#include <linux/gpio.h> 25#include <linux/gpio/consumer.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/of_gpio.h>
28#include <linux/of_platform.h> 27#include <linux/of_platform.h>
29#include <linux/platform_device.h> 28#include <linux/platform_device.h>
30#include <linux/regulator/consumer.h> 29#include <linux/regulator/consumer.h>
@@ -44,9 +43,6 @@ struct panel_desc {
44 } size; 43 } size;
45}; 44};
46 45
47/* TODO: convert to gpiod_*() API once it's been merged */
48#define GPIO_ACTIVE_LOW (1 << 0)
49
50struct panel_simple { 46struct panel_simple {
51 struct drm_panel base; 47 struct drm_panel base;
52 bool enabled; 48 bool enabled;
@@ -57,8 +53,7 @@ struct panel_simple {
57 struct regulator *supply; 53 struct regulator *supply;
58 struct i2c_adapter *ddc; 54 struct i2c_adapter *ddc;
59 55
60 unsigned long enable_gpio_flags; 56 struct gpio_desc *enable_gpio;
61 int enable_gpio;
62}; 57};
63 58
64static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) 59static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
@@ -110,12 +105,8 @@ static int panel_simple_disable(struct drm_panel *panel)
110 backlight_update_status(p->backlight); 105 backlight_update_status(p->backlight);
111 } 106 }
112 107
113 if (gpio_is_valid(p->enable_gpio)) { 108 if (p->enable_gpio)
114 if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) 109 gpiod_set_value_cansleep(p->enable_gpio, 0);
115 gpio_set_value(p->enable_gpio, 1);
116 else
117 gpio_set_value(p->enable_gpio, 0);
118 }
119 110
120 regulator_disable(p->supply); 111 regulator_disable(p->supply);
121 p->enabled = false; 112 p->enabled = false;
@@ -137,12 +128,8 @@ static int panel_simple_enable(struct drm_panel *panel)
137 return err; 128 return err;
138 } 129 }
139 130
140 if (gpio_is_valid(p->enable_gpio)) { 131 if (p->enable_gpio)
141 if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) 132 gpiod_set_value_cansleep(p->enable_gpio, 1);
142 gpio_set_value(p->enable_gpio, 0);
143 else
144 gpio_set_value(p->enable_gpio, 1);
145 }
146 133
147 if (p->backlight) { 134 if (p->backlight) {
148 p->backlight->props.power = FB_BLANK_UNBLANK; 135 p->backlight->props.power = FB_BLANK_UNBLANK;
@@ -185,7 +172,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
185{ 172{
186 struct device_node *backlight, *ddc; 173 struct device_node *backlight, *ddc;
187 struct panel_simple *panel; 174 struct panel_simple *panel;
188 enum of_gpio_flags flags;
189 int err; 175 int err;
190 176
191 panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); 177 panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
@@ -199,29 +185,20 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
199 if (IS_ERR(panel->supply)) 185 if (IS_ERR(panel->supply))
200 return PTR_ERR(panel->supply); 186 return PTR_ERR(panel->supply);
201 187
202 panel->enable_gpio = of_get_named_gpio_flags(dev->of_node, 188 panel->enable_gpio = devm_gpiod_get(dev, "enable");
203 "enable-gpios", 0, 189 if (IS_ERR(panel->enable_gpio)) {
204 &flags); 190 err = PTR_ERR(panel->enable_gpio);
205 if (gpio_is_valid(panel->enable_gpio)) { 191 if (err != -ENOENT) {
206 unsigned int value; 192 dev_err(dev, "failed to request GPIO: %d\n", err);
207
208 if (flags & OF_GPIO_ACTIVE_LOW)
209 panel->enable_gpio_flags |= GPIO_ACTIVE_LOW;
210
211 err = gpio_request(panel->enable_gpio, "enable");
212 if (err < 0) {
213 dev_err(dev, "failed to request GPIO#%u: %d\n",
214 panel->enable_gpio, err);
215 return err; 193 return err;
216 } 194 }
217 195
218 value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0; 196 panel->enable_gpio = NULL;
219 197 } else {
220 err = gpio_direction_output(panel->enable_gpio, value); 198 err = gpiod_direction_output(panel->enable_gpio, 0);
221 if (err < 0) { 199 if (err < 0) {
222 dev_err(dev, "failed to setup GPIO%u: %d\n", 200 dev_err(dev, "failed to setup GPIO: %d\n", err);
223 panel->enable_gpio, err); 201 return err;
224 goto free_gpio;
225 } 202 }
226 } 203 }
227 204
@@ -230,10 +207,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
230 panel->backlight = of_find_backlight_by_node(backlight); 207 panel->backlight = of_find_backlight_by_node(backlight);
231 of_node_put(backlight); 208 of_node_put(backlight);
232 209
233 if (!panel->backlight) { 210 if (!panel->backlight)
234 err = -EPROBE_DEFER; 211 return -EPROBE_DEFER;
235 goto free_gpio;
236 }
237 } 212 }
238 213
239 ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); 214 ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
@@ -265,9 +240,6 @@ free_ddc:
265free_backlight: 240free_backlight:
266 if (panel->backlight) 241 if (panel->backlight)
267 put_device(&panel->backlight->dev); 242 put_device(&panel->backlight->dev);
268free_gpio:
269 if (gpio_is_valid(panel->enable_gpio))
270 gpio_free(panel->enable_gpio);
271 243
272 return err; 244 return err;
273} 245}
@@ -287,11 +259,6 @@ static int panel_simple_remove(struct device *dev)
287 if (panel->backlight) 259 if (panel->backlight)
288 put_device(&panel->backlight->dev); 260 put_device(&panel->backlight->dev);
289 261
290 if (gpio_is_valid(panel->enable_gpio))
291 gpio_free(panel->enable_gpio);
292
293 regulator_disable(panel->supply);
294
295 return 0; 262 return 0;
296} 263}
297 264
@@ -361,6 +328,28 @@ static const struct panel_desc chunghwa_claa101wb01 = {
361 }, 328 },
362}; 329};
363 330
331static const struct drm_display_mode lg_lp129qe_mode = {
332 .clock = 285250,
333 .hdisplay = 2560,
334 .hsync_start = 2560 + 48,
335 .hsync_end = 2560 + 48 + 32,
336 .htotal = 2560 + 48 + 32 + 80,
337 .vdisplay = 1700,
338 .vsync_start = 1700 + 3,
339 .vsync_end = 1700 + 3 + 10,
340 .vtotal = 1700 + 3 + 10 + 36,
341 .vrefresh = 60,
342};
343
344static const struct panel_desc lg_lp129qe = {
345 .modes = &lg_lp129qe_mode,
346 .num_modes = 1,
347 .size = {
348 .width = 272,
349 .height = 181,
350 },
351};
352
364static const struct drm_display_mode samsung_ltn101nt05_mode = { 353static const struct drm_display_mode samsung_ltn101nt05_mode = {
365 .clock = 54030, 354 .clock = 54030,
366 .hdisplay = 1024, 355 .hdisplay = 1024,
@@ -394,6 +383,9 @@ static const struct of_device_id platform_of_match[] = {
394 .compatible = "chunghwa,claa101wb01", 383 .compatible = "chunghwa,claa101wb01",
395 .data = &chunghwa_claa101wb01 384 .data = &chunghwa_claa101wb01
396 }, { 385 }, {
386 .compatible = "lg,lp129qe",
387 .data = &lg_lp129qe,
388 }, {
397 .compatible = "samsung,ltn101nt05", 389 .compatible = "samsung,ltn101nt05",
398 .data = &samsung_ltn101nt05, 390 .data = &samsung_ltn101nt05,
399 }, { 391 }, {
@@ -433,10 +425,65 @@ static struct platform_driver panel_simple_platform_driver = {
433struct panel_desc_dsi { 425struct panel_desc_dsi {
434 struct panel_desc desc; 426 struct panel_desc desc;
435 427
428 unsigned long flags;
436 enum mipi_dsi_pixel_format format; 429 enum mipi_dsi_pixel_format format;
437 unsigned int lanes; 430 unsigned int lanes;
438}; 431};
439 432
433static const struct drm_display_mode lg_ld070wx3_sl01_mode = {
434 .clock = 71000,
435 .hdisplay = 800,
436 .hsync_start = 800 + 32,
437 .hsync_end = 800 + 32 + 1,
438 .htotal = 800 + 32 + 1 + 57,
439 .vdisplay = 1280,
440 .vsync_start = 1280 + 28,
441 .vsync_end = 1280 + 28 + 1,
442 .vtotal = 1280 + 28 + 1 + 14,
443 .vrefresh = 60,
444};
445
446static const struct panel_desc_dsi lg_ld070wx3_sl01 = {
447 .desc = {
448 .modes = &lg_ld070wx3_sl01_mode,
449 .num_modes = 1,
450 .size = {
451 .width = 94,
452 .height = 151,
453 },
454 },
455 .flags = MIPI_DSI_MODE_VIDEO,
456 .format = MIPI_DSI_FMT_RGB888,
457 .lanes = 4,
458};
459
460static const struct drm_display_mode lg_lh500wx1_sd03_mode = {
461 .clock = 67000,
462 .hdisplay = 720,
463 .hsync_start = 720 + 12,
464 .hsync_end = 720 + 12 + 4,
465 .htotal = 720 + 12 + 4 + 112,
466 .vdisplay = 1280,
467 .vsync_start = 1280 + 8,
468 .vsync_end = 1280 + 8 + 4,
469 .vtotal = 1280 + 8 + 4 + 12,
470 .vrefresh = 60,
471};
472
473static const struct panel_desc_dsi lg_lh500wx1_sd03 = {
474 .desc = {
475 .modes = &lg_lh500wx1_sd03_mode,
476 .num_modes = 1,
477 .size = {
478 .width = 62,
479 .height = 110,
480 },
481 },
482 .flags = MIPI_DSI_MODE_VIDEO,
483 .format = MIPI_DSI_FMT_RGB888,
484 .lanes = 4,
485};
486
440static const struct drm_display_mode panasonic_vvx10f004b00_mode = { 487static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
441 .clock = 157200, 488 .clock = 157200,
442 .hdisplay = 1920, 489 .hdisplay = 1920,
@@ -459,12 +506,19 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
459 .height = 136, 506 .height = 136,
460 }, 507 },
461 }, 508 },
509 .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
462 .format = MIPI_DSI_FMT_RGB888, 510 .format = MIPI_DSI_FMT_RGB888,
463 .lanes = 4, 511 .lanes = 4,
464}; 512};
465 513
466static const struct of_device_id dsi_of_match[] = { 514static const struct of_device_id dsi_of_match[] = {
467 { 515 {
516 .compatible = "lg,ld070wx3-sl01",
517 .data = &lg_ld070wx3_sl01
518 }, {
519 .compatible = "lg,lh500wx1-sd03",
520 .data = &lg_lh500wx1_sd03
521 }, {
468 .compatible = "panasonic,vvx10f004b00", 522 .compatible = "panasonic,vvx10f004b00",
469 .data = &panasonic_vvx10f004b00 523 .data = &panasonic_vvx10f004b00
470 }, { 524 }, {
@@ -489,6 +543,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
489 if (err < 0) 543 if (err < 0)
490 return err; 544 return err;
491 545
546 dsi->mode_flags = desc->flags;
492 dsi->format = desc->format; 547 dsi->format = desc->format;
493 dsi->lanes = desc->lanes; 548 dsi->lanes = desc->lanes;
494 549
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 798bde2e5881..41bdd174657e 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -527,7 +527,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
527 bool recreate_primary = false; 527 bool recreate_primary = false;
528 int ret; 528 int ret;
529 int surf_id; 529 int surf_id;
530 if (!crtc->fb) { 530 if (!crtc->primary->fb) {
531 DRM_DEBUG_KMS("No FB bound\n"); 531 DRM_DEBUG_KMS("No FB bound\n");
532 return 0; 532 return 0;
533 } 533 }
@@ -536,7 +536,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
536 qfb = to_qxl_framebuffer(old_fb); 536 qfb = to_qxl_framebuffer(old_fb);
537 old_bo = gem_to_qxl_bo(qfb->obj); 537 old_bo = gem_to_qxl_bo(qfb->obj);
538 } 538 }
539 qfb = to_qxl_framebuffer(crtc->fb); 539 qfb = to_qxl_framebuffer(crtc->primary->fb);
540 bo = gem_to_qxl_bo(qfb->obj); 540 bo = gem_to_qxl_bo(qfb->obj);
541 if (!m) 541 if (!m)
542 /* and do we care? */ 542 /* and do we care? */
@@ -609,14 +609,14 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
609 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); 609 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
610 struct drm_device *dev = crtc->dev; 610 struct drm_device *dev = crtc->dev;
611 struct qxl_device *qdev = dev->dev_private; 611 struct qxl_device *qdev = dev->dev_private;
612 if (crtc->fb) { 612 if (crtc->primary->fb) {
613 struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb); 613 struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->primary->fb);
614 struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); 614 struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
615 int ret; 615 int ret;
616 ret = qxl_bo_reserve(bo, false); 616 ret = qxl_bo_reserve(bo, false);
617 qxl_bo_unpin(bo); 617 qxl_bo_unpin(bo);
618 qxl_bo_unreserve(bo); 618 qxl_bo_unreserve(bo);
619 crtc->fb = NULL; 619 crtc->primary->fb = NULL;
620 } 620 }
621 621
622 qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0); 622 qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index 821ab7b9409b..14e776f1d14e 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -349,7 +349,7 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release)
349 qxl_fence_add_release_locked(&qbo->fence, release->id); 349 qxl_fence_add_release_locked(&qbo->fence, release->id);
350 350
351 ttm_bo_add_to_lru(bo); 351 ttm_bo_add_to_lru(bo);
352 ww_mutex_unlock(&bo->resv->lock); 352 __ttm_bo_unreserve(bo);
353 entry->reserved = false; 353 entry->reserved = false;
354 } 354 }
355 spin_unlock(&bdev->fence_lock); 355 spin_unlock(&bdev->fence_lock);
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index 29c02e0e857f..d52c27527b9a 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -433,6 +433,7 @@ static int qxl_sync_obj_flush(void *sync_obj)
433 433
434static void qxl_sync_obj_unref(void **sync_obj) 434static void qxl_sync_obj_unref(void **sync_obj)
435{ 435{
436 *sync_obj = NULL;
436} 437}
437 438
438static void *qxl_sync_obj_ref(void *sync_obj) 439static void *qxl_sync_obj_ref(void *sync_obj)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index daa4dd375ab1..fb187c78978f 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
1106 int r; 1106 int r;
1107 1107
1108 /* no fb bound */ 1108 /* no fb bound */
1109 if (!atomic && !crtc->fb) { 1109 if (!atomic && !crtc->primary->fb) {
1110 DRM_DEBUG_KMS("No FB bound\n"); 1110 DRM_DEBUG_KMS("No FB bound\n");
1111 return 0; 1111 return 0;
1112 } 1112 }
@@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
1116 target_fb = fb; 1116 target_fb = fb;
1117 } 1117 }
1118 else { 1118 else {
1119 radeon_fb = to_radeon_framebuffer(crtc->fb); 1119 radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
1120 target_fb = crtc->fb; 1120 target_fb = crtc->primary->fb;
1121 } 1121 }
1122 1122
1123 /* If atomic, assume fb object is pinned & idle & fenced and 1123 /* If atomic, assume fb object is pinned & idle & fenced and
@@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
1316 /* set pageflip to happen anywhere in vblank interval */ 1316 /* set pageflip to happen anywhere in vblank interval */
1317 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); 1317 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
1318 1318
1319 if (!atomic && fb && fb != crtc->fb) { 1319 if (!atomic && fb && fb != crtc->primary->fb) {
1320 radeon_fb = to_radeon_framebuffer(fb); 1320 radeon_fb = to_radeon_framebuffer(fb);
1321 rbo = gem_to_radeon_bo(radeon_fb->obj); 1321 rbo = gem_to_radeon_bo(radeon_fb->obj);
1322 r = radeon_bo_reserve(rbo, false); 1322 r = radeon_bo_reserve(rbo, false);
@@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
1350 int r; 1350 int r;
1351 1351
1352 /* no fb bound */ 1352 /* no fb bound */
1353 if (!atomic && !crtc->fb) { 1353 if (!atomic && !crtc->primary->fb) {
1354 DRM_DEBUG_KMS("No FB bound\n"); 1354 DRM_DEBUG_KMS("No FB bound\n");
1355 return 0; 1355 return 0;
1356 } 1356 }
@@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
1360 target_fb = fb; 1360 target_fb = fb;
1361 } 1361 }
1362 else { 1362 else {
1363 radeon_fb = to_radeon_framebuffer(crtc->fb); 1363 radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
1364 target_fb = crtc->fb; 1364 target_fb = crtc->primary->fb;
1365 } 1365 }
1366 1366
1367 obj = radeon_fb->obj; 1367 obj = radeon_fb->obj;
@@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
1485 /* set pageflip to happen anywhere in vblank interval */ 1485 /* set pageflip to happen anywhere in vblank interval */
1486 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); 1486 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
1487 1487
1488 if (!atomic && fb && fb != crtc->fb) { 1488 if (!atomic && fb && fb != crtc->primary->fb) {
1489 radeon_fb = to_radeon_framebuffer(fb); 1489 radeon_fb = to_radeon_framebuffer(fb);
1490 rbo = gem_to_radeon_bo(radeon_fb->obj); 1490 rbo = gem_to_radeon_bo(radeon_fb->obj);
1491 r = radeon_bo_reserve(rbo, false); 1491 r = radeon_bo_reserve(rbo, false);
@@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
1972 int i; 1972 int i;
1973 1973
1974 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1974 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1975 if (crtc->fb) { 1975 if (crtc->primary->fb) {
1976 int r; 1976 int r;
1977 struct radeon_framebuffer *radeon_fb; 1977 struct radeon_framebuffer *radeon_fb;
1978 struct radeon_bo *rbo; 1978 struct radeon_bo *rbo;
1979 1979
1980 radeon_fb = to_radeon_framebuffer(crtc->fb); 1980 radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
1981 rbo = gem_to_radeon_bo(radeon_fb->obj); 1981 rbo = gem_to_radeon_bo(radeon_fb->obj);
1982 r = radeon_bo_reserve(rbo, false); 1982 r = radeon_bo_reserve(rbo, false);
1983 if (unlikely(r)) 1983 if (unlikely(r))
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 4ad7643fce5f..8b0ab170cef9 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -142,101 +142,69 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
142 return recv_bytes; 142 return recv_bytes;
143} 143}
144 144
145static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, 145#define HEADER_SIZE 4
146 u16 address, u8 *send, u8 send_bytes, u8 delay)
147{
148 struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
149 int ret;
150 u8 msg[20];
151 int msg_bytes = send_bytes + 4;
152 u8 ack;
153 unsigned retry;
154
155 if (send_bytes > 16)
156 return -1;
157 146
158 msg[0] = address; 147static ssize_t
159 msg[1] = address >> 8; 148radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
160 msg[2] = DP_AUX_NATIVE_WRITE << 4;
161 msg[3] = (msg_bytes << 4) | (send_bytes - 1);
162 memcpy(&msg[4], send, send_bytes);
163
164 for (retry = 0; retry < 7; retry++) {
165 ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
166 msg, msg_bytes, NULL, 0, delay, &ack);
167 if (ret == -EBUSY)
168 continue;
169 else if (ret < 0)
170 return ret;
171 ack >>= 4;
172 if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
173 return send_bytes;
174 else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
175 usleep_range(400, 500);
176 else
177 return -EIO;
178 }
179
180 return -EIO;
181}
182
183static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
184 u16 address, u8 *recv, int recv_bytes, u8 delay)
185{ 149{
186 struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 150 struct radeon_i2c_chan *chan =
187 u8 msg[4]; 151 container_of(aux, struct radeon_i2c_chan, aux);
188 int msg_bytes = 4;
189 u8 ack;
190 int ret; 152 int ret;
191 unsigned retry; 153 u8 tx_buf[20];
192 154 size_t tx_size;
193 msg[0] = address; 155 u8 ack, delay = 0;
194 msg[1] = address >> 8; 156
195 msg[2] = DP_AUX_NATIVE_READ << 4; 157 if (WARN_ON(msg->size > 16))
196 msg[3] = (msg_bytes << 4) | (recv_bytes - 1); 158 return -E2BIG;
197 159
198 for (retry = 0; retry < 7; retry++) { 160 tx_buf[0] = msg->address & 0xff;
199 ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, 161 tx_buf[1] = msg->address >> 8;
200 msg, msg_bytes, recv, recv_bytes, delay, &ack); 162 tx_buf[2] = msg->request << 4;
201 if (ret == -EBUSY) 163 tx_buf[3] = msg->size - 1;
202 continue; 164
203 else if (ret < 0) 165 switch (msg->request & ~DP_AUX_I2C_MOT) {
204 return ret; 166 case DP_AUX_NATIVE_WRITE:
205 ack >>= 4; 167 case DP_AUX_I2C_WRITE:
206 if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) 168 tx_size = HEADER_SIZE + msg->size;
207 return ret; 169 tx_buf[3] |= tx_size << 4;
208 else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) 170 memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size);
209 usleep_range(400, 500); 171 ret = radeon_process_aux_ch(chan,
210 else if (ret == 0) 172 tx_buf, tx_size, NULL, 0, delay, &ack);
211 return -EPROTO; 173 if (ret >= 0)
212 else 174 /* Return payload size. */
213 return -EIO; 175 ret = msg->size;
176 break;
177 case DP_AUX_NATIVE_READ:
178 case DP_AUX_I2C_READ:
179 tx_size = HEADER_SIZE;
180 tx_buf[3] |= tx_size << 4;
181 ret = radeon_process_aux_ch(chan,
182 tx_buf, tx_size, msg->buffer, msg->size, delay, &ack);
183 break;
184 default:
185 ret = -EINVAL;
186 break;
214 } 187 }
215 188
216 return -EIO; 189 if (ret > 0)
217} 190 msg->reply = ack >> 4;
218 191
219static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, 192 return ret;
220 u16 reg, u8 val)
221{
222 radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0);
223} 193}
224 194
225static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, 195void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
226 u16 reg)
227{ 196{
228 u8 val = 0; 197 struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
229
230 radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0);
231 198
232 return val; 199 dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev;
200 dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer;
233} 201}
234 202
235int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, 203int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
236 u8 write_byte, u8 *read_byte) 204 u8 write_byte, u8 *read_byte)
237{ 205{
238 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; 206 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
239 struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; 207 struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter);
240 u16 address = algo_data->address; 208 u16 address = algo_data->address;
241 u8 msg[5]; 209 u8 msg[5];
242 u8 reply[2]; 210 u8 reply[2];
@@ -246,34 +214,30 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
246 int ret; 214 int ret;
247 u8 ack; 215 u8 ack;
248 216
249 /* Set up the command byte */ 217 /* Set up the address */
250 if (mode & MODE_I2C_READ)
251 msg[2] = DP_AUX_I2C_READ << 4;
252 else
253 msg[2] = DP_AUX_I2C_WRITE << 4;
254
255 if (!(mode & MODE_I2C_STOP))
256 msg[2] |= DP_AUX_I2C_MOT << 4;
257
258 msg[0] = address; 218 msg[0] = address;
259 msg[1] = address >> 8; 219 msg[1] = address >> 8;
260 220
261 switch (mode) { 221 /* Set up the command byte */
262 case MODE_I2C_WRITE: 222 if (mode & MODE_I2C_READ) {
223 msg[2] = DP_AUX_I2C_READ << 4;
224 msg_bytes = 4;
225 msg[3] = msg_bytes << 4;
226 } else {
227 msg[2] = DP_AUX_I2C_WRITE << 4;
263 msg_bytes = 5; 228 msg_bytes = 5;
264 msg[3] = msg_bytes << 4; 229 msg[3] = msg_bytes << 4;
265 msg[4] = write_byte; 230 msg[4] = write_byte;
266 break;
267 case MODE_I2C_READ:
268 msg_bytes = 4;
269 msg[3] = msg_bytes << 4;
270 break;
271 default:
272 msg_bytes = 4;
273 msg[3] = 3 << 4;
274 break;
275 } 231 }
276 232
233 /* special handling for start/stop */
234 if (mode & (MODE_I2C_START | MODE_I2C_STOP))
235 msg[3] = 3 << 4;
236
237 /* Set MOT bit for all but stop */
238 if ((mode & MODE_I2C_STOP) == 0)
239 msg[2] |= DP_AUX_I2C_MOT << 4;
240
277 for (retry = 0; retry < 7; retry++) { 241 for (retry = 0; retry < 7; retry++) {
278 ret = radeon_process_aux_ch(auxch, 242 ret = radeon_process_aux_ch(auxch,
279 msg, msg_bytes, reply, reply_bytes, 0, &ack); 243 msg, msg_bytes, reply, reply_bytes, 0, &ack);
@@ -472,11 +436,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
472 if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) 436 if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
473 return; 437 return;
474 438
475 if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0)) 439 if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3))
476 DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", 440 DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
477 buf[0], buf[1], buf[2]); 441 buf[0], buf[1], buf[2]);
478 442
479 if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0)) 443 if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3))
480 DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", 444 DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
481 buf[0], buf[1], buf[2]); 445 buf[0], buf[1], buf[2]);
482} 446}
@@ -487,8 +451,8 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
487 u8 msg[DP_DPCD_SIZE]; 451 u8 msg[DP_DPCD_SIZE];
488 int ret, i; 452 int ret, i;
489 453
490 ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 454 ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg,
491 DP_DPCD_SIZE, 0); 455 DP_DPCD_SIZE);
492 if (ret > 0) { 456 if (ret > 0) {
493 memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); 457 memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
494 DRM_DEBUG_KMS("DPCD: "); 458 DRM_DEBUG_KMS("DPCD: ");
@@ -510,6 +474,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
510 struct drm_device *dev = encoder->dev; 474 struct drm_device *dev = encoder->dev;
511 struct radeon_device *rdev = dev->dev_private; 475 struct radeon_device *rdev = dev->dev_private;
512 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 476 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
477 struct radeon_connector_atom_dig *dig_connector;
513 int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 478 int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
514 u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); 479 u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
515 u8 tmp; 480 u8 tmp;
@@ -517,9 +482,15 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
517 if (!ASIC_IS_DCE4(rdev)) 482 if (!ASIC_IS_DCE4(rdev))
518 return panel_mode; 483 return panel_mode;
519 484
485 if (!radeon_connector->con_priv)
486 return panel_mode;
487
488 dig_connector = radeon_connector->con_priv;
489
520 if (dp_bridge != ENCODER_OBJECT_ID_NONE) { 490 if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
521 /* DP bridge chips */ 491 /* DP bridge chips */
522 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); 492 drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
493 DP_EDP_CONFIGURATION_CAP, &tmp);
523 if (tmp & 1) 494 if (tmp & 1)
524 panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 495 panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
525 else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || 496 else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
@@ -529,7 +500,8 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
529 panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 500 panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
530 } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 501 } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
531 /* eDP */ 502 /* eDP */
532 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); 503 drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
504 DP_EDP_CONFIGURATION_CAP, &tmp);
533 if (tmp & 1) 505 if (tmp & 1)
534 panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 506 panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
535 } 507 }
@@ -577,37 +549,42 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector,
577 return MODE_OK; 549 return MODE_OK;
578} 550}
579 551
580static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
581 u8 link_status[DP_LINK_STATUS_SIZE])
582{
583 int ret;
584 ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS,
585 link_status, DP_LINK_STATUS_SIZE, 100);
586 if (ret <= 0) {
587 return false;
588 }
589
590 DRM_DEBUG_KMS("link status %6ph\n", link_status);
591 return true;
592}
593
594bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) 552bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
595{ 553{
596 u8 link_status[DP_LINK_STATUS_SIZE]; 554 u8 link_status[DP_LINK_STATUS_SIZE];
597 struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; 555 struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
598 556
599 if (!radeon_dp_get_link_status(radeon_connector, link_status)) 557 if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0)
600 return false; 558 return false;
601 if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) 559 if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count))
602 return false; 560 return false;
603 return true; 561 return true;
604} 562}
605 563
564void radeon_dp_set_rx_power_state(struct drm_connector *connector,
565 u8 power_state)
566{
567 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
568 struct radeon_connector_atom_dig *dig_connector;
569
570 if (!radeon_connector->con_priv)
571 return;
572
573 dig_connector = radeon_connector->con_priv;
574
575 /* power up/down the sink */
576 if (dig_connector->dpcd[0] >= 0x11) {
577 drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux,
578 DP_SET_POWER, power_state);
579 usleep_range(1000, 2000);
580 }
581}
582
583
606struct radeon_dp_link_train_info { 584struct radeon_dp_link_train_info {
607 struct radeon_device *rdev; 585 struct radeon_device *rdev;
608 struct drm_encoder *encoder; 586 struct drm_encoder *encoder;
609 struct drm_connector *connector; 587 struct drm_connector *connector;
610 struct radeon_connector *radeon_connector;
611 int enc_id; 588 int enc_id;
612 int dp_clock; 589 int dp_clock;
613 int dp_lane_count; 590 int dp_lane_count;
@@ -617,6 +594,7 @@ struct radeon_dp_link_train_info {
617 u8 link_status[DP_LINK_STATUS_SIZE]; 594 u8 link_status[DP_LINK_STATUS_SIZE];
618 u8 tries; 595 u8 tries;
619 bool use_dpencoder; 596 bool use_dpencoder;
597 struct drm_dp_aux *aux;
620}; 598};
621 599
622static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) 600static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -627,8 +605,8 @@ static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
627 0, dp_info->train_set[0]); /* sets all lanes at once */ 605 0, dp_info->train_set[0]); /* sets all lanes at once */
628 606
629 /* set the vs/emph on the sink */ 607 /* set the vs/emph on the sink */
630 radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, 608 drm_dp_dpcd_write(dp_info->aux, DP_TRAINING_LANE0_SET,
631 dp_info->train_set, dp_info->dp_lane_count, 0); 609 dp_info->train_set, dp_info->dp_lane_count);
632} 610}
633 611
634static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) 612static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
@@ -663,7 +641,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
663 } 641 }
664 642
665 /* enable training pattern on the sink */ 643 /* enable training pattern on the sink */
666 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); 644 drm_dp_dpcd_writeb(dp_info->aux, DP_TRAINING_PATTERN_SET, tp);
667} 645}
668 646
669static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) 647static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
@@ -673,34 +651,30 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
673 u8 tmp; 651 u8 tmp;
674 652
675 /* power up the sink */ 653 /* power up the sink */
676 if (dp_info->dpcd[0] >= 0x11) { 654 radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0);
677 radeon_write_dpcd_reg(dp_info->radeon_connector,
678 DP_SET_POWER, DP_SET_POWER_D0);
679 usleep_range(1000, 2000);
680 }
681 655
682 /* possibly enable downspread on the sink */ 656 /* possibly enable downspread on the sink */
683 if (dp_info->dpcd[3] & 0x1) 657 if (dp_info->dpcd[3] & 0x1)
684 radeon_write_dpcd_reg(dp_info->radeon_connector, 658 drm_dp_dpcd_writeb(dp_info->aux,
685 DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); 659 DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
686 else 660 else
687 radeon_write_dpcd_reg(dp_info->radeon_connector, 661 drm_dp_dpcd_writeb(dp_info->aux,
688 DP_DOWNSPREAD_CTRL, 0); 662 DP_DOWNSPREAD_CTRL, 0);
689 663
690 if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && 664 if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
691 (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { 665 (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
692 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); 666 drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1);
693 } 667 }
694 668
695 /* set the lane count on the sink */ 669 /* set the lane count on the sink */
696 tmp = dp_info->dp_lane_count; 670 tmp = dp_info->dp_lane_count;
697 if (drm_dp_enhanced_frame_cap(dp_info->dpcd)) 671 if (drm_dp_enhanced_frame_cap(dp_info->dpcd))
698 tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 672 tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
699 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); 673 drm_dp_dpcd_writeb(dp_info->aux, DP_LANE_COUNT_SET, tmp);
700 674
701 /* set the link rate on the sink */ 675 /* set the link rate on the sink */
702 tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); 676 tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock);
703 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); 677 drm_dp_dpcd_writeb(dp_info->aux, DP_LINK_BW_SET, tmp);
704 678
705 /* start training on the source */ 679 /* start training on the source */
706 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 680 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
@@ -711,9 +685,9 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
711 dp_info->dp_clock, dp_info->enc_id, 0); 685 dp_info->dp_clock, dp_info->enc_id, 0);
712 686
713 /* disable the training pattern on the sink */ 687 /* disable the training pattern on the sink */
714 radeon_write_dpcd_reg(dp_info->radeon_connector, 688 drm_dp_dpcd_writeb(dp_info->aux,
715 DP_TRAINING_PATTERN_SET, 689 DP_TRAINING_PATTERN_SET,
716 DP_TRAINING_PATTERN_DISABLE); 690 DP_TRAINING_PATTERN_DISABLE);
717 691
718 return 0; 692 return 0;
719} 693}
@@ -723,9 +697,9 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
723 udelay(400); 697 udelay(400);
724 698
725 /* disable the training pattern on the sink */ 699 /* disable the training pattern on the sink */
726 radeon_write_dpcd_reg(dp_info->radeon_connector, 700 drm_dp_dpcd_writeb(dp_info->aux,
727 DP_TRAINING_PATTERN_SET, 701 DP_TRAINING_PATTERN_SET,
728 DP_TRAINING_PATTERN_DISABLE); 702 DP_TRAINING_PATTERN_DISABLE);
729 703
730 /* disable the training pattern on the source */ 704 /* disable the training pattern on the source */
731 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 705 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
@@ -757,7 +731,8 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info)
757 while (1) { 731 while (1) {
758 drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); 732 drm_dp_link_train_clock_recovery_delay(dp_info->dpcd);
759 733
760 if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { 734 if (drm_dp_dpcd_read_link_status(dp_info->aux,
735 dp_info->link_status) <= 0) {
761 DRM_ERROR("displayport link status failed\n"); 736 DRM_ERROR("displayport link status failed\n");
762 break; 737 break;
763 } 738 }
@@ -819,7 +794,8 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info)
819 while (1) { 794 while (1) {
820 drm_dp_link_train_channel_eq_delay(dp_info->dpcd); 795 drm_dp_link_train_channel_eq_delay(dp_info->dpcd);
821 796
822 if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { 797 if (drm_dp_dpcd_read_link_status(dp_info->aux,
798 dp_info->link_status) <= 0) {
823 DRM_ERROR("displayport link status failed\n"); 799 DRM_ERROR("displayport link status failed\n");
824 break; 800 break;
825 } 801 }
@@ -902,7 +878,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
902 else 878 else
903 dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; 879 dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A;
904 880
905 tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); 881 drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp);
906 if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) 882 if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
907 dp_info.tp3_supported = true; 883 dp_info.tp3_supported = true;
908 else 884 else
@@ -912,9 +888,9 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
912 dp_info.rdev = rdev; 888 dp_info.rdev = rdev;
913 dp_info.encoder = encoder; 889 dp_info.encoder = encoder;
914 dp_info.connector = connector; 890 dp_info.connector = connector;
915 dp_info.radeon_connector = radeon_connector;
916 dp_info.dp_lane_count = dig_connector->dp_lane_count; 891 dp_info.dp_lane_count = dig_connector->dp_lane_count;
917 dp_info.dp_clock = dig_connector->dp_clock; 892 dp_info.dp_clock = dig_connector->dp_clock;
893 dp_info.aux = &dig_connector->dp_i2c_bus->aux;
918 894
919 if (radeon_dp_link_train_init(&dp_info)) 895 if (radeon_dp_link_train_init(&dp_info))
920 goto done; 896 goto done;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 607dc14d195e..e6eb5097597f 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -1633,10 +1633,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1633 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1633 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1634 struct radeon_connector *radeon_connector = NULL; 1634 struct radeon_connector *radeon_connector = NULL;
1635 struct radeon_connector_atom_dig *radeon_dig_connector = NULL; 1635 struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
1636 bool travis_quirk = false;
1636 1637
1637 if (connector) { 1638 if (connector) {
1638 radeon_connector = to_radeon_connector(connector); 1639 radeon_connector = to_radeon_connector(connector);
1639 radeon_dig_connector = radeon_connector->con_priv; 1640 radeon_dig_connector = radeon_connector->con_priv;
1641 if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
1642 ENCODER_OBJECT_ID_TRAVIS) &&
1643 (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
1644 !ASIC_IS_DCE5(rdev))
1645 travis_quirk = true;
1640 } 1646 }
1641 1647
1642 switch (mode) { 1648 switch (mode) {
@@ -1657,17 +1663,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1657 atombios_external_encoder_setup(encoder, ext_encoder, 1663 atombios_external_encoder_setup(encoder, ext_encoder,
1658 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 1664 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1659 } 1665 }
1660 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1661 } else if (ASIC_IS_DCE4(rdev)) { 1666 } else if (ASIC_IS_DCE4(rdev)) {
1662 /* setup and enable the encoder */ 1667 /* setup and enable the encoder */
1663 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 1668 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1664 /* enable the transmitter */
1665 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1666 } else { 1669 } else {
1667 /* setup and enable the encoder and transmitter */ 1670 /* setup and enable the encoder and transmitter */
1668 atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); 1671 atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
1669 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 1672 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
1670 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1671 } 1673 }
1672 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 1674 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1673 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1675 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1675,68 +1677,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1675 ATOM_TRANSMITTER_ACTION_POWER_ON); 1677 ATOM_TRANSMITTER_ACTION_POWER_ON);
1676 radeon_dig_connector->edp_on = true; 1678 radeon_dig_connector->edp_on = true;
1677 } 1679 }
1680 }
1681 /* enable the transmitter */
1682 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1683 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1684 /* DP_SET_POWER_D0 is set in radeon_dp_link_train */
1678 radeon_dp_link_train(encoder, connector); 1685 radeon_dp_link_train(encoder, connector);
1679 if (ASIC_IS_DCE4(rdev)) 1686 if (ASIC_IS_DCE4(rdev))
1680 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 1687 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
1681 } 1688 }
1682 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1689 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1683 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 1690 atombios_dig_transmitter_setup(encoder,
1691 ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1692 if (ext_encoder)
1693 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1684 break; 1694 break;
1685 case DRM_MODE_DPMS_STANDBY: 1695 case DRM_MODE_DPMS_STANDBY:
1686 case DRM_MODE_DPMS_SUSPEND: 1696 case DRM_MODE_DPMS_SUSPEND:
1687 case DRM_MODE_DPMS_OFF: 1697 case DRM_MODE_DPMS_OFF:
1688 if (ASIC_IS_DCE4(rdev)) { 1698 if (ASIC_IS_DCE4(rdev)) {
1699 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
1700 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
1701 }
1702 if (ext_encoder)
1703 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
1704 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1705 atombios_dig_transmitter_setup(encoder,
1706 ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1707
1708 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
1709 connector && !travis_quirk)
1710 radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1711 if (ASIC_IS_DCE4(rdev)) {
1689 /* disable the transmitter */ 1712 /* disable the transmitter */
1690 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1713 atombios_dig_transmitter_setup(encoder,
1714 ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1691 } else { 1715 } else {
1692 /* disable the encoder and transmitter */ 1716 /* disable the encoder and transmitter */
1693 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1717 atombios_dig_transmitter_setup(encoder,
1718 ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1694 atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); 1719 atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
1695 } 1720 }
1696 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 1721 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1697 if (ASIC_IS_DCE4(rdev)) 1722 if (travis_quirk)
1698 atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 1723 radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1699 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1724 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1700 atombios_set_edp_panel_power(connector, 1725 atombios_set_edp_panel_power(connector,
1701 ATOM_TRANSMITTER_ACTION_POWER_OFF); 1726 ATOM_TRANSMITTER_ACTION_POWER_OFF);
1702 radeon_dig_connector->edp_on = false; 1727 radeon_dig_connector->edp_on = false;
1703 } 1728 }
1704 } 1729 }
1705 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1706 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1707 break;
1708 }
1709}
1710
1711static void
1712radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
1713 struct drm_encoder *ext_encoder,
1714 int mode)
1715{
1716 struct drm_device *dev = encoder->dev;
1717 struct radeon_device *rdev = dev->dev_private;
1718
1719 switch (mode) {
1720 case DRM_MODE_DPMS_ON:
1721 default:
1722 if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
1723 atombios_external_encoder_setup(encoder, ext_encoder,
1724 EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
1725 atombios_external_encoder_setup(encoder, ext_encoder,
1726 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
1727 } else
1728 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1729 break;
1730 case DRM_MODE_DPMS_STANDBY:
1731 case DRM_MODE_DPMS_SUSPEND:
1732 case DRM_MODE_DPMS_OFF:
1733 if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
1734 atombios_external_encoder_setup(encoder, ext_encoder,
1735 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
1736 atombios_external_encoder_setup(encoder, ext_encoder,
1737 EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
1738 } else
1739 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
1740 break; 1730 break;
1741 } 1731 }
1742} 1732}
@@ -1747,7 +1737,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1747 struct drm_device *dev = encoder->dev; 1737 struct drm_device *dev = encoder->dev;
1748 struct radeon_device *rdev = dev->dev_private; 1738 struct radeon_device *rdev = dev->dev_private;
1749 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1739 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1750 struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
1751 1740
1752 DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 1741 DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
1753 radeon_encoder->encoder_id, mode, radeon_encoder->devices, 1742 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1807,9 +1796,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1807 return; 1796 return;
1808 } 1797 }
1809 1798
1810 if (ext_encoder)
1811 radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
1812
1813 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1799 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1814 1800
1815} 1801}
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0ae991d3289a..745143c2358f 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -1096,7 +1096,7 @@ static const u32 spectre_golden_registers[] =
1096 0x8a14, 0xf000003f, 0x00000007, 1096 0x8a14, 0xf000003f, 0x00000007,
1097 0x8b24, 0xffffffff, 0x00ffffff, 1097 0x8b24, 0xffffffff, 0x00ffffff,
1098 0x28350, 0x3f3f3fff, 0x00000082, 1098 0x28350, 0x3f3f3fff, 0x00000082,
1099 0x28355, 0x0000003f, 0x00000000, 1099 0x28354, 0x0000003f, 0x00000000,
1100 0x3e78, 0x00000001, 0x00000002, 1100 0x3e78, 0x00000001, 0x00000002,
1101 0x913c, 0xffff03df, 0x00000004, 1101 0x913c, 0xffff03df, 0x00000004,
1102 0xc768, 0x00000008, 0x00000008, 1102 0xc768, 0x00000008, 0x00000008,
@@ -2029,6 +2029,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2029 break; 2029 break;
2030 case 5: 2030 case 5:
2031 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2031 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2032 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
2032 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); 2033 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
2033 break; 2034 break;
2034 case 6: 2035 case 6:
@@ -2049,6 +2050,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2049 break; 2050 break;
2050 case 9: 2051 case 9:
2051 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2052 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2053 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
2052 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING)); 2054 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
2053 break; 2055 break;
2054 case 10: 2056 case 10:
@@ -2071,6 +2073,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2071 break; 2073 break;
2072 case 13: 2074 case 13:
2073 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2075 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2076 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
2074 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING)); 2077 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
2075 break; 2078 break;
2076 case 14: 2079 case 14:
@@ -2093,6 +2096,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2093 break; 2096 break;
2094 case 27: 2097 case 27:
2095 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2098 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2099 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
2096 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING)); 2100 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
2097 break; 2101 break;
2098 case 28: 2102 case 28:
@@ -2247,6 +2251,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2247 break; 2251 break;
2248 case 5: 2252 case 5:
2249 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2253 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2254 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
2250 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); 2255 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
2251 break; 2256 break;
2252 case 6: 2257 case 6:
@@ -2267,6 +2272,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2267 break; 2272 break;
2268 case 9: 2273 case 9:
2269 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2274 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2275 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
2270 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING)); 2276 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
2271 break; 2277 break;
2272 case 10: 2278 case 10:
@@ -2289,6 +2295,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2289 break; 2295 break;
2290 case 13: 2296 case 13:
2291 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2297 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2298 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
2292 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING)); 2299 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
2293 break; 2300 break;
2294 case 14: 2301 case 14:
@@ -2311,6 +2318,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2311 break; 2318 break;
2312 case 27: 2319 case 27:
2313 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2320 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2321 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
2314 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING)); 2322 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
2315 break; 2323 break;
2316 case 28: 2324 case 28:
@@ -2467,6 +2475,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2467 break; 2475 break;
2468 case 5: 2476 case 5:
2469 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2477 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2478 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
2470 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); 2479 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
2471 break; 2480 break;
2472 case 6: 2481 case 6:
@@ -2487,6 +2496,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2487 break; 2496 break;
2488 case 9: 2497 case 9:
2489 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2498 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2499 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
2490 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING)); 2500 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
2491 break; 2501 break;
2492 case 10: 2502 case 10:
@@ -2509,6 +2519,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2509 break; 2519 break;
2510 case 13: 2520 case 13:
2511 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2521 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2522 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
2512 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING)); 2523 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
2513 break; 2524 break;
2514 case 14: 2525 case 14:
@@ -2531,6 +2542,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2531 break; 2542 break;
2532 case 27: 2543 case 27:
2533 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2544 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2545 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
2534 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING)); 2546 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
2535 break; 2547 break;
2536 case 28: 2548 case 28:
@@ -2593,6 +2605,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2593 break; 2605 break;
2594 case 5: 2606 case 5:
2595 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2607 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2608 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
2596 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); 2609 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
2597 break; 2610 break;
2598 case 6: 2611 case 6:
@@ -2613,6 +2626,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2613 break; 2626 break;
2614 case 9: 2627 case 9:
2615 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2628 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2629 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
2616 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING)); 2630 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
2617 break; 2631 break;
2618 case 10: 2632 case 10:
@@ -2635,6 +2649,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2635 break; 2649 break;
2636 case 13: 2650 case 13:
2637 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2651 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2652 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
2638 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING)); 2653 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
2639 break; 2654 break;
2640 case 14: 2655 case 14:
@@ -2657,6 +2672,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2657 break; 2672 break;
2658 case 27: 2673 case 27:
2659 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2674 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2675 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
2660 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING)); 2676 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
2661 break; 2677 break;
2662 case 28: 2678 case 28:
@@ -2813,6 +2829,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2813 break; 2829 break;
2814 case 5: 2830 case 5:
2815 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2831 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2832 PIPE_CONFIG(ADDR_SURF_P2) |
2816 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); 2833 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
2817 break; 2834 break;
2818 case 6: 2835 case 6:
@@ -2828,11 +2845,13 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2828 TILE_SPLIT(split_equal_to_row_size)); 2845 TILE_SPLIT(split_equal_to_row_size));
2829 break; 2846 break;
2830 case 8: 2847 case 8:
2831 gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED); 2848 gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
2849 PIPE_CONFIG(ADDR_SURF_P2);
2832 break; 2850 break;
2833 case 9: 2851 case 9:
2834 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2852 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2835 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING)); 2853 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
2854 PIPE_CONFIG(ADDR_SURF_P2));
2836 break; 2855 break;
2837 case 10: 2856 case 10:
2838 gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | 2857 gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
@@ -2854,6 +2873,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2854 break; 2873 break;
2855 case 13: 2874 case 13:
2856 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2875 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2876 PIPE_CONFIG(ADDR_SURF_P2) |
2857 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING)); 2877 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
2858 break; 2878 break;
2859 case 14: 2879 case 14:
@@ -2876,7 +2896,8 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
2876 break; 2896 break;
2877 case 27: 2897 case 27:
2878 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | 2898 gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
2879 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING)); 2899 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
2900 PIPE_CONFIG(ADDR_SURF_P2));
2880 break; 2901 break;
2881 case 28: 2902 case 28:
2882 gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) | 2903 gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
@@ -6521,8 +6542,8 @@ void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer)
6521 buffer[count++] = cpu_to_le32(0x00000000); 6542 buffer[count++] = cpu_to_le32(0x00000000);
6522 break; 6543 break;
6523 case CHIP_HAWAII: 6544 case CHIP_HAWAII:
6524 buffer[count++] = 0x3a00161a; 6545 buffer[count++] = cpu_to_le32(0x3a00161a);
6525 buffer[count++] = 0x0000002e; 6546 buffer[count++] = cpu_to_le32(0x0000002e);
6526 break; 6547 break;
6527 default: 6548 default:
6528 buffer[count++] = cpu_to_le32(0x00000000); 6549 buffer[count++] = cpu_to_le32(0x00000000);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 030f8e49c5ee..b6c32640df20 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
3220 3220
3221 if (rdev->mode_info.crtcs[0]->base.enabled) { 3221 if (rdev->mode_info.crtcs[0]->base.enabled) {
3222 mode1 = &rdev->mode_info.crtcs[0]->base.mode; 3222 mode1 = &rdev->mode_info.crtcs[0]->base.mode;
3223 pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; 3223 pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
3224 } 3224 }
3225 if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3225 if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
3226 if (rdev->mode_info.crtcs[1]->base.enabled) { 3226 if (rdev->mode_info.crtcs[1]->base.enabled) {
3227 mode2 = &rdev->mode_info.crtcs[1]->base.mode; 3227 mode2 = &rdev->mode_info.crtcs[1]->base.mode;
3228 pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; 3228 pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
3229 } 3229 }
3230 } 3230 }
3231 3231
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 82d4f865546e..c566b486ca08 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
89 89
90 if (crtc && crtc->enabled) { 90 if (crtc && crtc->enabled) {
91 drm_crtc_helper_set_mode(crtc, &crtc->mode, 91 drm_crtc_helper_set_mode(crtc, &crtc->mode,
92 crtc->x, crtc->y, crtc->fb); 92 crtc->x, crtc->y, crtc->primary->fb);
93 } 93 }
94} 94}
95 95
@@ -1595,6 +1595,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1595 uint32_t subpixel_order = SubPixelNone; 1595 uint32_t subpixel_order = SubPixelNone;
1596 bool shared_ddc = false; 1596 bool shared_ddc = false;
1597 bool is_dp_bridge = false; 1597 bool is_dp_bridge = false;
1598 bool has_aux = false;
1598 1599
1599 if (connector_type == DRM_MODE_CONNECTOR_Unknown) 1600 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
1600 return; 1601 return;
@@ -1672,7 +1673,9 @@ radeon_add_atom_connector(struct drm_device *dev,
1672 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); 1673 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
1673 else 1674 else
1674 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); 1675 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
1675 if (!radeon_dig_connector->dp_i2c_bus) 1676 if (radeon_dig_connector->dp_i2c_bus)
1677 has_aux = true;
1678 else
1676 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); 1679 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
1677 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); 1680 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
1678 if (!radeon_connector->ddc_bus) 1681 if (!radeon_connector->ddc_bus)
@@ -1895,7 +1898,9 @@ radeon_add_atom_connector(struct drm_device *dev,
1895 if (!radeon_dig_connector->dp_i2c_bus) 1898 if (!radeon_dig_connector->dp_i2c_bus)
1896 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); 1899 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
1897 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); 1900 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
1898 if (!radeon_connector->ddc_bus) 1901 if (radeon_connector->ddc_bus)
1902 has_aux = true;
1903 else
1899 DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); 1904 DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1900 } 1905 }
1901 subpixel_order = SubPixelHorizontalRGB; 1906 subpixel_order = SubPixelHorizontalRGB;
@@ -1939,7 +1944,9 @@ radeon_add_atom_connector(struct drm_device *dev,
1939 if (i2c_bus->valid) { 1944 if (i2c_bus->valid) {
1940 /* add DP i2c bus */ 1945 /* add DP i2c bus */
1941 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); 1946 radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
1942 if (!radeon_dig_connector->dp_i2c_bus) 1947 if (radeon_dig_connector->dp_i2c_bus)
1948 has_aux = true;
1949 else
1943 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); 1950 DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
1944 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); 1951 radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
1945 if (!radeon_connector->ddc_bus) 1952 if (!radeon_connector->ddc_bus)
@@ -2000,6 +2007,10 @@ radeon_add_atom_connector(struct drm_device *dev,
2000 2007
2001 connector->display_info.subpixel_order = subpixel_order; 2008 connector->display_info.subpixel_order = subpixel_order;
2002 drm_sysfs_connector_add(connector); 2009 drm_sysfs_connector_add(connector);
2010
2011 if (has_aux)
2012 radeon_dp_aux_init(radeon_connector);
2013
2003 return; 2014 return;
2004 2015
2005failed: 2016failed:
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 2e72dcd94b13..835516d2d257 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1424,7 +1424,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
1424 1424
1425 /* unpin the front buffers */ 1425 /* unpin the front buffers */
1426 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1426 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1427 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); 1427 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb);
1428 struct radeon_bo *robj; 1428 struct radeon_bo *robj;
1429 1429
1430 if (rfb == NULL || rfb->obj == NULL) { 1430 if (rfb == NULL || rfb->obj == NULL) {
@@ -1551,10 +1551,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
1551 /* reset hpd state */ 1551 /* reset hpd state */
1552 radeon_hpd_init(rdev); 1552 radeon_hpd_init(rdev);
1553 /* blat the mode back in */ 1553 /* blat the mode back in */
1554 drm_helper_resume_force_mode(dev); 1554 if (fbcon) {
1555 /* turn on display hw */ 1555 drm_helper_resume_force_mode(dev);
1556 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1556 /* turn on display hw */
1557 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 1557 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1558 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
1559 }
1558 } 1560 }
1559 1561
1560 drm_kms_helper_poll_enable(dev); 1562 drm_kms_helper_poll_enable(dev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index fbd8b930f2be..386cfa4c194d 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -34,6 +34,8 @@
34#include <drm/drm_crtc_helper.h> 34#include <drm/drm_crtc_helper.h>
35#include <drm/drm_edid.h> 35#include <drm/drm_edid.h>
36 36
37#include <linux/gcd.h>
38
37static void avivo_crtc_load_lut(struct drm_crtc *crtc) 39static void avivo_crtc_load_lut(struct drm_crtc *crtc)
38{ 40{
39 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 41 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -369,7 +371,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
369 work->event = event; 371 work->event = event;
370 work->rdev = rdev; 372 work->rdev = rdev;
371 work->crtc_id = radeon_crtc->crtc_id; 373 work->crtc_id = radeon_crtc->crtc_id;
372 old_radeon_fb = to_radeon_framebuffer(crtc->fb); 374 old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
373 new_radeon_fb = to_radeon_framebuffer(fb); 375 new_radeon_fb = to_radeon_framebuffer(fb);
374 /* schedule unpin of the old buffer */ 376 /* schedule unpin of the old buffer */
375 obj = old_radeon_fb->obj; 377 obj = old_radeon_fb->obj;
@@ -460,7 +462,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
460 spin_unlock_irqrestore(&dev->event_lock, flags); 462 spin_unlock_irqrestore(&dev->event_lock, flags);
461 463
462 /* update crtc fb */ 464 /* update crtc fb */
463 crtc->fb = fb; 465 crtc->primary->fb = fb;
464 466
465 r = drm_vblank_get(dev, radeon_crtc->crtc_id); 467 r = drm_vblank_get(dev, radeon_crtc->crtc_id);
466 if (r) { 468 if (r) {
@@ -792,6 +794,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
792 if (radeon_connector->edid) { 794 if (radeon_connector->edid) {
793 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); 795 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
794 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); 796 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
797 drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
795 return ret; 798 return ret;
796 } 799 }
797 drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); 800 drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
@@ -799,66 +802,57 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
799} 802}
800 803
801/* avivo */ 804/* avivo */
802static void avivo_get_fb_div(struct radeon_pll *pll,
803 u32 target_clock,
804 u32 post_div,
805 u32 ref_div,
806 u32 *fb_div,
807 u32 *frac_fb_div)
808{
809 u32 tmp = post_div * ref_div;
810 805
811 tmp *= target_clock; 806/**
812 *fb_div = tmp / pll->reference_freq; 807 * avivo_reduce_ratio - fractional number reduction
813 *frac_fb_div = tmp % pll->reference_freq; 808 *
814 809 * @nom: nominator
815 if (*fb_div > pll->max_feedback_div) 810 * @den: denominator
816 *fb_div = pll->max_feedback_div; 811 * @nom_min: minimum value for nominator
817 else if (*fb_div < pll->min_feedback_div) 812 * @den_min: minimum value for denominator
818 *fb_div = pll->min_feedback_div; 813 *
819} 814 * Find the greatest common divisor and apply it on both nominator and
820 815 * denominator, but make nominator and denominator are at least as large
821static u32 avivo_get_post_div(struct radeon_pll *pll, 816 * as their minimum values.
822 u32 target_clock) 817 */
818static void avivo_reduce_ratio(unsigned *nom, unsigned *den,
819 unsigned nom_min, unsigned den_min)
823{ 820{
824 u32 vco, post_div, tmp; 821 unsigned tmp;
825 822
826 if (pll->flags & RADEON_PLL_USE_POST_DIV) 823 /* reduce the numbers to a simpler ratio */
827 return pll->post_div; 824 tmp = gcd(*nom, *den);
828 825 *nom /= tmp;
829 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { 826 *den /= tmp;
830 if (pll->flags & RADEON_PLL_IS_LCD) 827
831 vco = pll->lcd_pll_out_min; 828 /* make sure nominator is large enough */
832 else 829 if (*nom < nom_min) {
833 vco = pll->pll_out_min; 830 tmp = (nom_min + *nom - 1) / *nom;
834 } else { 831 *nom *= tmp;
835 if (pll->flags & RADEON_PLL_IS_LCD) 832 *den *= tmp;
836 vco = pll->lcd_pll_out_max;
837 else
838 vco = pll->pll_out_max;
839 } 833 }
840 834
841 post_div = vco / target_clock; 835 /* make sure the denominator is large enough */
842 tmp = vco % target_clock; 836 if (*den < den_min) {
843 837 tmp = (den_min + *den - 1) / *den;
844 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { 838 *nom *= tmp;
845 if (tmp) 839 *den *= tmp;
846 post_div++;
847 } else {
848 if (!tmp)
849 post_div--;
850 } 840 }
851
852 if (post_div > pll->max_post_div)
853 post_div = pll->max_post_div;
854 else if (post_div < pll->min_post_div)
855 post_div = pll->min_post_div;
856
857 return post_div;
858} 841}
859 842
860#define MAX_TOLERANCE 10 843/**
861 844 * radeon_compute_pll_avivo - compute PLL paramaters
845 *
846 * @pll: information about the PLL
847 * @dot_clock_p: resulting pixel clock
848 * fb_div_p: resulting feedback divider
849 * frac_fb_div_p: fractional part of the feedback divider
850 * ref_div_p: resulting reference divider
851 * post_div_p: resulting reference divider
852 *
853 * Try to calculate the PLL parameters to generate the given frequency:
854 * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div)
855 */
862void radeon_compute_pll_avivo(struct radeon_pll *pll, 856void radeon_compute_pll_avivo(struct radeon_pll *pll,
863 u32 freq, 857 u32 freq,
864 u32 *dot_clock_p, 858 u32 *dot_clock_p,
@@ -867,53 +861,123 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
867 u32 *ref_div_p, 861 u32 *ref_div_p,
868 u32 *post_div_p) 862 u32 *post_div_p)
869{ 863{
870 u32 target_clock = freq / 10; 864 unsigned fb_div_min, fb_div_max, fb_div;
871 u32 post_div = avivo_get_post_div(pll, target_clock); 865 unsigned post_div_min, post_div_max, post_div;
872 u32 ref_div = pll->min_ref_div; 866 unsigned ref_div_min, ref_div_max, ref_div;
873 u32 fb_div = 0, frac_fb_div = 0, tmp; 867 unsigned post_div_best, diff_best;
868 unsigned nom, den, tmp;
874 869
875 if (pll->flags & RADEON_PLL_USE_REF_DIV) 870 /* determine allowed feedback divider range */
876 ref_div = pll->reference_div; 871 fb_div_min = pll->min_feedback_div;
872 fb_div_max = pll->max_feedback_div;
877 873
878 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { 874 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
879 avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div); 875 fb_div_min *= 10;
880 frac_fb_div = (100 * frac_fb_div) / pll->reference_freq; 876 fb_div_max *= 10;
881 if (frac_fb_div >= 5) { 877 }
882 frac_fb_div -= 5; 878
883 frac_fb_div = frac_fb_div / 10; 879 /* determine allowed ref divider range */
884 frac_fb_div++; 880 if (pll->flags & RADEON_PLL_USE_REF_DIV)
881 ref_div_min = pll->reference_div;
882 else
883 ref_div_min = pll->min_ref_div;
884 ref_div_max = pll->max_ref_div;
885
886 /* determine allowed post divider range */
887 if (pll->flags & RADEON_PLL_USE_POST_DIV) {
888 post_div_min = pll->post_div;
889 post_div_max = pll->post_div;
890 } else {
891 unsigned target_clock = freq / 10;
892 unsigned vco_min, vco_max;
893
894 if (pll->flags & RADEON_PLL_IS_LCD) {
895 vco_min = pll->lcd_pll_out_min;
896 vco_max = pll->lcd_pll_out_max;
897 } else {
898 vco_min = pll->pll_out_min;
899 vco_max = pll->pll_out_max;
885 } 900 }
886 if (frac_fb_div >= 10) { 901
887 fb_div++; 902 post_div_min = vco_min / target_clock;
888 frac_fb_div = 0; 903 if ((target_clock * post_div_min) < vco_min)
904 ++post_div_min;
905 if (post_div_min < pll->min_post_div)
906 post_div_min = pll->min_post_div;
907
908 post_div_max = vco_max / target_clock;
909 if ((target_clock * post_div_max) > vco_max)
910 --post_div_max;
911 if (post_div_max > pll->max_post_div)
912 post_div_max = pll->max_post_div;
913 }
914
915 /* represent the searched ratio as fractional number */
916 nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10;
917 den = pll->reference_freq;
918
919 /* reduce the numbers to a simpler ratio */
920 avivo_reduce_ratio(&nom, &den, fb_div_min, post_div_min);
921
922 /* now search for a post divider */
923 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP)
924 post_div_best = post_div_min;
925 else
926 post_div_best = post_div_max;
927 diff_best = ~0;
928
929 for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
930 unsigned diff = abs(den - den / post_div * post_div);
931 if (diff < diff_best || (diff == diff_best &&
932 !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) {
933
934 post_div_best = post_div;
935 diff_best = diff;
889 } 936 }
937 }
938 post_div = post_div_best;
939
940 /* get matching reference and feedback divider */
941 ref_div = max(den / post_div, 1u);
942 fb_div = nom;
943
944 /* we're almost done, but reference and feedback
945 divider might be to large now */
946
947 tmp = ref_div;
948
949 if (fb_div > fb_div_max) {
950 ref_div = ref_div * fb_div_max / fb_div;
951 fb_div = fb_div_max;
952 }
953
954 if (ref_div > ref_div_max) {
955 ref_div = ref_div_max;
956 fb_div = nom * ref_div_max / tmp;
957 }
958
959 /* reduce the numbers to a simpler ratio once more */
960 /* this also makes sure that the reference divider is large enough */
961 avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min);
962
963 /* and finally save the result */
964 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
965 *fb_div_p = fb_div / 10;
966 *frac_fb_div_p = fb_div % 10;
890 } else { 967 } else {
891 while (ref_div <= pll->max_ref_div) { 968 *fb_div_p = fb_div;
892 avivo_get_fb_div(pll, target_clock, post_div, ref_div, 969 *frac_fb_div_p = 0;
893 &fb_div, &frac_fb_div);
894 if (frac_fb_div >= (pll->reference_freq / 2))
895 fb_div++;
896 frac_fb_div = 0;
897 tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
898 tmp = (tmp * 10000) / target_clock;
899
900 if (tmp > (10000 + MAX_TOLERANCE))
901 ref_div++;
902 else if (tmp >= (10000 - MAX_TOLERANCE))
903 break;
904 else
905 ref_div++;
906 }
907 } 970 }
908 971
909 *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / 972 *dot_clock_p = ((pll->reference_freq * *fb_div_p * 10) +
910 (ref_div * post_div * 10); 973 (pll->reference_freq * *frac_fb_div_p)) /
911 *fb_div_p = fb_div; 974 (ref_div * post_div * 10);
912 *frac_fb_div_p = frac_fb_div;
913 *ref_div_p = ref_div; 975 *ref_div_p = ref_div;
914 *post_div_p = post_div; 976 *post_div_p = post_div;
915 DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n", 977
916 *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div); 978 DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
979 freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p,
980 ref_div, post_div);
917} 981}
918 982
919/* pre-avivo */ 983/* pre-avivo */
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 2dc2cc48f92b..d0eba48dd74e 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -79,7 +79,8 @@
79 * 2.35.0 - Add CIK macrotile mode array query 79 * 2.35.0 - Add CIK macrotile mode array query
80 * 2.36.0 - Fix CIK DCE tiling setup 80 * 2.36.0 - Fix CIK DCE tiling setup
81 * 2.37.0 - allow GS ring setup on r6xx/r7xx 81 * 2.37.0 - allow GS ring setup on r6xx/r7xx
82 * 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN) 82 * 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN),
83 * CIK: 1D and linear tiling modes contain valid PIPE_CONFIG
83 */ 84 */
84#define KMS_DRIVER_MAJOR 2 85#define KMS_DRIVER_MAJOR 2
85#define KMS_DRIVER_MINOR 38 86#define KMS_DRIVER_MINOR 38
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 6f1dfac17507..3e49342a20e6 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -575,10 +575,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
575 if (r) 575 if (r)
576 return r; 576 return r;
577 577
578 r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
579 if (r)
580 return r;
581
582 /* map the ib pool buffer read only into 578 /* map the ib pool buffer read only into
583 * virtual address space */ 579 * virtual address space */
584 bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, 580 bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0b158f98d287..cafb1ccf2ec3 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
385 385
386 DRM_DEBUG_KMS("\n"); 386 DRM_DEBUG_KMS("\n");
387 /* no fb bound */ 387 /* no fb bound */
388 if (!atomic && !crtc->fb) { 388 if (!atomic && !crtc->primary->fb) {
389 DRM_DEBUG_KMS("No FB bound\n"); 389 DRM_DEBUG_KMS("No FB bound\n");
390 return 0; 390 return 0;
391 } 391 }
@@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
395 target_fb = fb; 395 target_fb = fb;
396 } 396 }
397 else { 397 else {
398 radeon_fb = to_radeon_framebuffer(crtc->fb); 398 radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
399 target_fb = crtc->fb; 399 target_fb = crtc->primary->fb;
400 } 400 }
401 401
402 switch (target_fb->bits_per_pixel) { 402 switch (target_fb->bits_per_pixel) {
@@ -444,7 +444,7 @@ retry:
444 * We don't shutdown the display controller because new buffer 444 * We don't shutdown the display controller because new buffer
445 * will end up in same spot. 445 * will end up in same spot.
446 */ 446 */
447 if (!atomic && fb && fb != crtc->fb) { 447 if (!atomic && fb && fb != crtc->primary->fb) {
448 struct radeon_bo *old_rbo; 448 struct radeon_bo *old_rbo;
449 unsigned long nsize, osize; 449 unsigned long nsize, osize;
450 450
@@ -555,7 +555,7 @@ retry:
555 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); 555 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
556 WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); 556 WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
557 557
558 if (!atomic && fb && fb != crtc->fb) { 558 if (!atomic && fb && fb != crtc->primary->fb) {
559 radeon_fb = to_radeon_framebuffer(fb); 559 radeon_fb = to_radeon_framebuffer(fb);
560 rbo = gem_to_radeon_bo(radeon_fb->obj); 560 rbo = gem_to_radeon_bo(radeon_fb->obj);
561 r = radeon_bo_reserve(rbo, false); 561 r = radeon_bo_reserve(rbo, false);
@@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
599 } 599 }
600 } 600 }
601 601
602 switch (crtc->fb->bits_per_pixel) { 602 switch (crtc->primary->fb->bits_per_pixel) {
603 case 8: 603 case 8:
604 format = 2; 604 format = 2;
605 break; 605 break;
@@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
1087static void radeon_crtc_disable(struct drm_crtc *crtc) 1087static void radeon_crtc_disable(struct drm_crtc *crtc)
1088{ 1088{
1089 radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1089 radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1090 if (crtc->fb) { 1090 if (crtc->primary->fb) {
1091 int r; 1091 int r;
1092 struct radeon_framebuffer *radeon_fb; 1092 struct radeon_framebuffer *radeon_fb;
1093 struct radeon_bo *rbo; 1093 struct radeon_bo *rbo;
1094 1094
1095 radeon_fb = to_radeon_framebuffer(crtc->fb); 1095 radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
1096 rbo = gem_to_radeon_bo(radeon_fb->obj); 1096 rbo = gem_to_radeon_bo(radeon_fb->obj);
1097 r = radeon_bo_reserve(rbo, false); 1097 r = radeon_bo_reserve(rbo, false);
1098 if (unlikely(r)) 1098 if (unlikely(r))
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 402dbe32c234..832d9fa1a4c4 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -192,6 +192,7 @@ struct radeon_i2c_chan {
192 struct i2c_algo_dp_aux_data dp; 192 struct i2c_algo_dp_aux_data dp;
193 } algo; 193 } algo;
194 struct radeon_i2c_bus_rec rec; 194 struct radeon_i2c_bus_rec rec;
195 struct drm_dp_aux aux;
195}; 196};
196 197
197/* mostly for macs, but really any system without connector tables */ 198/* mostly for macs, but really any system without connector tables */
@@ -690,6 +691,9 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
690extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); 691extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
691extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, 692extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
692 struct drm_connector *connector); 693 struct drm_connector *connector);
694extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
695 u8 power_state);
696extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
693extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); 697extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
694extern void radeon_atom_encoder_init(struct radeon_device *rdev); 698extern void radeon_atom_encoder_init(struct radeon_device *rdev);
695extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev); 699extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 1375ff85b08a..19bec0dbfa38 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -104,7 +104,7 @@ bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
104 104
105void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) 105void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
106{ 106{
107 u32 c = 0; 107 u32 c = 0, i;
108 108
109 rbo->placement.fpfn = 0; 109 rbo->placement.fpfn = 0;
110 rbo->placement.lpfn = 0; 110 rbo->placement.lpfn = 0;
@@ -131,6 +131,17 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
131 rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; 131 rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
132 rbo->placement.num_placement = c; 132 rbo->placement.num_placement = c;
133 rbo->placement.num_busy_placement = c; 133 rbo->placement.num_busy_placement = c;
134
135 /*
136 * Use two-ended allocation depending on the buffer size to
137 * improve fragmentation quality.
138 * 512kb was measured as the most optimal number.
139 */
140 if (rbo->tbo.mem.size > 512 * 1024) {
141 for (i = 0; i < c; i++) {
142 rbo->placements[i] |= TTM_PL_FLAG_TOPDOWN;
143 }
144 }
134} 145}
135 146
136int radeon_bo_create(struct radeon_device *rdev, 147int radeon_bo_create(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 8b0dfdd23793..f8050f5429e2 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -262,6 +262,7 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
262 r = radeon_ib_test(rdev, i, ring); 262 r = radeon_ib_test(rdev, i, ring);
263 if (r) { 263 if (r) {
264 ring->ready = false; 264 ring->ready = false;
265 rdev->needs_reset = false;
265 266
266 if (i == RADEON_RING_TYPE_GFX_INDEX) { 267 if (i == RADEON_RING_TYPE_GFX_INDEX) {
267 /* oh, oh, that's really bad */ 268 /* oh, oh, that's really bad */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index fbf4be316d0b..299267db2898 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -299,7 +299,7 @@ static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
299{ 299{
300 struct drm_crtc *crtc = &rcrtc->crtc; 300 struct drm_crtc *crtc = &rcrtc->crtc;
301 301
302 rcar_du_plane_compute_base(rcrtc->plane, crtc->fb); 302 rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
303 rcar_du_plane_update_base(rcrtc->plane); 303 rcar_du_plane_update_base(rcrtc->plane);
304} 304}
305 305
@@ -358,10 +358,10 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
358 const struct rcar_du_format_info *format; 358 const struct rcar_du_format_info *format;
359 int ret; 359 int ret;
360 360
361 format = rcar_du_format_info(crtc->fb->pixel_format); 361 format = rcar_du_format_info(crtc->primary->fb->pixel_format);
362 if (format == NULL) { 362 if (format == NULL) {
363 dev_dbg(rcdu->dev, "mode_set: unsupported format %08x\n", 363 dev_dbg(rcdu->dev, "mode_set: unsupported format %08x\n",
364 crtc->fb->pixel_format); 364 crtc->primary->fb->pixel_format);
365 ret = -EINVAL; 365 ret = -EINVAL;
366 goto error; 366 goto error;
367 } 367 }
@@ -377,7 +377,7 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
377 rcrtc->plane->width = mode->hdisplay; 377 rcrtc->plane->width = mode->hdisplay;
378 rcrtc->plane->height = mode->vdisplay; 378 rcrtc->plane->height = mode->vdisplay;
379 379
380 rcar_du_plane_compute_base(rcrtc->plane, crtc->fb); 380 rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
381 381
382 rcrtc->outputs = 0; 382 rcrtc->outputs = 0;
383 383
@@ -510,7 +510,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
510 } 510 }
511 spin_unlock_irqrestore(&dev->event_lock, flags); 511 spin_unlock_irqrestore(&dev->event_lock, flags);
512 512
513 crtc->fb = fb; 513 crtc->primary->fb = fb;
514 rcar_du_crtc_update_base(rcrtc); 514 rcar_du_crtc_update_base(rcrtc);
515 515
516 if (event) { 516 if (event) {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index fbeabd9a281f..a87edfac111f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -248,7 +248,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
248 continue; 248 continue;
249 } 249 }
250 250
251 rcar_du_encoder_init(rcdu, pdata->type, pdata->output, pdata); 251 ret = rcar_du_encoder_init(rcdu, pdata->type, pdata->output,
252 pdata);
253 if (ret < 0)
254 return ret;
252 } 255 }
253 256
254 /* Set the possible CRTCs and possible clones. There's always at least 257 /* Set the possible CRTCs and possible clones. There's always at least
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 0428076f1ce8..e9e5e6d368cc 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -173,7 +173,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
173 if (scrtc->started) 173 if (scrtc->started)
174 return; 174 return;
175 175
176 format = shmob_drm_format_info(crtc->fb->pixel_format); 176 format = shmob_drm_format_info(crtc->primary->fb->pixel_format);
177 if (WARN_ON(format == NULL)) 177 if (WARN_ON(format == NULL))
178 return; 178 return;
179 179
@@ -247,7 +247,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
247 lcdc_write(sdev, LDDDSR, value); 247 lcdc_write(sdev, LDDDSR, value);
248 248
249 /* Setup planes. */ 249 /* Setup planes. */
250 list_for_each_entry(plane, &dev->mode_config.plane_list, head) { 250 drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
251 if (plane->crtc == crtc) 251 if (plane->crtc == crtc)
252 shmob_drm_plane_setup(plane); 252 shmob_drm_plane_setup(plane);
253 } 253 }
@@ -303,7 +303,7 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
303 int x, int y) 303 int x, int y)
304{ 304{
305 struct drm_crtc *crtc = &scrtc->crtc; 305 struct drm_crtc *crtc = &scrtc->crtc;
306 struct drm_framebuffer *fb = crtc->fb; 306 struct drm_framebuffer *fb = crtc->primary->fb;
307 struct shmob_drm_device *sdev = crtc->dev->dev_private; 307 struct shmob_drm_device *sdev = crtc->dev->dev_private;
308 struct drm_gem_cma_object *gem; 308 struct drm_gem_cma_object *gem;
309 unsigned int bpp; 309 unsigned int bpp;
@@ -382,15 +382,15 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
382 const struct shmob_drm_format_info *format; 382 const struct shmob_drm_format_info *format;
383 void *cache; 383 void *cache;
384 384
385 format = shmob_drm_format_info(crtc->fb->pixel_format); 385 format = shmob_drm_format_info(crtc->primary->fb->pixel_format);
386 if (format == NULL) { 386 if (format == NULL) {
387 dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n", 387 dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n",
388 crtc->fb->pixel_format); 388 crtc->primary->fb->pixel_format);
389 return -EINVAL; 389 return -EINVAL;
390 } 390 }
391 391
392 scrtc->format = format; 392 scrtc->format = format;
393 scrtc->line_size = crtc->fb->pitches[0]; 393 scrtc->line_size = crtc->primary->fb->pitches[0];
394 394
395 if (sdev->meram) { 395 if (sdev->meram) {
396 /* Enable MERAM cache if configured. We need to de-init 396 /* Enable MERAM cache if configured. We need to de-init
@@ -402,7 +402,7 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
402 } 402 }
403 403
404 cache = sh_mobile_meram_cache_alloc(sdev->meram, mdata, 404 cache = sh_mobile_meram_cache_alloc(sdev->meram, mdata,
405 crtc->fb->pitches[0], 405 crtc->primary->fb->pitches[0],
406 adjusted_mode->vdisplay, 406 adjusted_mode->vdisplay,
407 format->meram, 407 format->meram,
408 &scrtc->line_size); 408 &scrtc->line_size);
@@ -489,7 +489,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
489 } 489 }
490 spin_unlock_irqrestore(&dev->event_lock, flags); 490 spin_unlock_irqrestore(&dev->event_lock, flags);
491 491
492 crtc->fb = fb; 492 crtc->primary->fb = fb;
493 shmob_drm_crtc_update_base(scrtc); 493 shmob_drm_crtc_update_base(scrtc);
494 494
495 if (event) { 495 if (event) {
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 8d220afbd85f..d43f21bb4596 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -11,6 +11,8 @@ tegra-drm-y := \
11 hdmi.o \ 11 hdmi.o \
12 mipi-phy.o \ 12 mipi-phy.o \
13 dsi.o \ 13 dsi.o \
14 sor.o \
15 dpaux.o \
14 gr2d.o \ 16 gr2d.o \
15 gr3d.o 17 gr3d.o
16 18
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 9336006b475d..36c717af6cf9 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -235,14 +235,14 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
235 if (!dc->event) 235 if (!dc->event)
236 return; 236 return;
237 237
238 bo = tegra_fb_get_plane(crtc->fb, 0); 238 bo = tegra_fb_get_plane(crtc->primary->fb, 0);
239 239
240 /* check if new start address has been latched */ 240 /* check if new start address has been latched */
241 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); 241 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
242 base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); 242 base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
243 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); 243 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
244 244
245 if (base == bo->paddr + crtc->fb->offsets[0]) { 245 if (base == bo->paddr + crtc->primary->fb->offsets[0]) {
246 spin_lock_irqsave(&drm->event_lock, flags); 246 spin_lock_irqsave(&drm->event_lock, flags);
247 drm_send_vblank_event(drm, dc->pipe, dc->event); 247 drm_send_vblank_event(drm, dc->pipe, dc->event);
248 drm_vblank_put(drm, dc->pipe); 248 drm_vblank_put(drm, dc->pipe);
@@ -284,7 +284,7 @@ static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
284 } 284 }
285 285
286 tegra_dc_set_base(dc, 0, 0, fb); 286 tegra_dc_set_base(dc, 0, 0, fb);
287 crtc->fb = fb; 287 crtc->primary->fb = fb;
288 288
289 return 0; 289 return 0;
290} 290}
@@ -645,7 +645,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
645 struct drm_display_mode *adjusted, 645 struct drm_display_mode *adjusted,
646 int x, int y, struct drm_framebuffer *old_fb) 646 int x, int y, struct drm_framebuffer *old_fb)
647{ 647{
648 struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0); 648 struct tegra_bo *bo = tegra_fb_get_plane(crtc->primary->fb, 0);
649 struct tegra_dc *dc = to_tegra_dc(crtc); 649 struct tegra_dc *dc = to_tegra_dc(crtc);
650 struct tegra_dc_window window; 650 struct tegra_dc_window window;
651 unsigned long div, value; 651 unsigned long div, value;
@@ -682,9 +682,9 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
682 window.dst.y = 0; 682 window.dst.y = 0;
683 window.dst.w = mode->hdisplay; 683 window.dst.w = mode->hdisplay;
684 window.dst.h = mode->vdisplay; 684 window.dst.h = mode->vdisplay;
685 window.format = tegra_dc_format(crtc->fb->pixel_format); 685 window.format = tegra_dc_format(crtc->primary->fb->pixel_format);
686 window.bits_per_pixel = crtc->fb->bits_per_pixel; 686 window.bits_per_pixel = crtc->primary->fb->bits_per_pixel;
687 window.stride[0] = crtc->fb->pitches[0]; 687 window.stride[0] = crtc->primary->fb->pitches[0];
688 window.base[0] = bo->paddr; 688 window.base[0] = bo->paddr;
689 689
690 err = tegra_dc_setup_window(dc, 0, &window); 690 err = tegra_dc_setup_window(dc, 0, &window);
@@ -699,7 +699,7 @@ static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
699{ 699{
700 struct tegra_dc *dc = to_tegra_dc(crtc); 700 struct tegra_dc *dc = to_tegra_dc(crtc);
701 701
702 return tegra_dc_set_base(dc, x, y, crtc->fb); 702 return tegra_dc_set_base(dc, x, y, crtc->primary->fb);
703} 703}
704 704
705static void tegra_crtc_prepare(struct drm_crtc *crtc) 705static void tegra_crtc_prepare(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3c2c0ea1cd87..c94101494826 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -118,6 +118,7 @@
118#define DC_DISP_DISP_WIN_OPTIONS 0x402 118#define DC_DISP_DISP_WIN_OPTIONS 0x402
119#define HDMI_ENABLE (1 << 30) 119#define HDMI_ENABLE (1 << 30)
120#define DSI_ENABLE (1 << 29) 120#define DSI_ENABLE (1 << 29)
121#define SOR_ENABLE (1 << 25)
121 122
122#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 123#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
123#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) 124#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
new file mode 100644
index 000000000000..d536ed381fbd
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -0,0 +1,544 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/gpio.h>
12#include <linux/interrupt.h>
13#include <linux/io.h>
14#include <linux/of_gpio.h>
15#include <linux/platform_device.h>
16#include <linux/reset.h>
17#include <linux/regulator/consumer.h>
18
19#include <drm/drm_dp_helper.h>
20#include <drm/drm_panel.h>
21
22#include "dpaux.h"
23#include "drm.h"
24
25static DEFINE_MUTEX(dpaux_lock);
26static LIST_HEAD(dpaux_list);
27
28struct tegra_dpaux {
29 struct drm_dp_aux aux;
30 struct device *dev;
31
32 void __iomem *regs;
33 int irq;
34
35 struct tegra_output *output;
36
37 struct reset_control *rst;
38 struct clk *clk_parent;
39 struct clk *clk;
40
41 struct regulator *vdd;
42
43 struct completion complete;
44 struct list_head list;
45};
46
47static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
48{
49 return container_of(aux, struct tegra_dpaux, aux);
50}
51
52static inline unsigned long tegra_dpaux_readl(struct tegra_dpaux *dpaux,
53 unsigned long offset)
54{
55 return readl(dpaux->regs + (offset << 2));
56}
57
58static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
59 unsigned long value,
60 unsigned long offset)
61{
62 writel(value, dpaux->regs + (offset << 2));
63}
64
65static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
66 size_t size)
67{
68 unsigned long offset = DPAUX_DP_AUXDATA_WRITE(0);
69 size_t i, j;
70
71 for (i = 0; i < size; i += 4) {
72 size_t num = min_t(size_t, size - i, 4);
73 unsigned long value = 0;
74
75 for (j = 0; j < num; j++)
76 value |= buffer[i + j] << (j * 8);
77
78 tegra_dpaux_writel(dpaux, value, offset++);
79 }
80}
81
82static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
83 size_t size)
84{
85 unsigned long offset = DPAUX_DP_AUXDATA_READ(0);
86 size_t i, j;
87
88 for (i = 0; i < size; i += 4) {
89 size_t num = min_t(size_t, size - i, 4);
90 unsigned long value;
91
92 value = tegra_dpaux_readl(dpaux, offset++);
93
94 for (j = 0; j < num; j++)
95 buffer[i + j] = value >> (j * 8);
96 }
97}
98
99static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
100 struct drm_dp_aux_msg *msg)
101{
102 unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ;
103 unsigned long timeout = msecs_to_jiffies(250);
104 struct tegra_dpaux *dpaux = to_dpaux(aux);
105 unsigned long status;
106 ssize_t ret = 0;
107
108 if (msg->size < 1 || msg->size > 16)
109 return -EINVAL;
110
111 tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
112
113 switch (msg->request & ~DP_AUX_I2C_MOT) {
114 case DP_AUX_I2C_WRITE:
115 if (msg->request & DP_AUX_I2C_MOT)
116 value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
117 else
118 value = DPAUX_DP_AUXCTL_CMD_I2C_WR;
119
120 break;
121
122 case DP_AUX_I2C_READ:
123 if (msg->request & DP_AUX_I2C_MOT)
124 value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
125 else
126 value = DPAUX_DP_AUXCTL_CMD_I2C_RD;
127
128 break;
129
130 case DP_AUX_I2C_STATUS:
131 if (msg->request & DP_AUX_I2C_MOT)
132 value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
133 else
134 value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;
135
136 break;
137
138 case DP_AUX_NATIVE_WRITE:
139 value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
140 break;
141
142 case DP_AUX_NATIVE_READ:
143 value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
144 break;
145
146 default:
147 return -EINVAL;
148 }
149
150 value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
151 tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
152
153 if ((msg->request & DP_AUX_I2C_READ) == 0) {
154 tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
155 ret = msg->size;
156 }
157
158 /* start transaction */
159 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
160 value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
161 tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
162
163 status = wait_for_completion_timeout(&dpaux->complete, timeout);
164 if (!status)
165 return -ETIMEDOUT;
166
167 /* read status and clear errors */
168 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
169 tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);
170
171 if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
172 return -ETIMEDOUT;
173
174 if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
175 (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
176 (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
177 return -EIO;
178
179 switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
180 case 0x00:
181 msg->reply = DP_AUX_NATIVE_REPLY_ACK;
182 break;
183
184 case 0x01:
185 msg->reply = DP_AUX_NATIVE_REPLY_NACK;
186 break;
187
188 case 0x02:
189 msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
190 break;
191
192 case 0x04:
193 msg->reply = DP_AUX_I2C_REPLY_NACK;
194 break;
195
196 case 0x08:
197 msg->reply = DP_AUX_I2C_REPLY_DEFER;
198 break;
199 }
200
201 if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
202 if (msg->request & DP_AUX_I2C_READ) {
203 size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
204
205 if (WARN_ON(count != msg->size))
206 count = min_t(size_t, count, msg->size);
207
208 tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
209 ret = count;
210 }
211 }
212
213 return ret;
214}
215
216static irqreturn_t tegra_dpaux_irq(int irq, void *data)
217{
218 struct tegra_dpaux *dpaux = data;
219 irqreturn_t ret = IRQ_HANDLED;
220 unsigned long value;
221
222 /* clear interrupts */
223 value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
224 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
225
226 if (value & DPAUX_INTR_PLUG_EVENT) {
227 if (dpaux->output) {
228 drm_helper_hpd_irq_event(dpaux->output->connector.dev);
229 }
230 }
231
232 if (value & DPAUX_INTR_UNPLUG_EVENT) {
233 if (dpaux->output)
234 drm_helper_hpd_irq_event(dpaux->output->connector.dev);
235 }
236
237 if (value & DPAUX_INTR_IRQ_EVENT) {
238 /* TODO: handle this */
239 }
240
241 if (value & DPAUX_INTR_AUX_DONE)
242 complete(&dpaux->complete);
243
244 return ret;
245}
246
247static int tegra_dpaux_probe(struct platform_device *pdev)
248{
249 struct tegra_dpaux *dpaux;
250 struct resource *regs;
251 unsigned long value;
252 int err;
253
254 dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
255 if (!dpaux)
256 return -ENOMEM;
257
258 init_completion(&dpaux->complete);
259 INIT_LIST_HEAD(&dpaux->list);
260 dpaux->dev = &pdev->dev;
261
262 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
263 dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
264 if (IS_ERR(dpaux->regs))
265 return PTR_ERR(dpaux->regs);
266
267 dpaux->irq = platform_get_irq(pdev, 0);
268 if (dpaux->irq < 0) {
269 dev_err(&pdev->dev, "failed to get IRQ\n");
270 return -ENXIO;
271 }
272
273 dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
274 if (IS_ERR(dpaux->rst))
275 return PTR_ERR(dpaux->rst);
276
277 dpaux->clk = devm_clk_get(&pdev->dev, NULL);
278 if (IS_ERR(dpaux->clk))
279 return PTR_ERR(dpaux->clk);
280
281 err = clk_prepare_enable(dpaux->clk);
282 if (err < 0)
283 return err;
284
285 reset_control_deassert(dpaux->rst);
286
287 dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
288 if (IS_ERR(dpaux->clk_parent))
289 return PTR_ERR(dpaux->clk_parent);
290
291 err = clk_prepare_enable(dpaux->clk_parent);
292 if (err < 0)
293 return err;
294
295 err = clk_set_rate(dpaux->clk_parent, 270000000);
296 if (err < 0) {
297 dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
298 err);
299 return err;
300 }
301
302 dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
303 if (IS_ERR(dpaux->vdd))
304 return PTR_ERR(dpaux->vdd);
305
306 err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
307 dev_name(dpaux->dev), dpaux);
308 if (err < 0) {
309 dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
310 dpaux->irq, err);
311 return err;
312 }
313
314 dpaux->aux.transfer = tegra_dpaux_transfer;
315 dpaux->aux.dev = &pdev->dev;
316
317 err = drm_dp_aux_register_i2c_bus(&dpaux->aux);
318 if (err < 0)
319 return err;
320
321 /* enable and clear all interrupts */
322 value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
323 DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
324 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
325 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
326
327 mutex_lock(&dpaux_lock);
328 list_add_tail(&dpaux->list, &dpaux_list);
329 mutex_unlock(&dpaux_lock);
330
331 platform_set_drvdata(pdev, dpaux);
332
333 return 0;
334}
335
336static int tegra_dpaux_remove(struct platform_device *pdev)
337{
338 struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
339
340 drm_dp_aux_unregister_i2c_bus(&dpaux->aux);
341
342 mutex_lock(&dpaux_lock);
343 list_del(&dpaux->list);
344 mutex_unlock(&dpaux_lock);
345
346 clk_disable_unprepare(dpaux->clk_parent);
347 reset_control_assert(dpaux->rst);
348 clk_disable_unprepare(dpaux->clk);
349
350 return 0;
351}
352
353static const struct of_device_id tegra_dpaux_of_match[] = {
354 { .compatible = "nvidia,tegra124-dpaux", },
355 { },
356};
357
358struct platform_driver tegra_dpaux_driver = {
359 .driver = {
360 .name = "tegra-dpaux",
361 .of_match_table = tegra_dpaux_of_match,
362 },
363 .probe = tegra_dpaux_probe,
364 .remove = tegra_dpaux_remove,
365};
366
367struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
368{
369 struct tegra_dpaux *dpaux;
370
371 mutex_lock(&dpaux_lock);
372
373 list_for_each_entry(dpaux, &dpaux_list, list)
374 if (np == dpaux->dev->of_node) {
375 mutex_unlock(&dpaux_lock);
376 return dpaux;
377 }
378
379 mutex_unlock(&dpaux_lock);
380
381 return NULL;
382}
383
384int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
385{
386 unsigned long timeout;
387 int err;
388
389 dpaux->output = output;
390
391 err = regulator_enable(dpaux->vdd);
392 if (err < 0)
393 return err;
394
395 timeout = jiffies + msecs_to_jiffies(250);
396
397 while (time_before(jiffies, timeout)) {
398 enum drm_connector_status status;
399
400 status = tegra_dpaux_detect(dpaux);
401 if (status == connector_status_connected)
402 return 0;
403
404 usleep_range(1000, 2000);
405 }
406
407 return -ETIMEDOUT;
408}
409
410int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
411{
412 unsigned long timeout;
413 int err;
414
415 err = regulator_disable(dpaux->vdd);
416 if (err < 0)
417 return err;
418
419 timeout = jiffies + msecs_to_jiffies(250);
420
421 while (time_before(jiffies, timeout)) {
422 enum drm_connector_status status;
423
424 status = tegra_dpaux_detect(dpaux);
425 if (status == connector_status_disconnected) {
426 dpaux->output = NULL;
427 return 0;
428 }
429
430 usleep_range(1000, 2000);
431 }
432
433 return -ETIMEDOUT;
434}
435
436enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
437{
438 unsigned long value;
439
440 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
441
442 if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
443 return connector_status_connected;
444
445 return connector_status_disconnected;
446}
447
448int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
449{
450 unsigned long value;
451
452 value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
453 DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
454 DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
455 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
456 DPAUX_HYBRID_PADCTL_MODE_AUX;
457 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
458
459 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
460 value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
461 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
462
463 return 0;
464}
465
466int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
467{
468 unsigned long value;
469
470 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
471 value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
472 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
473
474 return 0;
475}
476
477int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
478{
479 int err;
480
481 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
482 encoding);
483 if (err < 0)
484 return err;
485
486 return 0;
487}
488
489int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
490 u8 pattern)
491{
492 u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
493 u8 status[DP_LINK_STATUS_SIZE], values[4];
494 unsigned int i;
495 int err;
496
497 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern);
498 if (err < 0)
499 return err;
500
501 if (tp == DP_TRAINING_PATTERN_DISABLE)
502 return 0;
503
504 for (i = 0; i < link->num_lanes; i++)
505 values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
506 DP_TRAIN_PRE_EMPHASIS_0 |
507 DP_TRAIN_MAX_SWING_REACHED |
508 DP_TRAIN_VOLTAGE_SWING_400;
509
510 err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values,
511 link->num_lanes);
512 if (err < 0)
513 return err;
514
515 usleep_range(500, 1000);
516
517 err = drm_dp_dpcd_read_link_status(&dpaux->aux, status);
518 if (err < 0)
519 return err;
520
521 switch (tp) {
522 case DP_TRAINING_PATTERN_1:
523 if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
524 return -EAGAIN;
525
526 break;
527
528 case DP_TRAINING_PATTERN_2:
529 if (!drm_dp_channel_eq_ok(status, link->num_lanes))
530 return -EAGAIN;
531
532 break;
533
534 default:
535 dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
536 return -EINVAL;
537 }
538
539 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
540 if (err < 0)
541 return err;
542
543 return 0;
544}
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h
new file mode 100644
index 000000000000..4f5bf10fdff9
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.h
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef DRM_TEGRA_DPAUX_H
10#define DRM_TEGRA_DPAUX_H
11
12#define DPAUX_CTXSW 0x00
13
14#define DPAUX_INTR_EN_AUX 0x01
15#define DPAUX_INTR_AUX 0x05
16#define DPAUX_INTR_AUX_DONE (1 << 3)
17#define DPAUX_INTR_IRQ_EVENT (1 << 2)
18#define DPAUX_INTR_UNPLUG_EVENT (1 << 1)
19#define DPAUX_INTR_PLUG_EVENT (1 << 0)
20
21#define DPAUX_DP_AUXDATA_WRITE(x) (0x09 + ((x) << 2))
22#define DPAUX_DP_AUXDATA_READ(x) (0x19 + ((x) << 2))
23#define DPAUX_DP_AUXADDR 0x29
24
25#define DPAUX_DP_AUXCTL 0x2d
26#define DPAUX_DP_AUXCTL_TRANSACTREQ (1 << 16)
27#define DPAUX_DP_AUXCTL_CMD_AUX_RD (9 << 12)
28#define DPAUX_DP_AUXCTL_CMD_AUX_WR (8 << 12)
29#define DPAUX_DP_AUXCTL_CMD_MOT_RQ (6 << 12)
30#define DPAUX_DP_AUXCTL_CMD_MOT_RD (5 << 12)
31#define DPAUX_DP_AUXCTL_CMD_MOT_WR (4 << 12)
32#define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12)
33#define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12)
34#define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12)
35#define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)
36
37#define DPAUX_DP_AUXSTAT 0x31
38#define DPAUX_DP_AUXSTAT_HPD_STATUS (1 << 28)
39#define DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK (0xf0000)
40#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR (1 << 11)
41#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR (1 << 10)
42#define DPAUX_DP_AUXSTAT_RX_ERROR (1 << 9)
43#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR (1 << 8)
44#define DPAUX_DP_AUXSTAT_REPLY_MASK (0xff)
45
46#define DPAUX_DP_AUX_SINKSTAT_LO 0x35
47#define DPAUX_DP_AUX_SINKSTAT_HI 0x39
48
49#define DPAUX_HPD_CONFIG 0x3d
50#define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME(x) (((x) & 0xffff) << 16)
51#define DPAUX_HPD_CONFIG_PLUG_MIN_TIME(x) ((x) & 0xffff)
52
53#define DPAUX_HPD_IRQ_CONFIG 0x41
54#define DPAUX_HPD_IRQ_CONFIG_MIN_LOW_TIME(x) ((x) & 0xffff)
55
56#define DPAUX_DP_AUX_CONFIG 0x45
57
58#define DPAUX_HYBRID_PADCTL 0x49
59#define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12)
60#define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8)
61#define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2)
62#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV (1 << 1)
63#define DPAUX_HYBRID_PADCTL_MODE_I2C (1 << 0)
64#define DPAUX_HYBRID_PADCTL_MODE_AUX (0 << 0)
65
66#define DPAUX_HYBRID_SPARE 0x4d
67#define DPAUX_HYBRID_SPARE_PAD_POWER_DOWN (1 << 0)
68
69#define DPAUX_SCRATCH_REG0 0x51
70#define DPAUX_SCRATCH_REG1 0x55
71#define DPAUX_SCRATCH_REG2 0x59
72
73#endif
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index c71594754f46..6f5b6e2f552e 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -665,6 +665,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
665 { .compatible = "nvidia,tegra114-hdmi", }, 665 { .compatible = "nvidia,tegra114-hdmi", },
666 { .compatible = "nvidia,tegra114-gr3d", }, 666 { .compatible = "nvidia,tegra114-gr3d", },
667 { .compatible = "nvidia,tegra124-dc", }, 667 { .compatible = "nvidia,tegra124-dc", },
668 { .compatible = "nvidia,tegra124-sor", },
668 { /* sentinel */ } 669 { /* sentinel */ }
669}; 670};
670 671
@@ -691,14 +692,22 @@ static int __init host1x_drm_init(void)
691 if (err < 0) 692 if (err < 0)
692 goto unregister_dc; 693 goto unregister_dc;
693 694
694 err = platform_driver_register(&tegra_hdmi_driver); 695 err = platform_driver_register(&tegra_sor_driver);
695 if (err < 0) 696 if (err < 0)
696 goto unregister_dsi; 697 goto unregister_dsi;
697 698
698 err = platform_driver_register(&tegra_gr2d_driver); 699 err = platform_driver_register(&tegra_hdmi_driver);
700 if (err < 0)
701 goto unregister_sor;
702
703 err = platform_driver_register(&tegra_dpaux_driver);
699 if (err < 0) 704 if (err < 0)
700 goto unregister_hdmi; 705 goto unregister_hdmi;
701 706
707 err = platform_driver_register(&tegra_gr2d_driver);
708 if (err < 0)
709 goto unregister_dpaux;
710
702 err = platform_driver_register(&tegra_gr3d_driver); 711 err = platform_driver_register(&tegra_gr3d_driver);
703 if (err < 0) 712 if (err < 0)
704 goto unregister_gr2d; 713 goto unregister_gr2d;
@@ -707,8 +716,12 @@ static int __init host1x_drm_init(void)
707 716
708unregister_gr2d: 717unregister_gr2d:
709 platform_driver_unregister(&tegra_gr2d_driver); 718 platform_driver_unregister(&tegra_gr2d_driver);
719unregister_dpaux:
720 platform_driver_unregister(&tegra_dpaux_driver);
710unregister_hdmi: 721unregister_hdmi:
711 platform_driver_unregister(&tegra_hdmi_driver); 722 platform_driver_unregister(&tegra_hdmi_driver);
723unregister_sor:
724 platform_driver_unregister(&tegra_sor_driver);
712unregister_dsi: 725unregister_dsi:
713 platform_driver_unregister(&tegra_dsi_driver); 726 platform_driver_unregister(&tegra_dsi_driver);
714unregister_dc: 727unregister_dc:
@@ -723,7 +736,9 @@ static void __exit host1x_drm_exit(void)
723{ 736{
724 platform_driver_unregister(&tegra_gr3d_driver); 737 platform_driver_unregister(&tegra_gr3d_driver);
725 platform_driver_unregister(&tegra_gr2d_driver); 738 platform_driver_unregister(&tegra_gr2d_driver);
739 platform_driver_unregister(&tegra_dpaux_driver);
726 platform_driver_unregister(&tegra_hdmi_driver); 740 platform_driver_unregister(&tegra_hdmi_driver);
741 platform_driver_unregister(&tegra_sor_driver);
727 platform_driver_unregister(&tegra_dsi_driver); 742 platform_driver_unregister(&tegra_dsi_driver);
728 platform_driver_unregister(&tegra_dc_driver); 743 platform_driver_unregister(&tegra_dc_driver);
729 host1x_driver_unregister(&host1x_drm_driver); 744 host1x_driver_unregister(&host1x_drm_driver);
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index bf1cac7658f8..126332c3ecbb 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -179,12 +179,14 @@ struct tegra_output_ops {
179 int (*check_mode)(struct tegra_output *output, 179 int (*check_mode)(struct tegra_output *output,
180 struct drm_display_mode *mode, 180 struct drm_display_mode *mode,
181 enum drm_mode_status *status); 181 enum drm_mode_status *status);
182 enum drm_connector_status (*detect)(struct tegra_output *output);
182}; 183};
183 184
184enum tegra_output_type { 185enum tegra_output_type {
185 TEGRA_OUTPUT_RGB, 186 TEGRA_OUTPUT_RGB,
186 TEGRA_OUTPUT_HDMI, 187 TEGRA_OUTPUT_HDMI,
187 TEGRA_OUTPUT_DSI, 188 TEGRA_OUTPUT_DSI,
189 TEGRA_OUTPUT_EDP,
188}; 190};
189 191
190struct tegra_output { 192struct tegra_output {
@@ -265,6 +267,22 @@ extern int tegra_output_remove(struct tegra_output *output);
265extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); 267extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
266extern int tegra_output_exit(struct tegra_output *output); 268extern int tegra_output_exit(struct tegra_output *output);
267 269
270/* from dpaux.c */
271
272struct tegra_dpaux;
273struct drm_dp_link;
274struct drm_dp_aux;
275
276struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np);
277enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux);
278int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output);
279int tegra_dpaux_detach(struct tegra_dpaux *dpaux);
280int tegra_dpaux_enable(struct tegra_dpaux *dpaux);
281int tegra_dpaux_disable(struct tegra_dpaux *dpaux);
282int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding);
283int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
284 u8 pattern);
285
268/* from fb.c */ 286/* from fb.c */
269struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, 287struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
270 unsigned int index); 288 unsigned int index);
@@ -278,7 +296,9 @@ extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
278 296
279extern struct platform_driver tegra_dc_driver; 297extern struct platform_driver tegra_dc_driver;
280extern struct platform_driver tegra_dsi_driver; 298extern struct platform_driver tegra_dsi_driver;
299extern struct platform_driver tegra_sor_driver;
281extern struct platform_driver tegra_hdmi_driver; 300extern struct platform_driver tegra_hdmi_driver;
301extern struct platform_driver tegra_dpaux_driver;
282extern struct platform_driver tegra_gr2d_driver; 302extern struct platform_driver tegra_gr2d_driver;
283extern struct platform_driver tegra_gr3d_driver; 303extern struct platform_driver tegra_gr3d_driver;
284 304
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index d452faab0235..0e599f0417c0 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#include <linux/clk.h> 9#include <linux/clk.h>
diff --git a/drivers/gpu/drm/tegra/dsi.h b/drivers/gpu/drm/tegra/dsi.h
index 00e79c1f448c..1db5cc24ea91 100644
--- a/drivers/gpu/drm/tegra/dsi.h
+++ b/drivers/gpu/drm/tegra/dsi.h
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#ifndef DRM_TEGRA_DSI_H 9#ifndef DRM_TEGRA_DSI_H
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index ef853e558036..bcf9895cef9f 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -8,14 +8,9 @@
8 * 8 *
9 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 9 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
10 * 10 *
11 * This program is free software; you can redistribute it and/or 11 * This program is free software; you can redistribute it and/or modify
12 * modify it under the terms of the GNU General Public License 12 * it under the terms of the GNU General Public License version 2 as
13 * as published by the Free Software Foundation; either version 2 13 * published by the Free Software Foundation.
14 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */ 14 */
20 15
21#include <linux/dma-buf.h> 16#include <linux/dma-buf.h>
@@ -394,6 +389,18 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
394 return -EINVAL; 389 return -EINVAL;
395} 390}
396 391
392static void *tegra_gem_prime_vmap(struct dma_buf *buf)
393{
394 struct drm_gem_object *gem = buf->priv;
395 struct tegra_bo *bo = to_tegra_bo(gem);
396
397 return bo->vaddr;
398}
399
400static void tegra_gem_prime_vunmap(struct dma_buf *buf, void *vaddr)
401{
402}
403
397static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { 404static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
398 .map_dma_buf = tegra_gem_prime_map_dma_buf, 405 .map_dma_buf = tegra_gem_prime_map_dma_buf,
399 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf, 406 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
@@ -403,6 +410,8 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
403 .kmap = tegra_gem_prime_kmap, 410 .kmap = tegra_gem_prime_kmap,
404 .kunmap = tegra_gem_prime_kunmap, 411 .kunmap = tegra_gem_prime_kunmap,
405 .mmap = tegra_gem_prime_mmap, 412 .mmap = tegra_gem_prime_mmap,
413 .vmap = tegra_gem_prime_vmap,
414 .vunmap = tegra_gem_prime_vunmap,
406}; 415};
407 416
408struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, 417struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index ffd4f792b410..2f3fe96c5154 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -3,17 +3,9 @@
3 * 3 *
4 * Copyright (c) 2012-2013, NVIDIA Corporation. 4 * Copyright (c) 2012-2013, NVIDIA Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify
7 * under the terms and conditions of the GNU General Public License, 7 * it under the terms of the GNU General Public License version 2 as
8 * version 2, as published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 9 */
18 10
19#ifndef __HOST1X_GEM_H 11#ifndef __HOST1X_GEM_H
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 7ec4259ffded..2c7ca748edf5 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -1,17 +1,9 @@
1/* 1/*
2 * Copyright (c) 2012-2013, NVIDIA Corporation. 2 * Copyright (c) 2012-2013, NVIDIA Corporation.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify
5 * under the terms and conditions of the GNU General Public License, 5 * it under the terms of the GNU General Public License version 2 as
6 * version 2, as published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 7 */
16 8
17#include <linux/clk.h> 9#include <linux/clk.h>
diff --git a/drivers/gpu/drm/tegra/mipi-phy.c b/drivers/gpu/drm/tegra/mipi-phy.c
index e2c4aedaee78..486d19d589c8 100644
--- a/drivers/gpu/drm/tegra/mipi-phy.c
+++ b/drivers/gpu/drm/tegra/mipi-phy.c
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#include <linux/errno.h> 9#include <linux/errno.h>
diff --git a/drivers/gpu/drm/tegra/mipi-phy.h b/drivers/gpu/drm/tegra/mipi-phy.h
index d3591694432d..012ea8ac36d7 100644
--- a/drivers/gpu/drm/tegra/mipi-phy.h
+++ b/drivers/gpu/drm/tegra/mipi-phy.h
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#ifndef DRM_TEGRA_MIPI_PHY_H 9#ifndef DRM_TEGRA_MIPI_PHY_H
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 57cecbd18ca8..a3e4f1eca6f7 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -77,6 +77,9 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
77 struct tegra_output *output = connector_to_output(connector); 77 struct tegra_output *output = connector_to_output(connector);
78 enum drm_connector_status status = connector_status_unknown; 78 enum drm_connector_status status = connector_status_unknown;
79 79
80 if (output->ops->detect)
81 return output->ops->detect(output);
82
80 if (gpio_is_valid(output->hpd_gpio)) { 83 if (gpio_is_valid(output->hpd_gpio)) {
81 if (gpio_get_value(output->hpd_gpio) == 0) 84 if (gpio_get_value(output->hpd_gpio) == 0)
82 status = connector_status_disconnected; 85 status = connector_status_disconnected;
@@ -292,6 +295,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
292 encoder = DRM_MODE_ENCODER_DSI; 295 encoder = DRM_MODE_ENCODER_DSI;
293 break; 296 break;
294 297
298 case TEGRA_OUTPUT_EDP:
299 connector = DRM_MODE_CONNECTOR_eDP;
300 encoder = DRM_MODE_ENCODER_TMDS;
301 break;
302
295 default: 303 default:
296 connector = DRM_MODE_CONNECTOR_Unknown; 304 connector = DRM_MODE_CONNECTOR_Unknown;
297 encoder = DRM_MODE_ENCODER_NONE; 305 encoder = DRM_MODE_ENCODER_NONE;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
new file mode 100644
index 000000000000..49ef5729f435
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -0,0 +1,1092 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/io.h>
11#include <linux/platform_device.h>
12#include <linux/reset.h>
13#include <linux/tegra-powergate.h>
14
15#include <drm/drm_dp_helper.h>
16
17#include "dc.h"
18#include "drm.h"
19#include "sor.h"
20
21struct tegra_sor {
22 struct host1x_client client;
23 struct tegra_output output;
24 struct device *dev;
25
26 void __iomem *regs;
27
28 struct reset_control *rst;
29 struct clk *clk_parent;
30 struct clk *clk_safe;
31 struct clk *clk_dp;
32 struct clk *clk;
33
34 struct tegra_dpaux *dpaux;
35
36 bool enabled;
37};
38
39static inline struct tegra_sor *
40host1x_client_to_sor(struct host1x_client *client)
41{
42 return container_of(client, struct tegra_sor, client);
43}
44
45static inline struct tegra_sor *to_sor(struct tegra_output *output)
46{
47 return container_of(output, struct tegra_sor, output);
48}
49
50static inline unsigned long tegra_sor_readl(struct tegra_sor *sor,
51 unsigned long offset)
52{
53 return readl(sor->regs + (offset << 2));
54}
55
56static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value,
57 unsigned long offset)
58{
59 writel(value, sor->regs + (offset << 2));
60}
61
62static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
63 struct drm_dp_link *link)
64{
65 unsigned long value;
66 unsigned int i;
67 u8 pattern;
68 int err;
69
70 /* setup lane parameters */
71 value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
72 SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
73 SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
74 SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
75 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT_0);
76
77 value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
78 SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
79 SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
80 SOR_LANE_PREEMPHASIS_LANE0(0x0f);
81 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS_0);
82
83 value = SOR_LANE_POST_CURSOR_LANE3(0x00) |
84 SOR_LANE_POST_CURSOR_LANE2(0x00) |
85 SOR_LANE_POST_CURSOR_LANE1(0x00) |
86 SOR_LANE_POST_CURSOR_LANE0(0x00);
87 tegra_sor_writel(sor, value, SOR_LANE_POST_CURSOR_0);
88
89 /* disable LVDS mode */
90 tegra_sor_writel(sor, 0, SOR_LVDS);
91
92 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
93 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
94 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
95 value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
96 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
97
98 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
99 value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
100 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
101 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
102
103 usleep_range(10, 100);
104
105 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
106 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
107 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
108 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
109
110 err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
111 if (err < 0)
112 return err;
113
114 for (i = 0, value = 0; i < link->num_lanes; i++) {
115 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
116 SOR_DP_TPG_SCRAMBLER_NONE |
117 SOR_DP_TPG_PATTERN_TRAIN1;
118 value = (value << 8) | lane;
119 }
120
121 tegra_sor_writel(sor, value, SOR_DP_TPG);
122
123 pattern = DP_TRAINING_PATTERN_1;
124
125 err = tegra_dpaux_train(sor->dpaux, link, pattern);
126 if (err < 0)
127 return err;
128
129 value = tegra_sor_readl(sor, SOR_DP_SPARE_0);
130 value |= SOR_DP_SPARE_SEQ_ENABLE;
131 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
132 value |= SOR_DP_SPARE_MACRO_SOR_CLK;
133 tegra_sor_writel(sor, value, SOR_DP_SPARE_0);
134
135 for (i = 0, value = 0; i < link->num_lanes; i++) {
136 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
137 SOR_DP_TPG_SCRAMBLER_NONE |
138 SOR_DP_TPG_PATTERN_TRAIN2;
139 value = (value << 8) | lane;
140 }
141
142 tegra_sor_writel(sor, value, SOR_DP_TPG);
143
144 pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
145
146 err = tegra_dpaux_train(sor->dpaux, link, pattern);
147 if (err < 0)
148 return err;
149
150 for (i = 0, value = 0; i < link->num_lanes; i++) {
151 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
152 SOR_DP_TPG_SCRAMBLER_GALIOS |
153 SOR_DP_TPG_PATTERN_NONE;
154 value = (value << 8) | lane;
155 }
156
157 tegra_sor_writel(sor, value, SOR_DP_TPG);
158
159 pattern = DP_TRAINING_PATTERN_DISABLE;
160
161 err = tegra_dpaux_train(sor->dpaux, link, pattern);
162 if (err < 0)
163 return err;
164
165 return 0;
166}
167
168static void tegra_sor_super_update(struct tegra_sor *sor)
169{
170 tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
171 tegra_sor_writel(sor, 1, SOR_SUPER_STATE_0);
172 tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
173}
174
175static void tegra_sor_update(struct tegra_sor *sor)
176{
177 tegra_sor_writel(sor, 0, SOR_STATE_0);
178 tegra_sor_writel(sor, 1, SOR_STATE_0);
179 tegra_sor_writel(sor, 0, SOR_STATE_0);
180}
181
182static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
183{
184 unsigned long value;
185
186 value = tegra_sor_readl(sor, SOR_PWM_DIV);
187 value &= ~SOR_PWM_DIV_MASK;
188 value |= 0x400; /* period */
189 tegra_sor_writel(sor, value, SOR_PWM_DIV);
190
191 value = tegra_sor_readl(sor, SOR_PWM_CTL);
192 value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
193 value |= 0x400; /* duty cycle */
194 value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
195 value |= SOR_PWM_CTL_TRIGGER;
196 tegra_sor_writel(sor, value, SOR_PWM_CTL);
197
198 timeout = jiffies + msecs_to_jiffies(timeout);
199
200 while (time_before(jiffies, timeout)) {
201 value = tegra_sor_readl(sor, SOR_PWM_CTL);
202 if ((value & SOR_PWM_CTL_TRIGGER) == 0)
203 return 0;
204
205 usleep_range(25, 100);
206 }
207
208 return -ETIMEDOUT;
209}
210
211static int tegra_sor_attach(struct tegra_sor *sor)
212{
213 unsigned long value, timeout;
214
215 /* wake up in normal mode */
216 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
217 value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
218 value |= SOR_SUPER_STATE_MODE_NORMAL;
219 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
220 tegra_sor_super_update(sor);
221
222 /* attach */
223 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
224 value |= SOR_SUPER_STATE_ATTACHED;
225 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
226 tegra_sor_super_update(sor);
227
228 timeout = jiffies + msecs_to_jiffies(250);
229
230 while (time_before(jiffies, timeout)) {
231 value = tegra_sor_readl(sor, SOR_TEST);
232 if ((value & SOR_TEST_ATTACHED) != 0)
233 return 0;
234
235 usleep_range(25, 100);
236 }
237
238 return -ETIMEDOUT;
239}
240
241static int tegra_sor_wakeup(struct tegra_sor *sor)
242{
243 struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
244 unsigned long value, timeout;
245
246 /* enable display controller outputs */
247 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
248 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
249 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
250 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
251
252 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
253 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
254
255 timeout = jiffies + msecs_to_jiffies(250);
256
257 /* wait for head to wake up */
258 while (time_before(jiffies, timeout)) {
259 value = tegra_sor_readl(sor, SOR_TEST);
260 value &= SOR_TEST_HEAD_MODE_MASK;
261
262 if (value == SOR_TEST_HEAD_MODE_AWAKE)
263 return 0;
264
265 usleep_range(25, 100);
266 }
267
268 return -ETIMEDOUT;
269}
270
271static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
272{
273 unsigned long value;
274
275 value = tegra_sor_readl(sor, SOR_PWR);
276 value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
277 tegra_sor_writel(sor, value, SOR_PWR);
278
279 timeout = jiffies + msecs_to_jiffies(timeout);
280
281 while (time_before(jiffies, timeout)) {
282 value = tegra_sor_readl(sor, SOR_PWR);
283 if ((value & SOR_PWR_TRIGGER) == 0)
284 return 0;
285
286 usleep_range(25, 100);
287 }
288
289 return -ETIMEDOUT;
290}
291
292static int tegra_output_sor_enable(struct tegra_output *output)
293{
294 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
295 struct drm_display_mode *mode = &dc->base.mode;
296 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
297 struct tegra_sor *sor = to_sor(output);
298 unsigned long value;
299 int err;
300
301 if (sor->enabled)
302 return 0;
303
304 err = clk_prepare_enable(sor->clk);
305 if (err < 0)
306 return err;
307
308 reset_control_deassert(sor->rst);
309
310 if (sor->dpaux) {
311 err = tegra_dpaux_enable(sor->dpaux);
312 if (err < 0)
313 dev_err(sor->dev, "failed to enable DP: %d\n", err);
314 }
315
316 err = clk_set_parent(sor->clk, sor->clk_safe);
317 if (err < 0)
318 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
319
320 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
321 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
322 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
323 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
324
325 value = tegra_sor_readl(sor, SOR_PLL_2);
326 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
327 tegra_sor_writel(sor, value, SOR_PLL_2);
328 usleep_range(20, 100);
329
330 value = tegra_sor_readl(sor, SOR_PLL_3);
331 value |= SOR_PLL_3_PLL_VDD_MODE_V3_3;
332 tegra_sor_writel(sor, value, SOR_PLL_3);
333
334 value = SOR_PLL_0_ICHPMP(0xf) | SOR_PLL_0_VCOCAP_RST |
335 SOR_PLL_0_PLLREG_LEVEL_V45 | SOR_PLL_0_RESISTOR_EXT;
336 tegra_sor_writel(sor, value, SOR_PLL_0);
337
338 value = tegra_sor_readl(sor, SOR_PLL_2);
339 value |= SOR_PLL_2_SEQ_PLLCAPPD;
340 value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
341 value |= SOR_PLL_2_LVDS_ENABLE;
342 tegra_sor_writel(sor, value, SOR_PLL_2);
343
344 value = SOR_PLL_1_TERM_COMPOUT | SOR_PLL_1_TMDS_TERM;
345 tegra_sor_writel(sor, value, SOR_PLL_1);
346
347 while (true) {
348 value = tegra_sor_readl(sor, SOR_PLL_2);
349 if ((value & SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE) == 0)
350 break;
351
352 usleep_range(250, 1000);
353 }
354
355 value = tegra_sor_readl(sor, SOR_PLL_2);
356 value &= ~SOR_PLL_2_POWERDOWN_OVERRIDE;
357 value &= ~SOR_PLL_2_PORT_POWERDOWN;
358 tegra_sor_writel(sor, value, SOR_PLL_2);
359
360 /*
361 * power up
362 */
363
364 /* set safe link bandwidth (1.62 Gbps) */
365 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
366 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
367 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
368 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
369
370 /* step 1 */
371 value = tegra_sor_readl(sor, SOR_PLL_2);
372 value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL_2_PORT_POWERDOWN |
373 SOR_PLL_2_BANDGAP_POWERDOWN;
374 tegra_sor_writel(sor, value, SOR_PLL_2);
375
376 value = tegra_sor_readl(sor, SOR_PLL_0);
377 value |= SOR_PLL_0_VCOPD | SOR_PLL_0_POWER_OFF;
378 tegra_sor_writel(sor, value, SOR_PLL_0);
379
380 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
381 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
382 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
383
384 /* step 2 */
385 err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
386 if (err < 0) {
387 dev_err(sor->dev, "failed to power on I/O rail: %d\n", err);
388 return err;
389 }
390
391 usleep_range(5, 100);
392
393 /* step 3 */
394 value = tegra_sor_readl(sor, SOR_PLL_2);
395 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
396 tegra_sor_writel(sor, value, SOR_PLL_2);
397
398 usleep_range(20, 100);
399
400 /* step 4 */
401 value = tegra_sor_readl(sor, SOR_PLL_0);
402 value &= ~SOR_PLL_0_POWER_OFF;
403 value &= ~SOR_PLL_0_VCOPD;
404 tegra_sor_writel(sor, value, SOR_PLL_0);
405
406 value = tegra_sor_readl(sor, SOR_PLL_2);
407 value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
408 tegra_sor_writel(sor, value, SOR_PLL_2);
409
410 usleep_range(200, 1000);
411
412 /* step 5 */
413 value = tegra_sor_readl(sor, SOR_PLL_2);
414 value &= ~SOR_PLL_2_PORT_POWERDOWN;
415 tegra_sor_writel(sor, value, SOR_PLL_2);
416
417 /* switch to DP clock */
418 err = clk_set_parent(sor->clk, sor->clk_dp);
419 if (err < 0)
420 dev_err(sor->dev, "failed to set DP parent clock: %d\n", err);
421
422 /* power dplanes (XXX parameterize based on link?) */
423 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
424 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
425 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
426 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
427
428 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
429 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
430 value |= SOR_DP_LINKCTL_LANE_COUNT(4);
431 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
432
433 /* start lane sequencer */
434 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
435 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
436 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
437
438 while (true) {
439 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
440 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
441 break;
442
443 usleep_range(250, 1000);
444 }
445
446 /* set link bandwidth (2.7 GHz, XXX: parameterize based on link?) */
447 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
448 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
449 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
450 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
451
452 /* set linkctl */
453 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
454 value |= SOR_DP_LINKCTL_ENABLE;
455
456 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
457 value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */
458
459 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
460 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
461
462 for (i = 0, value = 0; i < 4; i++) {
463 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
464 SOR_DP_TPG_SCRAMBLER_GALIOS |
465 SOR_DP_TPG_PATTERN_NONE;
466 value = (value << 8) | lane;
467 }
468
469 tegra_sor_writel(sor, value, SOR_DP_TPG);
470
471 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
472 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
473 value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */
474
475 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
476 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */
477
478 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
479 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */
480
481 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */
482
483 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
484 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
485 tegra_sor_writel(sor, value, SOR_DP_CONFIG_0);
486
487 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
488 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
489 value |= 137; /* XXX: don't hardcode? */
490 tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
491
492 value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
493 value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
494 value |= 2368; /* XXX: don't hardcode? */
495 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
496
497 /* enable pad calibration logic */
498 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
499 value |= SOR_DP_PADCTL_PAD_CAL_PD;
500 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
501
502 if (sor->dpaux) {
503 /* FIXME: properly convert to struct drm_dp_aux */
504 struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
505 struct drm_dp_link link;
506 u8 rate, lanes;
507
508 err = drm_dp_link_probe(aux, &link);
509 if (err < 0) {
510 dev_err(sor->dev, "failed to probe eDP link: %d\n",
511 err);
512 return err;
513 }
514
515 err = drm_dp_link_power_up(aux, &link);
516 if (err < 0) {
517 dev_err(sor->dev, "failed to power up eDP link: %d\n",
518 err);
519 return err;
520 }
521
522 err = drm_dp_link_configure(aux, &link);
523 if (err < 0) {
524 dev_err(sor->dev, "failed to configure eDP link: %d\n",
525 err);
526 return err;
527 }
528
529 rate = drm_dp_link_rate_to_bw_code(link.rate);
530 lanes = link.num_lanes;
531
532 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
533 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
534 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
535 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
536
537 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
538 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
539 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
540
541 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
542 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
543
544 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
545
546 /* disable training pattern generator */
547
548 for (i = 0; i < link.num_lanes; i++) {
549 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
550 SOR_DP_TPG_SCRAMBLER_GALIOS |
551 SOR_DP_TPG_PATTERN_NONE;
552 value = (value << 8) | lane;
553 }
554
555 tegra_sor_writel(sor, value, SOR_DP_TPG);
556
557 err = tegra_sor_dp_train_fast(sor, &link);
558 if (err < 0) {
559 dev_err(sor->dev, "DP fast link training failed: %d\n",
560 err);
561 return err;
562 }
563
564 dev_dbg(sor->dev, "fast link training succeeded\n");
565 }
566
567 err = tegra_sor_power_up(sor, 250);
568 if (err < 0) {
569 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
570 return err;
571 }
572
573 /* start display controller in continuous mode */
574 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
575 value |= WRITE_MUX;
576 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
577
578 tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
579 tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
580
581 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
582 value &= ~WRITE_MUX;
583 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
584
585 /*
586 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
587 * raster, associate with display controller)
588 */
589 value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 |
590 SOR_STATE_ASY_VSYNCPOL |
591 SOR_STATE_ASY_HSYNCPOL |
592 SOR_STATE_ASY_PROTOCOL_DP_A |
593 SOR_STATE_ASY_CRC_MODE_COMPLETE |
594 SOR_STATE_ASY_OWNER(dc->pipe + 1);
595 tegra_sor_writel(sor, value, SOR_STATE_1);
596
597 /*
598 * TODO: The video timing programming below doesn't seem to match the
599 * register definitions.
600 */
601
602 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
603 tegra_sor_writel(sor, value, SOR_HEAD_STATE_1(0));
604
605 vse = mode->vsync_end - mode->vsync_start - 1;
606 hse = mode->hsync_end - mode->hsync_start - 1;
607
608 value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
609 tegra_sor_writel(sor, value, SOR_HEAD_STATE_2(0));
610
611 vbe = vse + (mode->vsync_start - mode->vdisplay);
612 hbe = hse + (mode->hsync_start - mode->hdisplay);
613
614 value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
615 tegra_sor_writel(sor, value, SOR_HEAD_STATE_3(0));
616
617 vbs = vbe + mode->vdisplay;
618 hbs = hbe + mode->hdisplay;
619
620 value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
621 tegra_sor_writel(sor, value, SOR_HEAD_STATE_4(0));
622
623 /* XXX interlaced mode */
624 tegra_sor_writel(sor, 0x00000001, SOR_HEAD_STATE_5(0));
625
626 /* CSTM (LVDS, link A/B, upper) */
627 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_B | SOR_CSTM_LINK_ACT_B |
628 SOR_CSTM_UPPER;
629 tegra_sor_writel(sor, value, SOR_CSTM);
630
631 /* PWM setup */
632 err = tegra_sor_setup_pwm(sor, 250);
633 if (err < 0) {
634 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
635 return err;
636 }
637
638 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
639 value |= SOR_ENABLE;
640 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
641
642 tegra_sor_update(sor);
643
644 err = tegra_sor_attach(sor);
645 if (err < 0) {
646 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
647 return err;
648 }
649
650 err = tegra_sor_wakeup(sor);
651 if (err < 0) {
652 dev_err(sor->dev, "failed to enable DC: %d\n", err);
653 return err;
654 }
655
656 sor->enabled = true;
657
658 return 0;
659}
660
661static int tegra_sor_detach(struct tegra_sor *sor)
662{
663 unsigned long value, timeout;
664
665 /* switch to safe mode */
666 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
667 value &= ~SOR_SUPER_STATE_MODE_NORMAL;
668 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
669 tegra_sor_super_update(sor);
670
671 timeout = jiffies + msecs_to_jiffies(250);
672
673 while (time_before(jiffies, timeout)) {
674 value = tegra_sor_readl(sor, SOR_PWR);
675 if (value & SOR_PWR_MODE_SAFE)
676 break;
677 }
678
679 if ((value & SOR_PWR_MODE_SAFE) == 0)
680 return -ETIMEDOUT;
681
682 /* go to sleep */
683 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
684 value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
685 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
686 tegra_sor_super_update(sor);
687
688 /* detach */
689 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
690 value &= ~SOR_SUPER_STATE_ATTACHED;
691 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
692 tegra_sor_super_update(sor);
693
694 timeout = jiffies + msecs_to_jiffies(250);
695
696 while (time_before(jiffies, timeout)) {
697 value = tegra_sor_readl(sor, SOR_TEST);
698 if ((value & SOR_TEST_ATTACHED) == 0)
699 break;
700
701 usleep_range(25, 100);
702 }
703
704 if ((value & SOR_TEST_ATTACHED) != 0)
705 return -ETIMEDOUT;
706
707 return 0;
708}
709
710static int tegra_sor_power_down(struct tegra_sor *sor)
711{
712 unsigned long value, timeout;
713 int err;
714
715 value = tegra_sor_readl(sor, SOR_PWR);
716 value &= ~SOR_PWR_NORMAL_STATE_PU;
717 value |= SOR_PWR_TRIGGER;
718 tegra_sor_writel(sor, value, SOR_PWR);
719
720 timeout = jiffies + msecs_to_jiffies(250);
721
722 while (time_before(jiffies, timeout)) {
723 value = tegra_sor_readl(sor, SOR_PWR);
724 if ((value & SOR_PWR_TRIGGER) == 0)
725 return 0;
726
727 usleep_range(25, 100);
728 }
729
730 if ((value & SOR_PWR_TRIGGER) != 0)
731 return -ETIMEDOUT;
732
733 err = clk_set_parent(sor->clk, sor->clk_safe);
734 if (err < 0)
735 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
736
737 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
738 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
739 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
740 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
741
742 /* stop lane sequencer */
743 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
744 SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
745 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
746
747 timeout = jiffies + msecs_to_jiffies(250);
748
749 while (time_before(jiffies, timeout)) {
750 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
751 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
752 break;
753
754 usleep_range(25, 100);
755 }
756
757 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
758 return -ETIMEDOUT;
759
760 value = tegra_sor_readl(sor, SOR_PLL_2);
761 value |= SOR_PLL_2_PORT_POWERDOWN;
762 tegra_sor_writel(sor, value, SOR_PLL_2);
763
764 usleep_range(20, 100);
765
766 value = tegra_sor_readl(sor, SOR_PLL_0);
767 value |= SOR_PLL_0_POWER_OFF;
768 value |= SOR_PLL_0_VCOPD;
769 tegra_sor_writel(sor, value, SOR_PLL_0);
770
771 value = tegra_sor_readl(sor, SOR_PLL_2);
772 value |= SOR_PLL_2_SEQ_PLLCAPPD;
773 value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
774 tegra_sor_writel(sor, value, SOR_PLL_2);
775
776 usleep_range(20, 100);
777
778 return 0;
779}
780
781static int tegra_output_sor_disable(struct tegra_output *output)
782{
783 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
784 struct tegra_sor *sor = to_sor(output);
785 unsigned long value;
786 int err;
787
788 if (!sor->enabled)
789 return 0;
790
791 err = tegra_sor_detach(sor);
792 if (err < 0) {
793 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
794 return err;
795 }
796
797 tegra_sor_writel(sor, 0, SOR_STATE_1);
798 tegra_sor_update(sor);
799
800 /*
801 * The following accesses registers of the display controller, so make
802 * sure it's only executed when the output is attached to one.
803 */
804 if (dc) {
805 /*
806 * XXX: We can't do this here because it causes the SOR to go
807 * into an erroneous state and the output will look scrambled
808 * the next time it is enabled. Presumably this is because we
809 * should be doing this only on the next VBLANK. A possible
810 * solution would be to queue a "power-off" event to trigger
811 * this code to be run during the next VBLANK.
812 */
813 /*
814 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
815 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
816 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
817 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
818 */
819
820 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
821 value &= ~DISP_CTRL_MODE_MASK;
822 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
823
824 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
825 value &= ~SOR_ENABLE;
826 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
827
828 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
829 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
830 }
831
832 err = tegra_sor_power_down(sor);
833 if (err < 0) {
834 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
835 return err;
836 }
837
838 if (sor->dpaux) {
839 err = tegra_dpaux_disable(sor->dpaux);
840 if (err < 0) {
841 dev_err(sor->dev, "failed to disable DP: %d\n", err);
842 return err;
843 }
844 }
845
846 err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS);
847 if (err < 0) {
848 dev_err(sor->dev, "failed to power off I/O rail: %d\n", err);
849 return err;
850 }
851
852 reset_control_assert(sor->rst);
853 clk_disable_unprepare(sor->clk);
854
855 sor->enabled = false;
856
857 return 0;
858}
859
860static int tegra_output_sor_setup_clock(struct tegra_output *output,
861 struct clk *clk, unsigned long pclk)
862{
863 struct tegra_sor *sor = to_sor(output);
864 int err;
865
866 /* round to next MHz */
867 pclk = DIV_ROUND_UP(pclk / 2, 1000000) * 1000000;
868
869 err = clk_set_parent(clk, sor->clk_parent);
870 if (err < 0) {
871 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
872 return err;
873 }
874
875 err = clk_set_rate(sor->clk_parent, pclk);
876 if (err < 0) {
877 dev_err(sor->dev, "failed to set base clock rate to %lu Hz\n",
878 pclk * 2);
879 return err;
880 }
881
882 return 0;
883}
884
885static int tegra_output_sor_check_mode(struct tegra_output *output,
886 struct drm_display_mode *mode,
887 enum drm_mode_status *status)
888{
889 /*
890 * FIXME: For now, always assume that the mode is okay.
891 */
892
893 *status = MODE_OK;
894
895 return 0;
896}
897
898static enum drm_connector_status
899tegra_output_sor_detect(struct tegra_output *output)
900{
901 struct tegra_sor *sor = to_sor(output);
902
903 if (sor->dpaux)
904 return tegra_dpaux_detect(sor->dpaux);
905
906 return connector_status_unknown;
907}
908
909static const struct tegra_output_ops sor_ops = {
910 .enable = tegra_output_sor_enable,
911 .disable = tegra_output_sor_disable,
912 .setup_clock = tegra_output_sor_setup_clock,
913 .check_mode = tegra_output_sor_check_mode,
914 .detect = tegra_output_sor_detect,
915};
916
917static int tegra_sor_init(struct host1x_client *client)
918{
919 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
920 struct tegra_sor *sor = host1x_client_to_sor(client);
921 int err;
922
923 if (!sor->dpaux)
924 return -ENODEV;
925
926 sor->output.type = TEGRA_OUTPUT_EDP;
927
928 sor->output.dev = sor->dev;
929 sor->output.ops = &sor_ops;
930
931 err = tegra_output_init(tegra->drm, &sor->output);
932 if (err < 0) {
933 dev_err(sor->dev, "output setup failed: %d\n", err);
934 return err;
935 }
936
937 if (sor->dpaux) {
938 err = tegra_dpaux_attach(sor->dpaux, &sor->output);
939 if (err < 0) {
940 dev_err(sor->dev, "failed to attach DP: %d\n", err);
941 return err;
942 }
943 }
944
945 return 0;
946}
947
948static int tegra_sor_exit(struct host1x_client *client)
949{
950 struct tegra_sor *sor = host1x_client_to_sor(client);
951 int err;
952
953 err = tegra_output_disable(&sor->output);
954 if (err < 0) {
955 dev_err(sor->dev, "output failed to disable: %d\n", err);
956 return err;
957 }
958
959 if (sor->dpaux) {
960 err = tegra_dpaux_detach(sor->dpaux);
961 if (err < 0) {
962 dev_err(sor->dev, "failed to detach DP: %d\n", err);
963 return err;
964 }
965 }
966
967 err = tegra_output_exit(&sor->output);
968 if (err < 0) {
969 dev_err(sor->dev, "output cleanup failed: %d\n", err);
970 return err;
971 }
972
973 return 0;
974}
975
976static const struct host1x_client_ops sor_client_ops = {
977 .init = tegra_sor_init,
978 .exit = tegra_sor_exit,
979};
980
981static int tegra_sor_probe(struct platform_device *pdev)
982{
983 struct device_node *np;
984 struct tegra_sor *sor;
985 struct resource *regs;
986 int err;
987
988 sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
989 if (!sor)
990 return -ENOMEM;
991
992 sor->output.dev = sor->dev = &pdev->dev;
993
994 np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
995 if (np) {
996 sor->dpaux = tegra_dpaux_find_by_of_node(np);
997 of_node_put(np);
998
999 if (!sor->dpaux)
1000 return -EPROBE_DEFER;
1001 }
1002
1003 err = tegra_output_probe(&sor->output);
1004 if (err < 0)
1005 return err;
1006
1007 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1008 sor->regs = devm_ioremap_resource(&pdev->dev, regs);
1009 if (IS_ERR(sor->regs))
1010 return PTR_ERR(sor->regs);
1011
1012 sor->rst = devm_reset_control_get(&pdev->dev, "sor");
1013 if (IS_ERR(sor->rst))
1014 return PTR_ERR(sor->rst);
1015
1016 sor->clk = devm_clk_get(&pdev->dev, NULL);
1017 if (IS_ERR(sor->clk))
1018 return PTR_ERR(sor->clk);
1019
1020 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
1021 if (IS_ERR(sor->clk_parent))
1022 return PTR_ERR(sor->clk_parent);
1023
1024 err = clk_prepare_enable(sor->clk_parent);
1025 if (err < 0)
1026 return err;
1027
1028 sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
1029 if (IS_ERR(sor->clk_safe))
1030 return PTR_ERR(sor->clk_safe);
1031
1032 err = clk_prepare_enable(sor->clk_safe);
1033 if (err < 0)
1034 return err;
1035
1036 sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
1037 if (IS_ERR(sor->clk_dp))
1038 return PTR_ERR(sor->clk_dp);
1039
1040 err = clk_prepare_enable(sor->clk_dp);
1041 if (err < 0)
1042 return err;
1043
1044 INIT_LIST_HEAD(&sor->client.list);
1045 sor->client.ops = &sor_client_ops;
1046 sor->client.dev = &pdev->dev;
1047
1048 err = host1x_client_register(&sor->client);
1049 if (err < 0) {
1050 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1051 err);
1052 return err;
1053 }
1054
1055 platform_set_drvdata(pdev, sor);
1056
1057 return 0;
1058}
1059
1060static int tegra_sor_remove(struct platform_device *pdev)
1061{
1062 struct tegra_sor *sor = platform_get_drvdata(pdev);
1063 int err;
1064
1065 err = host1x_client_unregister(&sor->client);
1066 if (err < 0) {
1067 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1068 err);
1069 return err;
1070 }
1071
1072 clk_disable_unprepare(sor->clk_parent);
1073 clk_disable_unprepare(sor->clk_safe);
1074 clk_disable_unprepare(sor->clk_dp);
1075 clk_disable_unprepare(sor->clk);
1076
1077 return 0;
1078}
1079
1080static const struct of_device_id tegra_sor_of_match[] = {
1081 { .compatible = "nvidia,tegra124-sor", },
1082 { },
1083};
1084
1085struct platform_driver tegra_sor_driver = {
1086 .driver = {
1087 .name = "tegra-sor",
1088 .of_match_table = tegra_sor_of_match,
1089 },
1090 .probe = tegra_sor_probe,
1091 .remove = tegra_sor_remove,
1092};
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
new file mode 100644
index 000000000000..f4156d54cd05
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -0,0 +1,278 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef DRM_TEGRA_SOR_H
10#define DRM_TEGRA_SOR_H
11
12#define SOR_CTXSW 0x00
13
14#define SOR_SUPER_STATE_0 0x01
15
16#define SOR_SUPER_STATE_1 0x02
17#define SOR_SUPER_STATE_ATTACHED (1 << 3)
18#define SOR_SUPER_STATE_MODE_NORMAL (1 << 2)
19#define SOR_SUPER_STATE_HEAD_MODE_MASK (3 << 0)
20#define SOR_SUPER_STATE_HEAD_MODE_AWAKE (2 << 0)
21#define SOR_SUPER_STATE_HEAD_MODE_SNOOZE (1 << 0)
22#define SOR_SUPER_STATE_HEAD_MODE_SLEEP (0 << 0)
23
24#define SOR_STATE_0 0x03
25
26#define SOR_STATE_1 0x04
27#define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17)
28#define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17)
29#define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17)
30#define SOR_STATE_ASY_VSYNCPOL (1 << 13)
31#define SOR_STATE_ASY_HSYNCPOL (1 << 12)
32#define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8)
33#define SOR_STATE_ASY_PROTOCOL_CUSTOM (0xf << 8)
34#define SOR_STATE_ASY_PROTOCOL_DP_A (0x8 << 8)
35#define SOR_STATE_ASY_PROTOCOL_DP_B (0x9 << 8)
36#define SOR_STATE_ASY_PROTOCOL_LVDS (0x0 << 8)
37#define SOR_STATE_ASY_CRC_MODE_MASK (0x3 << 6)
38#define SOR_STATE_ASY_CRC_MODE_NON_ACTIVE (0x2 << 6)
39#define SOR_STATE_ASY_CRC_MODE_COMPLETE (0x1 << 6)
40#define SOR_STATE_ASY_CRC_MODE_ACTIVE (0x0 << 6)
41#define SOR_STATE_ASY_OWNER(x) (((x) & 0xf) << 0)
42
43#define SOR_HEAD_STATE_0(x) (0x05 + (x))
44#define SOR_HEAD_STATE_1(x) (0x07 + (x))
45#define SOR_HEAD_STATE_2(x) (0x09 + (x))
46#define SOR_HEAD_STATE_3(x) (0x0b + (x))
47#define SOR_HEAD_STATE_4(x) (0x0d + (x))
48#define SOR_HEAD_STATE_5(x) (0x0f + (x))
49#define SOR_CRC_CNTRL 0x11
50#define SOR_DP_DEBUG_MVID 0x12
51
52#define SOR_CLK_CNTRL 0x13
53#define SOR_CLK_CNTRL_DP_LINK_SPEED_MASK (0x1f << 2)
54#define SOR_CLK_CNTRL_DP_LINK_SPEED(x) (((x) & 0x1f) << 2)
55#define SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62 (0x06 << 2)
56#define SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70 (0x0a << 2)
57#define SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40 (0x14 << 2)
58#define SOR_CLK_CNTRL_DP_CLK_SEL_MASK (3 << 0)
59#define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK (0 << 0)
60#define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK (1 << 0)
61#define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK (2 << 0)
62#define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK (3 << 0)
63
64#define SOR_CAP 0x14
65
66#define SOR_PWR 0x15
67#define SOR_PWR_TRIGGER (1 << 31)
68#define SOR_PWR_MODE_SAFE (1 << 28)
69#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
70
71#define SOR_TEST 0x16
72#define SOR_TEST_ATTACHED (1 << 10)
73#define SOR_TEST_HEAD_MODE_MASK (3 << 8)
74#define SOR_TEST_HEAD_MODE_AWAKE (2 << 8)
75
76#define SOR_PLL_0 0x17
77#define SOR_PLL_0_ICHPMP_MASK (0xf << 24)
78#define SOR_PLL_0_ICHPMP(x) (((x) & 0xf) << 24)
79#define SOR_PLL_0_VCOCAP_MASK (0xf << 8)
80#define SOR_PLL_0_VCOCAP(x) (((x) & 0xf) << 8)
81#define SOR_PLL_0_VCOCAP_RST SOR_PLL_0_VCOCAP(3)
82#define SOR_PLL_0_PLLREG_MASK (0x3 << 6)
83#define SOR_PLL_0_PLLREG_LEVEL(x) (((x) & 0x3) << 6)
84#define SOR_PLL_0_PLLREG_LEVEL_V25 SOR_PLL_0_PLLREG_LEVEL(0)
85#define SOR_PLL_0_PLLREG_LEVEL_V15 SOR_PLL_0_PLLREG_LEVEL(1)
86#define SOR_PLL_0_PLLREG_LEVEL_V35 SOR_PLL_0_PLLREG_LEVEL(2)
87#define SOR_PLL_0_PLLREG_LEVEL_V45 SOR_PLL_0_PLLREG_LEVEL(3)
88#define SOR_PLL_0_PULLDOWN (1 << 5)
89#define SOR_PLL_0_RESISTOR_EXT (1 << 4)
90#define SOR_PLL_0_VCOPD (1 << 2)
91#define SOR_PLL_0_POWER_OFF (1 << 0)
92
93#define SOR_PLL_1 0x18
94/* XXX: read-only bit? */
95#define SOR_PLL_1_TERM_COMPOUT (1 << 15)
96#define SOR_PLL_1_TMDS_TERM (1 << 8)
97
98#define SOR_PLL_2 0x19
99#define SOR_PLL_2_LVDS_ENABLE (1 << 25)
100#define SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE (1 << 24)
101#define SOR_PLL_2_PORT_POWERDOWN (1 << 23)
102#define SOR_PLL_2_BANDGAP_POWERDOWN (1 << 22)
103#define SOR_PLL_2_POWERDOWN_OVERRIDE (1 << 18)
104#define SOR_PLL_2_SEQ_PLLCAPPD (1 << 17)
105
106#define SOR_PLL_3 0x1a
107#define SOR_PLL_3_PLL_VDD_MODE_V1_8 (0 << 13)
108#define SOR_PLL_3_PLL_VDD_MODE_V3_3 (1 << 13)
109
110#define SOR_CSTM 0x1b
111#define SOR_CSTM_LVDS (1 << 16)
112#define SOR_CSTM_LINK_ACT_B (1 << 15)
113#define SOR_CSTM_LINK_ACT_A (1 << 14)
114#define SOR_CSTM_UPPER (1 << 11)
115
116#define SOR_LVDS 0x1c
117#define SOR_CRC_A 0x1d
118#define SOR_CRC_B 0x1e
119#define SOR_BLANK 0x1f
120#define SOR_SEQ_CTL 0x20
121
122#define SOR_LANE_SEQ_CTL 0x21
123#define SOR_LANE_SEQ_CTL_TRIGGER (1 << 31)
124#define SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20)
125#define SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20)
126#define SOR_LANE_SEQ_CTL_POWER_STATE_UP (0 << 16)
127#define SOR_LANE_SEQ_CTL_POWER_STATE_DOWN (1 << 16)
128
129#define SOR_SEQ_INST(x) (0x22 + (x))
130
131#define SOR_PWM_DIV 0x32
132#define SOR_PWM_DIV_MASK 0xffffff
133
134#define SOR_PWM_CTL 0x33
135#define SOR_PWM_CTL_TRIGGER (1 << 31)
136#define SOR_PWM_CTL_CLK_SEL (1 << 30)
137#define SOR_PWM_CTL_DUTY_CYCLE_MASK 0xffffff
138
139#define SOR_VCRC_A_0 0x34
140#define SOR_VCRC_A_1 0x35
141#define SOR_VCRC_B_0 0x36
142#define SOR_VCRC_B_1 0x37
143#define SOR_CCRC_A_0 0x38
144#define SOR_CCRC_A_1 0x39
145#define SOR_CCRC_B_0 0x3a
146#define SOR_CCRC_B_1 0x3b
147#define SOR_EDATA_A_0 0x3c
148#define SOR_EDATA_A_1 0x3d
149#define SOR_EDATA_B_0 0x3e
150#define SOR_EDATA_B_1 0x3f
151#define SOR_COUNT_A_0 0x40
152#define SOR_COUNT_A_1 0x41
153#define SOR_COUNT_B_0 0x42
154#define SOR_COUNT_B_1 0x43
155#define SOR_DEBUG_A_0 0x44
156#define SOR_DEBUG_A_1 0x45
157#define SOR_DEBUG_B_0 0x46
158#define SOR_DEBUG_B_1 0x47
159#define SOR_TRIG 0x48
160#define SOR_MSCHECK 0x49
161#define SOR_XBAR_CTRL 0x4a
162#define SOR_XBAR_POL 0x4b
163
164#define SOR_DP_LINKCTL_0 0x4c
165#define SOR_DP_LINKCTL_LANE_COUNT_MASK (0x1f << 16)
166#define SOR_DP_LINKCTL_LANE_COUNT(x) (((1 << (x)) - 1) << 16)
167#define SOR_DP_LINKCTL_ENHANCED_FRAME (1 << 14)
168#define SOR_DP_LINKCTL_TU_SIZE_MASK (0x7f << 2)
169#define SOR_DP_LINKCTL_TU_SIZE(x) (((x) & 0x7f) << 2)
170#define SOR_DP_LINKCTL_ENABLE (1 << 0)
171
172#define SOR_DP_LINKCTL_1 0x4d
173
174#define SOR_LANE_DRIVE_CURRENT_0 0x4e
175#define SOR_LANE_DRIVE_CURRENT_1 0x4f
176#define SOR_LANE4_DRIVE_CURRENT_0 0x50
177#define SOR_LANE4_DRIVE_CURRENT_1 0x51
178#define SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24)
179#define SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16)
180#define SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8)
181#define SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0)
182
183#define SOR_LANE_PREEMPHASIS_0 0x52
184#define SOR_LANE_PREEMPHASIS_1 0x53
185#define SOR_LANE4_PREEMPHASIS_0 0x54
186#define SOR_LANE4_PREEMPHASIS_1 0x55
187#define SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24)
188#define SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16)
189#define SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8)
190#define SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0)
191
192#define SOR_LANE_POST_CURSOR_0 0x56
193#define SOR_LANE_POST_CURSOR_1 0x57
194#define SOR_LANE_POST_CURSOR_LANE3(x) (((x) & 0xff) << 24)
195#define SOR_LANE_POST_CURSOR_LANE2(x) (((x) & 0xff) << 16)
196#define SOR_LANE_POST_CURSOR_LANE1(x) (((x) & 0xff) << 8)
197#define SOR_LANE_POST_CURSOR_LANE0(x) (((x) & 0xff) << 0)
198
199#define SOR_DP_CONFIG_0 0x58
200#define SOR_DP_CONFIG_DISPARITY_NEGATIVE (1 << 31)
201#define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE (1 << 26)
202#define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY (1 << 24)
203#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK (0xf << 16)
204#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC(x) (((x) & 0xf) << 16)
205#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK (0x7f << 8)
206#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT(x) (((x) & 0x7f) << 8)
207#define SOR_DP_CONFIG_WATERMARK_MASK (0x3f << 0)
208#define SOR_DP_CONFIG_WATERMARK(x) (((x) & 0x3f) << 0)
209
210#define SOR_DP_CONFIG_1 0x59
211#define SOR_DP_MN_0 0x5a
212#define SOR_DP_MN_1 0x5b
213
214#define SOR_DP_PADCTL_0 0x5c
215#define SOR_DP_PADCTL_PAD_CAL_PD (1 << 23)
216#define SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22)
217#define SOR_DP_PADCTL_TX_PU_MASK (0xff << 8)
218#define SOR_DP_PADCTL_TX_PU(x) (((x) & 0xff) << 8)
219#define SOR_DP_PADCTL_CM_TXD_3 (1 << 7)
220#define SOR_DP_PADCTL_CM_TXD_2 (1 << 6)
221#define SOR_DP_PADCTL_CM_TXD_1 (1 << 5)
222#define SOR_DP_PADCTL_CM_TXD_0 (1 << 4)
223#define SOR_DP_PADCTL_PD_TXD_3 (1 << 3)
224#define SOR_DP_PADCTL_PD_TXD_0 (1 << 2)
225#define SOR_DP_PADCTL_PD_TXD_1 (1 << 1)
226#define SOR_DP_PADCTL_PD_TXD_2 (1 << 0)
227
228#define SOR_DP_PADCTL_1 0x5d
229
230#define SOR_DP_DEBUG_0 0x5e
231#define SOR_DP_DEBUG_1 0x5f
232
233#define SOR_DP_SPARE_0 0x60
234#define SOR_DP_SPARE_MACRO_SOR_CLK (1 << 2)
235#define SOR_DP_SPARE_PANEL_INTERNAL (1 << 1)
236#define SOR_DP_SPARE_SEQ_ENABLE (1 << 0)
237
238#define SOR_DP_SPARE_1 0x61
239#define SOR_DP_AUDIO_CTRL 0x62
240
241#define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63
242#define SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x01ffff << 0)
243
244#define SOR_DP_AUDIO_VBLANK_SYMBOLS 0x64
245#define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0)
246
247#define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65
248#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_0 0x66
249#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_1 0x67
250#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_2 0x68
251#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_3 0x69
252#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_4 0x6a
253#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_5 0x6b
254#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_6 0x6c
255
256#define SOR_DP_TPG 0x6d
257#define SOR_DP_TPG_CHANNEL_CODING (1 << 6)
258#define SOR_DP_TPG_SCRAMBLER_MASK (3 << 4)
259#define SOR_DP_TPG_SCRAMBLER_FIBONACCI (2 << 4)
260#define SOR_DP_TPG_SCRAMBLER_GALIOS (1 << 4)
261#define SOR_DP_TPG_SCRAMBLER_NONE (0 << 4)
262#define SOR_DP_TPG_PATTERN_MASK (0xf << 0)
263#define SOR_DP_TPG_PATTERN_HBR2 (0x8 << 0)
264#define SOR_DP_TPG_PATTERN_CSTM (0x7 << 0)
265#define SOR_DP_TPG_PATTERN_PRBS7 (0x6 << 0)
266#define SOR_DP_TPG_PATTERN_SBLERRRATE (0x5 << 0)
267#define SOR_DP_TPG_PATTERN_D102 (0x4 << 0)
268#define SOR_DP_TPG_PATTERN_TRAIN3 (0x3 << 0)
269#define SOR_DP_TPG_PATTERN_TRAIN2 (0x2 << 0)
270#define SOR_DP_TPG_PATTERN_TRAIN1 (0x1 << 0)
271#define SOR_DP_TPG_PATTERN_NONE (0x0 << 0)
272
273#define SOR_DP_TPG_CONFIG 0x6e
274#define SOR_DP_LQ_CSTM_0 0x6f
275#define SOR_DP_LQ_CSTM_1 0x70
276#define SOR_DP_LQ_CSTM_2 0x71
277
278#endif
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index d36efc13b16f..d642d4a02134 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -74,7 +74,7 @@ static void set_scanout(struct drm_crtc *crtc, int n)
74 drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]); 74 drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
75 drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq); 75 drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
76 } 76 }
77 tilcdc_crtc->scanout[n] = crtc->fb; 77 tilcdc_crtc->scanout[n] = crtc->primary->fb;
78 drm_framebuffer_reference(tilcdc_crtc->scanout[n]); 78 drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
79 tilcdc_crtc->dirty &= ~stat[n]; 79 tilcdc_crtc->dirty &= ~stat[n];
80 pm_runtime_put_sync(dev->dev); 80 pm_runtime_put_sync(dev->dev);
@@ -84,7 +84,7 @@ static void update_scanout(struct drm_crtc *crtc)
84{ 84{
85 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 85 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
86 struct drm_device *dev = crtc->dev; 86 struct drm_device *dev = crtc->dev;
87 struct drm_framebuffer *fb = crtc->fb; 87 struct drm_framebuffer *fb = crtc->primary->fb;
88 struct drm_gem_cma_object *gem; 88 struct drm_gem_cma_object *gem;
89 unsigned int depth, bpp; 89 unsigned int depth, bpp;
90 90
@@ -159,7 +159,7 @@ static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
159 return -EBUSY; 159 return -EBUSY;
160 } 160 }
161 161
162 crtc->fb = fb; 162 crtc->primary->fb = fb;
163 tilcdc_crtc->event = event; 163 tilcdc_crtc->event = event;
164 update_scanout(crtc); 164 update_scanout(crtc);
165 165
@@ -339,7 +339,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
339 if (priv->rev == 2) { 339 if (priv->rev == 2) {
340 unsigned int depth, bpp; 340 unsigned int depth, bpp;
341 341
342 drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp); 342 drm_fb_get_bpp_depth(crtc->primary->fb->pixel_format, &depth, &bpp);
343 switch (bpp) { 343 switch (bpp) {
344 case 16: 344 case 16:
345 break; 345 break;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 9df79ac7b8f5..4ab9f7171c4f 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -412,7 +412,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
412 int ret; 412 int ret;
413 413
414 spin_lock(&glob->lru_lock); 414 spin_lock(&glob->lru_lock);
415 ret = ttm_bo_reserve_nolru(bo, false, true, false, 0); 415 ret = __ttm_bo_reserve(bo, false, true, false, 0);
416 416
417 spin_lock(&bdev->fence_lock); 417 spin_lock(&bdev->fence_lock);
418 (void) ttm_bo_wait(bo, false, false, true); 418 (void) ttm_bo_wait(bo, false, false, true);
@@ -443,7 +443,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
443 ttm_bo_add_to_lru(bo); 443 ttm_bo_add_to_lru(bo);
444 } 444 }
445 445
446 ww_mutex_unlock(&bo->resv->lock); 446 __ttm_bo_unreserve(bo);
447 } 447 }
448 448
449 kref_get(&bo->list_kref); 449 kref_get(&bo->list_kref);
@@ -494,7 +494,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
494 sync_obj = driver->sync_obj_ref(bo->sync_obj); 494 sync_obj = driver->sync_obj_ref(bo->sync_obj);
495 spin_unlock(&bdev->fence_lock); 495 spin_unlock(&bdev->fence_lock);
496 496
497 ww_mutex_unlock(&bo->resv->lock); 497 __ttm_bo_unreserve(bo);
498 spin_unlock(&glob->lru_lock); 498 spin_unlock(&glob->lru_lock);
499 499
500 ret = driver->sync_obj_wait(sync_obj, false, interruptible); 500 ret = driver->sync_obj_wait(sync_obj, false, interruptible);
@@ -514,7 +514,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
514 return ret; 514 return ret;
515 515
516 spin_lock(&glob->lru_lock); 516 spin_lock(&glob->lru_lock);
517 ret = ttm_bo_reserve_nolru(bo, false, true, false, 0); 517 ret = __ttm_bo_reserve(bo, false, true, false, 0);
518 518
519 /* 519 /*
520 * We raced, and lost, someone else holds the reservation now, 520 * We raced, and lost, someone else holds the reservation now,
@@ -532,7 +532,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
532 spin_unlock(&bdev->fence_lock); 532 spin_unlock(&bdev->fence_lock);
533 533
534 if (ret || unlikely(list_empty(&bo->ddestroy))) { 534 if (ret || unlikely(list_empty(&bo->ddestroy))) {
535 ww_mutex_unlock(&bo->resv->lock); 535 __ttm_bo_unreserve(bo);
536 spin_unlock(&glob->lru_lock); 536 spin_unlock(&glob->lru_lock);
537 return ret; 537 return ret;
538 } 538 }
@@ -577,11 +577,11 @@ static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
577 kref_get(&nentry->list_kref); 577 kref_get(&nentry->list_kref);
578 } 578 }
579 579
580 ret = ttm_bo_reserve_nolru(entry, false, true, false, 0); 580 ret = __ttm_bo_reserve(entry, false, true, false, 0);
581 if (remove_all && ret) { 581 if (remove_all && ret) {
582 spin_unlock(&glob->lru_lock); 582 spin_unlock(&glob->lru_lock);
583 ret = ttm_bo_reserve_nolru(entry, false, false, 583 ret = __ttm_bo_reserve(entry, false, false,
584 false, 0); 584 false, 0);
585 spin_lock(&glob->lru_lock); 585 spin_lock(&glob->lru_lock);
586 } 586 }
587 587
@@ -726,7 +726,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
726 726
727 spin_lock(&glob->lru_lock); 727 spin_lock(&glob->lru_lock);
728 list_for_each_entry(bo, &man->lru, lru) { 728 list_for_each_entry(bo, &man->lru, lru) {
729 ret = ttm_bo_reserve_nolru(bo, false, true, false, 0); 729 ret = __ttm_bo_reserve(bo, false, true, false, 0);
730 if (!ret) 730 if (!ret)
731 break; 731 break;
732 } 732 }
@@ -1630,7 +1630,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
1630 1630
1631 spin_lock(&glob->lru_lock); 1631 spin_lock(&glob->lru_lock);
1632 list_for_each_entry(bo, &glob->swap_lru, swap) { 1632 list_for_each_entry(bo, &glob->swap_lru, swap) {
1633 ret = ttm_bo_reserve_nolru(bo, false, true, false, 0); 1633 ret = __ttm_bo_reserve(bo, false, true, false, 0);
1634 if (!ret) 1634 if (!ret)
1635 break; 1635 break;
1636 } 1636 }
@@ -1697,7 +1697,7 @@ out:
1697 * already swapped buffer. 1697 * already swapped buffer.
1698 */ 1698 */
1699 1699
1700 ww_mutex_unlock(&bo->resv->lock); 1700 __ttm_bo_unreserve(bo);
1701 kref_put(&bo->list_kref, ttm_bo_release_list); 1701 kref_put(&bo->list_kref, ttm_bo_release_list);
1702 return ret; 1702 return ret;
1703} 1703}
@@ -1731,10 +1731,10 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo)
1731 return -ERESTARTSYS; 1731 return -ERESTARTSYS;
1732 if (!ww_mutex_is_locked(&bo->resv->lock)) 1732 if (!ww_mutex_is_locked(&bo->resv->lock))
1733 goto out_unlock; 1733 goto out_unlock;
1734 ret = ttm_bo_reserve_nolru(bo, true, false, false, NULL); 1734 ret = __ttm_bo_reserve(bo, true, false, false, NULL);
1735 if (unlikely(ret != 0)) 1735 if (unlikely(ret != 0))
1736 goto out_unlock; 1736 goto out_unlock;
1737 ww_mutex_unlock(&bo->resv->lock); 1737 __ttm_bo_unreserve(bo);
1738 1738
1739out_unlock: 1739out_unlock:
1740 mutex_unlock(&bo->wu_mutex); 1740 mutex_unlock(&bo->wu_mutex);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c
index c58eba33bd5f..bd850c9f4bca 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c
@@ -55,6 +55,7 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
55 struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; 55 struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv;
56 struct drm_mm *mm = &rman->mm; 56 struct drm_mm *mm = &rman->mm;
57 struct drm_mm_node *node = NULL; 57 struct drm_mm_node *node = NULL;
58 enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
58 unsigned long lpfn; 59 unsigned long lpfn;
59 int ret; 60 int ret;
60 61
@@ -66,11 +67,15 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
66 if (!node) 67 if (!node)
67 return -ENOMEM; 68 return -ENOMEM;
68 69
70 if (bo->mem.placement & TTM_PL_FLAG_TOPDOWN)
71 aflags = DRM_MM_CREATE_TOP;
72
69 spin_lock(&rman->lock); 73 spin_lock(&rman->lock);
70 ret = drm_mm_insert_node_in_range(mm, node, mem->num_pages, 74 ret = drm_mm_insert_node_in_range_generic(mm, node, mem->num_pages,
71 mem->page_alignment, 75 mem->page_alignment, 0,
72 placement->fpfn, lpfn, 76 placement->fpfn, lpfn,
73 DRM_MM_SEARCH_BEST); 77 DRM_MM_SEARCH_BEST,
78 aflags);
74 spin_unlock(&rman->lock); 79 spin_unlock(&rman->lock);
75 80
76 if (unlikely(ret)) { 81 if (unlikely(ret)) {
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 479e9418e3d7..e8dac8758528 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -46,7 +46,7 @@ static void ttm_eu_backoff_reservation_locked(struct list_head *list)
46 ttm_bo_add_to_lru(bo); 46 ttm_bo_add_to_lru(bo);
47 entry->removed = false; 47 entry->removed = false;
48 } 48 }
49 ww_mutex_unlock(&bo->resv->lock); 49 __ttm_bo_unreserve(bo);
50 } 50 }
51} 51}
52 52
@@ -140,8 +140,8 @@ retry:
140 if (entry->reserved) 140 if (entry->reserved)
141 continue; 141 continue;
142 142
143 ret = ttm_bo_reserve_nolru(bo, true, (ticket == NULL), true, 143 ret = __ttm_bo_reserve(bo, true, (ticket == NULL), true,
144 ticket); 144 ticket);
145 145
146 if (ret == -EDEADLK) { 146 if (ret == -EDEADLK) {
147 /* uh oh, we lost out, drop every reservation and try 147 /* uh oh, we lost out, drop every reservation and try
@@ -224,7 +224,7 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
224 entry->old_sync_obj = bo->sync_obj; 224 entry->old_sync_obj = bo->sync_obj;
225 bo->sync_obj = driver->sync_obj_ref(sync_obj); 225 bo->sync_obj = driver->sync_obj_ref(sync_obj);
226 ttm_bo_add_to_lru(bo); 226 ttm_bo_add_to_lru(bo);
227 ww_mutex_unlock(&bo->resv->lock); 227 __ttm_bo_unreserve(bo);
228 entry->reserved = false; 228 entry->reserved = false;
229 } 229 }
230 spin_unlock(&bdev->fence_lock); 230 spin_unlock(&bdev->fence_lock);
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index 53b51c4e671a..d2a053352789 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -270,6 +270,52 @@ ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
270} 270}
271EXPORT_SYMBOL(ttm_base_object_lookup_for_ref); 271EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
272 272
273/**
274 * ttm_ref_object_exists - Check whether a caller has a valid ref object
275 * (has opened) a base object.
276 *
277 * @tfile: Pointer to a struct ttm_object_file identifying the caller.
278 * @base: Pointer to a struct base object.
279 *
280 * Checks wether the caller identified by @tfile has put a valid USAGE
281 * reference object on the base object identified by @base.
282 */
283bool ttm_ref_object_exists(struct ttm_object_file *tfile,
284 struct ttm_base_object *base)
285{
286 struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
287 struct drm_hash_item *hash;
288 struct ttm_ref_object *ref;
289
290 rcu_read_lock();
291 if (unlikely(drm_ht_find_item_rcu(ht, base->hash.key, &hash) != 0))
292 goto out_false;
293
294 /*
295 * Verify that the ref object is really pointing to our base object.
296 * Our base object could actually be dead, and the ref object pointing
297 * to another base object with the same handle.
298 */
299 ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
300 if (unlikely(base != ref->obj))
301 goto out_false;
302
303 /*
304 * Verify that the ref->obj pointer was actually valid!
305 */
306 rmb();
307 if (unlikely(atomic_read(&ref->kref.refcount) == 0))
308 goto out_false;
309
310 rcu_read_unlock();
311 return true;
312
313 out_false:
314 rcu_read_unlock();
315 return false;
316}
317EXPORT_SYMBOL(ttm_ref_object_exists);
318
273int ttm_ref_object_add(struct ttm_object_file *tfile, 319int ttm_ref_object_add(struct ttm_object_file *tfile,
274 struct ttm_base_object *base, 320 struct ttm_base_object *base,
275 enum ttm_ref_type ref_type, bool *existed) 321 enum ttm_ref_type ref_type, bool *existed)
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 2ae1eb7d1635..cddc4fcf35cf 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -310,7 +310,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
310 310
311{ 311{
312 struct drm_device *dev = crtc->dev; 312 struct drm_device *dev = crtc->dev;
313 struct udl_framebuffer *ufb = to_udl_fb(crtc->fb); 313 struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
314 struct udl_device *udl = dev->dev_private; 314 struct udl_device *udl = dev->dev_private;
315 char *buf; 315 char *buf;
316 char *wrptr; 316 char *wrptr;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 1e80152674b5..8bb26dcd9eae 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -117,10 +117,10 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
117 (void) vmw_context_binding_state_kill 117 (void) vmw_context_binding_state_kill
118 (&container_of(res, struct vmw_user_context, res)->cbs); 118 (&container_of(res, struct vmw_user_context, res)->cbs);
119 (void) vmw_gb_context_destroy(res); 119 (void) vmw_gb_context_destroy(res);
120 mutex_unlock(&dev_priv->binding_mutex);
120 if (dev_priv->pinned_bo != NULL && 121 if (dev_priv->pinned_bo != NULL &&
121 !dev_priv->query_cid_valid) 122 !dev_priv->query_cid_valid)
122 __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 123 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
123 mutex_unlock(&dev_priv->binding_mutex);
124 mutex_unlock(&dev_priv->cmdbuf_mutex); 124 mutex_unlock(&dev_priv->cmdbuf_mutex);
125 return; 125 return;
126 } 126 }
@@ -462,7 +462,6 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
462 struct vmw_resource *tmp; 462 struct vmw_resource *tmp;
463 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 463 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
464 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 464 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
465 struct vmw_master *vmaster = vmw_master(file_priv->master);
466 int ret; 465 int ret;
467 466
468 467
@@ -474,7 +473,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
474 if (unlikely(vmw_user_context_size == 0)) 473 if (unlikely(vmw_user_context_size == 0))
475 vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128; 474 vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
476 475
477 ret = ttm_read_lock(&vmaster->lock, true); 476 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
478 if (unlikely(ret != 0)) 477 if (unlikely(ret != 0))
479 return ret; 478 return ret;
480 479
@@ -521,7 +520,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
521out_err: 520out_err:
522 vmw_resource_unreference(&res); 521 vmw_resource_unreference(&res);
523out_unlock: 522out_unlock:
524 ttm_read_unlock(&vmaster->lock); 523 ttm_read_unlock(&dev_priv->reservation_sem);
525 return ret; 524 return ret;
526 525
527} 526}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index a75840211b3c..70ddce8358b0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -52,11 +52,10 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
52 struct ttm_placement *placement, 52 struct ttm_placement *placement,
53 bool interruptible) 53 bool interruptible)
54{ 54{
55 struct vmw_master *vmaster = dev_priv->active_master;
56 struct ttm_buffer_object *bo = &buf->base; 55 struct ttm_buffer_object *bo = &buf->base;
57 int ret; 56 int ret;
58 57
59 ret = ttm_write_lock(&vmaster->lock, interruptible); 58 ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
60 if (unlikely(ret != 0)) 59 if (unlikely(ret != 0))
61 return ret; 60 return ret;
62 61
@@ -71,7 +70,7 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
71 ttm_bo_unreserve(bo); 70 ttm_bo_unreserve(bo);
72 71
73err: 72err:
74 ttm_write_unlock(&vmaster->lock); 73 ttm_write_unlock(&dev_priv->reservation_sem);
75 return ret; 74 return ret;
76} 75}
77 76
@@ -95,12 +94,11 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
95 struct vmw_dma_buffer *buf, 94 struct vmw_dma_buffer *buf,
96 bool pin, bool interruptible) 95 bool pin, bool interruptible)
97{ 96{
98 struct vmw_master *vmaster = dev_priv->active_master;
99 struct ttm_buffer_object *bo = &buf->base; 97 struct ttm_buffer_object *bo = &buf->base;
100 struct ttm_placement *placement; 98 struct ttm_placement *placement;
101 int ret; 99 int ret;
102 100
103 ret = ttm_write_lock(&vmaster->lock, interruptible); 101 ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
104 if (unlikely(ret != 0)) 102 if (unlikely(ret != 0))
105 return ret; 103 return ret;
106 104
@@ -143,7 +141,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
143err_unreserve: 141err_unreserve:
144 ttm_bo_unreserve(bo); 142 ttm_bo_unreserve(bo);
145err: 143err:
146 ttm_write_unlock(&vmaster->lock); 144 ttm_write_unlock(&dev_priv->reservation_sem);
147 return ret; 145 return ret;
148} 146}
149 147
@@ -198,7 +196,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
198 struct vmw_dma_buffer *buf, 196 struct vmw_dma_buffer *buf,
199 bool pin, bool interruptible) 197 bool pin, bool interruptible)
200{ 198{
201 struct vmw_master *vmaster = dev_priv->active_master;
202 struct ttm_buffer_object *bo = &buf->base; 199 struct ttm_buffer_object *bo = &buf->base;
203 struct ttm_placement placement; 200 struct ttm_placement placement;
204 int ret = 0; 201 int ret = 0;
@@ -209,7 +206,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
209 placement = vmw_vram_placement; 206 placement = vmw_vram_placement;
210 placement.lpfn = bo->num_pages; 207 placement.lpfn = bo->num_pages;
211 208
212 ret = ttm_write_lock(&vmaster->lock, interruptible); 209 ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
213 if (unlikely(ret != 0)) 210 if (unlikely(ret != 0))
214 return ret; 211 return ret;
215 212
@@ -232,7 +229,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
232 229
233 ttm_bo_unreserve(bo); 230 ttm_bo_unreserve(bo);
234err_unlock: 231err_unlock:
235 ttm_write_unlock(&vmaster->lock); 232 ttm_write_unlock(&dev_priv->reservation_sem);
236 233
237 return ret; 234 return ret;
238} 235}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index c35715f26f40..4a223bbea3b3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -142,11 +142,11 @@
142 142
143static const struct drm_ioctl_desc vmw_ioctls[] = { 143static const struct drm_ioctl_desc vmw_ioctls[] = {
144 VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl, 144 VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
145 DRM_AUTH | DRM_UNLOCKED), 145 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
146 VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl, 146 VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
147 DRM_AUTH | DRM_UNLOCKED), 147 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
148 VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl, 148 VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
149 DRM_AUTH | DRM_UNLOCKED), 149 DRM_UNLOCKED | DRM_RENDER_ALLOW),
150 VMW_IOCTL_DEF(VMW_CURSOR_BYPASS, 150 VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
151 vmw_kms_cursor_bypass_ioctl, 151 vmw_kms_cursor_bypass_ioctl,
152 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), 152 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
@@ -159,29 +159,28 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
159 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), 159 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
160 160
161 VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl, 161 VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
162 DRM_AUTH | DRM_UNLOCKED), 162 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
163 VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl, 163 VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
164 DRM_AUTH | DRM_UNLOCKED), 164 DRM_UNLOCKED | DRM_RENDER_ALLOW),
165 VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl, 165 VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
166 DRM_AUTH | DRM_UNLOCKED), 166 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
167 VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl, 167 VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
168 DRM_AUTH | DRM_UNLOCKED), 168 DRM_UNLOCKED | DRM_RENDER_ALLOW),
169 VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl, 169 VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
170 DRM_AUTH | DRM_UNLOCKED), 170 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
171 VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl, 171 VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
172 DRM_AUTH | DRM_UNLOCKED), 172 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
173 VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl, 173 VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
174 DRM_AUTH | DRM_UNLOCKED), 174 DRM_UNLOCKED | DRM_RENDER_ALLOW),
175 VMW_IOCTL_DEF(VMW_FENCE_SIGNALED, 175 VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
176 vmw_fence_obj_signaled_ioctl, 176 vmw_fence_obj_signaled_ioctl,
177 DRM_AUTH | DRM_UNLOCKED), 177 DRM_UNLOCKED | DRM_RENDER_ALLOW),
178 VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl, 178 VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
179 DRM_AUTH | DRM_UNLOCKED), 179 DRM_UNLOCKED | DRM_RENDER_ALLOW),
180 VMW_IOCTL_DEF(VMW_FENCE_EVENT, 180 VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
181 vmw_fence_event_ioctl, 181 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
182 DRM_AUTH | DRM_UNLOCKED),
183 VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl, 182 VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
184 DRM_AUTH | DRM_UNLOCKED), 183 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
185 184
186 /* these allow direct access to the framebuffers mark as master only */ 185 /* these allow direct access to the framebuffers mark as master only */
187 VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl, 186 VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
@@ -194,19 +193,19 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
194 DRM_MASTER | DRM_UNLOCKED), 193 DRM_MASTER | DRM_UNLOCKED),
195 VMW_IOCTL_DEF(VMW_CREATE_SHADER, 194 VMW_IOCTL_DEF(VMW_CREATE_SHADER,
196 vmw_shader_define_ioctl, 195 vmw_shader_define_ioctl,
197 DRM_AUTH | DRM_UNLOCKED), 196 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
198 VMW_IOCTL_DEF(VMW_UNREF_SHADER, 197 VMW_IOCTL_DEF(VMW_UNREF_SHADER,
199 vmw_shader_destroy_ioctl, 198 vmw_shader_destroy_ioctl,
200 DRM_AUTH | DRM_UNLOCKED), 199 DRM_UNLOCKED | DRM_RENDER_ALLOW),
201 VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE, 200 VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
202 vmw_gb_surface_define_ioctl, 201 vmw_gb_surface_define_ioctl,
203 DRM_AUTH | DRM_UNLOCKED), 202 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
204 VMW_IOCTL_DEF(VMW_GB_SURFACE_REF, 203 VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
205 vmw_gb_surface_reference_ioctl, 204 vmw_gb_surface_reference_ioctl,
206 DRM_AUTH | DRM_UNLOCKED), 205 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
207 VMW_IOCTL_DEF(VMW_SYNCCPU, 206 VMW_IOCTL_DEF(VMW_SYNCCPU,
208 vmw_user_dmabuf_synccpu_ioctl, 207 vmw_user_dmabuf_synccpu_ioctl,
209 DRM_AUTH | DRM_UNLOCKED), 208 DRM_UNLOCKED | DRM_RENDER_ALLOW),
210}; 209};
211 210
212static struct pci_device_id vmw_pci_id_list[] = { 211static struct pci_device_id vmw_pci_id_list[] = {
@@ -606,6 +605,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
606 mutex_init(&dev_priv->release_mutex); 605 mutex_init(&dev_priv->release_mutex);
607 mutex_init(&dev_priv->binding_mutex); 606 mutex_init(&dev_priv->binding_mutex);
608 rwlock_init(&dev_priv->resource_lock); 607 rwlock_init(&dev_priv->resource_lock);
608 ttm_lock_init(&dev_priv->reservation_sem);
609 609
610 for (i = vmw_res_context; i < vmw_res_max; ++i) { 610 for (i = vmw_res_context; i < vmw_res_max; ++i) {
611 idr_init(&dev_priv->res_idr[i]); 611 idr_init(&dev_priv->res_idr[i]);
@@ -981,12 +981,70 @@ out_no_tfile:
981 return ret; 981 return ret;
982} 982}
983 983
984static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, 984static struct vmw_master *vmw_master_check(struct drm_device *dev,
985 unsigned long arg) 985 struct drm_file *file_priv,
986 unsigned int flags)
987{
988 int ret;
989 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
990 struct vmw_master *vmaster;
991
992 if (file_priv->minor->type != DRM_MINOR_LEGACY ||
993 !(flags & DRM_AUTH))
994 return NULL;
995
996 ret = mutex_lock_interruptible(&dev->master_mutex);
997 if (unlikely(ret != 0))
998 return ERR_PTR(-ERESTARTSYS);
999
1000 if (file_priv->is_master) {
1001 mutex_unlock(&dev->master_mutex);
1002 return NULL;
1003 }
1004
1005 /*
1006 * Check if we were previously master, but now dropped.
1007 */
1008 if (vmw_fp->locked_master) {
1009 mutex_unlock(&dev->master_mutex);
1010 DRM_ERROR("Dropped master trying to access ioctl that "
1011 "requires authentication.\n");
1012 return ERR_PTR(-EACCES);
1013 }
1014 mutex_unlock(&dev->master_mutex);
1015
1016 /*
1017 * Taking the drm_global_mutex after the TTM lock might deadlock
1018 */
1019 if (!(flags & DRM_UNLOCKED)) {
1020 DRM_ERROR("Refusing locked ioctl access.\n");
1021 return ERR_PTR(-EDEADLK);
1022 }
1023
1024 /*
1025 * Take the TTM lock. Possibly sleep waiting for the authenticating
1026 * master to become master again, or for a SIGTERM if the
1027 * authenticating master exits.
1028 */
1029 vmaster = vmw_master(file_priv->master);
1030 ret = ttm_read_lock(&vmaster->lock, true);
1031 if (unlikely(ret != 0))
1032 vmaster = ERR_PTR(ret);
1033
1034 return vmaster;
1035}
1036
1037static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
1038 unsigned long arg,
1039 long (*ioctl_func)(struct file *, unsigned int,
1040 unsigned long))
986{ 1041{
987 struct drm_file *file_priv = filp->private_data; 1042 struct drm_file *file_priv = filp->private_data;
988 struct drm_device *dev = file_priv->minor->dev; 1043 struct drm_device *dev = file_priv->minor->dev;
989 unsigned int nr = DRM_IOCTL_NR(cmd); 1044 unsigned int nr = DRM_IOCTL_NR(cmd);
1045 struct vmw_master *vmaster;
1046 unsigned int flags;
1047 long ret;
990 1048
991 /* 1049 /*
992 * Do extra checking on driver private ioctls. 1050 * Do extra checking on driver private ioctls.
@@ -995,18 +1053,44 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
995 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) 1053 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
996 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { 1054 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
997 const struct drm_ioctl_desc *ioctl = 1055 const struct drm_ioctl_desc *ioctl =
998 &vmw_ioctls[nr - DRM_COMMAND_BASE]; 1056 &vmw_ioctls[nr - DRM_COMMAND_BASE];
999 1057
1000 if (unlikely(ioctl->cmd_drv != cmd)) { 1058 if (unlikely(ioctl->cmd_drv != cmd)) {
1001 DRM_ERROR("Invalid command format, ioctl %d\n", 1059 DRM_ERROR("Invalid command format, ioctl %d\n",
1002 nr - DRM_COMMAND_BASE); 1060 nr - DRM_COMMAND_BASE);
1003 return -EINVAL; 1061 return -EINVAL;
1004 } 1062 }
1063 flags = ioctl->flags;
1064 } else if (!drm_ioctl_flags(nr, &flags))
1065 return -EINVAL;
1066
1067 vmaster = vmw_master_check(dev, file_priv, flags);
1068 if (unlikely(IS_ERR(vmaster))) {
1069 DRM_INFO("IOCTL ERROR %d\n", nr);
1070 return PTR_ERR(vmaster);
1005 } 1071 }
1006 1072
1007 return drm_ioctl(filp, cmd, arg); 1073 ret = ioctl_func(filp, cmd, arg);
1074 if (vmaster)
1075 ttm_read_unlock(&vmaster->lock);
1076
1077 return ret;
1078}
1079
1080static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
1081 unsigned long arg)
1082{
1083 return vmw_generic_ioctl(filp, cmd, arg, &drm_ioctl);
1008} 1084}
1009 1085
1086#ifdef CONFIG_COMPAT
1087static long vmw_compat_ioctl(struct file *filp, unsigned int cmd,
1088 unsigned long arg)
1089{
1090 return vmw_generic_ioctl(filp, cmd, arg, &drm_compat_ioctl);
1091}
1092#endif
1093
1010static void vmw_lastclose(struct drm_device *dev) 1094static void vmw_lastclose(struct drm_device *dev)
1011{ 1095{
1012 struct drm_crtc *crtc; 1096 struct drm_crtc *crtc;
@@ -1175,12 +1259,11 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
1175{ 1259{
1176 struct vmw_private *dev_priv = 1260 struct vmw_private *dev_priv =
1177 container_of(nb, struct vmw_private, pm_nb); 1261 container_of(nb, struct vmw_private, pm_nb);
1178 struct vmw_master *vmaster = dev_priv->active_master;
1179 1262
1180 switch (val) { 1263 switch (val) {
1181 case PM_HIBERNATION_PREPARE: 1264 case PM_HIBERNATION_PREPARE:
1182 case PM_SUSPEND_PREPARE: 1265 case PM_SUSPEND_PREPARE:
1183 ttm_suspend_lock(&vmaster->lock); 1266 ttm_suspend_lock(&dev_priv->reservation_sem);
1184 1267
1185 /** 1268 /**
1186 * This empties VRAM and unbinds all GMR bindings. 1269 * This empties VRAM and unbinds all GMR bindings.
@@ -1194,7 +1277,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
1194 case PM_POST_HIBERNATION: 1277 case PM_POST_HIBERNATION:
1195 case PM_POST_SUSPEND: 1278 case PM_POST_SUSPEND:
1196 case PM_POST_RESTORE: 1279 case PM_POST_RESTORE:
1197 ttm_suspend_unlock(&vmaster->lock); 1280 ttm_suspend_unlock(&dev_priv->reservation_sem);
1198 1281
1199 break; 1282 break;
1200 case PM_RESTORE_PREPARE: 1283 case PM_RESTORE_PREPARE:
@@ -1315,14 +1398,14 @@ static const struct file_operations vmwgfx_driver_fops = {
1315 .poll = vmw_fops_poll, 1398 .poll = vmw_fops_poll,
1316 .read = vmw_fops_read, 1399 .read = vmw_fops_read,
1317#if defined(CONFIG_COMPAT) 1400#if defined(CONFIG_COMPAT)
1318 .compat_ioctl = drm_compat_ioctl, 1401 .compat_ioctl = vmw_compat_ioctl,
1319#endif 1402#endif
1320 .llseek = noop_llseek, 1403 .llseek = noop_llseek,
1321}; 1404};
1322 1405
1323static struct drm_driver driver = { 1406static struct drm_driver driver = {
1324 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | 1407 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
1325 DRIVER_MODESET | DRIVER_PRIME, 1408 DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER,
1326 .load = vmw_driver_load, 1409 .load = vmw_driver_load,
1327 .unload = vmw_driver_unload, 1410 .unload = vmw_driver_unload,
1328 .lastclose = vmw_lastclose, 1411 .lastclose = vmw_lastclose,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 07831554dad7..6b252a887ae2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,9 +40,9 @@
40#include <drm/ttm/ttm_module.h> 40#include <drm/ttm/ttm_module.h>
41#include "vmwgfx_fence.h" 41#include "vmwgfx_fence.h"
42 42
43#define VMWGFX_DRIVER_DATE "20140228" 43#define VMWGFX_DRIVER_DATE "20140325"
44#define VMWGFX_DRIVER_MAJOR 2 44#define VMWGFX_DRIVER_MAJOR 2
45#define VMWGFX_DRIVER_MINOR 5 45#define VMWGFX_DRIVER_MINOR 6
46#define VMWGFX_DRIVER_PATCHLEVEL 0 46#define VMWGFX_DRIVER_PATCHLEVEL 0
47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) 48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -487,6 +487,11 @@ struct vmw_private {
487 uint32_t num_3d_resources; 487 uint32_t num_3d_resources;
488 488
489 /* 489 /*
490 * Replace this with an rwsem as soon as we have down_xx_interruptible()
491 */
492 struct ttm_lock reservation_sem;
493
494 /*
490 * Query processing. These members 495 * Query processing. These members
491 * are protected by the cmdbuf mutex. 496 * are protected by the cmdbuf mutex.
492 */ 497 */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index efb575a7996c..931490b9cfed 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -2712,7 +2712,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
2712{ 2712{
2713 struct vmw_private *dev_priv = vmw_priv(dev); 2713 struct vmw_private *dev_priv = vmw_priv(dev);
2714 struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data; 2714 struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
2715 struct vmw_master *vmaster = vmw_master(file_priv->master);
2716 int ret; 2715 int ret;
2717 2716
2718 /* 2717 /*
@@ -2729,7 +2728,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
2729 return -EINVAL; 2728 return -EINVAL;
2730 } 2729 }
2731 2730
2732 ret = ttm_read_lock(&vmaster->lock, true); 2731 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
2733 if (unlikely(ret != 0)) 2732 if (unlikely(ret != 0))
2734 return ret; 2733 return ret;
2735 2734
@@ -2745,6 +2744,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
2745 vmw_kms_cursor_post_execbuf(dev_priv); 2744 vmw_kms_cursor_post_execbuf(dev_priv);
2746 2745
2747out_unlock: 2746out_unlock:
2748 ttm_read_unlock(&vmaster->lock); 2747 ttm_read_unlock(&dev_priv->reservation_sem);
2749 return ret; 2748 return ret;
2750} 2749}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index ed5ce2a41bbf..a89ad938eacf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -147,7 +147,7 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
147 } 147 }
148 148
149 if (!vmw_kms_validate_mode_vram(vmw_priv, 149 if (!vmw_kms_validate_mode_vram(vmw_priv,
150 info->fix.line_length, 150 var->xres * var->bits_per_pixel/8,
151 var->yoffset + var->yres)) { 151 var->yoffset + var->yres)) {
152 DRM_ERROR("Requested geom can not fit in framebuffer\n"); 152 DRM_ERROR("Requested geom can not fit in framebuffer\n");
153 return -EINVAL; 153 return -EINVAL;
@@ -162,6 +162,8 @@ static int vmw_fb_set_par(struct fb_info *info)
162 struct vmw_private *vmw_priv = par->vmw_priv; 162 struct vmw_private *vmw_priv = par->vmw_priv;
163 int ret; 163 int ret;
164 164
165 info->fix.line_length = info->var.xres * info->var.bits_per_pixel/8;
166
165 ret = vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres, 167 ret = vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
166 info->fix.line_length, 168 info->fix.line_length,
167 par->bpp, par->depth); 169 par->bpp, par->depth);
@@ -177,6 +179,7 @@ static int vmw_fb_set_par(struct fb_info *info)
177 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, info->var.yoffset); 179 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, info->var.yoffset);
178 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres); 180 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
179 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres); 181 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
182 vmw_write(vmw_priv, SVGA_REG_BYTES_PER_LINE, info->fix.line_length);
180 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 183 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
181 } 184 }
182 185
@@ -377,14 +380,13 @@ static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
377 380
378 ne_placement.lpfn = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; 381 ne_placement.lpfn = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
379 382
380 /* interuptable? */ 383 (void) ttm_write_lock(&vmw_priv->reservation_sem, false);
381 ret = ttm_write_lock(&vmw_priv->fbdev_master.lock, false);
382 if (unlikely(ret != 0))
383 return ret;
384 384
385 vmw_bo = kmalloc(sizeof(*vmw_bo), GFP_KERNEL); 385 vmw_bo = kmalloc(sizeof(*vmw_bo), GFP_KERNEL);
386 if (!vmw_bo) 386 if (!vmw_bo) {
387 ret = -ENOMEM;
387 goto err_unlock; 388 goto err_unlock;
389 }
388 390
389 ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size, 391 ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size,
390 &ne_placement, 392 &ne_placement,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 47b70949bf3a..37881ecf5d7a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -226,7 +226,6 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
226 struct drm_vmw_present_arg *arg = 226 struct drm_vmw_present_arg *arg =
227 (struct drm_vmw_present_arg *)data; 227 (struct drm_vmw_present_arg *)data;
228 struct vmw_surface *surface; 228 struct vmw_surface *surface;
229 struct vmw_master *vmaster = vmw_master(file_priv->master);
230 struct drm_vmw_rect __user *clips_ptr; 229 struct drm_vmw_rect __user *clips_ptr;
231 struct drm_vmw_rect *clips = NULL; 230 struct drm_vmw_rect *clips = NULL;
232 struct drm_framebuffer *fb; 231 struct drm_framebuffer *fb;
@@ -271,7 +270,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
271 } 270 }
272 vfb = vmw_framebuffer_to_vfb(fb); 271 vfb = vmw_framebuffer_to_vfb(fb);
273 272
274 ret = ttm_read_lock(&vmaster->lock, true); 273 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
275 if (unlikely(ret != 0)) 274 if (unlikely(ret != 0))
276 goto out_no_ttm_lock; 275 goto out_no_ttm_lock;
277 276
@@ -291,7 +290,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
291 vmw_surface_unreference(&surface); 290 vmw_surface_unreference(&surface);
292 291
293out_no_surface: 292out_no_surface:
294 ttm_read_unlock(&vmaster->lock); 293 ttm_read_unlock(&dev_priv->reservation_sem);
295out_no_ttm_lock: 294out_no_ttm_lock:
296 drm_framebuffer_unreference(fb); 295 drm_framebuffer_unreference(fb);
297out_no_fb: 296out_no_fb:
@@ -311,7 +310,6 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
311 struct drm_vmw_fence_rep __user *user_fence_rep = 310 struct drm_vmw_fence_rep __user *user_fence_rep =
312 (struct drm_vmw_fence_rep __user *) 311 (struct drm_vmw_fence_rep __user *)
313 (unsigned long)arg->fence_rep; 312 (unsigned long)arg->fence_rep;
314 struct vmw_master *vmaster = vmw_master(file_priv->master);
315 struct drm_vmw_rect __user *clips_ptr; 313 struct drm_vmw_rect __user *clips_ptr;
316 struct drm_vmw_rect *clips = NULL; 314 struct drm_vmw_rect *clips = NULL;
317 struct drm_framebuffer *fb; 315 struct drm_framebuffer *fb;
@@ -361,7 +359,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
361 goto out_no_ttm_lock; 359 goto out_no_ttm_lock;
362 } 360 }
363 361
364 ret = ttm_read_lock(&vmaster->lock, true); 362 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
365 if (unlikely(ret != 0)) 363 if (unlikely(ret != 0))
366 goto out_no_ttm_lock; 364 goto out_no_ttm_lock;
367 365
@@ -369,7 +367,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
369 vfb, user_fence_rep, 367 vfb, user_fence_rep,
370 clips, num_clips); 368 clips, num_clips);
371 369
372 ttm_read_unlock(&vmaster->lock); 370 ttm_read_unlock(&dev_priv->reservation_sem);
373out_no_ttm_lock: 371out_no_ttm_lock:
374 drm_framebuffer_unreference(fb); 372 drm_framebuffer_unreference(fb);
375out_no_fb: 373out_no_fb:
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8a650413dea5..a2dde5ad8138 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -468,7 +468,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
468 num_units = 0; 468 num_units = 0;
469 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, 469 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
470 head) { 470 head) {
471 if (crtc->fb != &framebuffer->base) 471 if (crtc->primary->fb != &framebuffer->base)
472 continue; 472 continue;
473 units[num_units++] = vmw_crtc_to_du(crtc); 473 units[num_units++] = vmw_crtc_to_du(crtc);
474 } 474 }
@@ -596,7 +596,6 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
596 unsigned num_clips) 596 unsigned num_clips)
597{ 597{
598 struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); 598 struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
599 struct vmw_master *vmaster = vmw_master(file_priv->master);
600 struct vmw_framebuffer_surface *vfbs = 599 struct vmw_framebuffer_surface *vfbs =
601 vmw_framebuffer_to_vfbs(framebuffer); 600 vmw_framebuffer_to_vfbs(framebuffer);
602 struct drm_clip_rect norect; 601 struct drm_clip_rect norect;
@@ -611,7 +610,7 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
611 610
612 drm_modeset_lock_all(dev_priv->dev); 611 drm_modeset_lock_all(dev_priv->dev);
613 612
614 ret = ttm_read_lock(&vmaster->lock, true); 613 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
615 if (unlikely(ret != 0)) { 614 if (unlikely(ret != 0)) {
616 drm_modeset_unlock_all(dev_priv->dev); 615 drm_modeset_unlock_all(dev_priv->dev);
617 return ret; 616 return ret;
@@ -632,7 +631,7 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
632 flags, color, 631 flags, color,
633 clips, num_clips, inc, NULL); 632 clips, num_clips, inc, NULL);
634 633
635 ttm_read_unlock(&vmaster->lock); 634 ttm_read_unlock(&dev_priv->reservation_sem);
636 635
637 drm_modeset_unlock_all(dev_priv->dev); 636 drm_modeset_unlock_all(dev_priv->dev);
638 637
@@ -883,7 +882,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
883 882
884 num_units = 0; 883 num_units = 0;
885 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { 884 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
886 if (crtc->fb != &framebuffer->base) 885 if (crtc->primary->fb != &framebuffer->base)
887 continue; 886 continue;
888 units[num_units++] = vmw_crtc_to_du(crtc); 887 units[num_units++] = vmw_crtc_to_du(crtc);
889 } 888 }
@@ -954,7 +953,6 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
954 unsigned num_clips) 953 unsigned num_clips)
955{ 954{
956 struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); 955 struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
957 struct vmw_master *vmaster = vmw_master(file_priv->master);
958 struct vmw_framebuffer_dmabuf *vfbd = 956 struct vmw_framebuffer_dmabuf *vfbd =
959 vmw_framebuffer_to_vfbd(framebuffer); 957 vmw_framebuffer_to_vfbd(framebuffer);
960 struct drm_clip_rect norect; 958 struct drm_clip_rect norect;
@@ -962,7 +960,7 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
962 960
963 drm_modeset_lock_all(dev_priv->dev); 961 drm_modeset_lock_all(dev_priv->dev);
964 962
965 ret = ttm_read_lock(&vmaster->lock, true); 963 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
966 if (unlikely(ret != 0)) { 964 if (unlikely(ret != 0)) {
967 drm_modeset_unlock_all(dev_priv->dev); 965 drm_modeset_unlock_all(dev_priv->dev);
968 return ret; 966 return ret;
@@ -989,7 +987,7 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
989 clips, num_clips, increment, NULL); 987 clips, num_clips, increment, NULL);
990 } 988 }
991 989
992 ttm_read_unlock(&vmaster->lock); 990 ttm_read_unlock(&dev_priv->reservation_sem);
993 991
994 drm_modeset_unlock_all(dev_priv->dev); 992 drm_modeset_unlock_all(dev_priv->dev);
995 993
@@ -1245,7 +1243,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
1245 1243
1246 num_units = 0; 1244 num_units = 0;
1247 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { 1245 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
1248 if (crtc->fb != &vfb->base) 1246 if (crtc->primary->fb != &vfb->base)
1249 continue; 1247 continue;
1250 units[num_units++] = vmw_crtc_to_du(crtc); 1248 units[num_units++] = vmw_crtc_to_du(crtc);
1251 } 1249 }
@@ -1382,7 +1380,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
1382 1380
1383 num_units = 0; 1381 num_units = 0;
1384 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { 1382 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
1385 if (crtc->fb != &vfb->base) 1383 if (crtc->primary->fb != &vfb->base)
1386 continue; 1384 continue;
1387 units[num_units++] = vmw_crtc_to_du(crtc); 1385 units[num_units++] = vmw_crtc_to_du(crtc);
1388 } 1386 }
@@ -1725,7 +1723,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
1725 uint32_t page_flip_flags) 1723 uint32_t page_flip_flags)
1726{ 1724{
1727 struct vmw_private *dev_priv = vmw_priv(crtc->dev); 1725 struct vmw_private *dev_priv = vmw_priv(crtc->dev);
1728 struct drm_framebuffer *old_fb = crtc->fb; 1726 struct drm_framebuffer *old_fb = crtc->primary->fb;
1729 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); 1727 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
1730 struct drm_file *file_priv ; 1728 struct drm_file *file_priv ;
1731 struct vmw_fence_obj *fence = NULL; 1729 struct vmw_fence_obj *fence = NULL;
@@ -1743,7 +1741,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
1743 if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) 1741 if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
1744 return -EINVAL; 1742 return -EINVAL;
1745 1743
1746 crtc->fb = fb; 1744 crtc->primary->fb = fb;
1747 1745
1748 /* do a full screen dirty update */ 1746 /* do a full screen dirty update */
1749 clips.x1 = clips.y1 = 0; 1747 clips.x1 = clips.y1 = 0;
@@ -1783,7 +1781,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
1783 return ret; 1781 return ret;
1784 1782
1785out_no_fence: 1783out_no_fence:
1786 crtc->fb = old_fb; 1784 crtc->primary->fb = old_fb;
1787 return ret; 1785 return ret;
1788} 1786}
1789 1787
@@ -2022,7 +2020,6 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
2022 struct vmw_private *dev_priv = vmw_priv(dev); 2020 struct vmw_private *dev_priv = vmw_priv(dev);
2023 struct drm_vmw_update_layout_arg *arg = 2021 struct drm_vmw_update_layout_arg *arg =
2024 (struct drm_vmw_update_layout_arg *)data; 2022 (struct drm_vmw_update_layout_arg *)data;
2025 struct vmw_master *vmaster = vmw_master(file_priv->master);
2026 void __user *user_rects; 2023 void __user *user_rects;
2027 struct drm_vmw_rect *rects; 2024 struct drm_vmw_rect *rects;
2028 unsigned rects_size; 2025 unsigned rects_size;
@@ -2030,7 +2027,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
2030 int i; 2027 int i;
2031 struct drm_mode_config *mode_config = &dev->mode_config; 2028 struct drm_mode_config *mode_config = &dev->mode_config;
2032 2029
2033 ret = ttm_read_lock(&vmaster->lock, true); 2030 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
2034 if (unlikely(ret != 0)) 2031 if (unlikely(ret != 0))
2035 return ret; 2032 return ret;
2036 2033
@@ -2072,6 +2069,6 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
2072out_free: 2069out_free:
2073 kfree(rects); 2070 kfree(rects);
2074out_unlock: 2071out_unlock:
2075 ttm_read_unlock(&vmaster->lock); 2072 ttm_read_unlock(&dev_priv->reservation_sem);
2076 return ret; 2073 return ret;
2077} 2074}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index a055a26819c2..b2b9bd23aeee 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -93,7 +93,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
93 93
94 if (crtc == NULL) 94 if (crtc == NULL)
95 return 0; 95 return 0;
96 fb = entry->base.crtc.fb; 96 fb = entry->base.crtc.primary->fb;
97 97
98 return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], 98 return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
99 fb->bits_per_pixel, fb->depth); 99 fb->bits_per_pixel, fb->depth);
@@ -101,7 +101,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
101 101
102 if (!list_empty(&lds->active)) { 102 if (!list_empty(&lds->active)) {
103 entry = list_entry(lds->active.next, typeof(*entry), active); 103 entry = list_entry(lds->active.next, typeof(*entry), active);
104 fb = entry->base.crtc.fb; 104 fb = entry->base.crtc.primary->fb;
105 105
106 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], 106 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
107 fb->bits_per_pixel, fb->depth); 107 fb->bits_per_pixel, fb->depth);
@@ -259,7 +259,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
259 259
260 connector->encoder = NULL; 260 connector->encoder = NULL;
261 encoder->crtc = NULL; 261 encoder->crtc = NULL;
262 crtc->fb = NULL; 262 crtc->primary->fb = NULL;
263 crtc->enabled = false; 263 crtc->enabled = false;
264 264
265 vmw_ldu_del_active(dev_priv, ldu); 265 vmw_ldu_del_active(dev_priv, ldu);
@@ -280,7 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
280 280
281 vmw_fb_off(dev_priv); 281 vmw_fb_off(dev_priv);
282 282
283 crtc->fb = fb; 283 crtc->primary->fb = fb;
284 encoder->crtc = crtc; 284 encoder->crtc = crtc;
285 connector->encoder = encoder; 285 connector->encoder = encoder;
286 crtc->x = set->x; 286 crtc->x = set->x;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 9757b57f8388..01d68f0a69dc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -538,8 +538,13 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
538 return -EPERM; 538 return -EPERM;
539 539
540 vmw_user_bo = vmw_user_dma_buffer(bo); 540 vmw_user_bo = vmw_user_dma_buffer(bo);
541 return (vmw_user_bo->prime.base.tfile == tfile || 541
542 vmw_user_bo->prime.base.shareable) ? 0 : -EPERM; 542 /* Check that the caller has opened the object. */
543 if (likely(ttm_ref_object_exists(tfile, &vmw_user_bo->prime.base)))
544 return 0;
545
546 DRM_ERROR("Could not grant buffer access.\n");
547 return -EPERM;
543} 548}
544 549
545/** 550/**
@@ -676,10 +681,9 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
676 struct drm_vmw_dmabuf_rep *rep = &arg->rep; 681 struct drm_vmw_dmabuf_rep *rep = &arg->rep;
677 struct vmw_dma_buffer *dma_buf; 682 struct vmw_dma_buffer *dma_buf;
678 uint32_t handle; 683 uint32_t handle;
679 struct vmw_master *vmaster = vmw_master(file_priv->master);
680 int ret; 684 int ret;
681 685
682 ret = ttm_read_lock(&vmaster->lock, true); 686 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
683 if (unlikely(ret != 0)) 687 if (unlikely(ret != 0))
684 return ret; 688 return ret;
685 689
@@ -696,7 +700,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
696 vmw_dmabuf_unreference(&dma_buf); 700 vmw_dmabuf_unreference(&dma_buf);
697 701
698out_no_dmabuf: 702out_no_dmabuf:
699 ttm_read_unlock(&vmaster->lock); 703 ttm_read_unlock(&dev_priv->reservation_sem);
700 704
701 return ret; 705 return ret;
702} 706}
@@ -873,7 +877,6 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
873 struct vmw_resource *tmp; 877 struct vmw_resource *tmp;
874 struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 878 struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
875 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 879 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
876 struct vmw_master *vmaster = vmw_master(file_priv->master);
877 int ret; 880 int ret;
878 881
879 /* 882 /*
@@ -884,7 +887,7 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
884 if (unlikely(vmw_user_stream_size == 0)) 887 if (unlikely(vmw_user_stream_size == 0))
885 vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128; 888 vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128;
886 889
887 ret = ttm_read_lock(&vmaster->lock, true); 890 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
888 if (unlikely(ret != 0)) 891 if (unlikely(ret != 0))
889 return ret; 892 return ret;
890 893
@@ -932,7 +935,7 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
932out_err: 935out_err:
933 vmw_resource_unreference(&res); 936 vmw_resource_unreference(&res);
934out_unlock: 937out_unlock:
935 ttm_read_unlock(&vmaster->lock); 938 ttm_read_unlock(&dev_priv->reservation_sem);
936 return ret; 939 return ret;
937} 940}
938 941
@@ -985,14 +988,13 @@ int vmw_dumb_create(struct drm_file *file_priv,
985 struct drm_mode_create_dumb *args) 988 struct drm_mode_create_dumb *args)
986{ 989{
987 struct vmw_private *dev_priv = vmw_priv(dev); 990 struct vmw_private *dev_priv = vmw_priv(dev);
988 struct vmw_master *vmaster = vmw_master(file_priv->master);
989 struct vmw_dma_buffer *dma_buf; 991 struct vmw_dma_buffer *dma_buf;
990 int ret; 992 int ret;
991 993
992 args->pitch = args->width * ((args->bpp + 7) / 8); 994 args->pitch = args->width * ((args->bpp + 7) / 8);
993 args->size = args->pitch * args->height; 995 args->size = args->pitch * args->height;
994 996
995 ret = ttm_read_lock(&vmaster->lock, true); 997 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
996 if (unlikely(ret != 0)) 998 if (unlikely(ret != 0))
997 return ret; 999 return ret;
998 1000
@@ -1004,7 +1006,7 @@ int vmw_dumb_create(struct drm_file *file_priv,
1004 1006
1005 vmw_dmabuf_unreference(&dma_buf); 1007 vmw_dmabuf_unreference(&dma_buf);
1006out_no_dmabuf: 1008out_no_dmabuf:
1007 ttm_read_unlock(&vmaster->lock); 1009 ttm_read_unlock(&dev_priv->reservation_sem);
1008 return ret; 1010 return ret;
1009} 1011}
1010 1012
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 22406c8651ea..a95d3a0cabe4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -307,7 +307,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
307 307
308 connector->encoder = NULL; 308 connector->encoder = NULL;
309 encoder->crtc = NULL; 309 encoder->crtc = NULL;
310 crtc->fb = NULL; 310 crtc->primary->fb = NULL;
311 crtc->x = 0; 311 crtc->x = 0;
312 crtc->y = 0; 312 crtc->y = 0;
313 crtc->enabled = false; 313 crtc->enabled = false;
@@ -368,7 +368,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
368 368
369 connector->encoder = NULL; 369 connector->encoder = NULL;
370 encoder->crtc = NULL; 370 encoder->crtc = NULL;
371 crtc->fb = NULL; 371 crtc->primary->fb = NULL;
372 crtc->x = 0; 372 crtc->x = 0;
373 crtc->y = 0; 373 crtc->y = 0;
374 crtc->enabled = false; 374 crtc->enabled = false;
@@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
381 connector->encoder = encoder; 381 connector->encoder = encoder;
382 encoder->crtc = crtc; 382 encoder->crtc = crtc;
383 crtc->mode = *mode; 383 crtc->mode = *mode;
384 crtc->fb = fb; 384 crtc->primary->fb = fb;
385 crtc->x = set->x; 385 crtc->x = set->x;
386 crtc->y = set->y; 386 crtc->y = set->y;
387 crtc->enabled = true; 387 crtc->enabled = true;
@@ -572,5 +572,5 @@ void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
572 BUG_ON(!sou->base.is_implicit); 572 BUG_ON(!sou->base.is_implicit);
573 573
574 dev_priv->sou_priv->implicit_fb = 574 dev_priv->sou_priv->implicit_fb =
575 vmw_framebuffer_to_vfb(sou->base.crtc.fb); 575 vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
576} 576}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index ee3856578a12..c1559eeaffe9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -449,7 +449,6 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
449 struct drm_vmw_shader_create_arg *arg = 449 struct drm_vmw_shader_create_arg *arg =
450 (struct drm_vmw_shader_create_arg *)data; 450 (struct drm_vmw_shader_create_arg *)data;
451 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 451 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
452 struct vmw_master *vmaster = vmw_master(file_priv->master);
453 struct vmw_dma_buffer *buffer = NULL; 452 struct vmw_dma_buffer *buffer = NULL;
454 SVGA3dShaderType shader_type; 453 SVGA3dShaderType shader_type;
455 int ret; 454 int ret;
@@ -487,14 +486,14 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
487 goto out_bad_arg; 486 goto out_bad_arg;
488 } 487 }
489 488
490 ret = ttm_read_lock(&vmaster->lock, true); 489 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
491 if (unlikely(ret != 0)) 490 if (unlikely(ret != 0))
492 goto out_bad_arg; 491 goto out_bad_arg;
493 492
494 ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset, 493 ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
495 shader_type, tfile, &arg->shader_handle); 494 shader_type, tfile, &arg->shader_handle);
496 495
497 ttm_read_unlock(&vmaster->lock); 496 ttm_read_unlock(&dev_priv->reservation_sem);
498out_bad_arg: 497out_bad_arg:
499 vmw_dmabuf_unreference(&buffer); 498 vmw_dmabuf_unreference(&buffer);
500 return ret; 499 return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index e7af580ab977..4ecdbf3e59da 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -36,11 +36,13 @@
36 * @base: The TTM base object handling user-space visibility. 36 * @base: The TTM base object handling user-space visibility.
37 * @srf: The surface metadata. 37 * @srf: The surface metadata.
38 * @size: TTM accounting size for the surface. 38 * @size: TTM accounting size for the surface.
39 * @master: master of the creating client. Used for security check.
39 */ 40 */
40struct vmw_user_surface { 41struct vmw_user_surface {
41 struct ttm_prime_object prime; 42 struct ttm_prime_object prime;
42 struct vmw_surface srf; 43 struct vmw_surface srf;
43 uint32_t size; 44 uint32_t size;
45 struct drm_master *master;
44}; 46};
45 47
46/** 48/**
@@ -624,6 +626,8 @@ static void vmw_user_surface_free(struct vmw_resource *res)
624 struct vmw_private *dev_priv = srf->res.dev_priv; 626 struct vmw_private *dev_priv = srf->res.dev_priv;
625 uint32_t size = user_srf->size; 627 uint32_t size = user_srf->size;
626 628
629 if (user_srf->master)
630 drm_master_put(&user_srf->master);
627 kfree(srf->offsets); 631 kfree(srf->offsets);
628 kfree(srf->sizes); 632 kfree(srf->sizes);
629 kfree(srf->snooper.image); 633 kfree(srf->snooper.image);
@@ -697,7 +701,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
697 struct vmw_surface_offset *cur_offset; 701 struct vmw_surface_offset *cur_offset;
698 uint32_t num_sizes; 702 uint32_t num_sizes;
699 uint32_t size; 703 uint32_t size;
700 struct vmw_master *vmaster = vmw_master(file_priv->master);
701 const struct svga3d_surface_desc *desc; 704 const struct svga3d_surface_desc *desc;
702 705
703 if (unlikely(vmw_user_surface_size == 0)) 706 if (unlikely(vmw_user_surface_size == 0))
@@ -723,7 +726,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
723 return -EINVAL; 726 return -EINVAL;
724 } 727 }
725 728
726 ret = ttm_read_lock(&vmaster->lock, true); 729 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
727 if (unlikely(ret != 0)) 730 if (unlikely(ret != 0))
728 return ret; 731 return ret;
729 732
@@ -820,6 +823,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
820 823
821 user_srf->prime.base.shareable = false; 824 user_srf->prime.base.shareable = false;
822 user_srf->prime.base.tfile = NULL; 825 user_srf->prime.base.tfile = NULL;
826 if (drm_is_primary_client(file_priv))
827 user_srf->master = drm_master_get(file_priv->master);
823 828
824 /** 829 /**
825 * From this point, the generic resource management functions 830 * From this point, the generic resource management functions
@@ -862,7 +867,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
862 rep->sid = user_srf->prime.base.hash.key; 867 rep->sid = user_srf->prime.base.hash.key;
863 vmw_resource_unreference(&res); 868 vmw_resource_unreference(&res);
864 869
865 ttm_read_unlock(&vmaster->lock); 870 ttm_read_unlock(&dev_priv->reservation_sem);
866 return 0; 871 return 0;
867out_no_copy: 872out_no_copy:
868 kfree(srf->offsets); 873 kfree(srf->offsets);
@@ -873,7 +878,81 @@ out_no_sizes:
873out_no_user_srf: 878out_no_user_srf:
874 ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 879 ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
875out_unlock: 880out_unlock:
876 ttm_read_unlock(&vmaster->lock); 881 ttm_read_unlock(&dev_priv->reservation_sem);
882 return ret;
883}
884
885
886static int
887vmw_surface_handle_reference(struct vmw_private *dev_priv,
888 struct drm_file *file_priv,
889 uint32_t u_handle,
890 enum drm_vmw_handle_type handle_type,
891 struct ttm_base_object **base_p)
892{
893 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
894 struct vmw_user_surface *user_srf;
895 uint32_t handle;
896 struct ttm_base_object *base;
897 int ret;
898
899 if (handle_type == DRM_VMW_HANDLE_PRIME) {
900 ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
901 if (unlikely(ret != 0))
902 return ret;
903 } else {
904 if (unlikely(drm_is_render_client(file_priv))) {
905 DRM_ERROR("Render client refused legacy "
906 "surface reference.\n");
907 return -EACCES;
908 }
909 handle = u_handle;
910 }
911
912 ret = -EINVAL;
913 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
914 if (unlikely(base == NULL)) {
915 DRM_ERROR("Could not find surface to reference.\n");
916 goto out_no_lookup;
917 }
918
919 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
920 DRM_ERROR("Referenced object is not a surface.\n");
921 goto out_bad_resource;
922 }
923
924 if (handle_type != DRM_VMW_HANDLE_PRIME) {
925 user_srf = container_of(base, struct vmw_user_surface,
926 prime.base);
927
928 /*
929 * Make sure the surface creator has the same
930 * authenticating master.
931 */
932 if (drm_is_primary_client(file_priv) &&
933 user_srf->master != file_priv->master) {
934 DRM_ERROR("Trying to reference surface outside of"
935 " master domain.\n");
936 ret = -EACCES;
937 goto out_bad_resource;
938 }
939
940 ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
941 if (unlikely(ret != 0)) {
942 DRM_ERROR("Could not add a reference to a surface.\n");
943 goto out_bad_resource;
944 }
945 }
946
947 *base_p = base;
948 return 0;
949
950out_bad_resource:
951 ttm_base_object_unref(&base);
952out_no_lookup:
953 if (handle_type == DRM_VMW_HANDLE_PRIME)
954 (void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
955
877 return ret; 956 return ret;
878} 957}
879 958
@@ -898,27 +977,16 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
898 struct vmw_user_surface *user_srf; 977 struct vmw_user_surface *user_srf;
899 struct drm_vmw_size __user *user_sizes; 978 struct drm_vmw_size __user *user_sizes;
900 struct ttm_base_object *base; 979 struct ttm_base_object *base;
901 int ret = -EINVAL; 980 int ret;
902
903 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
904 if (unlikely(base == NULL)) {
905 DRM_ERROR("Could not find surface to reference.\n");
906 return -EINVAL;
907 }
908 981
909 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) 982 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
910 goto out_bad_resource; 983 req->handle_type, &base);
984 if (unlikely(ret != 0))
985 return ret;
911 986
912 user_srf = container_of(base, struct vmw_user_surface, prime.base); 987 user_srf = container_of(base, struct vmw_user_surface, prime.base);
913 srf = &user_srf->srf; 988 srf = &user_srf->srf;
914 989
915 ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
916 TTM_REF_USAGE, NULL);
917 if (unlikely(ret != 0)) {
918 DRM_ERROR("Could not add a reference to a surface.\n");
919 goto out_no_reference;
920 }
921
922 rep->flags = srf->flags; 990 rep->flags = srf->flags;
923 rep->format = srf->format; 991 rep->format = srf->format;
924 memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels)); 992 memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
@@ -931,10 +999,10 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
931 if (unlikely(ret != 0)) { 999 if (unlikely(ret != 0)) {
932 DRM_ERROR("copy_to_user failed %p %u\n", 1000 DRM_ERROR("copy_to_user failed %p %u\n",
933 user_sizes, srf->num_sizes); 1001 user_sizes, srf->num_sizes);
1002 ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
934 ret = -EFAULT; 1003 ret = -EFAULT;
935 } 1004 }
936out_bad_resource: 1005
937out_no_reference:
938 ttm_base_object_unref(&base); 1006 ttm_base_object_unref(&base);
939 1007
940 return ret; 1008 return ret;
@@ -1173,7 +1241,6 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1173 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1241 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1174 int ret; 1242 int ret;
1175 uint32_t size; 1243 uint32_t size;
1176 struct vmw_master *vmaster = vmw_master(file_priv->master);
1177 const struct svga3d_surface_desc *desc; 1244 const struct svga3d_surface_desc *desc;
1178 uint32_t backup_handle; 1245 uint32_t backup_handle;
1179 1246
@@ -1189,7 +1256,7 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1189 return -EINVAL; 1256 return -EINVAL;
1190 } 1257 }
1191 1258
1192 ret = ttm_read_lock(&vmaster->lock, true); 1259 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1193 if (unlikely(ret != 0)) 1260 if (unlikely(ret != 0))
1194 return ret; 1261 return ret;
1195 1262
@@ -1228,6 +1295,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1228 1295
1229 user_srf->prime.base.shareable = false; 1296 user_srf->prime.base.shareable = false;
1230 user_srf->prime.base.tfile = NULL; 1297 user_srf->prime.base.tfile = NULL;
1298 if (drm_is_primary_client(file_priv))
1299 user_srf->master = drm_master_get(file_priv->master);
1231 1300
1232 /** 1301 /**
1233 * From this point, the generic resource management functions 1302 * From this point, the generic resource management functions
@@ -1283,12 +1352,12 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1283 1352
1284 vmw_resource_unreference(&res); 1353 vmw_resource_unreference(&res);
1285 1354
1286 ttm_read_unlock(&vmaster->lock); 1355 ttm_read_unlock(&dev_priv->reservation_sem);
1287 return 0; 1356 return 0;
1288out_no_user_srf: 1357out_no_user_srf:
1289 ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 1358 ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
1290out_unlock: 1359out_unlock:
1291 ttm_read_unlock(&vmaster->lock); 1360 ttm_read_unlock(&dev_priv->reservation_sem);
1292 return ret; 1361 return ret;
1293} 1362}
1294 1363
@@ -1315,14 +1384,10 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1315 uint32_t backup_handle; 1384 uint32_t backup_handle;
1316 int ret = -EINVAL; 1385 int ret = -EINVAL;
1317 1386
1318 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid); 1387 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1319 if (unlikely(base == NULL)) { 1388 req->handle_type, &base);
1320 DRM_ERROR("Could not find surface to reference.\n"); 1389 if (unlikely(ret != 0))
1321 return -EINVAL; 1390 return ret;
1322 }
1323
1324 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
1325 goto out_bad_resource;
1326 1391
1327 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1392 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1328 srf = &user_srf->srf; 1393 srf = &user_srf->srf;
@@ -1331,13 +1396,6 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1331 goto out_bad_resource; 1396 goto out_bad_resource;
1332 } 1397 }
1333 1398
1334 ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
1335 TTM_REF_USAGE, NULL);
1336 if (unlikely(ret != 0)) {
1337 DRM_ERROR("Could not add a reference to a GB surface.\n");
1338 goto out_bad_resource;
1339 }
1340
1341 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ 1399 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1342 ret = vmw_user_dmabuf_reference(tfile, srf->res.backup, 1400 ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
1343 &backup_handle); 1401 &backup_handle);
@@ -1346,8 +1404,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1346 if (unlikely(ret != 0)) { 1404 if (unlikely(ret != 0)) {
1347 DRM_ERROR("Could not add a reference to a GB surface " 1405 DRM_ERROR("Could not add a reference to a GB surface "
1348 "backup buffer.\n"); 1406 "backup buffer.\n");
1349 (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 1407 (void) ttm_ref_object_base_unref(tfile, base->hash.key,
1350 req->sid,
1351 TTM_REF_USAGE); 1408 TTM_REF_USAGE);
1352 goto out_bad_resource; 1409 goto out_bad_resource;
1353 } 1410 }
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index bfb09d802abd..b10550ee1d89 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -102,6 +102,7 @@ u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)
102{ 102{
103 return (u32)atomic_add_return(incrs, &sp->max_val); 103 return (u32)atomic_add_return(incrs, &sp->max_val);
104} 104}
105EXPORT_SYMBOL(host1x_syncpt_incr_max);
105 106
106 /* 107 /*
107 * Write cached syncpoint and waitbase values to hardware. 108 * Write cached syncpoint and waitbase values to hardware.
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 22be104fbda9..39a7519a2853 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -120,7 +120,7 @@ static int ipu_page_flip(struct drm_crtc *crtc,
120 120
121 ipu_crtc->newfb = fb; 121 ipu_crtc->newfb = fb;
122 ipu_crtc->page_flip_event = event; 122 ipu_crtc->page_flip_event = event;
123 crtc->fb = fb; 123 crtc->primary->fb = fb;
124 124
125 return 0; 125 return 0;
126} 126}
@@ -192,7 +192,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
192 return ret; 192 return ret;
193 } 193 }
194 194
195 return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->fb, 195 return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->primary->fb,
196 0, 0, mode->hdisplay, mode->vdisplay, 196 0, 0, mode->hdisplay, mode->vdisplay,
197 x, y, mode->hdisplay, mode->vdisplay); 197 x, y, mode->hdisplay, mode->vdisplay);
198} 198}
@@ -218,7 +218,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
218 218
219 if (ipu_crtc->newfb) { 219 if (ipu_crtc->newfb) {
220 ipu_crtc->newfb = NULL; 220 ipu_crtc->newfb = NULL;
221 ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.fb, 221 ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.primary->fb,
222 ipu_crtc->plane[0]->x, ipu_crtc->plane[0]->y); 222 ipu_crtc->plane[0]->x, ipu_crtc->plane[0]->y);
223 ipu_crtc_handle_pageflip(ipu_crtc); 223 ipu_crtc_handle_pageflip(ipu_crtc);
224 } 224 }
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
index 34b642a12f8b..5128dc399d36 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -68,7 +68,7 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
68 68
69 cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 69 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
70 if (!cma_obj) { 70 if (!cma_obj) {
71 DRM_LOG_KMS("entry is null.\n"); 71 DRM_DEBUG_KMS("entry is null.\n");
72 return -EFAULT; 72 return -EFAULT;
73 } 73 }
74 74
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 75c8a8e7efc0..fcf2d48ac6d1 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -29,11 +29,4 @@ config EXYNOS_LCD_S6E8AX0
29 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its 29 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
30 LCD control driver. 30 LCD control driver.
31 31
32config EXYNOS_DP
33 bool "EXYNOS DP driver support"
34 depends on OF && ARCH_EXYNOS
35 default n
36 help
37 This enables support for DP device.
38
39endif # EXYNOS_VIDEO 32endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
index ec7772e452a9..b5b1bd228abb 100644
--- a/drivers/video/exynos/Makefile
+++ b/drivers/video/exynos/Makefile
@@ -5,4 +5,3 @@
5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ 5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
6 exynos_mipi_dsi_lowlevel.o 6 exynos_mipi_dsi_lowlevel.o
7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o 7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
8obj-$(CONFIG_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
diff --git a/include/drm/bridge/ptn3460.h b/include/drm/bridge/ptn3460.h
new file mode 100644
index 000000000000..ff62344fec6c
--- /dev/null
+++ b/include/drm/bridge/ptn3460.h
@@ -0,0 +1,37 @@
1/*
2 * Copyright (C) 2013 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#ifndef _DRM_BRIDGE_PTN3460_H_
15#define _DRM_BRIDGE_PTN3460_H_
16
17struct drm_device;
18struct drm_encoder;
19struct i2c_client;
20struct device_node;
21
22#if defined(CONFIG_DRM_PTN3460) || defined(CONFIG_DRM_PTN3460_MODULE)
23
24int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
25 struct i2c_client *client, struct device_node *node);
26#else
27
28static inline int ptn3460_init(struct drm_device *dev,
29 struct drm_encoder *encoder, struct i2c_client *client,
30 struct device_node *node)
31{
32 return 0;
33}
34
35#endif
36
37#endif
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index daac00a93126..a7c2a862b4f4 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -88,46 +88,41 @@ struct videomode;
88#include <drm/drm_hashtab.h> 88#include <drm/drm_hashtab.h>
89#include <drm/drm_mm.h> 89#include <drm/drm_mm.h>
90 90
91#define DRM_UT_CORE 0x01
92#define DRM_UT_DRIVER 0x02
93#define DRM_UT_KMS 0x04
94#define DRM_UT_PRIME 0x08
95/* 91/*
96 * Three debug levels are defined. 92 * 4 debug categories are defined:
97 * drm_core, drm_driver, drm_kms 93 *
98 * drm_core level can be used in the generic drm code. For example: 94 * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
99 * drm_ioctl, drm_mm, drm_memory 95 * This is the category used by the DRM_DEBUG() macro.
100 * The macro definition of DRM_DEBUG is used. 96 *
101 * DRM_DEBUG(fmt, args...) 97 * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
102 * The debug info by using the DRM_DEBUG can be obtained by adding 98 * This is the category used by the DRM_DEBUG_DRIVER() macro.
103 * the boot option of "drm.debug=1".
104 * 99 *
105 * drm_driver level can be used in the specific drm driver. It is used 100 * KMS: used in the modesetting code.
106 * to add the debug info related with the drm driver. For example: 101 * This is the category used by the DRM_DEBUG_KMS() macro.
107 * i915_drv, i915_dma, i915_gem, radeon_drv,
108 * The macro definition of DRM_DEBUG_DRIVER can be used.
109 * DRM_DEBUG_DRIVER(fmt, args...)
110 * The debug info by using the DRM_DEBUG_DRIVER can be obtained by
111 * adding the boot option of "drm.debug=0x02"
112 * 102 *
113 * drm_kms level can be used in the KMS code related with specific drm driver. 103 * PRIME: used in the prime code.
114 * It is used to add the debug info related with KMS mode. For example: 104 * This is the category used by the DRM_DEBUG_PRIME() macro.
115 * the connector/crtc ,
116 * The macro definition of DRM_DEBUG_KMS can be used.
117 * DRM_DEBUG_KMS(fmt, args...)
118 * The debug info by using the DRM_DEBUG_KMS can be obtained by
119 * adding the boot option of "drm.debug=0x04"
120 * 105 *
121 * If we add the boot option of "drm.debug=0x06", we can get the debug info by 106 * Enabling verbose debug messages is done through the drm.debug parameter,
122 * using the DRM_DEBUG_KMS and DRM_DEBUG_DRIVER. 107 * each category being enabled by a bit.
123 * If we add the boot option of "drm.debug=0x05", we can get the debug info by 108 *
124 * using the DRM_DEBUG_KMS and DRM_DEBUG. 109 * drm.debug=0x1 will enable CORE messages
110 * drm.debug=0x2 will enable DRIVER messages
111 * drm.debug=0x3 will enable CORE and DRIVER messages
112 * ...
113 * drm.debug=0xf will enable all messages
114 *
115 * An interesting feature is that it's possible to enable verbose logging at
116 * run-time by echoing the debug value in its sysfs node:
117 * # echo 0xf > /sys/module/drm/parameters/debug
125 */ 118 */
119#define DRM_UT_CORE 0x01
120#define DRM_UT_DRIVER 0x02
121#define DRM_UT_KMS 0x04
122#define DRM_UT_PRIME 0x08
126 123
127extern __printf(4, 5) 124extern __printf(2, 3)
128void drm_ut_debug_printk(unsigned int request_level, 125void drm_ut_debug_printk(const char *function_name,
129 const char *prefix,
130 const char *function_name,
131 const char *format, ...); 126 const char *format, ...);
132extern __printf(2, 3) 127extern __printf(2, 3)
133int drm_err(const char *func, const char *format, ...); 128int drm_err(const char *func, const char *format, ...);
@@ -212,55 +207,30 @@ int drm_err(const char *func, const char *format, ...);
212#if DRM_DEBUG_CODE 207#if DRM_DEBUG_CODE
213#define DRM_DEBUG(fmt, args...) \ 208#define DRM_DEBUG(fmt, args...) \
214 do { \ 209 do { \
215 drm_ut_debug_printk(DRM_UT_CORE, DRM_NAME, \ 210 if (unlikely(drm_debug & DRM_UT_CORE)) \
216 __func__, fmt, ##args); \ 211 drm_ut_debug_printk(__func__, fmt, ##args); \
217 } while (0) 212 } while (0)
218 213
219#define DRM_DEBUG_DRIVER(fmt, args...) \ 214#define DRM_DEBUG_DRIVER(fmt, args...) \
220 do { \ 215 do { \
221 drm_ut_debug_printk(DRM_UT_DRIVER, DRM_NAME, \ 216 if (unlikely(drm_debug & DRM_UT_DRIVER)) \
222 __func__, fmt, ##args); \ 217 drm_ut_debug_printk(__func__, fmt, ##args); \
223 } while (0) 218 } while (0)
224#define DRM_DEBUG_KMS(fmt, args...) \ 219#define DRM_DEBUG_KMS(fmt, args...) \
225 do { \ 220 do { \
226 drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \ 221 if (unlikely(drm_debug & DRM_UT_KMS)) \
227 __func__, fmt, ##args); \ 222 drm_ut_debug_printk(__func__, fmt, ##args); \
228 } while (0) 223 } while (0)
229#define DRM_DEBUG_PRIME(fmt, args...) \ 224#define DRM_DEBUG_PRIME(fmt, args...) \
230 do { \ 225 do { \
231 drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME, \ 226 if (unlikely(drm_debug & DRM_UT_PRIME)) \
232 __func__, fmt, ##args); \ 227 drm_ut_debug_printk(__func__, fmt, ##args); \
233 } while (0)
234#define DRM_LOG(fmt, args...) \
235 do { \
236 drm_ut_debug_printk(DRM_UT_CORE, NULL, \
237 NULL, fmt, ##args); \
238 } while (0)
239#define DRM_LOG_KMS(fmt, args...) \
240 do { \
241 drm_ut_debug_printk(DRM_UT_KMS, NULL, \
242 NULL, fmt, ##args); \
243 } while (0)
244#define DRM_LOG_MODE(fmt, args...) \
245 do { \
246 drm_ut_debug_printk(DRM_UT_MODE, NULL, \
247 NULL, fmt, ##args); \
248 } while (0)
249#define DRM_LOG_DRIVER(fmt, args...) \
250 do { \
251 drm_ut_debug_printk(DRM_UT_DRIVER, NULL, \
252 NULL, fmt, ##args); \
253 } while (0) 228 } while (0)
254#else 229#else
255#define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0) 230#define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0)
256#define DRM_DEBUG_KMS(fmt, args...) do { } while (0) 231#define DRM_DEBUG_KMS(fmt, args...) do { } while (0)
257#define DRM_DEBUG_PRIME(fmt, args...) do { } while (0) 232#define DRM_DEBUG_PRIME(fmt, args...) do { } while (0)
258#define DRM_DEBUG(fmt, arg...) do { } while (0) 233#define DRM_DEBUG(fmt, arg...) do { } while (0)
259#define DRM_LOG(fmt, arg...) do { } while (0)
260#define DRM_LOG_KMS(fmt, args...) do { } while (0)
261#define DRM_LOG_MODE(fmt, arg...) do { } while (0)
262#define DRM_LOG_DRIVER(fmt, arg...) do { } while (0)
263
264#endif 234#endif
265 235
266/*@}*/ 236/*@}*/
@@ -435,9 +405,15 @@ struct drm_prime_file_private {
435struct drm_file { 405struct drm_file {
436 unsigned always_authenticated :1; 406 unsigned always_authenticated :1;
437 unsigned authenticated :1; 407 unsigned authenticated :1;
438 unsigned is_master :1; /* this file private is a master for a minor */ 408 /* Whether we're master for a minor. Protected by master_mutex */
409 unsigned is_master :1;
439 /* true when the client has asked us to expose stereo 3D mode flags */ 410 /* true when the client has asked us to expose stereo 3D mode flags */
440 unsigned stereo_allowed :1; 411 unsigned stereo_allowed :1;
412 /*
413 * true if client understands CRTC primary planes and cursor planes
414 * in the plane list
415 */
416 unsigned universal_planes:1;
441 417
442 struct pid *pid; 418 struct pid *pid;
443 kuid_t uid; 419 kuid_t uid;
@@ -714,29 +690,29 @@ struct drm_gem_object {
714 690
715#include <drm/drm_crtc.h> 691#include <drm/drm_crtc.h>
716 692
717/* per-master structure */ 693/**
694 * struct drm_master - drm master structure
695 *
696 * @refcount: Refcount for this master object.
697 * @minor: Link back to minor char device we are master for. Immutable.
698 * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex.
699 * @unique_len: Length of unique field. Protected by drm_global_mutex.
700 * @unique_size: Amount allocated. Protected by drm_global_mutex.
701 * @magiclist: Hash of used authentication tokens. Protected by struct_mutex.
702 * @magicfree: List of used authentication tokens. Protected by struct_mutex.
703 * @lock: DRI lock information.
704 * @driver_priv: Pointer to driver-private information.
705 */
718struct drm_master { 706struct drm_master {
719 707 struct kref refcount;
720 struct kref refcount; /* refcount for this master */ 708 struct drm_minor *minor;
721 709 char *unique;
722 struct list_head head; /**< each minor contains a list of masters */ 710 int unique_len;
723 struct drm_minor *minor; /**< link back to minor we are a master for */ 711 int unique_size;
724
725 char *unique; /**< Unique identifier: e.g., busid */
726 int unique_len; /**< Length of unique field */
727 int unique_size; /**< amount allocated */
728
729 int blocked; /**< Blocked due to VC switch? */
730
731 /** \name Authentication */
732 /*@{ */
733 struct drm_open_hash magiclist; 712 struct drm_open_hash magiclist;
734 struct list_head magicfree; 713 struct list_head magicfree;
735 /*@} */ 714 struct drm_lock_data lock;
736 715 void *driver_priv;
737 struct drm_lock_data lock; /**< Information on hardware lock */
738
739 void *driver_priv; /**< Private structure for driver to use */
740}; 716};
741 717
742/* Size of ringbuffer for vblank timestamps. Just double-buffer 718/* Size of ringbuffer for vblank timestamps. Just double-buffer
@@ -1051,8 +1027,8 @@ struct drm_minor {
1051 struct list_head debugfs_list; 1027 struct list_head debugfs_list;
1052 struct mutex debugfs_lock; /* Protects debugfs_list. */ 1028 struct mutex debugfs_lock; /* Protects debugfs_list. */
1053 1029
1054 struct drm_master *master; /* currently active master for this node */ 1030 /* currently active master for this node. Protected by master_mutex */
1055 struct list_head master_list; 1031 struct drm_master *master;
1056 struct drm_mode_group mode_group; 1032 struct drm_mode_group mode_group;
1057}; 1033};
1058 1034
@@ -1102,6 +1078,7 @@ struct drm_device {
1102 /*@{ */ 1078 /*@{ */
1103 spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ 1079 spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
1104 struct mutex struct_mutex; /**< For others */ 1080 struct mutex struct_mutex; /**< For others */
1081 struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */
1105 /*@} */ 1082 /*@} */
1106 1083
1107 /** \name Usage Counters */ 1084 /** \name Usage Counters */
@@ -1232,11 +1209,21 @@ static inline bool drm_modeset_is_locked(struct drm_device *dev)
1232 return mutex_is_locked(&dev->mode_config.mutex); 1209 return mutex_is_locked(&dev->mode_config.mutex);
1233} 1210}
1234 1211
1235static inline bool drm_is_render_client(struct drm_file *file_priv) 1212static inline bool drm_is_render_client(const struct drm_file *file_priv)
1236{ 1213{
1237 return file_priv->minor->type == DRM_MINOR_RENDER; 1214 return file_priv->minor->type == DRM_MINOR_RENDER;
1238} 1215}
1239 1216
1217static inline bool drm_is_control_client(const struct drm_file *file_priv)
1218{
1219 return file_priv->minor->type == DRM_MINOR_CONTROL;
1220}
1221
1222static inline bool drm_is_primary_client(const struct drm_file *file_priv)
1223{
1224 return file_priv->minor->type == DRM_MINOR_LEGACY;
1225}
1226
1240/******************************************************************/ 1227/******************************************************************/
1241/** \name Internal function definitions */ 1228/** \name Internal function definitions */
1242/*@{*/ 1229/*@{*/
@@ -1247,6 +1234,7 @@ extern long drm_ioctl(struct file *filp,
1247extern long drm_compat_ioctl(struct file *filp, 1234extern long drm_compat_ioctl(struct file *filp,
1248 unsigned int cmd, unsigned long arg); 1235 unsigned int cmd, unsigned long arg);
1249extern int drm_lastclose(struct drm_device *dev); 1236extern int drm_lastclose(struct drm_device *dev);
1237extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
1250 1238
1251 /* Device support (drm_fops.h) */ 1239 /* Device support (drm_fops.h) */
1252extern struct mutex drm_global_mutex; 1240extern struct mutex drm_global_mutex;
@@ -1426,6 +1414,7 @@ extern void drm_put_dev(struct drm_device *dev);
1426extern void drm_unplug_dev(struct drm_device *dev); 1414extern void drm_unplug_dev(struct drm_device *dev);
1427extern unsigned int drm_debug; 1415extern unsigned int drm_debug;
1428extern unsigned int drm_rnodes; 1416extern unsigned int drm_rnodes;
1417extern unsigned int drm_universal_planes;
1429 1418
1430extern unsigned int drm_vblank_offdelay; 1419extern unsigned int drm_vblank_offdelay;
1431extern unsigned int drm_timestamp_precision; 1420extern unsigned int drm_timestamp_precision;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 27f828c9d7f2..e55fccbe7c42 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -270,6 +270,8 @@ struct drm_crtc_funcs {
270 * @dev: parent DRM device 270 * @dev: parent DRM device
271 * @head: list management 271 * @head: list management
272 * @base: base KMS object for ID tracking etc. 272 * @base: base KMS object for ID tracking etc.
273 * @primary: primary plane for this CRTC
274 * @cursor: cursor plane for this CRTC
273 * @enabled: is this CRTC enabled? 275 * @enabled: is this CRTC enabled?
274 * @mode: current mode timings 276 * @mode: current mode timings
275 * @hwmode: mode timings as programmed to hw regs 277 * @hwmode: mode timings as programmed to hw regs
@@ -305,8 +307,9 @@ struct drm_crtc {
305 307
306 struct drm_mode_object base; 308 struct drm_mode_object base;
307 309
308 /* framebuffer the connector is currently bound to */ 310 /* primary and cursor planes for CRTC */
309 struct drm_framebuffer *fb; 311 struct drm_plane *primary;
312 struct drm_plane *cursor;
310 313
311 /* Temporary tracking of the old fb while a modeset is ongoing. Used 314 /* Temporary tracking of the old fb while a modeset is ongoing. Used
312 * by drm_mode_set_config_internal to implement correct refcounting. */ 315 * by drm_mode_set_config_internal to implement correct refcounting. */
@@ -541,6 +544,12 @@ struct drm_plane_funcs {
541 struct drm_property *property, uint64_t val); 544 struct drm_property *property, uint64_t val);
542}; 545};
543 546
547enum drm_plane_type {
548 DRM_PLANE_TYPE_OVERLAY,
549 DRM_PLANE_TYPE_PRIMARY,
550 DRM_PLANE_TYPE_CURSOR,
551};
552
544/** 553/**
545 * drm_plane - central DRM plane control structure 554 * drm_plane - central DRM plane control structure
546 * @dev: DRM device this plane belongs to 555 * @dev: DRM device this plane belongs to
@@ -553,6 +562,7 @@ struct drm_plane_funcs {
553 * @fb: currently bound fb 562 * @fb: currently bound fb
554 * @funcs: helper functions 563 * @funcs: helper functions
555 * @properties: property tracking for this plane 564 * @properties: property tracking for this plane
565 * @type: type of plane (overlay, primary, cursor)
556 */ 566 */
557struct drm_plane { 567struct drm_plane {
558 struct drm_device *dev; 568 struct drm_device *dev;
@@ -570,6 +580,8 @@ struct drm_plane {
570 const struct drm_plane_funcs *funcs; 580 const struct drm_plane_funcs *funcs;
571 581
572 struct drm_object_properties properties; 582 struct drm_object_properties properties;
583
584 enum drm_plane_type type;
573}; 585};
574 586
575/** 587/**
@@ -732,7 +744,15 @@ struct drm_mode_config {
732 struct list_head bridge_list; 744 struct list_head bridge_list;
733 int num_encoder; 745 int num_encoder;
734 struct list_head encoder_list; 746 struct list_head encoder_list;
735 int num_plane; 747
748 /*
749 * Track # of overlay planes separately from # of total planes. By
750 * default we only advertise overlay planes to userspace; if userspace
751 * sets the "universal plane" capability bit, we'll go ahead and
752 * expose all planes.
753 */
754 int num_overlay_plane;
755 int num_total_plane;
736 struct list_head plane_list; 756 struct list_head plane_list;
737 757
738 int num_crtc; 758 int num_crtc;
@@ -754,6 +774,7 @@ struct drm_mode_config {
754 struct list_head property_blob_list; 774 struct list_head property_blob_list;
755 struct drm_property *edid_property; 775 struct drm_property *edid_property;
756 struct drm_property *dpms_property; 776 struct drm_property *dpms_property;
777 struct drm_property *plane_type_property;
757 778
758 /* DVI-I properties */ 779 /* DVI-I properties */
759 struct drm_property *dvi_i_subconnector_property; 780 struct drm_property *dvi_i_subconnector_property;
@@ -806,6 +827,11 @@ extern void drm_modeset_lock_all(struct drm_device *dev);
806extern void drm_modeset_unlock_all(struct drm_device *dev); 827extern void drm_modeset_unlock_all(struct drm_device *dev);
807extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); 828extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
808 829
830extern int drm_crtc_init_with_planes(struct drm_device *dev,
831 struct drm_crtc *crtc,
832 struct drm_plane *primary,
833 void *cursor,
834 const struct drm_crtc_funcs *funcs);
809extern int drm_crtc_init(struct drm_device *dev, 835extern int drm_crtc_init(struct drm_device *dev,
810 struct drm_crtc *crtc, 836 struct drm_crtc *crtc,
811 const struct drm_crtc_funcs *funcs); 837 const struct drm_crtc_funcs *funcs);
@@ -857,14 +883,25 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
857 return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); 883 return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
858} 884}
859 885
886extern int drm_universal_plane_init(struct drm_device *dev,
887 struct drm_plane *plane,
888 unsigned long possible_crtcs,
889 const struct drm_plane_funcs *funcs,
890 const uint32_t *formats,
891 uint32_t format_count,
892 enum drm_plane_type type);
860extern int drm_plane_init(struct drm_device *dev, 893extern int drm_plane_init(struct drm_device *dev,
861 struct drm_plane *plane, 894 struct drm_plane *plane,
862 unsigned long possible_crtcs, 895 unsigned long possible_crtcs,
863 const struct drm_plane_funcs *funcs, 896 const struct drm_plane_funcs *funcs,
864 const uint32_t *formats, uint32_t format_count, 897 const uint32_t *formats, uint32_t format_count,
865 bool priv); 898 bool is_primary);
866extern void drm_plane_cleanup(struct drm_plane *plane); 899extern void drm_plane_cleanup(struct drm_plane *plane);
867extern void drm_plane_force_disable(struct drm_plane *plane); 900extern void drm_plane_force_disable(struct drm_plane *plane);
901extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
902 int x, int y,
903 const struct drm_display_mode *mode,
904 const struct drm_framebuffer *fb);
868 905
869extern void drm_encoder_cleanup(struct drm_encoder *encoder); 906extern void drm_encoder_cleanup(struct drm_encoder *encoder);
870 907
@@ -1036,4 +1073,9 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
1036 return mo ? obj_to_encoder(mo) : NULL; 1073 return mo ? obj_to_encoder(mo) : NULL;
1037} 1074}
1038 1075
1076/* Plane list iterator for legacy (overlay only) planes. */
1077#define drm_for_each_legacy_plane(plane, planelist) \
1078 list_for_each_entry(plane, planelist, head) \
1079 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1080
1039#endif /* __DRM_CRTC_H__ */ 1081#endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 89b4d7db1ebd..2a3cea91606d 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -1,6 +1,8 @@
1#ifndef __DRM_GEM_CMA_HELPER_H__ 1#ifndef __DRM_GEM_CMA_HELPER_H__
2#define __DRM_GEM_CMA_HELPER_H__ 2#define __DRM_GEM_CMA_HELPER_H__
3 3
4#include <drm/drmP.h>
5
4struct drm_gem_cma_object { 6struct drm_gem_cma_object {
5 struct drm_gem_object base; 7 struct drm_gem_object base;
6 dma_addr_t paddr; 8 dma_addr_t paddr;
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index d32628acdd90..7209df15a3cd 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -17,6 +17,11 @@
17struct mipi_dsi_host; 17struct mipi_dsi_host;
18struct mipi_dsi_device; 18struct mipi_dsi_device;
19 19
20/* request ACK from peripheral */
21#define MIPI_DSI_MSG_REQ_ACK BIT(0)
22/* use Low Power Mode to transmit message */
23#define MIPI_DSI_MSG_USE_LPM BIT(1)
24
20/** 25/**
21 * struct mipi_dsi_msg - read/write DSI buffer 26 * struct mipi_dsi_msg - read/write DSI buffer
22 * @channel: virtual channel id 27 * @channel: virtual channel id
@@ -29,6 +34,7 @@ struct mipi_dsi_device;
29struct mipi_dsi_msg { 34struct mipi_dsi_msg {
30 u8 channel; 35 u8 channel;
31 u8 type; 36 u8 type;
37 u16 flags;
32 38
33 size_t tx_len; 39 size_t tx_len;
34 const void *tx_buf; 40 const void *tx_buf;
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 8b6981ab3fcf..a24addfdfcec 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -47,8 +47,17 @@
47enum drm_mm_search_flags { 47enum drm_mm_search_flags {
48 DRM_MM_SEARCH_DEFAULT = 0, 48 DRM_MM_SEARCH_DEFAULT = 0,
49 DRM_MM_SEARCH_BEST = 1 << 0, 49 DRM_MM_SEARCH_BEST = 1 << 0,
50 DRM_MM_SEARCH_BELOW = 1 << 1,
50}; 51};
51 52
53enum drm_mm_allocator_flags {
54 DRM_MM_CREATE_DEFAULT = 0,
55 DRM_MM_CREATE_TOP = 1 << 0,
56};
57
58#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT
59#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP
60
52struct drm_mm_node { 61struct drm_mm_node {
53 struct list_head node_list; 62 struct list_head node_list;
54 struct list_head hole_stack; 63 struct list_head hole_stack;
@@ -186,6 +195,9 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
186 * Implementation Note: 195 * Implementation Note:
187 * We need to inline list_for_each_entry in order to be able to set hole_start 196 * We need to inline list_for_each_entry in order to be able to set hole_start
188 * and hole_end on each iteration while keeping the macro sane. 197 * and hole_end on each iteration while keeping the macro sane.
198 *
199 * The __drm_mm_for_each_hole version is similar, but with added support for
200 * going backwards.
189 */ 201 */
190#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \ 202#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
191 for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \ 203 for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
@@ -195,6 +207,14 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
195 1 : 0; \ 207 1 : 0; \
196 entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack)) 208 entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
197 209
210#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
211 for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
212 &entry->hole_stack != &(mm)->hole_stack ? \
213 hole_start = drm_mm_hole_node_start(entry), \
214 hole_end = drm_mm_hole_node_end(entry), \
215 1 : 0; \
216 entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
217
198/* 218/*
199 * Basic range manager support (drm_mm.c) 219 * Basic range manager support (drm_mm.c)
200 */ 220 */
@@ -205,7 +225,8 @@ int drm_mm_insert_node_generic(struct drm_mm *mm,
205 unsigned long size, 225 unsigned long size,
206 unsigned alignment, 226 unsigned alignment,
207 unsigned long color, 227 unsigned long color,
208 enum drm_mm_search_flags flags); 228 enum drm_mm_search_flags sflags,
229 enum drm_mm_allocator_flags aflags);
209/** 230/**
210 * drm_mm_insert_node - search for space and insert @node 231 * drm_mm_insert_node - search for space and insert @node
211 * @mm: drm_mm to allocate from 232 * @mm: drm_mm to allocate from
@@ -228,7 +249,8 @@ static inline int drm_mm_insert_node(struct drm_mm *mm,
228 unsigned alignment, 249 unsigned alignment,
229 enum drm_mm_search_flags flags) 250 enum drm_mm_search_flags flags)
230{ 251{
231 return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags); 252 return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags,
253 DRM_MM_CREATE_DEFAULT);
232} 254}
233 255
234int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, 256int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
@@ -238,7 +260,8 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
238 unsigned long color, 260 unsigned long color,
239 unsigned long start, 261 unsigned long start,
240 unsigned long end, 262 unsigned long end,
241 enum drm_mm_search_flags flags); 263 enum drm_mm_search_flags sflags,
264 enum drm_mm_allocator_flags aflags);
242/** 265/**
243 * drm_mm_insert_node_in_range - ranged search for space and insert @node 266 * drm_mm_insert_node_in_range - ranged search for space and insert @node
244 * @mm: drm_mm to allocate from 267 * @mm: drm_mm to allocate from
@@ -266,7 +289,8 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
266 enum drm_mm_search_flags flags) 289 enum drm_mm_search_flags flags)
267{ 290{
268 return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 291 return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
269 0, start, end, flags); 292 0, start, end, flags,
293 DRM_MM_CREATE_DEFAULT);
270} 294}
271 295
272void drm_mm_remove_node(struct drm_mm_node *node); 296void drm_mm_remove_node(struct drm_mm_node *node);
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
new file mode 100644
index 000000000000..09824becee3e
--- /dev/null
+++ b/include/drm/drm_plane_helper.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2011-2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#ifndef DRM_PLANE_HELPER_H
25#define DRM_PLANE_HELPER_H
26
27/**
28 * DOC: plane helpers
29 *
30 * Helper functions to assist with creation and handling of CRTC primary
31 * planes.
32 */
33
34extern int drm_primary_helper_update(struct drm_plane *plane,
35 struct drm_crtc *crtc,
36 struct drm_framebuffer *fb,
37 int crtc_x, int crtc_y,
38 unsigned int crtc_w, unsigned int crtc_h,
39 uint32_t src_x, uint32_t src_y,
40 uint32_t src_w, uint32_t src_h);
41extern int drm_primary_helper_disable(struct drm_plane *plane);
42extern void drm_primary_helper_destroy(struct drm_plane *plane);
43extern const struct drm_plane_funcs drm_primary_helper_funcs;
44extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
45 uint32_t *formats,
46 int num_formats);
47
48
49#endif
diff --git a/include/drm/gma_drm.h b/include/drm/gma_drm.h
index 884613ee00ad..87ac5e6ca551 100644
--- a/include/drm/gma_drm.h
+++ b/include/drm/gma_drm.h
@@ -19,73 +19,7 @@
19 * 19 *
20 **************************************************************************/ 20 **************************************************************************/
21 21
22#ifndef _PSB_DRM_H_ 22#ifndef _GMA_DRM_H_
23#define _PSB_DRM_H_ 23#define _GMA_DRM_H_
24
25/*
26 * Manage the LUT for an output
27 */
28struct drm_psb_dpst_lut_arg {
29 uint8_t lut[256];
30 int output_id;
31};
32
33/*
34 * Validate modes
35 */
36struct drm_psb_mode_operation_arg {
37 u32 obj_id;
38 u16 operation;
39 struct drm_mode_modeinfo mode;
40 u64 data;
41};
42
43/*
44 * Query the stolen memory for smarter management of
45 * memory by the server
46 */
47struct drm_psb_stolen_memory_arg {
48 u32 base;
49 u32 size;
50};
51
52struct drm_psb_get_pipe_from_crtc_id_arg {
53 /** ID of CRTC being requested **/
54 u32 crtc_id;
55 /** pipe of requested CRTC **/
56 u32 pipe;
57};
58
59struct drm_psb_gem_create {
60 __u64 size;
61 __u32 handle;
62 __u32 flags;
63#define GMA_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */
64};
65
66struct drm_psb_gem_mmap {
67 __u32 handle;
68 __u32 pad;
69 /**
70 * Fake offset to use for subsequent mmap call
71 *
72 * This is a fixed-size type for 32/64 compatibility.
73 */
74 __u64 offset;
75};
76
77/* Controlling the kernel modesetting buffers */
78
79#define DRM_GMA_GEM_CREATE 0x00 /* Create a GEM object */
80#define DRM_GMA_GEM_MMAP 0x01 /* Map GEM memory */
81#define DRM_GMA_STOLEN_MEMORY 0x02 /* Report stolen memory */
82#define DRM_GMA_2D_OP 0x03 /* Will be merged later */
83#define DRM_GMA_GAMMA 0x04 /* Set gamma table */
84#define DRM_GMA_ADB 0x05 /* Get backlight */
85#define DRM_GMA_DPST_BL 0x06 /* Set backlight */
86#define DRM_GMA_MODE_OPERATION 0x07 /* Mode validation/DC set */
87#define PSB_MODE_OPERATION_MODE_VALID 0x01
88#define DRM_GMA_GET_PIPE_FROM_CRTC_ID 0x08 /* CRTC to physical pipe# */
89
90 24
91#endif 25#endif
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 5d8aabe68f6c..a5183da3ef92 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -788,7 +788,7 @@ extern void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo);
788extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo); 788extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
789 789
790/** 790/**
791 * ttm_bo_reserve_nolru: 791 * __ttm_bo_reserve:
792 * 792 *
793 * @bo: A pointer to a struct ttm_buffer_object. 793 * @bo: A pointer to a struct ttm_buffer_object.
794 * @interruptible: Sleep interruptible if waiting. 794 * @interruptible: Sleep interruptible if waiting.
@@ -809,10 +809,10 @@ extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
809 * -EALREADY: Bo already reserved using @ticket. This error code will only 809 * -EALREADY: Bo already reserved using @ticket. This error code will only
810 * be returned if @use_ticket is set to true. 810 * be returned if @use_ticket is set to true.
811 */ 811 */
812static inline int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo, 812static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
813 bool interruptible, 813 bool interruptible,
814 bool no_wait, bool use_ticket, 814 bool no_wait, bool use_ticket,
815 struct ww_acquire_ctx *ticket) 815 struct ww_acquire_ctx *ticket)
816{ 816{
817 int ret = 0; 817 int ret = 0;
818 818
@@ -888,8 +888,7 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,
888 888
889 WARN_ON(!atomic_read(&bo->kref.refcount)); 889 WARN_ON(!atomic_read(&bo->kref.refcount));
890 890
891 ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_ticket, 891 ret = __ttm_bo_reserve(bo, interruptible, no_wait, use_ticket, ticket);
892 ticket);
893 if (likely(ret == 0)) 892 if (likely(ret == 0))
894 ttm_bo_del_sub_from_lru(bo); 893 ttm_bo_del_sub_from_lru(bo);
895 894
@@ -929,20 +928,14 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
929} 928}
930 929
931/** 930/**
932 * ttm_bo_unreserve_ticket 931 * __ttm_bo_unreserve
933 * @bo: A pointer to a struct ttm_buffer_object. 932 * @bo: A pointer to a struct ttm_buffer_object.
934 * @ticket: ww_acquire_ctx used for reserving
935 * 933 *
936 * Unreserve a previous reservation of @bo made with @ticket. 934 * Unreserve a previous reservation of @bo where the buffer object is
935 * already on lru lists.
937 */ 936 */
938static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, 937static inline void __ttm_bo_unreserve(struct ttm_buffer_object *bo)
939 struct ww_acquire_ctx *t)
940{ 938{
941 if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
942 spin_lock(&bo->glob->lru_lock);
943 ttm_bo_add_to_lru(bo);
944 spin_unlock(&bo->glob->lru_lock);
945 }
946 ww_mutex_unlock(&bo->resv->lock); 939 ww_mutex_unlock(&bo->resv->lock);
947} 940}
948 941
@@ -955,7 +948,25 @@ static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo,
955 */ 948 */
956static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) 949static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo)
957{ 950{
958 ttm_bo_unreserve_ticket(bo, NULL); 951 if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
952 spin_lock(&bo->glob->lru_lock);
953 ttm_bo_add_to_lru(bo);
954 spin_unlock(&bo->glob->lru_lock);
955 }
956 __ttm_bo_unreserve(bo);
957}
958
959/**
960 * ttm_bo_unreserve_ticket
961 * @bo: A pointer to a struct ttm_buffer_object.
962 * @ticket: ww_acquire_ctx used for reserving
963 *
964 * Unreserve a previous reservation of @bo made with @ticket.
965 */
966static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo,
967 struct ww_acquire_ctx *t)
968{
969 ttm_bo_unreserve(bo);
959} 970}
960 971
961/* 972/*
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h
index 0097cc03034e..ed953f98f0e1 100644
--- a/include/drm/ttm/ttm_object.h
+++ b/include/drm/ttm/ttm_object.h
@@ -244,6 +244,10 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
244extern int ttm_ref_object_add(struct ttm_object_file *tfile, 244extern int ttm_ref_object_add(struct ttm_object_file *tfile,
245 struct ttm_base_object *base, 245 struct ttm_base_object *base,
246 enum ttm_ref_type ref_type, bool *existed); 246 enum ttm_ref_type ref_type, bool *existed);
247
248extern bool ttm_ref_object_exists(struct ttm_object_file *tfile,
249 struct ttm_base_object *base);
250
247/** 251/**
248 * ttm_ref_object_base_unref 252 * ttm_ref_object_base_unref
249 * 253 *
diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h
index c84ff153a564..8ed44f9bbdfb 100644
--- a/include/drm/ttm/ttm_placement.h
+++ b/include/drm/ttm/ttm_placement.h
@@ -65,6 +65,8 @@
65 * reference the buffer. 65 * reference the buffer.
66 * TTM_PL_FLAG_NO_EVICT means that the buffer may never 66 * TTM_PL_FLAG_NO_EVICT means that the buffer may never
67 * be evicted to make room for other buffers. 67 * be evicted to make room for other buffers.
68 * TTM_PL_FLAG_TOPDOWN requests to be placed from the
69 * top of the memory area, instead of the bottom.
68 */ 70 */
69 71
70#define TTM_PL_FLAG_CACHED (1 << 16) 72#define TTM_PL_FLAG_CACHED (1 << 16)
@@ -72,6 +74,7 @@
72#define TTM_PL_FLAG_WC (1 << 18) 74#define TTM_PL_FLAG_WC (1 << 18)
73#define TTM_PL_FLAG_SHARED (1 << 20) 75#define TTM_PL_FLAG_SHARED (1 << 20)
74#define TTM_PL_FLAG_NO_EVICT (1 << 21) 76#define TTM_PL_FLAG_NO_EVICT (1 << 21)
77#define TTM_PL_FLAG_TOPDOWN (1 << 22)
75 78
76#define TTM_PL_MASK_CACHING (TTM_PL_FLAG_CACHED | \ 79#define TTM_PL_MASK_CACHING (TTM_PL_FLAG_CACHED | \
77 TTM_PL_FLAG_UNCACHED | \ 80 TTM_PL_FLAG_UNCACHED | \
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3af847273277..d2b52999e771 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -136,6 +136,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp);
136u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); 136u32 host1x_syncpt_read_min(struct host1x_syncpt *sp);
137u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); 137u32 host1x_syncpt_read_max(struct host1x_syncpt *sp);
138int host1x_syncpt_incr(struct host1x_syncpt *sp); 138int host1x_syncpt_incr(struct host1x_syncpt *sp);
139u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
139int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, 140int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
140 u32 *value); 141 u32 *value);
141struct host1x_syncpt *host1x_syncpt_request(struct device *dev, 142struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b06c8ed68707..9abbeb924cbb 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -619,6 +619,15 @@ struct drm_gem_open {
619#define DRM_PRIME_CAP_EXPORT 0x2 619#define DRM_PRIME_CAP_EXPORT 0x2
620#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 620#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
621#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 621#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
622/*
623 * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight
624 * combination for the hardware cursor. The intention is that a hardware
625 * agnostic userspace can query a cursor plane size to use.
626 *
627 * Note that the cross-driver contract is to merely return a valid size;
628 * drivers are free to attach another meaning on top, eg. i915 returns the
629 * maximum plane size.
630 */
622#define DRM_CAP_CURSOR_WIDTH 0x8 631#define DRM_CAP_CURSOR_WIDTH 0x8
623#define DRM_CAP_CURSOR_HEIGHT 0x9 632#define DRM_CAP_CURSOR_HEIGHT 0x9
624 633
@@ -637,6 +646,14 @@ struct drm_get_cap {
637 */ 646 */
638#define DRM_CLIENT_CAP_STEREO_3D 1 647#define DRM_CLIENT_CAP_STEREO_3D 1
639 648
649/**
650 * DRM_CLIENT_CAP_UNIVERSAL_PLANES
651 *
652 * If set to 1, the DRM core will expose all planes (overlay, primary, and
653 * cursor) to userspace.
654 */
655#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
656
640/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ 657/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
641struct drm_set_client_cap { 658struct drm_set_client_cap {
642 __u64 capability; 659 __u64 capability;
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index d3c62074016d..0664c31f010c 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -50,6 +50,7 @@ struct drm_msm_timespec {
50 50
51#define MSM_PARAM_GPU_ID 0x01 51#define MSM_PARAM_GPU_ID 0x01
52#define MSM_PARAM_GMEM_SIZE 0x02 52#define MSM_PARAM_GMEM_SIZE 0x02
53#define MSM_PARAM_CHIP_ID 0x03
53 54
54struct drm_msm_param { 55struct drm_msm_param {
55 uint32_t pipe; /* in, MSM_PIPE_x */ 56 uint32_t pipe; /* in, MSM_PIPE_x */
@@ -69,6 +70,12 @@ struct drm_msm_param {
69#define MSM_BO_WC 0x00020000 70#define MSM_BO_WC 0x00020000
70#define MSM_BO_UNCACHED 0x00040000 71#define MSM_BO_UNCACHED 0x00040000
71 72
73#define MSM_BO_FLAGS (MSM_BO_SCANOUT | \
74 MSM_BO_GPU_READONLY | \
75 MSM_BO_CACHED | \
76 MSM_BO_WC | \
77 MSM_BO_UNCACHED)
78
72struct drm_msm_gem_new { 79struct drm_msm_gem_new {
73 uint64_t size; /* in */ 80 uint64_t size; /* in */
74 uint32_t flags; /* in, mask of MSM_BO_x */ 81 uint32_t flags; /* in, mask of MSM_BO_x */
@@ -85,6 +92,8 @@ struct drm_msm_gem_info {
85#define MSM_PREP_WRITE 0x02 92#define MSM_PREP_WRITE 0x02
86#define MSM_PREP_NOSYNC 0x04 93#define MSM_PREP_NOSYNC 0x04
87 94
95#define MSM_PREP_FLAGS (MSM_PREP_READ | MSM_PREP_WRITE | MSM_PREP_NOSYNC)
96
88struct drm_msm_gem_cpu_prep { 97struct drm_msm_gem_cpu_prep {
89 uint32_t handle; /* in */ 98 uint32_t handle; /* in */
90 uint32_t op; /* in, mask of MSM_PREP_x */ 99 uint32_t op; /* in, mask of MSM_PREP_x */
@@ -152,6 +161,9 @@ struct drm_msm_gem_submit_cmd {
152 */ 161 */
153#define MSM_SUBMIT_BO_READ 0x0001 162#define MSM_SUBMIT_BO_READ 0x0001
154#define MSM_SUBMIT_BO_WRITE 0x0002 163#define MSM_SUBMIT_BO_WRITE 0x0002
164
165#define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
166
155struct drm_msm_gem_submit_bo { 167struct drm_msm_gem_submit_bo {
156 uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */ 168 uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */
157 uint32_t handle; /* in, GEM handle */ 169 uint32_t handle; /* in, GEM handle */
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index 5e1ab552cbed..b042b48495d9 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -1,17 +1,23 @@
1/* 1/*
2 * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * under the terms and conditions of the GNU General Public License, 5 * copy of this software and associated documentation files (the "Software"),
6 * version 2, as published by the Free Software Foundation. 6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
7 * 10 *
8 * This program is distributed in the hope it will be useful, but WITHOUT 11 * The above copyright notice and this permission notice shall be included in
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * all copies or substantial portions of the Software.
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 * 13 *
13 * You should have received a copy of the GNU General Public License 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
15 */ 21 */
16 22
17#ifndef _UAPI_TEGRA_DRM_H_ 23#ifndef _UAPI_TEGRA_DRM_H_
diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h
index 87792a5fee3b..4fc66f6b12ce 100644
--- a/include/uapi/drm/vmwgfx_drm.h
+++ b/include/uapi/drm/vmwgfx_drm.h
@@ -90,6 +90,15 @@
90#define DRM_VMW_PARAM_MAX_MOB_SIZE 10 90#define DRM_VMW_PARAM_MAX_MOB_SIZE 10
91 91
92/** 92/**
93 * enum drm_vmw_handle_type - handle type for ref ioctls
94 *
95 */
96enum drm_vmw_handle_type {
97 DRM_VMW_HANDLE_LEGACY = 0,
98 DRM_VMW_HANDLE_PRIME = 1
99};
100
101/**
93 * struct drm_vmw_getparam_arg 102 * struct drm_vmw_getparam_arg
94 * 103 *
95 * @value: Returned value. //Out 104 * @value: Returned value. //Out
@@ -177,6 +186,7 @@ struct drm_vmw_surface_create_req {
177 * struct drm_wmv_surface_arg 186 * struct drm_wmv_surface_arg
178 * 187 *
179 * @sid: Surface id of created surface or surface to destroy or reference. 188 * @sid: Surface id of created surface or surface to destroy or reference.
189 * @handle_type: Handle type for DRM_VMW_REF_SURFACE Ioctl.
180 * 190 *
181 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl. 191 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
182 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl. 192 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
@@ -185,7 +195,7 @@ struct drm_vmw_surface_create_req {
185 195
186struct drm_vmw_surface_arg { 196struct drm_vmw_surface_arg {
187 int32_t sid; 197 int32_t sid;
188 uint32_t pad64; 198 enum drm_vmw_handle_type handle_type;
189}; 199};
190 200
191/** 201/**