Merge tag 'drm-intel-next-2014-03-21' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Wed, 2 Apr 2014 21:51:54 +0000 (07:51 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 2 Apr 2014 21:51:54 +0000 (07:51 +1000)
- Inherit/reuse firmwar framebuffers (for real this time) from Jesse, less
  flicker for fastbooting.
- More flexible cloning for hdmi (Ville).
- Some PPGTT fixes from Ben.
- Ring init fixes from Naresh Kumar.
- set_cache_level regression fixes for the vma conversion from Ville&Chris.
- Conversion to the new dp aux helpers (Jani).
- Unification of runtime pm with pc8 support from Paulo, prep work for runtime
  pm on other platforms than HSW.
- Larger cursor sizes (Sagar Kamble).
- Piles of improvements and fixes all over, as usual.

* tag 'drm-intel-next-2014-03-21' of git://anongit.freedesktop.org/drm-intel: (75 commits)
  drm/i915: Include a note about the dangers of I915_READ64/I915_WRITE64
  drm/i915/sdvo: fix questionable return value check
  drm/i915: Fix unsafe loop iteration over vma whilst unbinding them
  drm/i915: Enabling 128x128 and 256x256 ARGB Cursor Support
  drm/i915: Print how many objects are shared in per-process stats
  drm/i915: Per-process stats work better when evaluated per-process
  drm/i915: remove rps local variables
  drm/i915: Remove extraneous MMIO for RPS
  drm/i915: Rename and comment all the RPS *stuff*
  drm/i915: Store the HW min frequency as min_freq
  drm/i915: Fix coding style for RPS
  drm/i915: Reorganize the overclock code
  drm/i915: init pm.suspended earlier
  drm/i915: update the PC8 and runtime PM documentation
  drm/i915: rename __hsw_do_{en, dis}able_pc8
  drm/i915: kill struct i915_package_c8
  drm/i915: move pc8.irqs_disabled to pm.irqs_disabled
  drm/i915: remove dev_priv->pc8.enabled
  drm/i915: don't get/put PC8 when getting/putting power wells
  drm/i915: make intel_aux_display_runtime_get get runtime PM, not PC8
  ...

Conflicts:
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c

315 files changed:
Documentation/DocBook/drm.tmpl
Documentation/devicetree/bindings/drm/bridge/ptn3460.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/exynos_dp.txt
Documentation/devicetree/bindings/video/exynos_hdmi.txt
Documentation/devicetree/bindings/video/samsung-fimd.txt
MAINTAINERS
arch/arm/boot/dts/exynos4210-universal_c210.dts
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/Kconfig [new file with mode: 0644]
drivers/gpu/drm/bridge/Makefile [new file with mode: 0644]
drivers/gpu/drm/bridge/ptn3460.c [new file with mode: 0644]
drivers/gpu/drm/cirrus/cirrus_mode.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_plane_helper.c [new file with mode: 0644]
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/Makefile
drivers/gpu/drm/exynos/exynos_dp_core.c [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_dp_core.h [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_dp_reg.c [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_dp_reg.h [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_connector.h
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_dpi.c [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_encoder.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.c [deleted file]
drivers/gpu/drm/exynos/exynos_drm_hdmi.h [deleted file]
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_drm_plane.h
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/exynos/exynos_mixer.h [new file with mode: 0644]
drivers/gpu/drm/gma500/Makefile
drivers/gpu/drm/gma500/blitter.c [new file with mode: 0644]
drivers/gpu/drm/gma500/blitter.h [new file with mode: 0644]
drivers/gpu/drm/gma500/cdv_device.c
drivers/gpu/drm/gma500/cdv_intel_crt.c
drivers/gpu/drm/gma500/cdv_intel_display.c
drivers/gpu/drm/gma500/cdv_intel_dp.c
drivers/gpu/drm/gma500/cdv_intel_hdmi.c
drivers/gpu/drm/gma500/cdv_intel_lvds.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/gem.c
drivers/gpu/drm/gma500/gem.h [new file with mode: 0644]
drivers/gpu/drm/gma500/gma_device.c [new file with mode: 0644]
drivers/gpu/drm/gma500/gma_device.h [new file with mode: 0644]
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/gma_display.h
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/gma500/gtt.h
drivers/gpu/drm/gma500/mdfld_dsi_output.c
drivers/gpu/drm/gma500/mdfld_intel_display.c
drivers/gpu/drm/gma500/mmu.c
drivers/gpu/drm/gma500/mmu.h [new file with mode: 0644]
drivers/gpu/drm/gma500/oaktrail_crtc.c
drivers/gpu/drm/gma500/oaktrail_hdmi.c
drivers/gpu/drm/gma500/oaktrail_lvds.c
drivers/gpu/drm/gma500/opregion.c
drivers/gpu/drm/gma500/psb_device.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_intel_display.c
drivers/gpu/drm/gma500/psb_intel_drv.h
drivers/gpu/drm/gma500/psb_intel_lvds.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/i915/dvo_ch7xxx.c
drivers/gpu/drm/i915/dvo_ivch.c
drivers/gpu/drm/i915/dvo_ns2501.c
drivers/gpu/drm/i915/dvo_sil164.c
drivers/gpu/drm/i915/dvo_tfp410.c
drivers/gpu/drm/i915/i915_cmd_parser.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/core/namedb.c
drivers/gpu/drm/nouveau/core/core/parent.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/engine/device/gm100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/device/nv04.c
drivers/gpu/drm/nouveau/core/engine/device/nv10.c
drivers/gpu/drm/nouveau/core/engine/device/nv20.c
drivers/gpu/drm/nouveau/core/engine/device/nv30.c
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/device/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
drivers/gpu/drm/nouveau/core/engine/disp/gm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/engine/disp/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
drivers/gpu/drm/nouveau/core/engine/falcon.c
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c [deleted file]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
drivers/gpu/drm/nouveau/core/engine/graph/gm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c [deleted file]
drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c
drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
drivers/gpu/drm/nouveau/core/engine/xtensa.c
drivers/gpu/drm/nouveau/core/include/core/class.h
drivers/gpu/drm/nouveau/core/include/core/device.h
drivers/gpu/drm/nouveau/core/include/core/namedb.h
drivers/gpu/drm/nouveau/core/include/engine/device.h
drivers/gpu/drm/nouveau/core/include/engine/disp.h
drivers/gpu/drm/nouveau/core/include/engine/graph.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/include/subdev/therm.h
drivers/gpu/drm/nouveau/core/include/subdev/timer.h
drivers/gpu/drm/nouveau/core/os.h
drivers/gpu/drm/nouveau/core/subdev/bar/base.c
drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c [deleted file]
drivers/gpu/drm/nouveau/core/subdev/mc/base.c
drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/timer/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_agp.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_hwmon.c
drivers/gpu/drm/nouveau/nouveau_sysfs.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/udl/udl_modeset.c
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/imx-drm/ipuv3-plane.c
drivers/video/exynos/Kconfig
drivers/video/exynos/Makefile
drivers/video/exynos/exynos_dp_core.c [deleted file]
drivers/video/exynos/exynos_dp_core.h [deleted file]
drivers/video/exynos/exynos_dp_reg.c [deleted file]
drivers/video/exynos/exynos_dp_reg.h [deleted file]
include/drm/bridge/ptn3460.h [new file with mode: 0644]
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/drm_plane_helper.h [new file with mode: 0644]
include/drm/gma_drm.h
include/drm/ttm/ttm_object.h
include/uapi/drm/drm.h
include/uapi/drm/vmwgfx_drm.h

index 9f5457ac037347cf5cc16413667ae99ed0fea666..702c4474919c54c29cb021a86eeb54e90f5bdffa 100644 (file)
@@ -1194,7 +1194,7 @@ int max_width, max_height;</synopsis>
           pointer to CRTC functions.
         </para>
       </sect3>
-      <sect3>
+      <sect3 id="drm-kms-crtcops">
         <title>CRTC Operations</title>
         <sect4>
           <title>Set Configuration</title>
@@ -1335,15 +1335,47 @@ int max_width, max_height;</synopsis>
        optionally scale it to a destination size. The result is then blended
        with or overlayed on top of a CRTC.
       </para>
+      <para>
+      The DRM core recognizes three types of planes:
+      <itemizedlist>
+        <listitem>
+        DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC.  Primary
+        planes are the planes operated upon by by CRTC modesetting and flipping
+        operations described in <xref linkend="drm-kms-crtcops"/>.
+        </listitem>
+        <listitem>
+        DRM_PLANE_TYPE_CURSOR represents a "cursor" plane for a CRTC.  Cursor
+        planes are the planes operated upon by the DRM_IOCTL_MODE_CURSOR and
+        DRM_IOCTL_MODE_CURSOR2 ioctls.
+        </listitem>
+        <listitem>
+        DRM_PLANE_TYPE_OVERLAY represents all non-primary, non-cursor planes.
+        Some drivers refer to these types of planes as "sprites" internally.
+        </listitem>
+      </itemizedlist>
+      For compatibility with legacy userspace, only overlay planes are made
+      available to userspace by default.  Userspace clients may set the
+      DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate that
+      they wish to receive a universal plane list containing all plane types.
+      </para>
       <sect3>
         <title>Plane Initialization</title>
         <para>
-          Planes are optional. To create a plane, a KMS drivers allocates and
+          To create a plane, a KMS drivers allocates and
           zeroes an instances of struct <structname>drm_plane</structname>
           (possibly as part of a larger structure) and registers it with a call
-          to <function>drm_plane_init</function>. The function takes a bitmask
+          to <function>drm_universal_plane_init</function>. The function takes a bitmask
           of the CRTCs that can be associated with the plane, a pointer to the
-          plane functions and a list of format supported formats.
+          plane functions, a list of format supported formats, and the type of
+          plane (primary, cursor, or overlay) being initialized.
+        </para>
+        <para>
+          Cursor and overlay planes are optional.  All drivers should provide
+          one primary plane per CRTC (although this requirement may change in
+          the future); drivers that do not wish to provide special handling for
+          primary planes may make use of the helper functions described in
+          <xref linkend="drm-kms-planehelpers"/> to create and register a
+          primary plane with standard capabilities.
         </para>
       </sect3>
       <sect3>
@@ -1774,7 +1806,7 @@ void intel_crt_init(struct drm_device *dev)
   <sect1>
     <title>Mode Setting Helper Functions</title>
     <para>
-      The CRTC, encoder and connector functions provided by the drivers
+      The plane, CRTC, encoder and connector functions provided by the drivers
       implement the DRM API. They're called by the DRM core and ioctl handlers
       to handle device state changes and configuration request. As implementing
       those functions often requires logic not specific to drivers, mid-layer
@@ -1782,8 +1814,8 @@ void intel_crt_init(struct drm_device *dev)
     </para>
     <para>
       The DRM core contains one mid-layer implementation. The mid-layer provides
-      implementations of several CRTC, encoder and connector functions (called
-      from the top of the mid-layer) that pre-process requests and call
+      implementations of several plane, CRTC, encoder and connector functions
+      (called from the top of the mid-layer) that pre-process requests and call
       lower-level functions provided by the driver (at the bottom of the
       mid-layer). For instance, the
       <function>drm_crtc_helper_set_config</function> function can be used to
@@ -2293,6 +2325,10 @@ void intel_crt_init(struct drm_device *dev)
 !Iinclude/linux/hdmi.h
 !Edrivers/video/hdmi.c
     </sect2>
+    <sect2>
+      <title id="drm-kms-planehelpers">Plane Helper Reference</title>
+!Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers
+    </sect2>
   </sect1>
 
   <!-- 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 (file)
index 0000000..52b93b2
--- /dev/null
@@ -0,0 +1,27 @@
+ptn3460 bridge bindings
+
+Required properties:
+       - compatible: "nxp,ptn3460"
+       - reg: i2c address of the bridge
+       - powerdown-gpio: OF device-tree gpio specification
+       - reset-gpio: OF device-tree gpio specification
+       - edid-emulation: The EDID emulation entry to use
+               +-------+------------+------------------+
+               | Value | Resolution | Description      |
+               |   0   |  1024x768  | NXP Generic      |
+               |   1   |  1920x1080 | NXP Generic      |
+               |   2   |  1920x1080 | NXP Generic      |
+               |   3   |  1600x900  | Samsung LTM200KT |
+               |   4   |  1920x1080 | Samsung LTM230HT |
+               |   5   |  1366x768  | NXP Generic      |
+               |   6   |  1600x900  | ChiMei M215HGE   |
+               +-------+------------+------------------+
+
+Example:
+       lvds-bridge@20 {
+               compatible = "nxp,ptn3460";
+               reg = <0x20>;
+               powerdown-gpio = <&gpy2 5 1 0 0>;
+               reset-gpio = <&gpx1 5 1 0 0>;
+               edid-emulation = <5>;
+       };
index 3289d76a21d0b2d01b81620e0c19fb10af29cf6b..57ccdde02c3ab9fb8deb5c60dd72fcf7d3081390 100644 (file)
@@ -49,6 +49,8 @@ Required properties for dp-controller:
        -samsung,lane-count:
                number of lanes supported by the panel.
                        LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+       - display-timings: timings for the connected panel as described by
+               Documentation/devicetree/bindings/video/display-timing.txt
 
 Optional properties for dp-controller:
        -interlaced:
@@ -84,4 +86,19 @@ Board Specific portion:
                samsung,color-depth = <1>;
                samsung,link-rate = <0x0a>;
                samsung,lane-count = <4>;
+
+               display-timings {
+                       native-mode = <&lcd_timing>;
+                       lcd_timing: 1366x768 {
+                               clock-frequency = <70589280>;
+                               hactive = <1366>;
+                               vactive = <768>;
+                               hfront-porch = <40>;
+                               hback-porch = <40>;
+                               hsync-len = <32>;
+                               vback-porch = <10>;
+                               vfront-porch = <12>;
+                               vsync-len = <6>;
+                       };
+               };
        };
index 50decf8e1b90a573b11dc864c7b30612a5d5c5a0..f9187a259259f4a25dc80dfe08e66457228fa1fe 100644 (file)
@@ -25,6 +25,9 @@ Required properties:
                sclk_pixel.
 - clock-names: aliases as per driver requirements for above clock IDs:
        "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi".
+- ddc: phandle to the hdmi ddc node
+- phy: phandle to the hdmi phy node
+
 Example:
 
        hdmi {
@@ -32,4 +35,6 @@ Example:
                reg = <0x14530000 0x100000>;
                interrupts = <0 95 0>;
                hpd-gpio = <&gpx3 7 1>;
+               ddc = <&hdmi_ddc_node>;
+               phy = <&hdmi_phy_node>;
        };
index 778838a0336add7028b0c5732a27af635d2e3011..2dad41b689af7a41b02cab8b3498395523b4a5fb 100644 (file)
@@ -39,6 +39,23 @@ Required properties:
 
 Optional Properties:
 - samsung,power-domain: a phandle to FIMD power domain node.
+- samsung,invert-vden: video enable signal is inverted
+- samsung,invert-vclk: video clock signal is inverted
+- display-timings: timing settings for FIMD, as described in document [1].
+               Can be used in case timings cannot be provided otherwise
+               or to override timings provided by the panel.
+
+The device node can contain 'port' child nodes according to the bindings defined
+in [2]. The following are properties specific to those nodes:
+- reg: (required) port index, can be:
+               0 - for CAMIF0 input,
+               1 - for CAMIF1 input,
+               2 - for CAMIF2 input,
+               3 - for parallel output,
+               4 - for write-back interface
+
+[1]: Documentation/devicetree/bindings/video/display-timing.txt
+[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
 
 Example:
 
index b3fdb0f004ba36fed1ca4895671217730b9f2c21..1a308b8e10a43a7622848002cc506d6fa0890f12 100644 (file)
@@ -3393,12 +3393,6 @@ S:       Maintained
 F:     drivers/extcon/
 F:     Documentation/extcon/
 
-EXYNOS DP DRIVER
-M:     Jingoo Han <jg1.han@samsung.com>
-L:     linux-fbdev@vger.kernel.org
-S:     Maintained
-F:     drivers/video/exynos/exynos_dp*
-
 EXYNOS MIPI DISPLAY DRIVERS
 M:     Inki Dae <inki.dae@samsung.com>
 M:     Donghwa Lee <dh09.lee@samsung.com>
index d2e3f5f5916dad4c325ab4dc3f71ff0ef34d9b39..477208d98c6df4f138d92ff4f5c24d5a40ff8c7c 100644 (file)
                                        regulator-name = "VLCD+VMIPI_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
                                };
 
                                ldo8_reg: LDO8 {
                                        regulator-name = "VCC_3.0V_LCD";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-max-microvolt = <3000000>;
+                                       regulator-always-on;
                                };
 
                                buck1_reg: BUCK1 {
                };
        };
 
+       fimd: fimd@11c00000 {
+               pinctrl-0 = <&lcd_clk>, <&lcd_data24>;
+               pinctrl-names = "default";
+               status = "okay";
+               samsung,invert-vden;
+               samsung,invert-vclk;
+               display-timings {
+                       timing {
+                               clock-frequency = <23492370>;
+                               hactive = <480>;
+                               vactive = <800>;
+                               hback-porch = <16>;
+                               hfront-porch = <16>;
+                               vback-porch = <2>;
+                               vfront-porch = <28>;
+                               hsync-len = <2>;
+                               vsync-len = <1>;
+                               hsync-active = <0>;
+                               vsync-active = <0>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                       };
+               };
+       };
+
        pwm@139D0000 {
                compatible = "samsung,s5p6440-pwm";
                status = "okay";
index 8e7fa4dbaed867ca45cb9c885db53543a65a74b9..d1cc2f613a78bb29e9969953402f856d77edd9e9 100644 (file)
@@ -199,3 +199,5 @@ source "drivers/gpu/drm/msm/Kconfig"
 source "drivers/gpu/drm/tegra/Kconfig"
 
 source "drivers/gpu/drm/panel/Kconfig"
+
+source "drivers/gpu/drm/bridge/Kconfig"
index 292a79d64146274428ad1ef251d08e1d78d46bf5..9d25dbbe6771e4ff9ff1f7cfdce782999f82f0bf 100644 (file)
@@ -13,7 +13,8 @@ drm-y       :=        drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
                drm_crtc.o drm_modes.o drm_edid.o \
                drm_info.o drm_debugfs.o drm_encoder_slave.o \
                drm_trace_points.o drm_global.o drm_prime.o \
-               drm_rect.o drm_vma_manager.o drm_flip_work.o
+               drm_rect.o drm_vma_manager.o drm_flip_work.o \
+               drm_plane_helper.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -63,3 +64,4 @@ obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y                  += i2c/
 obj-y                  += panel/
+obj-y                  += bridge/
index d8e398275ca8213a66890741941b266bfdeda3f0..5831e4109e7595c7c70c76e496ac536356017f08 100644 (file)
@@ -478,11 +478,12 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
        unsigned i;
        bool interlaced;
 
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
        interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
 
-       i = armada_drm_crtc_calc_fb(dcrtc->crtc.fb, x, y, regs, interlaced);
+       i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb,
+                                   x, y, regs, interlaced);
 
        rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
        lm = adj->crtc_htotal - adj->crtc_hsync_end;
@@ -567,10 +568,10 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
-       val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt);
-       val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.fb)->mod);
+       val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
+       val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
 
-       if (drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt > CFG_420)
+       if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
                val |= CFG_PALETTE_ENA;
 
        if (interlaced)
@@ -608,7 +609,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        struct armada_regs regs[4];
        unsigned i;
 
-       i = armada_drm_crtc_calc_fb(crtc->fb, crtc->x, crtc->y, regs,
+       i = armada_drm_crtc_calc_fb(crtc->primary->fb, crtc->x, crtc->y, regs,
                                    dcrtc->interlaced);
        armada_reg_queue_end(regs, i);
 
@@ -616,7 +617,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
 
        /* Take a reference to the new fb as we're using it */
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
        /* Update the base in the CRTC */
        armada_drm_crtc_update_regs(dcrtc, regs);
@@ -637,7 +638,7 @@ static void armada_drm_crtc_disable(struct drm_crtc *crtc)
        struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 
        armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       armada_drm_crtc_finish_fb(dcrtc, crtc->fb, true);
+       armada_drm_crtc_finish_fb(dcrtc, crtc->primary->fb, true);
 
        /* Power down most RAMs and FIFOs */
        writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
@@ -904,7 +905,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
        int ret;
 
        /* We don't support changing the pixel format */
-       if (fb->pixel_format != crtc->fb->pixel_format)
+       if (fb->pixel_format != crtc->primary->fb->pixel_format)
                return -EINVAL;
 
        work = kmalloc(sizeof(*work), GFP_KERNEL);
@@ -912,7 +913,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
                return -ENOMEM;
 
        work->event = event;
-       work->old_fb = dcrtc->crtc.fb;
+       work->old_fb = dcrtc->crtc.primary->fb;
 
        i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs,
                                    dcrtc->interlaced);
@@ -941,7 +942,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
         * will _not_ drop that reference on successful return from this
         * function.  Simply mark this new framebuffer as the current one.
         */
-       dcrtc->crtc.fb = fb;
+       dcrtc->crtc.primary->fb = fb;
 
        /*
         * Finally, if the display is blanked, we won't receive an
index cca063b110831aa4d4fc2f46afd6e9cc35ac30b9..a4afdc8bb578b826979b16431efef7183dee8f1a 100644 (file)
@@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
        u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
        u32 hborder, vborder;
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
                color_index = VGAModeIndex - 1;
@@ -176,7 +176,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
 
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
-               ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel);
+               ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
                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)
 
        u16 offset;
 
-       offset = crtc->fb->pitches[0] >> 3;
+       offset = crtc->primary->fb->pitches[0] >> 3;
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
 }
@@ -365,7 +365,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
        struct ast_private *ast = crtc->dev->dev_private;
        u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                jregA0 = 0x70;
                jregA3 = 0x01;
@@ -418,7 +418,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
 static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
                     struct ast_vbios_mode_info *vbios_mode)
 {
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                break;
        default:
@@ -490,7 +490,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
                ast_bo_unreserve(bo);
        }
 
-       ast_fb = to_ast_framebuffer(crtc->fb);
+       ast_fb = to_ast_framebuffer(crtc->primary->fb);
        obj = ast_fb->obj;
        bo = gem_to_ast_bo(obj);
 
index 62ec7d4b38161af806f0b993791313d669f4cbe9..dcf2e55f4ae91e2ded094d156899c2815c0a00bf 100644 (file)
@@ -62,10 +62,10 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                }
        }
 
-       if (WARN_ON(crtc->fb == NULL))
+       if (WARN_ON(crtc->primary->fb == NULL))
                return -EINVAL;
 
-       bochs_fb = to_bochs_framebuffer(crtc->fb);
+       bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
        bo = gem_to_bochs_bo(bochs_fb->obj);
        ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
        if (ret)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
new file mode 100644 (file)
index 0000000..884923f
--- /dev/null
@@ -0,0 +1,5 @@
+config DRM_PTN3460
+       tristate "PTN3460 DP/LVDS bridge"
+       depends on DRM
+       select DRM_KMS_HELPER
+       ---help---
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
new file mode 100644 (file)
index 0000000..b4733e1
--- /dev/null
@@ -0,0 +1,3 @@
+ccflags-y := -Iinclude/drm
+
+obj-$(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 (file)
index 0000000..a9e5c1a
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * NXP PTN3460 DP/LVDS bridge driver
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include "drmP.h"
+#include "drm_edid.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+#include "bridge/ptn3460.h"
+
+#define PTN3460_EDID_ADDR                      0x0
+#define PTN3460_EDID_EMULATION_ADDR            0x84
+#define PTN3460_EDID_ENABLE_EMULATION          0
+#define PTN3460_EDID_EMULATION_SELECTION       1
+#define PTN3460_EDID_SRAM_LOAD_ADDR            0x85
+
+struct ptn3460_bridge {
+       struct drm_connector connector;
+       struct i2c_client *client;
+       struct drm_encoder *encoder;
+       struct drm_bridge *bridge;
+       struct edid *edid;
+       int gpio_pd_n;
+       int gpio_rst_n;
+       u32 edid_emulation;
+       bool enabled;
+};
+
+static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr,
+               u8 *buf, int len)
+{
+       int ret;
+
+       ret = i2c_master_send(ptn_bridge->client, &addr, 1);
+       if (ret <= 0) {
+               DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
+               return ret;
+       }
+
+       ret = i2c_master_recv(ptn_bridge->client, buf, len);
+       if (ret <= 0) {
+               DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ptn3460_write_byte(struct ptn3460_bridge *ptn_bridge, char addr,
+               char val)
+{
+       int ret;
+       char buf[2];
+
+       buf[0] = addr;
+       buf[1] = val;
+
+       ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf));
+       if (ret <= 0) {
+               DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
+{
+       int ret;
+       char val;
+
+       /* Load the selected edid into SRAM (accessed at PTN3460_EDID_ADDR) */
+       ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_SRAM_LOAD_ADDR,
+                       ptn_bridge->edid_emulation);
+       if (ret) {
+               DRM_ERROR("Failed to transfer edid to sram, ret=%d\n", ret);
+               return ret;
+       }
+
+       /* Enable EDID emulation and select the desired EDID */
+       val = 1 << PTN3460_EDID_ENABLE_EMULATION |
+               ptn_bridge->edid_emulation << PTN3460_EDID_EMULATION_SELECTION;
+
+       ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_EMULATION_ADDR, val);
+       if (ret) {
+               DRM_ERROR("Failed to write edid value, ret=%d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ptn3460_pre_enable(struct drm_bridge *bridge)
+{
+       struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
+       int ret;
+
+       if (ptn_bridge->enabled)
+               return;
+
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
+               gpio_set_value(ptn_bridge->gpio_pd_n, 1);
+
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n)) {
+               gpio_set_value(ptn_bridge->gpio_rst_n, 0);
+               udelay(10);
+               gpio_set_value(ptn_bridge->gpio_rst_n, 1);
+       }
+
+       /*
+        * There's a bug in the PTN chip where it falsely asserts hotplug before
+        * it is fully functional. We're forced to wait for the maximum start up
+        * time specified in the chip's datasheet to make sure we're really up.
+        */
+       msleep(90);
+
+       ret = ptn3460_select_edid(ptn_bridge);
+       if (ret)
+               DRM_ERROR("Select edid failed ret=%d\n", ret);
+
+       ptn_bridge->enabled = true;
+}
+
+static void ptn3460_enable(struct drm_bridge *bridge)
+{
+}
+
+static void ptn3460_disable(struct drm_bridge *bridge)
+{
+       struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
+
+       if (!ptn_bridge->enabled)
+               return;
+
+       ptn_bridge->enabled = false;
+
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n))
+               gpio_set_value(ptn_bridge->gpio_rst_n, 1);
+
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
+               gpio_set_value(ptn_bridge->gpio_pd_n, 0);
+}
+
+static void ptn3460_post_disable(struct drm_bridge *bridge)
+{
+}
+
+void ptn3460_bridge_destroy(struct drm_bridge *bridge)
+{
+       struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
+
+       drm_bridge_cleanup(bridge);
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
+               gpio_free(ptn_bridge->gpio_pd_n);
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n))
+               gpio_free(ptn_bridge->gpio_rst_n);
+       /* Nothing else to free, we've got devm allocated memory */
+}
+
+struct drm_bridge_funcs ptn3460_bridge_funcs = {
+       .pre_enable = ptn3460_pre_enable,
+       .enable = ptn3460_enable,
+       .disable = ptn3460_disable,
+       .post_disable = ptn3460_post_disable,
+       .destroy = ptn3460_bridge_destroy,
+};
+
+int ptn3460_get_modes(struct drm_connector *connector)
+{
+       struct ptn3460_bridge *ptn_bridge;
+       u8 *edid;
+       int ret, num_modes;
+       bool power_off;
+
+       ptn_bridge = container_of(connector, struct ptn3460_bridge, connector);
+
+       if (ptn_bridge->edid)
+               return drm_add_edid_modes(connector, ptn_bridge->edid);
+
+       power_off = !ptn_bridge->enabled;
+       ptn3460_pre_enable(ptn_bridge->bridge);
+
+       edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+       if (!edid) {
+               DRM_ERROR("Failed to allocate edid\n");
+               return 0;
+       }
+
+       ret = ptn3460_read_bytes(ptn_bridge, PTN3460_EDID_ADDR, edid,
+                       EDID_LENGTH);
+       if (ret) {
+               kfree(edid);
+               num_modes = 0;
+               goto out;
+       }
+
+       ptn_bridge->edid = (struct edid *)edid;
+       drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
+
+       num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
+
+out:
+       if (power_off)
+               ptn3460_disable(ptn_bridge->bridge);
+
+       return num_modes;
+}
+
+static int ptn3460_mode_valid(struct drm_connector *connector,
+               struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+struct drm_encoder *ptn3460_best_encoder(struct drm_connector *connector)
+{
+       struct ptn3460_bridge *ptn_bridge;
+
+       ptn_bridge = container_of(connector, struct ptn3460_bridge, connector);
+
+       return ptn_bridge->encoder;
+}
+
+struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = {
+       .get_modes = ptn3460_get_modes,
+       .mode_valid = ptn3460_mode_valid,
+       .best_encoder = ptn3460_best_encoder,
+};
+
+enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
+               bool force)
+{
+       return connector_status_connected;
+}
+
+void ptn3460_connector_destroy(struct drm_connector *connector)
+{
+       drm_connector_cleanup(connector);
+}
+
+struct drm_connector_funcs ptn3460_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = ptn3460_detect,
+       .destroy = ptn3460_connector_destroy,
+};
+
+int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
+               struct i2c_client *client, struct device_node *node)
+{
+       int ret;
+       struct drm_bridge *bridge;
+       struct ptn3460_bridge *ptn_bridge;
+
+       bridge = devm_kzalloc(dev->dev, sizeof(*bridge), GFP_KERNEL);
+       if (!bridge) {
+               DRM_ERROR("Failed to allocate drm bridge\n");
+               return -ENOMEM;
+       }
+
+       ptn_bridge = devm_kzalloc(dev->dev, sizeof(*ptn_bridge), GFP_KERNEL);
+       if (!ptn_bridge) {
+               DRM_ERROR("Failed to allocate ptn bridge\n");
+               return -ENOMEM;
+       }
+
+       ptn_bridge->client = client;
+       ptn_bridge->encoder = encoder;
+       ptn_bridge->bridge = bridge;
+       ptn_bridge->gpio_pd_n = of_get_named_gpio(node, "powerdown-gpio", 0);
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n)) {
+               ret = gpio_request_one(ptn_bridge->gpio_pd_n,
+                               GPIOF_OUT_INIT_HIGH, "PTN3460_PD_N");
+               if (ret) {
+                       DRM_ERROR("Request powerdown-gpio failed (%d)\n", ret);
+                       return ret;
+               }
+       }
+
+       ptn_bridge->gpio_rst_n = of_get_named_gpio(node, "reset-gpio", 0);
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n)) {
+               /*
+                * Request the reset pin low to avoid the bridge being
+                * initialized prematurely
+                */
+               ret = gpio_request_one(ptn_bridge->gpio_rst_n,
+                               GPIOF_OUT_INIT_LOW, "PTN3460_RST_N");
+               if (ret) {
+                       DRM_ERROR("Request reset-gpio failed (%d)\n", ret);
+                       gpio_free(ptn_bridge->gpio_pd_n);
+                       return ret;
+               }
+       }
+
+       ret = of_property_read_u32(node, "edid-emulation",
+                       &ptn_bridge->edid_emulation);
+       if (ret) {
+               DRM_ERROR("Can't read edid emulation value\n");
+               goto err;
+       }
+
+       ret = drm_bridge_init(dev, bridge, &ptn3460_bridge_funcs);
+       if (ret) {
+               DRM_ERROR("Failed to initialize bridge with drm\n");
+               goto err;
+       }
+
+       bridge->driver_private = ptn_bridge;
+       encoder->bridge = bridge;
+
+       ret = drm_connector_init(dev, &ptn_bridge->connector,
+                       &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
+               goto err;
+       }
+       drm_connector_helper_add(&ptn_bridge->connector,
+                       &ptn3460_connector_helper_funcs);
+       drm_sysfs_connector_add(&ptn_bridge->connector);
+       drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
+
+       return 0;
+
+err:
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
+               gpio_free(ptn_bridge->gpio_pd_n);
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n))
+               gpio_free(ptn_bridge->gpio_rst_n);
+       return ret;
+}
index 530f78f84deed250a2f96350254657b49a0166c9..2d64aea83df21a05a74c7470ab8054350063e8df 100644 (file)
@@ -149,7 +149,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
                cirrus_bo_unreserve(bo);
        }
 
-       cirrus_fb = to_cirrus_framebuffer(crtc->fb);
+       cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
        obj = cirrus_fb->obj;
        bo = gem_to_cirrus_bo(obj);
 
@@ -268,7 +268,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
        sr07 = RREG8(SEQ_DATA);
        sr07 &= 0xe0;
        hdr = 0;
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                sr07 |= 0x11;
                break;
@@ -291,13 +291,13 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
        WREG_SEQ(0x7, sr07);
 
        /* Program the pitch */
-       tmp = crtc->fb->pitches[0] / 8;
+       tmp = crtc->primary->fb->pitches[0] / 8;
        WREG_CRT(VGA_CRTC_OFFSET, tmp);
 
        /* Enable extended blanking and pitch bits, and enable full memory */
        tmp = 0x22;
-       tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
-       tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
+       tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
+       tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
        WREG_CRT(0x1b, tmp);
 
        /* Enable high-colour modes */
index 16ca28ed5ee8e25046071bad99a9afc65ee34a7d..d8b7099abece7b9ccc44ee21550aa67423855f3f 100644 (file)
@@ -121,6 +121,13 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] =
 
 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
 
+static const struct drm_prop_enum_list drm_plane_type_enum_list[] =
+{
+       { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
+       { DRM_PLANE_TYPE_PRIMARY, "Primary" },
+       { DRM_PLANE_TYPE_CURSOR, "Cursor" },
+};
+
 /*
  * Optional properties
  */
@@ -662,7 +669,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
                drm_modeset_lock_all(dev);
                /* remove from any CRTC */
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-                       if (crtc->fb == fb) {
+                       if (crtc->primary->fb == fb) {
                                /* should turn off the crtc */
                                memset(&set, 0, sizeof(struct drm_mode_set));
                                set.crtc = crtc;
@@ -685,9 +692,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 EXPORT_SYMBOL(drm_framebuffer_remove);
 
 /**
- * drm_crtc_init - Initialise a new CRTC object
+ * drm_crtc_init_with_planes - Initialise a new CRTC object with
+ *    specified primary and cursor planes.
  * @dev: DRM device
  * @crtc: CRTC object to init
+ * @primary: Primary plane for CRTC
+ * @cursor: Cursor plane for CRTC
  * @funcs: callbacks for the new CRTC
  *
  * Inits a new object created as base part of a driver crtc object.
@@ -695,8 +705,10 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
  * Returns:
  * Zero on success, error code on failure.
  */
-int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
-                  const struct drm_crtc_funcs *funcs)
+int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
+                             struct drm_plane *primary,
+                             void *cursor,
+                             const struct drm_crtc_funcs *funcs)
 {
        int ret;
 
@@ -717,12 +729,16 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
        list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
        dev->mode_config.num_crtc++;
 
+       crtc->primary = primary;
+       if (primary)
+               primary->possible_crtcs = 1 << drm_crtc_index(crtc);
+
  out:
        drm_modeset_unlock_all(dev);
 
        return ret;
 }
-EXPORT_SYMBOL(drm_crtc_init);
+EXPORT_SYMBOL(drm_crtc_init_with_planes);
 
 /**
  * drm_crtc_cleanup - Clean up the core crtc usage
@@ -1000,26 +1016,25 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
 /**
- * drm_plane_init - Initialise a new plane object
+ * drm_universal_plane_init - Initialize a new universal plane object
  * @dev: DRM device
  * @plane: plane object to init
  * @possible_crtcs: bitmask of possible CRTCs
  * @funcs: callbacks for the new plane
  * @formats: array of supported formats (%DRM_FORMAT_*)
  * @format_count: number of elements in @formats
- * @priv: plane is private (hidden from userspace)?
+ * @type: type of plane (overlay, primary, cursor)
  *
- * Inits a preallocate plane object created as base part of a driver plane
- * object.
+ * Initializes a plane object of type @type.
  *
  * Returns:
  * Zero on success, error code on failure.
  */
-int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
-                  unsigned long possible_crtcs,
-                  const struct drm_plane_funcs *funcs,
-                  const uint32_t *formats, uint32_t format_count,
-                  bool priv)
+int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
+                            unsigned long possible_crtcs,
+                            const struct drm_plane_funcs *funcs,
+                            const uint32_t *formats, uint32_t format_count,
+                            enum drm_plane_type type)
 {
        int ret;
 
@@ -1044,23 +1059,53 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
        memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
        plane->format_count = format_count;
        plane->possible_crtcs = possible_crtcs;
+       plane->type = type;
 
-       /* private planes are not exposed to userspace, but depending on
-        * display hardware, might be convenient to allow sharing programming
-        * for the scanout engine with the crtc implementation.
-        */
-       if (!priv) {
-               list_add_tail(&plane->head, &dev->mode_config.plane_list);
-               dev->mode_config.num_plane++;
-       } else {
-               INIT_LIST_HEAD(&plane->head);
-       }
+       list_add_tail(&plane->head, &dev->mode_config.plane_list);
+       dev->mode_config.num_total_plane++;
+       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+               dev->mode_config.num_overlay_plane++;
+
+       drm_object_attach_property(&plane->base,
+                                  dev->mode_config.plane_type_property,
+                                  plane->type);
 
  out:
        drm_modeset_unlock_all(dev);
 
        return ret;
 }
+EXPORT_SYMBOL(drm_universal_plane_init);
+
+/**
+ * drm_plane_init - Initialize a legacy plane
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @format_count: number of elements in @formats
+ * @is_primary: plane type (primary vs overlay)
+ *
+ * Legacy API to initialize a DRM plane.
+ *
+ * New drivers should call drm_universal_plane_init() instead.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
+                  unsigned long possible_crtcs,
+                  const struct drm_plane_funcs *funcs,
+                  const uint32_t *formats, uint32_t format_count,
+                  bool is_primary)
+{
+       enum drm_plane_type type;
+
+       type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+       return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
+                                       formats, format_count, type);
+}
 EXPORT_SYMBOL(drm_plane_init);
 
 /**
@@ -1078,11 +1123,13 @@ void drm_plane_cleanup(struct drm_plane *plane)
        drm_modeset_lock_all(dev);
        kfree(plane->format_types);
        drm_mode_object_put(dev, &plane->base);
-       /* if not added to a list, it must be a private plane */
-       if (!list_empty(&plane->head)) {
-               list_del(&plane->head);
-               dev->mode_config.num_plane--;
-       }
+
+       BUG_ON(list_empty(&plane->head));
+
+       list_del(&plane->head);
+       dev->mode_config.num_total_plane--;
+       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+               dev->mode_config.num_overlay_plane--;
        drm_modeset_unlock_all(dev);
 }
 EXPORT_SYMBOL(drm_plane_cleanup);
@@ -1134,6 +1181,21 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
        return 0;
 }
 
+static int drm_mode_create_standard_plane_properties(struct drm_device *dev)
+{
+       struct drm_property *type;
+
+       /*
+        * Standard properties (apply to all planes)
+        */
+       type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
+                                       "type", drm_plane_type_enum_list,
+                                       ARRAY_SIZE(drm_plane_type_enum_list));
+       dev->mode_config.plane_type_property = type;
+
+       return 0;
+}
+
 /**
  * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
  * @dev: DRM device
@@ -1492,9 +1554,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        mutex_unlock(&file_priv->fbs_lock);
 
        drm_modeset_lock_all(dev);
-       mode_group = &file_priv->master->minor->mode_group;
-       if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
+       if (!drm_is_primary_client(file_priv)) {
 
+               mode_group = NULL;
                list_for_each(lh, &dev->mode_config.crtc_list)
                        crtc_count++;
 
@@ -1505,6 +1567,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
                        encoder_count++;
        } else {
 
+               mode_group = &file_priv->master->minor->mode_group;
                crtc_count = mode_group->num_crtcs;
                connector_count = mode_group->num_connectors;
                encoder_count = mode_group->num_encoders;
@@ -1519,7 +1582,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        if (card_res->count_crtcs >= crtc_count) {
                copied = 0;
                crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
-               if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
+               if (!mode_group) {
                        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                                            head) {
                                DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
@@ -1546,7 +1609,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        if (card_res->count_encoders >= encoder_count) {
                copied = 0;
                encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
-               if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
+               if (!mode_group) {
                        list_for_each_entry(encoder,
                                            &dev->mode_config.encoder_list,
                                            head) {
@@ -1577,7 +1640,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        if (card_res->count_connectors >= connector_count) {
                copied = 0;
                connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
-               if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
+               if (!mode_group) {
                        list_for_each_entry(connector,
                                            &dev->mode_config.connector_list,
                                            head) {
@@ -1651,8 +1714,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
        crtc_resp->x = crtc->x;
        crtc_resp->y = crtc->y;
        crtc_resp->gamma_size = crtc->gamma_size;
-       if (crtc->fb)
-               crtc_resp->fb_id = crtc->fb->base.id;
+       if (crtc->primary->fb)
+               crtc_resp->fb_id = crtc->primary->fb->base.id;
        else
                crtc_resp->fb_id = 0;
 
@@ -1896,6 +1959,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
        struct drm_plane *plane;
        uint32_t __user *plane_ptr;
        int copied = 0, ret = 0;
+       unsigned num_planes;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -1903,15 +1967,28 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
        drm_modeset_lock_all(dev);
        config = &dev->mode_config;
 
+       if (file_priv->universal_planes)
+               num_planes = config->num_total_plane;
+       else
+               num_planes = config->num_overlay_plane;
+
        /*
         * This ioctl is called twice, once to determine how much space is
         * needed, and the 2nd time to fill it.
         */
-       if (config->num_plane &&
-           (plane_resp->count_planes >= config->num_plane)) {
+       if (num_planes &&
+           (plane_resp->count_planes >= num_planes)) {
                plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
 
                list_for_each_entry(plane, &config->plane_list, head) {
+                       /*
+                        * Unless userspace set the 'universal planes'
+                        * capability bit, only advertise overlays.
+                        */
+                       if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
+                           !file_priv->universal_planes)
+                               continue;
+
                        if (put_user(plane->base.id, plane_ptr + copied)) {
                                ret = -EFAULT;
                                goto out;
@@ -1919,7 +1996,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
                        copied++;
                }
        }
-       plane_resp->count_planes = config->num_plane;
+       plane_resp->count_planes = num_planes;
 
 out:
        drm_modeset_unlock_all(dev);
@@ -2155,19 +2232,21 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
         * crtcs. Atomic modeset will have saner semantics ...
         */
        list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
-               tmp->old_fb = tmp->fb;
+               tmp->old_fb = tmp->primary->fb;
 
        fb = set->fb;
 
        ret = crtc->funcs->set_config(set);
        if (ret == 0) {
+               crtc->primary->crtc = crtc;
+
                /* crtc->fb must be updated by ->set_config, enforces this. */
-               WARN_ON(fb != crtc->fb);
+               WARN_ON(fb != crtc->primary->fb);
        }
 
        list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
-               if (tmp->fb)
-                       drm_framebuffer_reference(tmp->fb);
+               if (tmp->primary->fb)
+                       drm_framebuffer_reference(tmp->primary->fb);
                if (tmp->old_fb)
                        drm_framebuffer_unreference(tmp->old_fb);
        }
@@ -2176,14 +2255,19 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
 }
 EXPORT_SYMBOL(drm_mode_set_config_internal);
 
-/*
- * Checks that the framebuffer is big enough for the CRTC viewport
- * (x, y, hdisplay, vdisplay)
+/**
+ * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
+ *     CRTC viewport
+ * @crtc: CRTC that framebuffer will be displayed on
+ * @x: x panning
+ * @y: y panning
+ * @mode: mode that framebuffer will be displayed under
+ * @fb: framebuffer to check size of
  */
-static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
-                                  int x, int y,
-                                  const struct drm_display_mode *mode,
-                                  const struct drm_framebuffer *fb)
+int drm_crtc_check_viewport(const struct drm_crtc *crtc,
+                           int x, int y,
+                           const struct drm_display_mode *mode,
+                           const struct drm_framebuffer *fb)
 
 {
        int hdisplay, vdisplay;
@@ -2214,6 +2298,7 @@ static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
 
        return 0;
 }
+EXPORT_SYMBOL(drm_crtc_check_viewport);
 
 /**
  * drm_mode_setcrtc - set CRTC configuration
@@ -2265,12 +2350,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                /* If we have a mode we need a framebuffer. */
                /* If we pass -1, set the mode with the currently bound fb */
                if (crtc_req->fb_id == -1) {
-                       if (!crtc->fb) {
+                       if (!crtc->primary->fb) {
                                DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
                                ret = -EINVAL;
                                goto out;
                        }
-                       fb = crtc->fb;
+                       fb = crtc->primary->fb;
                        /* Make refcounting symmetric with the lookup path. */
                        drm_framebuffer_reference(fb);
                } else {
@@ -2846,7 +2931,8 @@ int drm_mode_getfb(struct drm_device *dev,
        r->bpp = fb->bits_per_pixel;
        r->pitch = fb->pitches[0];
        if (fb->funcs->create_handle) {
-               if (file_priv->is_master || capable(CAP_SYS_ADMIN)) {
+               if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
+                   drm_is_control_client(file_priv)) {
                        ret = fb->funcs->create_handle(fb, file_priv,
                                                       &r->handle);
                } else {
@@ -4063,7 +4149,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        crtc = obj_to_crtc(obj);
 
        mutex_lock(&crtc->mutex);
-       if (crtc->fb == NULL) {
+       if (crtc->primary->fb == NULL) {
                /* The framebuffer is currently unbound, presumably
                 * due to a hotplug event, that userspace has not
                 * yet discovered.
@@ -4085,7 +4171,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        if (ret)
                goto out;
 
-       if (crtc->fb->pixel_format != fb->pixel_format) {
+       if (crtc->primary->fb->pixel_format != fb->pixel_format) {
                DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
                ret = -EINVAL;
                goto out;
@@ -4118,7 +4204,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
                        (void (*) (struct drm_pending_event *)) kfree;
        }
 
-       old_fb = crtc->fb;
+       old_fb = crtc->primary->fb;
        ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
        if (ret) {
                if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4136,7 +4222,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
                 * Failing to do so will screw with the reference counting
                 * on framebuffers.
                 */
-               WARN_ON(crtc->fb != fb);
+               WARN_ON(crtc->primary->fb != fb);
                /* Unref only the old framebuffer. */
                fb = NULL;
        }
@@ -4525,6 +4611,7 @@ void drm_mode_config_init(struct drm_device *dev)
 
        drm_modeset_lock_all(dev);
        drm_mode_create_standard_connector_properties(dev);
+       drm_mode_create_standard_plane_properties(dev);
        drm_modeset_unlock_all(dev);
 
        /* Just to be sure */
@@ -4532,6 +4619,8 @@ void drm_mode_config_init(struct drm_device *dev)
        dev->mode_config.num_connector = 0;
        dev->mode_config.num_crtc = 0;
        dev->mode_config.num_encoder = 0;
+       dev->mode_config.num_overlay_plane = 0;
+       dev->mode_config.num_total_plane = 0;
 }
 EXPORT_SYMBOL(drm_mode_config_init);
 
index a8551785407339dd1cd9426263a1ac44d7d68aa8..1fbe8427c70e536bff5233c7cf81dba1355c0342 100644 (file)
@@ -278,17 +278,7 @@ drm_encoder_disable(struct drm_encoder *encoder)
                encoder->bridge->funcs->post_disable(encoder->bridge);
 }
 
-/**
- * drm_helper_disable_unused_functions - disable unused objects
- * @dev: DRM device
- *
- * This function walks through the entire mode setting configuration of @dev. It
- * will remove any crtc links of unused encoders and encoder links of
- * disconnected connectors. Then it will disable all unused encoders and crtcs
- * either by calling their disable callback if available or by calling their
- * dpms callback with DRM_MODE_DPMS_OFF.
- */
-void drm_helper_disable_unused_functions(struct drm_device *dev)
+static void __drm_helper_disable_unused_functions(struct drm_device *dev)
 {
        struct drm_encoder *encoder;
        struct drm_connector *connector;
@@ -299,8 +289,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (!connector->encoder)
                        continue;
-               if (connector->status == connector_status_disconnected)
-                       connector->encoder = NULL;
        }
 
        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)
                                (*crtc_funcs->disable)(crtc);
                        else
                                (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
-                       crtc->fb = NULL;
+                       crtc->primary->fb = NULL;
                }
        }
 }
+
+/**
+ * drm_helper_disable_unused_functions - disable unused objects
+ * @dev: DRM device
+ *
+ * This function walks through the entire mode setting configuration of @dev. It
+ * will remove any crtc links of unused encoders and encoder links of
+ * disconnected connectors. Then it will disable all unused encoders and crtcs
+ * either by calling their disable callback if available or by calling their
+ * dpms callback with DRM_MODE_DPMS_OFF.
+ */
+void drm_helper_disable_unused_functions(struct drm_device *dev)
+{
+       drm_modeset_lock_all(dev);
+       __drm_helper_disable_unused_functions(dev);
+       drm_modeset_unlock_all(dev);
+}
 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
 
 /*
@@ -552,7 +557,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
                }
        }
 
-       drm_helper_disable_unused_functions(dev);
+       __drm_helper_disable_unused_functions(dev);
        return 0;
 }
 
@@ -646,19 +651,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        save_set.mode = &set->crtc->mode;
        save_set.x = set->crtc->x;
        save_set.y = set->crtc->y;
-       save_set.fb = set->crtc->fb;
+       save_set.fb = set->crtc->primary->fb;
 
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
-       if (set->crtc->fb != set->fb) {
+       if (set->crtc->primary->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
-               if (set->crtc->fb == NULL) {
+               if (set->crtc->primary->fb == NULL) {
                        DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
                        mode_changed = true;
                } else if (set->fb == NULL) {
                        mode_changed = true;
                } else if (set->fb->pixel_format !=
-                          set->crtc->fb->pixel_format) {
+                          set->crtc->primary->fb->pixel_format) {
                        mode_changed = true;
                } else
                        fb_changed = true;
@@ -688,12 +693,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                                if (new_encoder == NULL)
                                        /* don't break so fail path works correct */
                                        fail = 1;
-                               break;
 
                                if (connector->dpms != DRM_MODE_DPMS_ON) {
                                        DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
                                        mode_changed = true;
                                }
+
+                               break;
                        }
                }
 
@@ -759,13 +765,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        DRM_DEBUG_KMS("attempting to set mode from"
                                        " userspace\n");
                        drm_mode_debug_printmodeline(set->mode);
-                       set->crtc->fb = set->fb;
+                       set->crtc->primary->fb = set->fb;
                        if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
                                                      set->x, set->y,
                                                      save_set.fb)) {
                                DRM_ERROR("failed to set mode on [CRTC:%d]\n",
                                          set->crtc->base.id);
-                               set->crtc->fb = save_set.fb;
+                               set->crtc->primary->fb = save_set.fb;
                                ret = -EINVAL;
                                goto fail;
                        }
@@ -776,17 +782,17 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                                set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
                        }
                }
-               drm_helper_disable_unused_functions(dev);
+               __drm_helper_disable_unused_functions(dev);
        } else if (fb_changed) {
                set->crtc->x = set->x;
                set->crtc->y = set->y;
-               set->crtc->fb = set->fb;
+               set->crtc->primary->fb = set->fb;
                ret = crtc_funcs->mode_set_base(set->crtc,
                                                set->x, set->y, save_set.fb);
                if (ret != 0) {
                        set->crtc->x = save_set.x;
                        set->crtc->y = save_set.y;
-                       set->crtc->fb = save_set.fb;
+                       set->crtc->primary->fb = save_set.fb;
                        goto fail;
                }
        }
@@ -976,13 +982,14 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
        int encoder_dpms;
        bool ret;
 
+       drm_modeset_lock_all(dev);
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 
                if (!crtc->enabled)
                        continue;
 
                ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                                              crtc->x, crtc->y, crtc->fb);
+                                              crtc->x, crtc->y, crtc->primary->fb);
 
                /* Restoring the old config should never fail! */
                if (ret == false)
@@ -1009,7 +1016,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
        }
 
        /* disable the unused connectors while restoring the modesetting */
-       drm_helper_disable_unused_functions(dev);
+       __drm_helper_disable_unused_functions(dev);
+       drm_modeset_unlock_all(dev);
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);
 
index 17832d0481476f744ea54f4ab40b96b01a8a28a6..f4babed2f5570eb3664bd556df030b0ff51bc45c 100644 (file)
@@ -402,7 +402,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
                }
        }
 
-       DRM_ERROR("too many retries, giving up\n");
+       DRM_DEBUG_KMS("too many retries, giving up\n");
        return -EIO;
 }
 
@@ -656,7 +656,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
                }
        }
 
-       DRM_ERROR("too many retries, giving up\n");
+       DRM_DEBUG_KMS("too many retries, giving up\n");
        return -EREMOTEIO;
 }
 
index ec651be2f3cbdf72eeab77537fcba7cc38625041..03711d00aaaea91d4225088f6311ad309dc262d1 100644 (file)
@@ -285,6 +285,45 @@ static int drm_version(struct drm_device *dev, void *data,
        return err;
 }
 
+/**
+ * drm_ioctl_permit - Check ioctl permissions against caller
+ *
+ * @flags: ioctl permission flags.
+ * @file_priv: Pointer to struct drm_file identifying the caller.
+ *
+ * Checks whether the caller is allowed to run an ioctl with the
+ * indicated permissions. If so, returns zero. Otherwise returns an
+ * error code suitable for ioctl return.
+ */
+static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+{
+       /* ROOT_ONLY is only for CAP_SYS_ADMIN */
+       if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
+               return -EACCES;
+
+       /* AUTH is only for authenticated or render client */
+       if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
+                    !file_priv->authenticated))
+               return -EACCES;
+
+       /* MASTER is only for master or control clients */
+       if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
+                    !drm_is_control_client(file_priv)))
+               return -EACCES;
+
+       /* Control clients must be explicitly allowed */
+       if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
+                    drm_is_control_client(file_priv)))
+               return -EACCES;
+
+       /* Render clients must be explicitly allowed */
+       if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
+                    drm_is_render_client(file_priv)))
+               return -EACCES;
+
+       return 0;
+}
+
 /**
  * Called whenever a process performs an ioctl on /dev/drm.
  *
@@ -350,52 +389,51 @@ long drm_ioctl(struct file *filp,
        /* Do not trust userspace, use our own definition */
        func = ioctl->func;
 
-       if (!func) {
+       if (unlikely(!func)) {
                DRM_DEBUG("no function\n");
                retcode = -EINVAL;
-       } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
-                  ((ioctl->flags & DRM_AUTH) && !drm_is_render_client(file_priv) && !file_priv->authenticated) ||
-                  ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
-                  (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL)) ||
-                  (!(ioctl->flags & DRM_RENDER_ALLOW) && drm_is_render_client(file_priv))) {
-               retcode = -EACCES;
-       } else {
-               if (cmd & (IOC_IN | IOC_OUT)) {
-                       if (asize <= sizeof(stack_kdata)) {
-                               kdata = stack_kdata;
-                       } else {
-                               kdata = kmalloc(asize, GFP_KERNEL);
-                               if (!kdata) {
-                                       retcode = -ENOMEM;
-                                       goto err_i1;
-                               }
-                       }
-                       if (asize > usize)
-                               memset(kdata + usize, 0, asize - usize);
-               }
+               goto err_i1;
+       }
 
-               if (cmd & IOC_IN) {
-                       if (copy_from_user(kdata, (void __user *)arg,
-                                          usize) != 0) {
-                               retcode = -EFAULT;
+       retcode = drm_ioctl_permit(ioctl->flags, file_priv);
+       if (unlikely(retcode))
+               goto err_i1;
+
+       if (cmd & (IOC_IN | IOC_OUT)) {
+               if (asize <= sizeof(stack_kdata)) {
+                       kdata = stack_kdata;
+               } else {
+                       kdata = kmalloc(asize, GFP_KERNEL);
+                       if (!kdata) {
+                               retcode = -ENOMEM;
                                goto err_i1;
                        }
-               } else
-                       memset(kdata, 0, usize);
-
-               if (ioctl->flags & DRM_UNLOCKED)
-                       retcode = func(dev, kdata, file_priv);
-               else {
-                       mutex_lock(&drm_global_mutex);
-                       retcode = func(dev, kdata, file_priv);
-                       mutex_unlock(&drm_global_mutex);
                }
+               if (asize > usize)
+                       memset(kdata + usize, 0, asize - usize);
+       }
 
-               if (cmd & IOC_OUT) {
-                       if (copy_to_user((void __user *)arg, kdata,
-                                        usize) != 0)
-                               retcode = -EFAULT;
+       if (cmd & IOC_IN) {
+               if (copy_from_user(kdata, (void __user *)arg,
+                                  usize) != 0) {
+                       retcode = -EFAULT;
+                       goto err_i1;
                }
+       } else
+               memset(kdata, 0, usize);
+
+       if (ioctl->flags & DRM_UNLOCKED)
+               retcode = func(dev, kdata, file_priv);
+       else {
+               mutex_lock(&drm_global_mutex);
+               retcode = func(dev, kdata, file_priv);
+               mutex_unlock(&drm_global_mutex);
+       }
+
+       if (cmd & IOC_OUT) {
+               if (copy_to_user((void __user *)arg, kdata,
+                                usize) != 0)
+                       retcode = -EFAULT;
        }
 
       err_i1:
@@ -412,3 +450,21 @@ long drm_ioctl(struct file *filp,
        return retcode;
 }
 EXPORT_SYMBOL(drm_ioctl);
+
+/**
+ * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ *
+ * @nr: Ioctl number.
+ * @flags: Where to return the ioctl permission flags
+ */
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+{
+       if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
+           (nr < DRM_COMMAND_BASE)) {
+               *flags = drm_ioctls[nr].flags;
+               return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(drm_ioctl_flags);
index 87876198801d405bbb61301c698bc69a6e16e415..9795c0636da2664f93adfbc98a2f49b06d601cc9 100644 (file)
@@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
 
        list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
                if (crtc->base.id == c->base.id)
-                       return c->fb;
+                       return c->primary->fb;
        }
 
        return NULL;
@@ -291,7 +291,8 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
        drm_warn_on_modeset_not_all_locked(dev);
 
        list_for_each_entry(plane, &dev->mode_config.plane_list, head)
-               drm_plane_force_disable(plane);
+               if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+                       drm_plane_force_disable(plane);
 
        for (i = 0; i < fb_helper->crtc_count; i++) {
                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)
                return false;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->fb)
+               if (crtc->primary->fb)
                        crtcs_bound++;
-               if (crtc->fb == fb_helper->fb)
+               if (crtc->primary->fb == fb_helper->fb)
                        bound++;
        }
 
@@ -1536,9 +1537,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 
        drm_fb_helper_parse_command_line(fb_helper);
 
+       mutex_lock(&dev->mode_config.mutex);
        count = drm_fb_helper_probe_connector_modes(fb_helper,
                                                    dev->mode_config.max_width,
                                                    dev->mode_config.max_height);
+       mutex_unlock(&dev->mode_config.mutex);
        /*
         * we shouldn't end up with no modes here.
         */
index 9b02f126fb0d9ac1e76a08f573dac7d7f2212fa7..a0ce39c96f8e9c7c8bb320fb00850d8f4eec09bd 100644 (file)
@@ -231,12 +231,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 
        /* if there is no current master make this fd it, but do not create
         * any master object for render clients */
-       mutex_lock(&dev->struct_mutex);
-       if (!priv->minor->master && !drm_is_render_client(priv)) {
+       mutex_lock(&dev->master_mutex);
+       if (drm_is_primary_client(priv) && !priv->minor->master) {
                /* create a new master */
                priv->minor->master = drm_master_create(priv->minor);
                if (!priv->minor->master) {
-                       mutex_unlock(&dev->struct_mutex);
                        ret = -ENOMEM;
                        goto out_close;
                }
@@ -244,37 +243,31 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
                priv->is_master = 1;
                /* take another reference for the copy in the local file priv */
                priv->master = drm_master_get(priv->minor->master);
-
                priv->authenticated = 1;
 
-               mutex_unlock(&dev->struct_mutex);
                if (dev->driver->master_create) {
                        ret = dev->driver->master_create(dev, priv->master);
                        if (ret) {
-                               mutex_lock(&dev->struct_mutex);
                                /* drop both references if this fails */
                                drm_master_put(&priv->minor->master);
                                drm_master_put(&priv->master);
-                               mutex_unlock(&dev->struct_mutex);
                                goto out_close;
                        }
                }
-               mutex_lock(&dev->struct_mutex);
                if (dev->driver->master_set) {
                        ret = dev->driver->master_set(dev, priv, true);
                        if (ret) {
                                /* drop both references if this fails */
                                drm_master_put(&priv->minor->master);
                                drm_master_put(&priv->master);
-                               mutex_unlock(&dev->struct_mutex);
                                goto out_close;
                        }
                }
-       } else if (!drm_is_render_client(priv)) {
+       } else if (drm_is_primary_client(priv)) {
                /* get a reference to the master */
                priv->master = drm_master_get(priv->minor->master);
        }
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&dev->master_mutex);
 
        mutex_lock(&dev->struct_mutex);
        list_add(&priv->lhead, &dev->filelist);
@@ -302,6 +295,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        return 0;
 
 out_close:
+       mutex_unlock(&dev->master_mutex);
        if (dev->driver->postclose)
                dev->driver->postclose(dev, priv);
 out_prime_destroy:
@@ -489,11 +483,13 @@ int drm_release(struct inode *inode, struct file *filp)
        }
        mutex_unlock(&dev->ctxlist_mutex);
 
-       mutex_lock(&dev->struct_mutex);
+       mutex_lock(&dev->master_mutex);
 
        if (file_priv->is_master) {
                struct drm_master *master = file_priv->master;
                struct drm_file *temp;
+
+               mutex_lock(&dev->struct_mutex);
                list_for_each_entry(temp, &dev->filelist, lhead) {
                        if ((temp->master == file_priv->master) &&
                            (temp != file_priv))
@@ -512,6 +508,7 @@ int drm_release(struct inode *inode, struct file *filp)
                        master->lock.file_priv = NULL;
                        wake_up_interruptible_all(&master->lock.lock_queue);
                }
+               mutex_unlock(&dev->struct_mutex);
 
                if (file_priv->minor->master == file_priv->master) {
                        /* drop the reference held my the minor */
@@ -521,10 +518,13 @@ int drm_release(struct inode *inode, struct file *filp)
                }
        }
 
-       /* drop the reference held my the file priv */
+       /* drop the master reference held by the file priv */
        if (file_priv->master)
                drm_master_put(&file_priv->master);
        file_priv->is_master = 0;
+       mutex_unlock(&dev->master_mutex);
+
+       mutex_lock(&dev->struct_mutex);
        list_del(&file_priv->lhead);
        mutex_unlock(&dev->struct_mutex);
 
index f4dc9b7a3831f32d43f0e53cd8ed9791cac665ad..93a42040bedb38a2bd21c4a8409a6ad83081674f 100644 (file)
@@ -328,6 +328,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
                        return -EINVAL;
                file_priv->stereo_allowed = req->value;
                break;
+       case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
+               if (!drm_universal_planes)
+                       return -EINVAL;
+               if (req->value > 1)
+                       return -EINVAL;
+               file_priv->universal_planes = req->value;
+               break;
        default:
                return -EINVAL;
        }
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
new file mode 100644 (file)
index 0000000..e768d35
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * DRM universal plane helper functions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/list.h>
+#include <drm/drmP.h>
+#include <drm/drm_rect.h>
+
+#define SUBPIXEL_MASK 0xffff
+
+/*
+ * This is the minimal list of formats that seem to be safe for modeset use
+ * with all current DRM drivers.  Most hardware can actually support more
+ * formats than this and drivers may specify a more accurate list when
+ * creating the primary plane.  However drivers that still call
+ * drm_plane_init() will use this minimal format list as the default.
+ */
+const static uint32_t safe_modeset_formats[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+};
+
+/*
+ * Returns the connectors currently associated with a CRTC.  This function
+ * should be called twice:  once with a NULL connector list to retrieve
+ * the list size, and once with the properly allocated list to be filled in.
+ */
+static int get_connectors_for_crtc(struct drm_crtc *crtc,
+                                  struct drm_connector **connector_list,
+                                  int num_connectors)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_connector *connector;
+       int count = 0;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+               if (connector->encoder && connector->encoder->crtc == crtc) {
+                       if (connector_list != NULL && count < num_connectors)
+                               *(connector_list++) = connector;
+
+                       count++;
+               }
+
+       return count;
+}
+
+/**
+ * drm_primary_helper_update() - Helper for primary plane update
+ * @plane: plane object to update
+ * @crtc: owning CRTC of owning plane
+ * @fb: framebuffer to flip onto plane
+ * @crtc_x: x offset of primary plane on crtc
+ * @crtc_y: y offset of primary plane on crtc
+ * @crtc_w: width of primary plane rectangle on crtc
+ * @crtc_h: height of primary plane rectangle on crtc
+ * @src_x: x offset of @fb for panning
+ * @src_y: y offset of @fb for panning
+ * @src_w: width of source rectangle in @fb
+ * @src_h: height of source rectangle in @fb
+ *
+ * Provides a default plane update handler for primary planes.  This is handler
+ * is called in response to a userspace SetPlane operation on the plane with a
+ * non-NULL framebuffer.  We call the driver's modeset handler to update the
+ * framebuffer.
+ *
+ * SetPlane() on a primary plane of a disabled CRTC is not supported, and will
+ * return an error.
+ *
+ * Note that we make some assumptions about hardware limitations that may not be
+ * true for all hardware --
+ *   1) Primary plane cannot be repositioned.
+ *   2) Primary plane cannot be scaled.
+ *   3) Primary plane must cover the entire CRTC.
+ *   4) Subpixel positioning is not supported.
+ * Drivers for hardware that don't have these restrictions can provide their
+ * own implementation rather than using this helper.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
+                             struct drm_framebuffer *fb,
+                             int crtc_x, int crtc_y,
+                             unsigned int crtc_w, unsigned int crtc_h,
+                             uint32_t src_x, uint32_t src_y,
+                             uint32_t src_w, uint32_t src_h)
+{
+       struct drm_mode_set set = {
+               .crtc = crtc,
+               .fb = fb,
+               .mode = &crtc->mode,
+               .x = src_x >> 16,
+               .y = src_y >> 16,
+       };
+       struct drm_rect dest = {
+               .x1 = crtc_x,
+               .y1 = crtc_y,
+               .x2 = crtc_x + crtc_w,
+               .y2 = crtc_y + crtc_h,
+       };
+       struct drm_rect clip = {
+               .x2 = crtc->mode.hdisplay,
+               .y2 = crtc->mode.vdisplay,
+       };
+       struct drm_connector **connector_list;
+       struct drm_framebuffer *tmpfb;
+       int num_connectors, ret;
+
+       if (!crtc->enabled) {
+               DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n");
+               return -EINVAL;
+       }
+
+       /* Disallow subpixel positioning */
+       if ((src_x | src_y | src_w | src_h) & SUBPIXEL_MASK) {
+               DRM_DEBUG_KMS("Primary plane does not support subpixel positioning\n");
+               return -EINVAL;
+       }
+
+       /* Primary planes are locked to their owning CRTC */
+       if (plane->possible_crtcs != drm_crtc_mask(crtc)) {
+               DRM_DEBUG_KMS("Cannot change primary plane CRTC\n");
+               return -EINVAL;
+       }
+
+       /* Disallow scaling */
+       if (crtc_w != src_w || crtc_h != src_h) {
+               DRM_DEBUG_KMS("Can't scale primary plane\n");
+               return -EINVAL;
+       }
+
+       /* Make sure primary plane covers entire CRTC */
+       drm_rect_intersect(&dest, &clip);
+       if (dest.x1 != 0 || dest.y1 != 0 ||
+           dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) {
+               DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n");
+               return -EINVAL;
+       }
+
+       /* Framebuffer must be big enough to cover entire plane */
+       ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb);
+       if (ret)
+               return ret;
+
+       /* Find current connectors for CRTC */
+       num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
+       BUG_ON(num_connectors == 0);
+       connector_list = kzalloc(num_connectors * sizeof(*connector_list),
+                                GFP_KERNEL);
+       if (!connector_list)
+               return -ENOMEM;
+       get_connectors_for_crtc(crtc, connector_list, num_connectors);
+
+       set.connectors = connector_list;
+       set.num_connectors = num_connectors;
+
+       /*
+        * set_config() adjusts crtc->primary->fb; however the DRM setplane
+        * code that called us expects to handle the framebuffer update and
+        * reference counting; save and restore the current fb before
+        * calling it.
+        *
+        * N.B., we call set_config() directly here rather than using
+        * drm_mode_set_config_internal.  We're reprogramming the same
+        * connectors that were already in use, so we shouldn't need the extra
+        * cross-CRTC fb refcounting to accomodate stealing connectors.
+        * drm_mode_setplane() already handles the basic refcounting for the
+        * framebuffers involved in this operation.
+        */
+       tmpfb = plane->fb;
+       ret = crtc->funcs->set_config(&set);
+       plane->fb = tmpfb;
+
+       kfree(connector_list);
+       return ret;
+}
+EXPORT_SYMBOL(drm_primary_helper_update);
+
+/**
+ * drm_primary_helper_disable() - Helper for primary plane disable
+ * @plane: plane to disable
+ *
+ * Provides a default plane disable handler for primary planes.  This is handler
+ * is called in response to a userspace SetPlane operation on the plane with a
+ * NULL framebuffer parameter.  We call the driver's modeset handler with a NULL
+ * framebuffer to disable the CRTC if no other planes are currently enabled.
+ * If other planes are still enabled on the same CRTC, we return -EBUSY.
+ *
+ * Note that some hardware may be able to disable the primary plane without
+ * disabling the whole CRTC.  Drivers for such hardware should provide their
+ * own disable handler that disables just the primary plane (and they'll likely
+ * need to provide their own update handler as well to properly re-enable a
+ * disabled primary plane).
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+int drm_primary_helper_disable(struct drm_plane *plane)
+{
+       struct drm_plane *p;
+       struct drm_mode_set set = {
+               .crtc = plane->crtc,
+               .fb = NULL,
+       };
+
+       if (plane->crtc == NULL || plane->fb == NULL)
+               /* Already disabled */
+               return 0;
+
+       list_for_each_entry(p, &plane->dev->mode_config.plane_list, head)
+               if (p != plane && p->fb) {
+                       DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n");
+                       return -EBUSY;
+               }
+
+       /*
+        * N.B.  We call set_config() directly here rather than
+        * drm_mode_set_config_internal() since drm_mode_setplane() already
+        * handles the basic refcounting and we don't need the special
+        * cross-CRTC refcounting (no chance of stealing connectors from
+        * other CRTC's with this update).
+        */
+       return plane->crtc->funcs->set_config(&set);
+}
+EXPORT_SYMBOL(drm_primary_helper_disable);
+
+/**
+ * drm_primary_helper_destroy() - Helper for primary plane destruction
+ * @plane: plane to destroy
+ *
+ * Provides a default plane destroy handler for primary planes.  This handler
+ * is called during CRTC destruction.  We disable the primary plane, remove
+ * it from the DRM plane list, and deallocate the plane structure.
+ */
+void drm_primary_helper_destroy(struct drm_plane *plane)
+{
+       plane->funcs->disable_plane(plane);
+       drm_plane_cleanup(plane);
+       kfree(plane);
+}
+EXPORT_SYMBOL(drm_primary_helper_destroy);
+
+const struct drm_plane_funcs drm_primary_helper_funcs = {
+       .update_plane = drm_primary_helper_update,
+       .disable_plane = drm_primary_helper_disable,
+       .destroy = drm_primary_helper_destroy,
+};
+EXPORT_SYMBOL(drm_primary_helper_funcs);
+
+/**
+ * drm_primary_helper_create_plane() - Create a generic primary plane
+ * @dev: drm device
+ * @formats: pixel formats supported, or NULL for a default safe list
+ * @num_formats: size of @formats; ignored if @formats is NULL
+ *
+ * Allocates and initializes a primary plane that can be used with the primary
+ * plane helpers.  Drivers that wish to use driver-specific plane structures or
+ * provide custom handler functions may perform their own allocation and
+ * initialization rather than calling this function.
+ */
+struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
+                                                 const uint32_t *formats,
+                                                 int num_formats)
+{
+       struct drm_plane *primary;
+       int ret;
+
+       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+       if (primary == NULL) {
+               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+               return NULL;
+       }
+
+       if (formats == NULL) {
+               formats = safe_modeset_formats;
+               num_formats = ARRAY_SIZE(safe_modeset_formats);
+       }
+
+       /* possible_crtc's will be filled in later by crtc_init */
+       ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs,
+                            formats, num_formats,
+                            DRM_PLANE_TYPE_PRIMARY);
+       if (ret) {
+               kfree(primary);
+               primary = NULL;
+       }
+
+       return primary;
+}
+EXPORT_SYMBOL(drm_primary_helper_create_plane);
+
+/**
+ * drm_crtc_init - Legacy CRTC initialization function
+ * @dev: DRM device
+ * @crtc: CRTC object to init
+ * @funcs: callbacks for the new CRTC
+ *
+ * Initialize a CRTC object with a default helper-provided primary plane and no
+ * cursor plane.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+                 const struct drm_crtc_funcs *funcs)
+{
+       struct drm_plane *primary;
+
+       primary = drm_primary_helper_create_plane(dev, NULL, 0);
+       return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs);
+}
+EXPORT_SYMBOL(drm_crtc_init);
index dc2c6095d850ea1b285893666ec2565baab9e371..4c24c3ac1efaf28225aa635834e982c9f5a6055b 100644 (file)
@@ -45,6 +45,10 @@ EXPORT_SYMBOL(drm_debug);
 unsigned int drm_rnodes = 0;   /* 1 to enable experimental render nodes API */
 EXPORT_SYMBOL(drm_rnodes);
 
+/* 1 to allow user space to request universal planes (experimental) */
+unsigned int drm_universal_planes = 0;
+EXPORT_SYMBOL(drm_universal_planes);
+
 unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
 EXPORT_SYMBOL(drm_vblank_offdelay);
 
@@ -68,6 +72,7 @@ MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
 
 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(rnodes, drm_rnodes, int, 0600);
+module_param_named(universal_planes, drm_universal_planes, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
 module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
@@ -97,26 +102,18 @@ int drm_err(const char *func, const char *format, ...)
 }
 EXPORT_SYMBOL(drm_err);
 
-void drm_ut_debug_printk(unsigned int request_level,
-                        const char *prefix,
-                        const char *function_name,
-                        const char *format, ...)
+void drm_ut_debug_printk(const char *function_name, const char *format, ...)
 {
        struct va_format vaf;
        va_list args;
 
-       if (drm_debug & request_level) {
-               va_start(args, format);
-               vaf.fmt = format;
-               vaf.va = &args;
-
-               if (function_name)
-                       printk(KERN_DEBUG "[%s:%s], %pV", prefix,
-                              function_name, &vaf);
-               else
-                       printk(KERN_DEBUG "%pV", &vaf);
-               va_end(args);
-       }
+       va_start(args, format);
+       vaf.fmt = format;
+       vaf.va = &args;
+
+       printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
+
+       va_end(args);
 }
 EXPORT_SYMBOL(drm_ut_debug_printk);
 
@@ -135,8 +132,6 @@ struct drm_master *drm_master_create(struct drm_minor *minor)
        INIT_LIST_HEAD(&master->magicfree);
        master->minor = minor;
 
-       list_add_tail(&master->head, &minor->master_list);
-
        return master;
 }
 
@@ -154,8 +149,7 @@ static void drm_master_destroy(struct kref *kref)
        struct drm_device *dev = master->minor->dev;
        struct drm_map_list *r_list, *list_temp;
 
-       list_del(&master->head);
-
+       mutex_lock(&dev->struct_mutex);
        if (dev->driver->master_destroy)
                dev->driver->master_destroy(dev, master);
 
@@ -183,6 +177,7 @@ static void drm_master_destroy(struct kref *kref)
 
        drm_ht_remove(&master->magiclist);
 
+       mutex_unlock(&dev->struct_mutex);
        kfree(master);
 }
 
@@ -198,19 +193,20 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 {
        int ret = 0;
 
+       mutex_lock(&dev->master_mutex);
        if (file_priv->is_master)
-               return 0;
-
-       if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
-               return -EINVAL;
+               goto out_unlock;
 
-       if (!file_priv->master)
-               return -EINVAL;
+       if (file_priv->minor->master) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
 
-       if (file_priv->minor->master)
-               return -EINVAL;
+       if (!file_priv->master) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
 
-       mutex_lock(&dev->struct_mutex);
        file_priv->minor->master = drm_master_get(file_priv->master);
        file_priv->is_master = 1;
        if (dev->driver->master_set) {
@@ -220,27 +216,33 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
                        drm_master_put(&file_priv->minor->master);
                }
        }
-       mutex_unlock(&dev->struct_mutex);
 
+out_unlock:
+       mutex_unlock(&dev->master_mutex);
        return ret;
 }
 
 int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
 {
+       int ret = -EINVAL;
+
+       mutex_lock(&dev->master_mutex);
        if (!file_priv->is_master)
-               return -EINVAL;
+               goto out_unlock;
 
        if (!file_priv->minor->master)
-               return -EINVAL;
+               goto out_unlock;
 
-       mutex_lock(&dev->struct_mutex);
+       ret = 0;
        if (dev->driver->master_drop)
                dev->driver->master_drop(dev, file_priv, false);
        drm_master_put(&file_priv->minor->master);
        file_priv->is_master = 0;
-       mutex_unlock(&dev->struct_mutex);
-       return 0;
+
+out_unlock:
+       mutex_unlock(&dev->master_mutex);
+       return ret;
 }
 
 /*
@@ -281,7 +283,6 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
 
        minor->type = type;
        minor->dev = dev;
-       INIT_LIST_HEAD(&minor->master_list);
 
        *drm_minor_get_slot(dev, type) = minor;
        return 0;
@@ -572,6 +573,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
        spin_lock_init(&dev->event_lock);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
+       mutex_init(&dev->master_mutex);
 
        dev->anon_inode = drm_fs_inode_new();
        if (IS_ERR(dev->anon_inode)) {
@@ -625,6 +627,7 @@ err_minors:
        drm_minor_free(dev, DRM_MINOR_CONTROL);
        drm_fs_inode_free(dev->anon_inode);
 err_free:
+       mutex_destroy(&dev->master_mutex);
        kfree(dev);
        return NULL;
 }
@@ -646,6 +649,8 @@ static void drm_dev_release(struct kref *ref)
        drm_minor_free(dev, DRM_MINOR_CONTROL);
 
        kfree(dev->devname);
+
+       mutex_destroy(&dev->master_mutex);
        kfree(dev);
 }
 
index 6e1a1a20cf6b4ab94a0f06f43d6470416dfcc879..56f95811a5e5a930a7aecd33a582d18cc92f9db4 100644 (file)
@@ -31,6 +31,21 @@ config DRM_EXYNOS_FIMD
        help
          Choose this option if you want to use Exynos FIMD for DRM.
 
+config DRM_EXYNOS_DPI
+       bool "EXYNOS DRM parallel output support"
+       depends on DRM_EXYNOS
+       select DRM_PANEL
+       default n
+       help
+         This enables support for Exynos parallel output.
+
+config DRM_EXYNOS_DP
+       bool "EXYNOS DRM DP driver support"
+       depends on DRM_EXYNOS && ARCH_EXYNOS
+       default DRM_EXYNOS
+       help
+         This enables support for DP device.
+
 config DRM_EXYNOS_HDMI
        bool "Exynos DRM HDMI"
        depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
index 639b49e1ec0586ceed662dbbfe3075bbf1157aa9..babcd52b65df9ffa29c9b4b987a79ab902816e91 100644 (file)
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
-exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
+exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \
                exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
                exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
                exynos_drm_plane.o
@@ -11,9 +11,9 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
 exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)    += exynos_drm_fimd.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)    += exynos_hdmi.o exynos_mixer.o \
-                                          exynos_ddc.o exynos_hdmiphy.o \
-                                          exynos_drm_hdmi.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_DPI)     += exynos_drm_dpi.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_DP)      += exynos_dp_core.o exynos_dp_reg.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)    += exynos_hdmi.o exynos_mixer.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)    += exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)     += exynos_drm_g2d.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_IPP)     += exynos_drm_ipp.o
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
new file mode 100644 (file)
index 0000000..a59bca9
--- /dev/null
@@ -0,0 +1,1357 @@
+/*
+ * Samsung SoC DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/bridge/ptn3460.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_dp_core.h"
+
+#define ctx_from_connector(c)  container_of(c, struct exynos_dp_device, \
+                                       connector)
+
+struct bridge_init {
+       struct i2c_client *client;
+       struct device_node *node;
+};
+
+static int exynos_dp_init_dp(struct exynos_dp_device *dp)
+{
+       exynos_dp_reset(dp);
+
+       exynos_dp_swreset(dp);
+
+       exynos_dp_init_analog_param(dp);
+       exynos_dp_init_interrupt(dp);
+
+       /* SW defined function Normal operation */
+       exynos_dp_enable_sw_function(dp);
+
+       exynos_dp_config_interrupt(dp);
+       exynos_dp_init_analog_func(dp);
+
+       exynos_dp_init_hpd(dp);
+       exynos_dp_init_aux(dp);
+
+       return 0;
+}
+
+static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
+{
+       int timeout_loop = 0;
+
+       while (exynos_dp_get_plug_in_status(dp) != 0) {
+               timeout_loop++;
+               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                       dev_err(dp->dev, "failed to get hpd plug status\n");
+                       return -ETIMEDOUT;
+               }
+               usleep_range(10, 11);
+       }
+
+       return 0;
+}
+
+static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
+{
+       int i;
+       unsigned char sum = 0;
+
+       for (i = 0; i < EDID_BLOCK_LENGTH; i++)
+               sum = sum + edid_data[i];
+
+       return sum;
+}
+
+static int exynos_dp_read_edid(struct exynos_dp_device *dp)
+{
+       unsigned char edid[EDID_BLOCK_LENGTH * 2];
+       unsigned int extend_block = 0;
+       unsigned char sum;
+       unsigned char test_vector;
+       int retval;
+
+       /*
+        * EDID device address is 0x50.
+        * However, if necessary, you must have set upper address
+        * into E-EDID in I2C device, 0x30.
+        */
+
+       /* Read Extension Flag, Number of 128-byte EDID extension blocks */
+       retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+                               EDID_EXTENSION_FLAG,
+                               &extend_block);
+       if (retval)
+               return retval;
+
+       if (extend_block > 0) {
+               dev_dbg(dp->dev, "EDID data includes a single extension!\n");
+
+               /* Read EDID data */
+               retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+                                               EDID_HEADER_PATTERN,
+                                               EDID_BLOCK_LENGTH,
+                                               &edid[EDID_HEADER_PATTERN]);
+               if (retval != 0) {
+                       dev_err(dp->dev, "EDID Read failed!\n");
+                       return -EIO;
+               }
+               sum = exynos_dp_calc_edid_check_sum(edid);
+               if (sum != 0) {
+                       dev_err(dp->dev, "EDID bad checksum!\n");
+                       return -EIO;
+               }
+
+               /* Read additional EDID data */
+               retval = exynos_dp_read_bytes_from_i2c(dp,
+                               I2C_EDID_DEVICE_ADDR,
+                               EDID_BLOCK_LENGTH,
+                               EDID_BLOCK_LENGTH,
+                               &edid[EDID_BLOCK_LENGTH]);
+               if (retval != 0) {
+                       dev_err(dp->dev, "EDID Read failed!\n");
+                       return -EIO;
+               }
+               sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
+               if (sum != 0) {
+                       dev_err(dp->dev, "EDID bad checksum!\n");
+                       return -EIO;
+               }
+
+               exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
+                                       &test_vector);
+               if (test_vector & DPCD_TEST_EDID_READ) {
+                       exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TEST_EDID_CHECKSUM,
+                               edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
+                       exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TEST_RESPONSE,
+                               DPCD_TEST_EDID_CHECKSUM_WRITE);
+               }
+       } else {
+               dev_info(dp->dev, "EDID data does not include any extensions.\n");
+
+               /* Read EDID data */
+               retval = exynos_dp_read_bytes_from_i2c(dp,
+                               I2C_EDID_DEVICE_ADDR,
+                               EDID_HEADER_PATTERN,
+                               EDID_BLOCK_LENGTH,
+                               &edid[EDID_HEADER_PATTERN]);
+               if (retval != 0) {
+                       dev_err(dp->dev, "EDID Read failed!\n");
+                       return -EIO;
+               }
+               sum = exynos_dp_calc_edid_check_sum(edid);
+               if (sum != 0) {
+                       dev_err(dp->dev, "EDID bad checksum!\n");
+                       return -EIO;
+               }
+
+               exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_TEST_REQUEST,
+                       &test_vector);
+               if (test_vector & DPCD_TEST_EDID_READ) {
+                       exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TEST_EDID_CHECKSUM,
+                               edid[EDID_CHECKSUM]);
+                       exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TEST_RESPONSE,
+                               DPCD_TEST_EDID_CHECKSUM_WRITE);
+               }
+       }
+
+       dev_err(dp->dev, "EDID Read success!\n");
+       return 0;
+}
+
+static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
+{
+       u8 buf[12];
+       int i;
+       int retval;
+
+       /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
+       retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+                               12, buf);
+       if (retval)
+               return retval;
+
+       /* Read EDID */
+       for (i = 0; i < 3; i++) {
+               retval = exynos_dp_read_edid(dp);
+               if (!retval)
+                       break;
+       }
+
+       return retval;
+}
+
+static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
+                                               bool enable)
+{
+       u8 data;
+
+       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
+
+       if (enable)
+               exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+                       DPCD_ENHANCED_FRAME_EN |
+                       DPCD_LANE_COUNT_SET(data));
+       else
+               exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+                       DPCD_LANE_COUNT_SET(data));
+}
+
+static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
+{
+       u8 data;
+       int retval;
+
+       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+       retval = DPCD_ENHANCED_FRAME_CAP(data);
+
+       return retval;
+}
+
+static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
+{
+       u8 data;
+
+       data = exynos_dp_is_enhanced_mode_available(dp);
+       exynos_dp_enable_rx_to_enhanced_mode(dp, data);
+       exynos_dp_enable_enhanced_mode(dp, data);
+}
+
+static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
+{
+       exynos_dp_set_training_pattern(dp, DP_NONE);
+
+       exynos_dp_write_byte_to_dpcd(dp,
+               DPCD_ADDR_TRAINING_PATTERN_SET,
+               DPCD_TRAINING_PATTERN_DISABLED);
+}
+
+static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
+                                       int pre_emphasis, int lane)
+{
+       switch (lane) {
+       case 0:
+               exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
+               break;
+       case 1:
+               exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
+               break;
+
+       case 2:
+               exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
+               break;
+
+       case 3:
+               exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
+               break;
+       }
+}
+
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
+{
+       u8 buf[4];
+       int lane, lane_count, pll_tries, retval;
+
+       lane_count = dp->link_train.lane_count;
+
+       dp->link_train.lt_state = CLOCK_RECOVERY;
+       dp->link_train.eq_loop = 0;
+
+       for (lane = 0; lane < lane_count; lane++)
+               dp->link_train.cr_loop[lane] = 0;
+
+       /* Set link rate and count as you want to establish*/
+       exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
+       exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
+
+       /* Setup RX configuration */
+       buf[0] = dp->link_train.link_rate;
+       buf[1] = dp->link_train.lane_count;
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+                               2, buf);
+       if (retval)
+               return retval;
+
+       /* Set TX pre-emphasis to minimum */
+       for (lane = 0; lane < lane_count; lane++)
+               exynos_dp_set_lane_lane_pre_emphasis(dp,
+                       PRE_EMPHASIS_LEVEL_0, lane);
+
+       /* Wait for PLL lock */
+       pll_tries = 0;
+       while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+               if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+                       dev_err(dp->dev, "Wait for PLL lock timed out\n");
+                       return -ETIMEDOUT;
+               }
+
+               pll_tries++;
+               usleep_range(90, 120);
+       }
+
+       /* Set training pattern 1 */
+       exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
+
+       /* Set RX training pattern */
+       retval = exynos_dp_write_byte_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+       if (retval)
+               return retval;
+
+       for (lane = 0; lane < lane_count; lane++)
+               buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
+                           DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
+
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count, buf);
+
+       return retval;
+}
+
+static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
+{
+       int shift = (lane & 1) * 4;
+       u8 link_value = link_status[lane>>1];
+
+       return (link_value >> shift) & 0xf;
+}
+
+static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
+{
+       int lane;
+       u8 lane_status;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = exynos_dp_get_lane_status(link_status, lane);
+               if ((lane_status & DPCD_LANE_CR_DONE) == 0)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+                               int lane_count)
+{
+       int lane;
+       u8 lane_status;
+
+       if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+               return -EINVAL;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = exynos_dp_get_lane_status(link_status, lane);
+               lane_status &= DPCD_CHANNEL_EQ_BITS;
+               if (lane_status != DPCD_CHANNEL_EQ_BITS)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
+                                                       int lane)
+{
+       int shift = (lane & 1) * 4;
+       u8 link_value = adjust_request[lane>>1];
+
+       return (link_value >> shift) & 0x3;
+}
+
+static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
+                                       u8 adjust_request[2],
+                                       int lane)
+{
+       int shift = (lane & 1) * 4;
+       u8 link_value = adjust_request[lane>>1];
+
+       return ((link_value >> shift) & 0xc) >> 2;
+}
+
+static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
+                                       u8 training_lane_set, int lane)
+{
+       switch (lane) {
+       case 0:
+               exynos_dp_set_lane0_link_training(dp, training_lane_set);
+               break;
+       case 1:
+               exynos_dp_set_lane1_link_training(dp, training_lane_set);
+               break;
+
+       case 2:
+               exynos_dp_set_lane2_link_training(dp, training_lane_set);
+               break;
+
+       case 3:
+               exynos_dp_set_lane3_link_training(dp, training_lane_set);
+               break;
+       }
+}
+
+static unsigned int exynos_dp_get_lane_link_training(
+                               struct exynos_dp_device *dp,
+                               int lane)
+{
+       u32 reg;
+
+       switch (lane) {
+       case 0:
+               reg = exynos_dp_get_lane0_link_training(dp);
+               break;
+       case 1:
+               reg = exynos_dp_get_lane1_link_training(dp);
+               break;
+       case 2:
+               reg = exynos_dp_get_lane2_link_training(dp);
+               break;
+       case 3:
+               reg = exynos_dp_get_lane3_link_training(dp);
+               break;
+       default:
+               WARN_ON(1);
+               return 0;
+       }
+
+       return reg;
+}
+
+static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
+{
+       exynos_dp_training_pattern_dis(dp);
+       exynos_dp_set_enhanced_mode(dp);
+
+       dp->link_train.lt_state = FAILED;
+}
+
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+                                       u8 adjust_request[2])
+{
+       int lane, lane_count;
+       u8 voltage_swing, pre_emphasis, training_lane;
+
+       lane_count = dp->link_train.lane_count;
+       for (lane = 0; lane < lane_count; lane++) {
+               voltage_swing = exynos_dp_get_adjust_request_voltage(
+                                               adjust_request, lane);
+               pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+                                               adjust_request, lane);
+               training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+                               DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+               if (voltage_swing == VOLTAGE_LEVEL_3)
+                       training_lane |= DPCD_MAX_SWING_REACHED;
+               if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+                       training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+               dp->link_train.training_lane[lane] = training_lane;
+       }
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+       int lane, lane_count, retval;
+       u8 voltage_swing, pre_emphasis, training_lane;
+       u8 link_status[2], adjust_request[2];
+
+       usleep_range(100, 101);
+
+       lane_count = dp->link_train.lane_count;
+
+       retval =  exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+       if (retval)
+               return retval;
+
+       retval =  exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+       if (retval)
+               return retval;
+
+       if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
+               /* set training pattern 2 for EQ */
+               exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
+
+               retval = exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TRAINING_PATTERN_SET,
+                               DPCD_SCRAMBLING_DISABLED |
+                               DPCD_TRAINING_PATTERN_2);
+               if (retval)
+                       return retval;
+
+               dev_info(dp->dev, "Link Training Clock Recovery success\n");
+               dp->link_train.lt_state = EQUALIZER_TRAINING;
+       } else {
+               for (lane = 0; lane < lane_count; lane++) {
+                       training_lane = exynos_dp_get_lane_link_training(
+                                                       dp, lane);
+                       voltage_swing = exynos_dp_get_adjust_request_voltage(
+                                                       adjust_request, lane);
+                       pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+                                                       adjust_request, lane);
+
+                       if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+                                       voltage_swing &&
+                           DPCD_PRE_EMPHASIS_GET(training_lane) ==
+                                       pre_emphasis)
+                               dp->link_train.cr_loop[lane]++;
+
+                       if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+                           voltage_swing == VOLTAGE_LEVEL_3 ||
+                           pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+                               dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+                                       dp->link_train.cr_loop[lane],
+                                       voltage_swing, pre_emphasis);
+                               exynos_dp_reduce_link_rate(dp);
+                               return -EIO;
+                       }
+               }
+       }
+
+       exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+       for (lane = 0; lane < lane_count; lane++)
+               exynos_dp_set_lane_link_training(dp,
+                       dp->link_train.training_lane[lane], lane);
+
+       retval = exynos_dp_write_bytes_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
+                       dp->link_train.training_lane);
+       if (retval)
+               return retval;
+
+       return retval;
+}
+
+static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
+{
+       int lane, lane_count, retval;
+       u32 reg;
+       u8 link_align, link_status[2], adjust_request[2];
+
+       usleep_range(400, 401);
+
+       lane_count = dp->link_train.lane_count;
+
+       retval = exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+       if (retval)
+               return retval;
+
+       if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+               exynos_dp_reduce_link_rate(dp);
+               return -EIO;
+       }
+
+       retval = exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+       if (retval)
+               return retval;
+
+       retval = exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+       if (retval)
+               return retval;
+
+       exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+       if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+               /* traing pattern Set to Normal */
+               exynos_dp_training_pattern_dis(dp);
+
+               dev_info(dp->dev, "Link Training success!\n");
+
+               exynos_dp_get_link_bandwidth(dp, &reg);
+               dp->link_train.link_rate = reg;
+               dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+                       dp->link_train.link_rate);
+
+               exynos_dp_get_lane_count(dp, &reg);
+               dp->link_train.lane_count = reg;
+               dev_dbg(dp->dev, "final lane count = %.2x\n",
+                       dp->link_train.lane_count);
+
+               /* set enhanced mode if available */
+               exynos_dp_set_enhanced_mode(dp);
+               dp->link_train.lt_state = FINISHED;
+
+               return 0;
+       }
+
+       /* not all locked */
+       dp->link_train.eq_loop++;
+
+       if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+               dev_err(dp->dev, "EQ Max loop\n");
+               exynos_dp_reduce_link_rate(dp);
+               return -EIO;
+       }
+
+       for (lane = 0; lane < lane_count; lane++)
+               exynos_dp_set_lane_link_training(dp,
+                       dp->link_train.training_lane[lane], lane);
+
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count, dp->link_train.training_lane);
+
+       return retval;
+}
+
+static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
+                                       u8 *bandwidth)
+{
+       u8 data;
+
+       /*
+        * For DP rev.1.1, Maximum link rate of Main Link lanes
+        * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
+        */
+       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
+       *bandwidth = data;
+}
+
+static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
+                                       u8 *lane_count)
+{
+       u8 data;
+
+       /*
+        * For DP rev.1.1, Maximum number of Main Link lanes
+        * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
+        */
+       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+       *lane_count = DPCD_MAX_LANE_COUNT(data);
+}
+
+static void exynos_dp_init_training(struct exynos_dp_device *dp,
+                       enum link_lane_count_type max_lane,
+                       enum link_rate_type max_rate)
+{
+       /*
+        * MACRO_RST must be applied after the PLL_LOCK to avoid
+        * the DP inter pair skew issue for at least 10 us
+        */
+       exynos_dp_reset_macro(dp);
+
+       /* Initialize by reading RX's DPCD */
+       exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
+       exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
+
+       if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
+          (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
+               dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
+                       dp->link_train.link_rate);
+               dp->link_train.link_rate = LINK_RATE_1_62GBPS;
+       }
+
+       if (dp->link_train.lane_count == 0) {
+               dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
+                       dp->link_train.lane_count);
+               dp->link_train.lane_count = (u8)LANE_COUNT1;
+       }
+
+       /* Setup TX lane count & rate */
+       if (dp->link_train.lane_count > max_lane)
+               dp->link_train.lane_count = max_lane;
+       if (dp->link_train.link_rate > max_rate)
+               dp->link_train.link_rate = max_rate;
+
+       /* All DP analog module power up */
+       exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+}
+
+static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
+{
+       int retval = 0, training_finished = 0;
+
+       dp->link_train.lt_state = START;
+
+       /* Process here */
+       while (!retval && !training_finished) {
+               switch (dp->link_train.lt_state) {
+               case START:
+                       retval = exynos_dp_link_start(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT link start failed!\n");
+                       break;
+               case CLOCK_RECOVERY:
+                       retval = exynos_dp_process_clock_recovery(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT CR failed!\n");
+                       break;
+               case EQUALIZER_TRAINING:
+                       retval = exynos_dp_process_equalizer_training(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT EQ failed!\n");
+                       break;
+               case FINISHED:
+                       training_finished = 1;
+                       break;
+               case FAILED:
+                       return -EREMOTEIO;
+               }
+       }
+       if (retval)
+               dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
+
+       return retval;
+}
+
+static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
+                               u32 count,
+                               u32 bwtype)
+{
+       int i;
+       int retval;
+
+       for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
+               exynos_dp_init_training(dp, count, bwtype);
+               retval = exynos_dp_sw_link_training(dp);
+               if (retval == 0)
+                       break;
+
+               usleep_range(100, 110);
+       }
+
+       return retval;
+}
+
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
+{
+       int retval = 0;
+       int timeout_loop = 0;
+       int done_count = 0;
+
+       exynos_dp_config_video_slave_mode(dp);
+
+       exynos_dp_set_video_color_format(dp);
+
+       if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+               dev_err(dp->dev, "PLL is not locked yet.\n");
+               return -EINVAL;
+       }
+
+       for (;;) {
+               timeout_loop++;
+               if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
+                       break;
+               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                       dev_err(dp->dev, "Timeout of video streamclk ok\n");
+                       return -ETIMEDOUT;
+               }
+
+               usleep_range(1, 2);
+       }
+
+       /* Set to use the register calculated M/N video */
+       exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
+
+       /* For video bist, Video timing must be generated by register */
+       exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
+
+       /* Disable video mute */
+       exynos_dp_enable_video_mute(dp, 0);
+
+       /* Configure video slave mode */
+       exynos_dp_enable_video_master(dp, 0);
+
+       /* Enable video */
+       exynos_dp_start_video(dp);
+
+       timeout_loop = 0;
+
+       for (;;) {
+               timeout_loop++;
+               if (exynos_dp_is_video_stream_on(dp) == 0) {
+                       done_count++;
+                       if (done_count > 10)
+                               break;
+               } else if (done_count) {
+                       done_count = 0;
+               }
+               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                       dev_err(dp->dev, "Timeout of video streamclk ok\n");
+                       return -ETIMEDOUT;
+               }
+
+               usleep_range(1000, 1001);
+       }
+
+       if (retval != 0)
+               dev_err(dp->dev, "Video stream is not detected!\n");
+
+       return retval;
+}
+
+static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
+{
+       u8 data;
+
+       if (enable) {
+               exynos_dp_enable_scrambling(dp);
+
+               exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       &data);
+               exynos_dp_write_byte_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
+       } else {
+               exynos_dp_disable_scrambling(dp);
+
+               exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       &data);
+               exynos_dp_write_byte_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       (u8)(data | DPCD_SCRAMBLING_DISABLED));
+       }
+}
+
+static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
+{
+       struct exynos_dp_device *dp = arg;
+
+       enum dp_irq_type irq_type;
+
+       irq_type = exynos_dp_get_irq_type(dp);
+       switch (irq_type) {
+       case DP_IRQ_TYPE_HP_CABLE_IN:
+               dev_dbg(dp->dev, "Received irq - cable in\n");
+               schedule_work(&dp->hotplug_work);
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       case DP_IRQ_TYPE_HP_CABLE_OUT:
+               dev_dbg(dp->dev, "Received irq - cable out\n");
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       case DP_IRQ_TYPE_HP_CHANGE:
+               /*
+                * We get these change notifications once in a while, but there
+                * is nothing we can do with them. Just ignore it for now and
+                * only handle cable changes.
+                */
+               dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       default:
+               dev_err(dp->dev, "Received irq - unknown type!\n");
+               break;
+       }
+       return IRQ_HANDLED;
+}
+
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+       struct exynos_dp_device *dp;
+       int ret;
+
+       dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+       ret = exynos_dp_detect_hpd(dp);
+       if (ret) {
+               /* Cable has been disconnected, we're done */
+               return;
+       }
+
+       ret = exynos_dp_handle_edid(dp);
+       if (ret) {
+               dev_err(dp->dev, "unable to handle edid\n");
+               return;
+       }
+
+       ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+                                       dp->video_info->link_rate);
+       if (ret) {
+               dev_err(dp->dev, "unable to do link train\n");
+               return;
+       }
+
+       exynos_dp_enable_scramble(dp, 1);
+       exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+       exynos_dp_enable_enhanced_mode(dp, 1);
+
+       exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+       exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+       exynos_dp_init_video(dp);
+       ret = exynos_dp_config_video(dp);
+       if (ret)
+               dev_err(dp->dev, "unable to config video\n");
+}
+
+static enum drm_connector_status exynos_dp_detect(
+                               struct drm_connector *connector, bool force)
+{
+       return connector_status_connected;
+}
+
+static void exynos_dp_connector_destroy(struct drm_connector *connector)
+{
+}
+
+static struct drm_connector_funcs exynos_dp_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = exynos_dp_detect,
+       .destroy = exynos_dp_connector_destroy,
+};
+
+static int exynos_dp_get_modes(struct drm_connector *connector)
+{
+       struct exynos_dp_device *dp = ctx_from_connector(connector);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_create(connector->dev);
+       if (!mode) {
+               DRM_ERROR("failed to create a new display mode.\n");
+               return 0;
+       }
+
+       drm_display_mode_from_videomode(&dp->panel.vm, mode);
+       mode->width_mm = dp->panel.width_mm;
+       mode->height_mm = dp->panel.height_mm;
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       drm_mode_set_name(mode);
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static int exynos_dp_mode_valid(struct drm_connector *connector,
+                       struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static struct drm_encoder *exynos_dp_best_encoder(
+                       struct drm_connector *connector)
+{
+       struct exynos_dp_device *dp = ctx_from_connector(connector);
+
+       return dp->encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
+       .get_modes = exynos_dp_get_modes,
+       .mode_valid = exynos_dp_mode_valid,
+       .best_encoder = exynos_dp_best_encoder,
+};
+
+static int exynos_dp_initialize(struct exynos_drm_display *display,
+                               struct drm_device *drm_dev)
+{
+       struct exynos_dp_device *dp = display->ctx;
+
+       dp->drm_dev = drm_dev;
+
+       return 0;
+}
+
+static bool find_bridge(const char *compat, struct bridge_init *bridge)
+{
+       bridge->client = NULL;
+       bridge->node = of_find_compatible_node(NULL, NULL, compat);
+       if (!bridge->node)
+               return false;
+
+       bridge->client = of_find_i2c_device_by_node(bridge->node);
+       if (!bridge->client)
+               return false;
+
+       return true;
+}
+
+/* returns the number of bridges attached */
+static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
+               struct drm_encoder *encoder)
+{
+       struct bridge_init bridge;
+       int ret;
+
+       if (find_bridge("nxp,ptn3460", &bridge)) {
+               ret = ptn3460_init(dev, encoder, bridge.client, bridge.node);
+               if (!ret)
+                       return 1;
+       }
+       return 0;
+}
+
+static int exynos_dp_create_connector(struct exynos_drm_display *display,
+                               struct drm_encoder *encoder)
+{
+       struct exynos_dp_device *dp = display->ctx;
+       struct drm_connector *connector = &dp->connector;
+       int ret;
+
+       dp->encoder = encoder;
+
+       /* Pre-empt DP connector creation if there's a bridge */
+       ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder);
+       if (ret)
+               return 0;
+
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       ret = drm_connector_init(dp->drm_dev, connector,
+                       &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
+               return ret;
+       }
+
+       drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
+       drm_sysfs_connector_add(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+       if (dp->phy) {
+               phy_power_on(dp->phy);
+       } else if (dp->phy_addr) {
+               u32 reg;
+
+               reg = __raw_readl(dp->phy_addr);
+               reg |= dp->enable_mask;
+               __raw_writel(reg, dp->phy_addr);
+       }
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+       if (dp->phy) {
+               phy_power_off(dp->phy);
+       } else if (dp->phy_addr) {
+               u32 reg;
+
+               reg = __raw_readl(dp->phy_addr);
+               reg &= ~(dp->enable_mask);
+               __raw_writel(reg, dp->phy_addr);
+       }
+}
+
+static void exynos_dp_poweron(struct exynos_dp_device *dp)
+{
+       if (dp->dpms_mode == DRM_MODE_DPMS_ON)
+               return;
+
+       clk_prepare_enable(dp->clock);
+       exynos_dp_phy_init(dp);
+       exynos_dp_init_dp(dp);
+       enable_irq(dp->irq);
+}
+
+static void exynos_dp_poweroff(struct exynos_dp_device *dp)
+{
+       if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+               return;
+
+       disable_irq(dp->irq);
+       flush_work(&dp->hotplug_work);
+       exynos_dp_phy_exit(dp);
+       clk_disable_unprepare(dp->clock);
+}
+
+static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
+{
+       struct exynos_dp_device *dp = display->ctx;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               exynos_dp_poweron(dp);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               exynos_dp_poweroff(dp);
+               break;
+       default:
+               break;
+       };
+       dp->dpms_mode = mode;
+}
+
+static struct exynos_drm_display_ops exynos_dp_display_ops = {
+       .initialize = exynos_dp_initialize,
+       .create_connector = exynos_dp_create_connector,
+       .dpms = exynos_dp_dpms,
+};
+
+static struct exynos_drm_display exynos_dp_display = {
+       .type = EXYNOS_DISPLAY_TYPE_LCD,
+       .ops = &exynos_dp_display_ops,
+};
+
+static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+       struct device_node *dp_node = dev->of_node;
+       struct video_info *dp_video_config;
+
+       dp_video_config = devm_kzalloc(dev,
+                               sizeof(*dp_video_config), GFP_KERNEL);
+       if (!dp_video_config) {
+               dev_err(dev, "memory allocation for video config failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       dp_video_config->h_sync_polarity =
+               of_property_read_bool(dp_node, "hsync-active-high");
+
+       dp_video_config->v_sync_polarity =
+               of_property_read_bool(dp_node, "vsync-active-high");
+
+       dp_video_config->interlaced =
+               of_property_read_bool(dp_node, "interlaced");
+
+       if (of_property_read_u32(dp_node, "samsung,color-space",
+                               &dp_video_config->color_space)) {
+               dev_err(dev, "failed to get color-space\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+                               &dp_video_config->dynamic_range)) {
+               dev_err(dev, "failed to get dynamic-range\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+                               &dp_video_config->ycbcr_coeff)) {
+               dev_err(dev, "failed to get ycbcr-coeff\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,color-depth",
+                               &dp_video_config->color_depth)) {
+               dev_err(dev, "failed to get color-depth\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,link-rate",
+                               &dp_video_config->link_rate)) {
+               dev_err(dev, "failed to get link-rate\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,lane-count",
+                               &dp_video_config->lane_count)) {
+               dev_err(dev, "failed to get lane-count\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       return dp_video_config;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+       struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
+       u32 phy_base;
+       int ret = 0;
+
+       dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
+       if (!dp_phy_node) {
+               dp->phy = devm_phy_get(dp->dev, "dp");
+               if (IS_ERR(dp->phy))
+                       return PTR_ERR(dp->phy);
+               else
+                       return 0;
+       }
+
+       if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+               dev_err(dp->dev, "failed to get reg for dptx-phy\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+                               &dp->enable_mask)) {
+               dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dp->phy_addr = ioremap(phy_base, SZ_4);
+       if (!dp->phy_addr) {
+               dev_err(dp->dev, "failed to ioremap dp-phy\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+err:
+       of_node_put(dp_phy_node);
+
+       return ret;
+}
+
+static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
+{
+       int ret;
+
+       ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm,
+                       OF_USE_NATIVE_MODE);
+       if (ret) {
+               DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+static int exynos_dp_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct exynos_dp_device *dp;
+
+       int ret = 0;
+
+       dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+                               GFP_KERNEL);
+       if (!dp) {
+               dev_err(&pdev->dev, "no memory for device data\n");
+               return -ENOMEM;
+       }
+
+       dp->dev = &pdev->dev;
+       dp->dpms_mode = DRM_MODE_DPMS_OFF;
+
+       dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
+       if (IS_ERR(dp->video_info))
+               return PTR_ERR(dp->video_info);
+
+       ret = exynos_dp_dt_parse_phydata(dp);
+       if (ret)
+               return ret;
+
+       ret = exynos_dp_dt_parse_panel(dp);
+       if (ret)
+               return ret;
+
+       dp->clock = devm_clk_get(&pdev->dev, "dp");
+       if (IS_ERR(dp->clock)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               return PTR_ERR(dp->clock);
+       }
+
+       clk_prepare_enable(dp->clock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(dp->reg_base))
+               return PTR_ERR(dp->reg_base);
+
+       dp->irq = platform_get_irq(pdev, 0);
+       if (dp->irq == -ENXIO) {
+               dev_err(&pdev->dev, "failed to get irq\n");
+               return -ENODEV;
+       }
+
+       INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
+
+       exynos_dp_phy_init(dp);
+
+       exynos_dp_init_dp(dp);
+
+       ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+                               "exynos-dp", dp);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request irq\n");
+               return ret;
+       }
+       disable_irq(dp->irq);
+
+       exynos_dp_display.ctx = dp;
+
+       platform_set_drvdata(pdev, &exynos_dp_display);
+       exynos_drm_display_register(&exynos_dp_display);
+
+       return 0;
+}
+
+static int exynos_dp_remove(struct platform_device *pdev)
+{
+       struct exynos_drm_display *display = platform_get_drvdata(pdev);
+
+       exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
+       exynos_drm_display_unregister(&exynos_dp_display);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_dp_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct exynos_drm_display *display = platform_get_drvdata(pdev);
+
+       exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
+       return 0;
+}
+
+static int exynos_dp_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct exynos_drm_display *display = platform_get_drvdata(pdev);
+
+       exynos_dp_dpms(display, DRM_MODE_DPMS_ON);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_dp_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
+};
+
+static const struct of_device_id exynos_dp_match[] = {
+       { .compatible = "samsung,exynos5-dp" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
+struct platform_driver dp_driver = {
+       .probe          = exynos_dp_probe,
+       .remove         = exynos_dp_remove,
+       .driver         = {
+               .name   = "exynos-dp",
+               .owner  = THIS_MODULE,
+               .pm     = &exynos_dp_pm_ops,
+               .of_match_table = exynos_dp_match,
+       },
+};
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DP Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
new file mode 100644 (file)
index 0000000..d6a900d
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Header file for Samsung DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _EXYNOS_DP_CORE_H
+#define _EXYNOS_DP_CORE_H
+
+#include <drm/drm_crtc.h>
+#include <drm/exynos_drm.h>
+
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+enum link_rate_type {
+       LINK_RATE_1_62GBPS = 0x06,
+       LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+       LANE_COUNT1 = 1,
+       LANE_COUNT2 = 2,
+       LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+       START,
+       CLOCK_RECOVERY,
+       EQUALIZER_TRAINING,
+       FINISHED,
+       FAILED
+};
+
+enum voltage_swing_level {
+       VOLTAGE_LEVEL_0,
+       VOLTAGE_LEVEL_1,
+       VOLTAGE_LEVEL_2,
+       VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+       PRE_EMPHASIS_LEVEL_0,
+       PRE_EMPHASIS_LEVEL_1,
+       PRE_EMPHASIS_LEVEL_2,
+       PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+       PRBS7,
+       D10_2,
+       TRAINING_PTN1,
+       TRAINING_PTN2,
+       DP_NONE
+};
+
+enum color_space {
+       COLOR_RGB,
+       COLOR_YCBCR422,
+       COLOR_YCBCR444
+};
+
+enum color_depth {
+       COLOR_6,
+       COLOR_8,
+       COLOR_10,
+       COLOR_12
+};
+
+enum color_coefficient {
+       COLOR_YCBCR601,
+       COLOR_YCBCR709
+};
+
+enum dynamic_range {
+       VESA,
+       CEA
+};
+
+enum pll_status {
+       PLL_UNLOCKED,
+       PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+       CALCULATED_M,
+       REGISTER_M
+};
+
+enum video_timing_recognition_type {
+       VIDEO_TIMING_FROM_CAPTURE,
+       VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+       AUX_BLOCK,
+       CH0_BLOCK,
+       CH1_BLOCK,
+       CH2_BLOCK,
+       CH3_BLOCK,
+       ANALOG_TOTAL,
+       POWER_ALL
+};
+
+enum dp_irq_type {
+       DP_IRQ_TYPE_HP_CABLE_IN,
+       DP_IRQ_TYPE_HP_CABLE_OUT,
+       DP_IRQ_TYPE_HP_CHANGE,
+       DP_IRQ_TYPE_UNKNOWN,
+};
+
+struct video_info {
+       char *name;
+
+       bool h_sync_polarity;
+       bool v_sync_polarity;
+       bool interlaced;
+
+       enum color_space color_space;
+       enum dynamic_range dynamic_range;
+       enum color_coefficient ycbcr_coeff;
+       enum color_depth color_depth;
+
+       enum link_rate_type link_rate;
+       enum link_lane_count_type lane_count;
+};
+
+struct link_train {
+       int eq_loop;
+       int cr_loop[4];
+
+       u8 link_rate;
+       u8 lane_count;
+       u8 training_lane[4];
+
+       enum link_training_state lt_state;
+};
+
+struct exynos_dp_device {
+       struct device           *dev;
+       struct drm_device       *drm_dev;
+       struct drm_connector    connector;
+       struct drm_encoder      *encoder;
+       struct clk              *clock;
+       unsigned int            irq;
+       void __iomem            *reg_base;
+       void __iomem            *phy_addr;
+       unsigned int            enable_mask;
+
+       struct video_info       *video_info;
+       struct link_train       link_train;
+       struct work_struct      hotplug_work;
+       struct phy              *phy;
+       int                     dpms_mode;
+
+       struct exynos_drm_panel_info panel;
+};
+
+/* exynos_dp_reg.c */
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_stop_video(struct exynos_dp_device *dp);
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
+void exynos_dp_reset(struct exynos_dp_device *dp);
+void exynos_dp_swreset(struct exynos_dp_device *dp);
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+                               enum analog_power_block block,
+                               bool enable);
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
+void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
+void exynos_dp_reset_aux(struct exynos_dp_device *dp);
+void exynos_dp_init_aux(struct exynos_dp_device *dp);
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned char data);
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned char *data);
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char data[]);
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char data[]);
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr);
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr,
+                               unsigned int *data);
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char edid[]);
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+                                enum pattern_set pattern);
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+                               u32 training_lane);
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+                               u32 training_lane);
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+                               u32 training_lane);
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+                               u32 training_lane);
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
+void exynos_dp_reset_macro(struct exynos_dp_device *dp);
+void exynos_dp_init_video(struct exynos_dp_device *dp);
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+                       enum clock_recovery_m_value_type type,
+                       u32 m_value,
+                       u32 n_value);
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_start_video(struct exynos_dp_device *dp);
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
+
+/* I2C EDID Chip ID, Slave Address */
+#define I2C_EDID_DEVICE_ADDR                   0x50
+#define I2C_E_EDID_DEVICE_ADDR                 0x30
+
+#define EDID_BLOCK_LENGTH                      0x80
+#define EDID_HEADER_PATTERN                    0x00
+#define EDID_EXTENSION_FLAG                    0x7e
+#define EDID_CHECKSUM                          0x7f
+
+/* Definition for DPCD Register */
+#define DPCD_ADDR_DPCD_REV                     0x0000
+#define DPCD_ADDR_MAX_LINK_RATE                        0x0001
+#define DPCD_ADDR_MAX_LANE_COUNT               0x0002
+#define DPCD_ADDR_LINK_BW_SET                  0x0100
+#define DPCD_ADDR_LANE_COUNT_SET               0x0101
+#define DPCD_ADDR_TRAINING_PATTERN_SET         0x0102
+#define DPCD_ADDR_TRAINING_LANE0_SET           0x0103
+#define DPCD_ADDR_LANE0_1_STATUS               0x0202
+#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED    0x0204
+#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1       0x0206
+#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3       0x0207
+#define DPCD_ADDR_TEST_REQUEST                 0x0218
+#define DPCD_ADDR_TEST_RESPONSE                        0x0260
+#define DPCD_ADDR_TEST_EDID_CHECKSUM           0x0261
+#define DPCD_ADDR_SINK_POWER_STATE             0x0600
+
+/* DPCD_ADDR_MAX_LANE_COUNT */
+#define DPCD_ENHANCED_FRAME_CAP(x)             (((x) >> 7) & 0x1)
+#define DPCD_MAX_LANE_COUNT(x)                 ((x) & 0x1f)
+
+/* DPCD_ADDR_LANE_COUNT_SET */
+#define DPCD_ENHANCED_FRAME_EN                 (0x1 << 7)
+#define DPCD_LANE_COUNT_SET(x)                 ((x) & 0x1f)
+
+/* DPCD_ADDR_TRAINING_PATTERN_SET */
+#define DPCD_SCRAMBLING_DISABLED               (0x1 << 5)
+#define DPCD_SCRAMBLING_ENABLED                        (0x0 << 5)
+#define DPCD_TRAINING_PATTERN_2                        (0x2 << 0)
+#define DPCD_TRAINING_PATTERN_1                        (0x1 << 0)
+#define DPCD_TRAINING_PATTERN_DISABLED         (0x0 << 0)
+
+/* DPCD_ADDR_TRAINING_LANE0_SET */
+#define DPCD_MAX_PRE_EMPHASIS_REACHED          (0x1 << 5)
+#define DPCD_PRE_EMPHASIS_SET(x)               (((x) & 0x3) << 3)
+#define DPCD_PRE_EMPHASIS_GET(x)               (((x) >> 3) & 0x3)
+#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0      (0x0 << 3)
+#define DPCD_MAX_SWING_REACHED                 (0x1 << 2)
+#define DPCD_VOLTAGE_SWING_SET(x)              (((x) & 0x3) << 0)
+#define DPCD_VOLTAGE_SWING_GET(x)              (((x) >> 0) & 0x3)
+#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0     (0x0 << 0)
+
+/* DPCD_ADDR_LANE0_1_STATUS */
+#define DPCD_LANE_SYMBOL_LOCKED                        (0x1 << 2)
+#define DPCD_LANE_CHANNEL_EQ_DONE              (0x1 << 1)
+#define DPCD_LANE_CR_DONE                      (0x1 << 0)
+#define DPCD_CHANNEL_EQ_BITS                   (DPCD_LANE_CR_DONE|     \
+                                                DPCD_LANE_CHANNEL_EQ_DONE|\
+                                                DPCD_LANE_SYMBOL_LOCKED)
+
+/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
+#define DPCD_LINK_STATUS_UPDATED               (0x1 << 7)
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED    (0x1 << 6)
+#define DPCD_INTERLANE_ALIGN_DONE              (0x1 << 0)
+
+/* DPCD_ADDR_TEST_REQUEST */
+#define DPCD_TEST_EDID_READ                    (0x1 << 2)
+
+/* DPCD_ADDR_TEST_RESPONSE */
+#define DPCD_TEST_EDID_CHECKSUM_WRITE          (0x1 << 2)
+
+/* DPCD_ADDR_SINK_POWER_STATE */
+#define DPCD_SET_POWER_STATE_D0                        (0x1 << 0)
+#define DPCD_SET_POWER_STATE_D4                        (0x2 << 0)
+
+#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c
new file mode 100644 (file)
index 0000000..b70da50
--- /dev/null
@@ -0,0 +1,1243 @@
+/*
+ * Samsung DP (Display port) register interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "exynos_dp_core.h"
+#include "exynos_dp_reg.h"
+
+#define COMMON_INT_MASK_1      0
+#define COMMON_INT_MASK_2      0
+#define COMMON_INT_MASK_3      0
+#define COMMON_INT_MASK_4      (HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK           INT_HPD
+
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
+{
+       u32 reg;
+
+       if (enable) {
+               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+               reg |= HDCP_VIDEO_MUTE;
+               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+       } else {
+               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+               reg &= ~HDCP_VIDEO_MUTE;
+               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+       }
+}
+
+void exynos_dp_stop_video(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+       reg &= ~VIDEO_EN;
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
+{
+       u32 reg;
+
+       if (enable)
+               reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
+                       LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
+       else
+               reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
+                       LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
+
+       writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
+}
+
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = TX_TERMINAL_CTRL_50_OHM;
+       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
+
+       reg = SEL_24M | TX_DVDD_BIT_1_0625V;
+       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
+
+       reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
+       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
+
+       reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
+               TX_CUR1_2X | TX_CUR_16_MA;
+       writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
+
+       reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
+               CH1_AMP_400_MV | CH0_AMP_400_MV;
+       writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
+}
+
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
+{
+       /* Set interrupt pin assertion polarity as high */
+       writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
+
+       /* Clear pending regisers */
+       writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+       writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
+       writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
+       writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+       writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
+
+       /* 0:mask,1: unmask */
+       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+       writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+void exynos_dp_reset(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       exynos_dp_stop_video(dp);
+       exynos_dp_enable_video_mute(dp, 0);
+
+       reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
+               AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
+               HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+       reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
+               SERDES_FIFO_FUNC_EN_N |
+               LS_CLK_DOMAIN_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+
+       usleep_range(20, 30);
+
+       exynos_dp_lane_swap(dp, 0);
+
+       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+       writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+       writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
+       writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
+
+       writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
+       writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
+
+       writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
+
+       writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+       writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
+       writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
+
+       writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
+       writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
+
+       writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_swreset(struct exynos_dp_device *dp)
+{
+       writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
+}
+
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* 0: mask, 1: unmask */
+       reg = COMMON_INT_MASK_1;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+
+       reg = COMMON_INT_MASK_2;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+
+       reg = COMMON_INT_MASK_3;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+
+       reg = COMMON_INT_MASK_4;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+
+       reg = INT_STA_MASK;
+       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+       if (reg & PLL_LOCK)
+               return PLL_LOCKED;
+       else
+               return PLL_UNLOCKED;
+}
+
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
+{
+       u32 reg;
+
+       if (enable) {
+               reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+               reg |= DP_PLL_PD;
+               writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+       } else {
+               reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+               reg &= ~DP_PLL_PD;
+               writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+       }
+}
+
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+                               enum analog_power_block block,
+                               bool enable)
+{
+       u32 reg;
+
+       switch (block) {
+       case AUX_BLOCK:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= AUX_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~AUX_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case CH0_BLOCK:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= CH0_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~CH0_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case CH1_BLOCK:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= CH1_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~CH1_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case CH2_BLOCK:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= CH2_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~CH2_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case CH3_BLOCK:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= CH3_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~CH3_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case ANALOG_TOTAL:
+               if (enable) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg |= DP_PHY_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+                       reg &= ~DP_PHY_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       case POWER_ALL:
+               if (enable) {
+                       reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
+                               CH1_PD | CH0_PD;
+                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+               } else {
+                       writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
+{
+       u32 reg;
+       int timeout_loop = 0;
+
+       exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+
+       reg = PLL_LOCK_CHG;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+       reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
+       writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+
+       /* Power up PLL */
+       if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+               exynos_dp_set_pll_power_down(dp, 0);
+
+               while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+                       timeout_loop++;
+                       if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                               dev_err(dp->dev, "failed to get pll lock status\n");
+                               return;
+                       }
+                       usleep_range(10, 20);
+               }
+       }
+
+       /* Enable Serdes FIFO function and Link symbol clock domain module */
+       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+       reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
+               | AUX_FUNC_EN_N);
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = HOTPLUG_CHG | HPD_LOST | PLUG;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+       reg = INT_HPD;
+       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       exynos_dp_clear_hotplug_interrupts(dp);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+       reg &= ~(F_HPD | HPD_CTRL);
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+}
+
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* Parse hotplug interrupt status register */
+       reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+       if (reg & PLUG)
+               return DP_IRQ_TYPE_HP_CABLE_IN;
+
+       if (reg & HPD_LOST)
+               return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+       if (reg & HOTPLUG_CHG)
+               return DP_IRQ_TYPE_HP_CHANGE;
+
+       return DP_IRQ_TYPE_UNKNOWN;
+}
+
+void exynos_dp_reset_aux(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* Disable AUX channel module */
+       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+       reg |= AUX_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_init_aux(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* Clear inerrupts related to AUX channel */
+       reg = RPLY_RECEIV | AUX_ERR;
+       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+
+       exynos_dp_reset_aux(dp);
+
+       /* Disable AUX transaction H/W retry */
+       reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
+               AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+       writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
+
+       /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+       reg = DEFER_CTRL_EN | DEFER_COUNT(1);
+       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
+
+       /* Enable AUX channel module */
+       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+       reg &= ~AUX_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+       if (reg & HPD_STATUS)
+               return 0;
+
+       return -EINVAL;
+}
+
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+       reg &= ~SW_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+}
+
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
+{
+       int reg;
+       int retval = 0;
+       int timeout_loop = 0;
+
+       /* Enable AUX CH operation */
+       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+       reg |= AUX_EN;
+       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+       /* Is AUX CH command reply received? */
+       reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+       while (!(reg & RPLY_RECEIV)) {
+               timeout_loop++;
+               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                       dev_err(dp->dev, "AUX CH command reply failed!\n");
+                       return -ETIMEDOUT;
+               }
+               reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+               usleep_range(10, 11);
+       }
+
+       /* Clear interrupt source for AUX CH command reply */
+       writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
+
+       /* Clear interrupt source for AUX CH access error */
+       reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+       if (reg & AUX_ERR) {
+               writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
+               return -EREMOTEIO;
+       }
+
+       /* Check AUX CH error access status */
+       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
+       if ((reg & AUX_STATUS_MASK) != 0) {
+               dev_err(dp->dev, "AUX CH error happens: %d\n\n",
+                       reg & AUX_STATUS_MASK);
+               return -EREMOTEIO;
+       }
+
+       return retval;
+}
+
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned char data)
+{
+       u32 reg;
+       int i;
+       int retval;
+
+       for (i = 0; i < 3; i++) {
+               /* Clear AUX CH data buffer */
+               reg = BUF_CLR;
+               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+               /* Select DPCD device address */
+               reg = AUX_ADDR_7_0(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+               reg = AUX_ADDR_15_8(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+               reg = AUX_ADDR_19_16(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+               /* Write data buffer */
+               reg = (unsigned int)data;
+               writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+               /*
+                * Set DisplayPort transaction and write 1 byte
+                * If bit 3 is 1, DisplayPort transaction.
+                * If Bit 3 is 0, I2C transaction.
+                */
+               reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+               /* Start AUX transaction */
+               retval = exynos_dp_start_aux_transaction(dp);
+               if (retval == 0)
+                       break;
+               else
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
+       }
+
+       return retval;
+}
+
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned char *data)
+{
+       u32 reg;
+       int i;
+       int retval;
+
+       for (i = 0; i < 3; i++) {
+               /* Clear AUX CH data buffer */
+               reg = BUF_CLR;
+               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+               /* Select DPCD device address */
+               reg = AUX_ADDR_7_0(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+               reg = AUX_ADDR_15_8(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+               reg = AUX_ADDR_19_16(reg_addr);
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+               /*
+                * Set DisplayPort transaction and read 1 byte
+                * If bit 3 is 1, DisplayPort transaction.
+                * If Bit 3 is 0, I2C transaction.
+                */
+               reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+               /* Start AUX transaction */
+               retval = exynos_dp_start_aux_transaction(dp);
+               if (retval == 0)
+                       break;
+               else
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
+       }
+
+       /* Read data buffer */
+       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+       *data = (unsigned char)(reg & 0xff);
+
+       return retval;
+}
+
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char data[])
+{
+       u32 reg;
+       unsigned int start_offset;
+       unsigned int cur_data_count;
+       unsigned int cur_data_idx;
+       int i;
+       int retval = 0;
+
+       /* Clear AUX CH data buffer */
+       reg = BUF_CLR;
+       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+       start_offset = 0;
+       while (start_offset < count) {
+               /* Buffer size of AUX CH is 16 * 4bytes */
+               if ((count - start_offset) > 16)
+                       cur_data_count = 16;
+               else
+                       cur_data_count = count - start_offset;
+
+               for (i = 0; i < 3; i++) {
+                       /* Select DPCD device address */
+                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+                       for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+                            cur_data_idx++) {
+                               reg = data[start_offset + cur_data_idx];
+                               writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
+                                                         + 4 * cur_data_idx);
+                       }
+
+                       /*
+                        * Set DisplayPort transaction and write
+                        * If bit 3 is 1, DisplayPort transaction.
+                        * If Bit 3 is 0, I2C transaction.
+                        */
+                       reg = AUX_LENGTH(cur_data_count) |
+                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+                       /* Start AUX transaction */
+                       retval = exynos_dp_start_aux_transaction(dp);
+                       if (retval == 0)
+                               break;
+                       else
+                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                                       __func__);
+               }
+
+               start_offset += cur_data_count;
+       }
+
+       return retval;
+}
+
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char data[])
+{
+       u32 reg;
+       unsigned int start_offset;
+       unsigned int cur_data_count;
+       unsigned int cur_data_idx;
+       int i;
+       int retval = 0;
+
+       /* Clear AUX CH data buffer */
+       reg = BUF_CLR;
+       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+       start_offset = 0;
+       while (start_offset < count) {
+               /* Buffer size of AUX CH is 16 * 4bytes */
+               if ((count - start_offset) > 16)
+                       cur_data_count = 16;
+               else
+                       cur_data_count = count - start_offset;
+
+               /* AUX CH Request Transaction process */
+               for (i = 0; i < 3; i++) {
+                       /* Select DPCD device address */
+                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+                       /*
+                        * Set DisplayPort transaction and read
+                        * If bit 3 is 1, DisplayPort transaction.
+                        * If Bit 3 is 0, I2C transaction.
+                        */
+                       reg = AUX_LENGTH(cur_data_count) |
+                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+                       /* Start AUX transaction */
+                       retval = exynos_dp_start_aux_transaction(dp);
+                       if (retval == 0)
+                               break;
+                       else
+                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                                       __func__);
+               }
+
+               for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+                   cur_data_idx++) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+                                                + 4 * cur_data_idx);
+                       data[start_offset + cur_data_idx] =
+                               (unsigned char)reg;
+               }
+
+               start_offset += cur_data_count;
+       }
+
+       return retval;
+}
+
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr)
+{
+       u32 reg;
+       int retval;
+
+       /* Set EDID device address */
+       reg = device_addr;
+       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+       writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+       writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+       /* Set offset from base address of EDID device */
+       writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+       /*
+        * Set I2C transaction and write address
+        * If bit 3 is 1, DisplayPort transaction.
+        * If Bit 3 is 0, I2C transaction.
+        */
+       reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
+               AUX_TX_COMM_WRITE;
+       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+       /* Start AUX transaction */
+       retval = exynos_dp_start_aux_transaction(dp);
+       if (retval != 0)
+               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+
+       return retval;
+}
+
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr,
+                               unsigned int *data)
+{
+       u32 reg;
+       int i;
+       int retval;
+
+       for (i = 0; i < 3; i++) {
+               /* Clear AUX CH data buffer */
+               reg = BUF_CLR;
+               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+               /* Select EDID device */
+               retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
+               if (retval != 0)
+                       continue;
+
+               /*
+                * Set I2C transaction and read data
+                * If bit 3 is 1, DisplayPort transaction.
+                * If Bit 3 is 0, I2C transaction.
+                */
+               reg = AUX_TX_COMM_I2C_TRANSACTION |
+                       AUX_TX_COMM_READ;
+               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+               /* Start AUX transaction */
+               retval = exynos_dp_start_aux_transaction(dp);
+               if (retval == 0)
+                       break;
+               else
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
+       }
+
+       /* Read data */
+       if (retval == 0)
+               *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+       return retval;
+}
+
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+                               unsigned int device_addr,
+                               unsigned int reg_addr,
+                               unsigned int count,
+                               unsigned char edid[])
+{
+       u32 reg;
+       unsigned int i, j;
+       unsigned int cur_data_idx;
+       unsigned int defer = 0;
+       int retval = 0;
+
+       for (i = 0; i < count; i += 16) {
+               for (j = 0; j < 3; j++) {
+                       /* Clear AUX CH data buffer */
+                       reg = BUF_CLR;
+                       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+                       /* Set normal AUX CH command */
+                       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+                       reg &= ~ADDR_ONLY;
+                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+                       /*
+                        * If Rx sends defer, Tx sends only reads
+                        * request without sending address
+                        */
+                       if (!defer)
+                               retval = exynos_dp_select_i2c_device(dp,
+                                               device_addr, reg_addr + i);
+                       else
+                               defer = 0;
+
+                       if (retval == 0) {
+                               /*
+                                * Set I2C transaction and write data
+                                * If bit 3 is 1, DisplayPort transaction.
+                                * If Bit 3 is 0, I2C transaction.
+                                */
+                               reg = AUX_LENGTH(16) |
+                                       AUX_TX_COMM_I2C_TRANSACTION |
+                                       AUX_TX_COMM_READ;
+                               writel(reg, dp->reg_base +
+                                       EXYNOS_DP_AUX_CH_CTL_1);
+
+                               /* Start AUX transaction */
+                               retval = exynos_dp_start_aux_transaction(dp);
+                               if (retval == 0)
+                                       break;
+                               else
+                                       dev_dbg(dp->dev,
+                                               "%s: Aux Transaction fail!\n",
+                                               __func__);
+                       }
+                       /* Check if Rx sends defer */
+                       reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
+                       if (reg == AUX_RX_COMM_AUX_DEFER ||
+                               reg == AUX_RX_COMM_I2C_DEFER) {
+                               dev_err(dp->dev, "Defer: %d\n\n", reg);
+                               defer = 1;
+                       }
+               }
+
+               for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+                       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+                                                + 4 * cur_data_idx);
+                       edid[i + cur_data_idx] = (unsigned char)reg;
+               }
+       }
+
+       return retval;
+}
+
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
+{
+       u32 reg;
+
+       reg = bwtype;
+       if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
+               writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+}
+
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+       *bwtype = reg;
+}
+
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
+{
+       u32 reg;
+
+       reg = count;
+       writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+}
+
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+       *count = reg;
+}
+
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
+{
+       u32 reg;
+
+       if (enable) {
+               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+               reg |= ENHANCED;
+               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+       } else {
+               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+               reg &= ~ENHANCED;
+               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+       }
+}
+
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+                                enum pattern_set pattern)
+{
+       u32 reg;
+
+       switch (pattern) {
+       case PRBS7:
+               reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
+               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+               break;
+       case D10_2:
+               reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
+               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+               break;
+       case TRAINING_PTN1:
+               reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
+               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+               break;
+       case TRAINING_PTN2:
+               reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
+               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+               break;
+       case DP_NONE:
+               reg = SCRAMBLING_ENABLE |
+                       LINK_QUAL_PATTERN_SET_DISABLE |
+                       SW_TRAINING_PATTERN_SET_NORMAL;
+               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+               break;
+       default:
+               break;
+       }
+}
+
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+                                       u32 training_lane)
+{
+       u32 reg;
+
+       reg = training_lane;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+                                       u32 training_lane)
+{
+       u32 reg;
+
+       reg = training_lane;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+                                       u32 training_lane)
+{
+       u32 reg;
+
+       reg = training_lane;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+                                       u32 training_lane)
+{
+       u32 reg;
+
+       reg = training_lane;
+       writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+       return reg;
+}
+
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+       return reg;
+}
+
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+       return reg;
+}
+
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+       return reg;
+}
+
+void exynos_dp_reset_macro(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
+       reg |= MACRO_RST;
+       writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+       /* 10 us is the minimum reset time. */
+       usleep_range(10, 20);
+
+       reg &= ~MACRO_RST;
+       writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+}
+
+void exynos_dp_init_video(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
+       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+       reg = 0x0;
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+       reg = CHA_CRI(4) | CHA_CTRL;
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+       reg = 0x0;
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+       reg = VID_HRES_TH(2) | VID_VRES_TH(0);
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
+}
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* Configure the input color depth, color space, dynamic range */
+       reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+               (dp->video_info->color_depth << IN_BPC_SHIFT) |
+               (dp->video_info->color_space << IN_COLOR_F_SHIFT);
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
+
+       /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+       reg &= ~IN_YC_COEFFI_MASK;
+       if (dp->video_info->ycbcr_coeff)
+               reg |= IN_YC_COEFFI_ITU709;
+       else
+               reg |= IN_YC_COEFFI_ITU601;
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+}
+
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+       if (!(reg & DET_STA)) {
+               dev_dbg(dp->dev, "Input stream clock not detected.\n");
+               return -EINVAL;
+       }
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+       dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
+
+       if (reg & CHA_STA) {
+               dev_dbg(dp->dev, "Input stream clk is changing\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+               enum clock_recovery_m_value_type type,
+               u32 m_value,
+               u32 n_value)
+{
+       u32 reg;
+
+       if (type == REGISTER_M) {
+               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+               reg |= FIX_M_VID;
+               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+               reg = m_value & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
+               reg = (m_value >> 8) & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
+               reg = (m_value >> 16) & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
+
+               reg = n_value & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
+               reg = (n_value >> 8) & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
+               reg = (n_value >> 16) & 0xff;
+               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
+       } else  {
+               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+               reg &= ~FIX_M_VID;
+               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+               writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
+               writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
+               writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
+       }
+}
+
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
+{
+       u32 reg;
+
+       if (type == VIDEO_TIMING_FROM_CAPTURE) {
+               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+               reg &= ~FORMAT_SEL;
+               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+       } else {
+               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+               reg |= FORMAT_SEL;
+               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+       }
+}
+
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
+{
+       u32 reg;
+
+       if (enable) {
+               reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+               reg &= ~VIDEO_MODE_MASK;
+               reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
+               writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+       } else {
+               reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+               reg &= ~VIDEO_MODE_MASK;
+               reg |= VIDEO_MODE_SLAVE_MODE;
+               writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+       }
+}
+
+void exynos_dp_start_video(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+       reg |= VIDEO_EN;
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+       if (!(reg & STRM_VALID)) {
+               dev_dbg(dp->dev, "Input video stream is not detected.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+       reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
+       reg |= MASTER_VID_FUNC_EN_N;
+       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+       reg &= ~INTERACE_SCAN_CFG;
+       reg |= (dp->video_info->interlaced << 2);
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+       reg &= ~VSYNC_POLARITY_CFG;
+       reg |= (dp->video_info->v_sync_polarity << 1);
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+       reg &= ~HSYNC_POLARITY_CFG;
+       reg |= (dp->video_info->h_sync_polarity << 0);
+       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+       reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
+       writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+       reg &= ~SCRAMBLING_DISABLE;
+       writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
+
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+       reg |= SCRAMBLING_DISABLE;
+       writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h b/drivers/gpu/drm/exynos/exynos_dp_reg.h
new file mode 100644 (file)
index 0000000..2e9bd0e
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Register definition file for Samsung DP driver
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _EXYNOS_DP_REG_H
+#define _EXYNOS_DP_REG_H
+
+#define EXYNOS_DP_TX_SW_RESET                  0x14
+#define EXYNOS_DP_FUNC_EN_1                    0x18
+#define EXYNOS_DP_FUNC_EN_2                    0x1C
+#define EXYNOS_DP_VIDEO_CTL_1                  0x20
+#define EXYNOS_DP_VIDEO_CTL_2                  0x24
+#define EXYNOS_DP_VIDEO_CTL_3                  0x28
+
+#define EXYNOS_DP_VIDEO_CTL_8                  0x3C
+#define EXYNOS_DP_VIDEO_CTL_10                 0x44
+
+#define EXYNOS_DP_LANE_MAP                     0x35C
+
+#define EXYNOS_DP_ANALOG_CTL_1                 0x370
+#define EXYNOS_DP_ANALOG_CTL_2                 0x374
+#define EXYNOS_DP_ANALOG_CTL_3                 0x378
+#define EXYNOS_DP_PLL_FILTER_CTL_1             0x37C
+#define EXYNOS_DP_TX_AMP_TUNING_CTL            0x380
+
+#define EXYNOS_DP_AUX_HW_RETRY_CTL             0x390
+
+#define EXYNOS_DP_COMMON_INT_STA_1             0x3C4
+#define EXYNOS_DP_COMMON_INT_STA_2             0x3C8
+#define EXYNOS_DP_COMMON_INT_STA_3             0x3CC
+#define EXYNOS_DP_COMMON_INT_STA_4             0x3D0
+#define EXYNOS_DP_INT_STA                      0x3DC
+#define EXYNOS_DP_COMMON_INT_MASK_1            0x3E0
+#define EXYNOS_DP_COMMON_INT_MASK_2            0x3E4
+#define EXYNOS_DP_COMMON_INT_MASK_3            0x3E8
+#define EXYNOS_DP_COMMON_INT_MASK_4            0x3EC
+#define EXYNOS_DP_INT_STA_MASK                 0x3F8
+#define EXYNOS_DP_INT_CTL                      0x3FC
+
+#define EXYNOS_DP_SYS_CTL_1                    0x600
+#define EXYNOS_DP_SYS_CTL_2                    0x604
+#define EXYNOS_DP_SYS_CTL_3                    0x608
+#define EXYNOS_DP_SYS_CTL_4                    0x60C
+
+#define EXYNOS_DP_PKT_SEND_CTL                 0x640
+#define EXYNOS_DP_HDCP_CTL                     0x648
+
+#define EXYNOS_DP_LINK_BW_SET                  0x680
+#define EXYNOS_DP_LANE_COUNT_SET               0x684
+#define EXYNOS_DP_TRAINING_PTN_SET             0x688
+#define EXYNOS_DP_LN0_LINK_TRAINING_CTL                0x68C
+#define EXYNOS_DP_LN1_LINK_TRAINING_CTL                0x690
+#define EXYNOS_DP_LN2_LINK_TRAINING_CTL                0x694
+#define EXYNOS_DP_LN3_LINK_TRAINING_CTL                0x698
+
+#define EXYNOS_DP_DEBUG_CTL                    0x6C0
+#define EXYNOS_DP_HPD_DEGLITCH_L               0x6C4
+#define EXYNOS_DP_HPD_DEGLITCH_H               0x6C8
+#define EXYNOS_DP_LINK_DEBUG_CTL               0x6E0
+
+#define EXYNOS_DP_M_VID_0                      0x700
+#define EXYNOS_DP_M_VID_1                      0x704
+#define EXYNOS_DP_M_VID_2                      0x708
+#define EXYNOS_DP_N_VID_0                      0x70C
+#define EXYNOS_DP_N_VID_1                      0x710
+#define EXYNOS_DP_N_VID_2                      0x714
+
+#define EXYNOS_DP_PLL_CTL                      0x71C
+#define EXYNOS_DP_PHY_PD                       0x720
+#define EXYNOS_DP_PHY_TEST                     0x724
+
+#define EXYNOS_DP_VIDEO_FIFO_THRD              0x730
+#define EXYNOS_DP_AUDIO_MARGIN                 0x73C
+
+#define EXYNOS_DP_M_VID_GEN_FILTER_TH          0x764
+#define EXYNOS_DP_M_AUD_GEN_FILTER_TH          0x778
+#define EXYNOS_DP_AUX_CH_STA                   0x780
+#define EXYNOS_DP_AUX_CH_DEFER_CTL             0x788
+#define EXYNOS_DP_AUX_RX_COMM                  0x78C
+#define EXYNOS_DP_BUFFER_DATA_CTL              0x790
+#define EXYNOS_DP_AUX_CH_CTL_1                 0x794
+#define EXYNOS_DP_AUX_ADDR_7_0                 0x798
+#define EXYNOS_DP_AUX_ADDR_15_8                        0x79C
+#define EXYNOS_DP_AUX_ADDR_19_16               0x7A0
+#define EXYNOS_DP_AUX_CH_CTL_2                 0x7A4
+
+#define EXYNOS_DP_BUF_DATA_0                   0x7C0
+
+#define EXYNOS_DP_SOC_GENERAL_CTL              0x800
+
+/* EXYNOS_DP_TX_SW_RESET */
+#define RESET_DP_TX                            (0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_1 */
+#define MASTER_VID_FUNC_EN_N                   (0x1 << 7)
+#define SLAVE_VID_FUNC_EN_N                    (0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N                     (0x1 << 4)
+#define AUD_FUNC_EN_N                          (0x1 << 3)
+#define HDCP_FUNC_EN_N                         (0x1 << 2)
+#define CRC_FUNC_EN_N                          (0x1 << 1)
+#define SW_FUNC_EN_N                           (0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_2 */
+#define SSC_FUNC_EN_N                          (0x1 << 7)
+#define AUX_FUNC_EN_N                          (0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N                  (0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N                        (0x1 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define VIDEO_EN                               (0x1 << 7)
+#define HDCP_VIDEO_MUTE                                (0x1 << 6)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define IN_D_RANGE_MASK                                (0x1 << 7)
+#define IN_D_RANGE_SHIFT                       (7)
+#define IN_D_RANGE_CEA                         (0x1 << 7)
+#define IN_D_RANGE_VESA                                (0x0 << 7)
+#define IN_BPC_MASK                            (0x7 << 4)
+#define IN_BPC_SHIFT                           (4)
+#define IN_BPC_12_BITS                         (0x3 << 4)
+#define IN_BPC_10_BITS                         (0x2 << 4)
+#define IN_BPC_8_BITS                          (0x1 << 4)
+#define IN_BPC_6_BITS                          (0x0 << 4)
+#define IN_COLOR_F_MASK                                (0x3 << 0)
+#define IN_COLOR_F_SHIFT                       (0)
+#define IN_COLOR_F_YCBCR444                    (0x2 << 0)
+#define IN_COLOR_F_YCBCR422                    (0x1 << 0)
+#define IN_COLOR_F_RGB                         (0x0 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_3 */
+#define IN_YC_COEFFI_MASK                      (0x1 << 7)
+#define IN_YC_COEFFI_SHIFT                     (7)
+#define IN_YC_COEFFI_ITU709                    (0x1 << 7)
+#define IN_YC_COEFFI_ITU601                    (0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK               (0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_SHIFT              (4)
+#define VID_CHK_UPDATE_TYPE_1                  (0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0                  (0x0 << 4)
+
+/* EXYNOS_DP_VIDEO_CTL_8 */
+#define VID_HRES_TH(x)                         (((x) & 0xf) << 4)
+#define VID_VRES_TH(x)                         (((x) & 0xf) << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_10 */
+#define FORMAT_SEL                             (0x1 << 4)
+#define INTERACE_SCAN_CFG                      (0x1 << 2)
+#define VSYNC_POLARITY_CFG                     (0x1 << 1)
+#define HSYNC_POLARITY_CFG                     (0x1 << 0)
+
+/* EXYNOS_DP_LANE_MAP */
+#define LANE3_MAP_LOGIC_LANE_0                 (0x0 << 6)
+#define LANE3_MAP_LOGIC_LANE_1                 (0x1 << 6)
+#define LANE3_MAP_LOGIC_LANE_2                 (0x2 << 6)
+#define LANE3_MAP_LOGIC_LANE_3                 (0x3 << 6)
+#define LANE2_MAP_LOGIC_LANE_0                 (0x0 << 4)
+#define LANE2_MAP_LOGIC_LANE_1                 (0x1 << 4)
+#define LANE2_MAP_LOGIC_LANE_2                 (0x2 << 4)
+#define LANE2_MAP_LOGIC_LANE_3                 (0x3 << 4)
+#define LANE1_MAP_LOGIC_LANE_0                 (0x0 << 2)
+#define LANE1_MAP_LOGIC_LANE_1                 (0x1 << 2)
+#define LANE1_MAP_LOGIC_LANE_2                 (0x2 << 2)
+#define LANE1_MAP_LOGIC_LANE_3                 (0x3 << 2)
+#define LANE0_MAP_LOGIC_LANE_0                 (0x0 << 0)
+#define LANE0_MAP_LOGIC_LANE_1                 (0x1 << 0)
+#define LANE0_MAP_LOGIC_LANE_2                 (0x2 << 0)
+#define LANE0_MAP_LOGIC_LANE_3                 (0x3 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_1 */
+#define TX_TERMINAL_CTRL_50_OHM                        (0x1 << 4)
+
+/* EXYNOS_DP_ANALOG_CTL_2 */
+#define SEL_24M                                        (0x1 << 3)
+#define TX_DVDD_BIT_1_0625V                    (0x4 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_3 */
+#define DRIVE_DVDD_BIT_1_0625V                 (0x4 << 5)
+#define VCO_BIT_600_MICRO                      (0x5 << 0)
+
+/* EXYNOS_DP_PLL_FILTER_CTL_1 */
+#define PD_RING_OSC                            (0x1 << 6)
+#define AUX_TERMINAL_CTRL_50_OHM               (0x2 << 4)
+#define TX_CUR1_2X                             (0x1 << 2)
+#define TX_CUR_16_MA                           (0x3 << 0)
+
+/* EXYNOS_DP_TX_AMP_TUNING_CTL */
+#define CH3_AMP_400_MV                         (0x0 << 24)
+#define CH2_AMP_400_MV                         (0x0 << 16)
+#define CH1_AMP_400_MV                         (0x0 << 8)
+#define CH0_AMP_400_MV                         (0x0 << 0)
+
+/* EXYNOS_DP_AUX_HW_RETRY_CTL */
+#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)       (((x) & 0x7) << 8)
+#define AUX_HW_RETRY_INTERVAL_MASK             (0x3 << 3)
+#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
+#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
+#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS        (0x2 << 3)
+#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS        (0x3 << 3)
+#define AUX_HW_RETRY_COUNT_SEL(x)              (((x) & 0x7) << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_1 */
+#define VSYNC_DET                              (0x1 << 7)
+#define PLL_LOCK_CHG                           (0x1 << 6)
+#define SPDIF_ERR                              (0x1 << 5)
+#define SPDIF_UNSTBL                           (0x1 << 4)
+#define VID_FORMAT_CHG                         (0x1 << 3)
+#define AUD_CLK_CHG                            (0x1 << 2)
+#define VID_CLK_CHG                            (0x1 << 1)
+#define SW_INT                                 (0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_2 */
+#define ENC_EN_CHG                             (0x1 << 6)
+#define HW_BKSV_RDY                            (0x1 << 3)
+#define HW_SHA_DONE                            (0x1 << 2)
+#define HW_AUTH_STATE_CHG                      (0x1 << 1)
+#define HW_AUTH_DONE                           (0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_3 */
+#define AFIFO_UNDER                            (0x1 << 7)
+#define AFIFO_OVER                             (0x1 << 6)
+#define R0_CHK_FLAG                            (0x1 << 5)
+
+/* EXYNOS_DP_COMMON_INT_STA_4 */
+#define PSR_ACTIVE                             (0x1 << 7)
+#define PSR_INACTIVE                           (0x1 << 6)
+#define SPDIF_BI_PHASE_ERR                     (0x1 << 5)
+#define HOTPLUG_CHG                            (0x1 << 2)
+#define HPD_LOST                               (0x1 << 1)
+#define PLUG                                   (0x1 << 0)
+
+/* EXYNOS_DP_INT_STA */
+#define INT_HPD                                        (0x1 << 6)
+#define HW_TRAINING_FINISH                     (0x1 << 5)
+#define RPLY_RECEIV                            (0x1 << 1)
+#define AUX_ERR                                        (0x1 << 0)
+
+/* EXYNOS_DP_INT_CTL */
+#define SOFT_INT_CTRL                          (0x1 << 2)
+#define INT_POL1                               (0x1 << 1)
+#define INT_POL0                               (0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_1 */
+#define DET_STA                                        (0x1 << 2)
+#define FORCE_DET                              (0x1 << 1)
+#define DET_CTRL                               (0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_2 */
+#define CHA_CRI(x)                             (((x) & 0xf) << 4)
+#define CHA_STA                                        (0x1 << 2)
+#define FORCE_CHA                              (0x1 << 1)
+#define CHA_CTRL                               (0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_3 */
+#define HPD_STATUS                             (0x1 << 6)
+#define F_HPD                                  (0x1 << 5)
+#define HPD_CTRL                               (0x1 << 4)
+#define HDCP_RDY                               (0x1 << 3)
+#define STRM_VALID                             (0x1 << 2)
+#define F_VALID                                        (0x1 << 1)
+#define VALID_CTRL                             (0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_4 */
+#define FIX_M_AUD                              (0x1 << 4)
+#define ENHANCED                               (0x1 << 3)
+#define FIX_M_VID                              (0x1 << 2)
+#define M_VID_UPDATE_CTRL                      (0x3 << 0)
+
+/* EXYNOS_DP_TRAINING_PTN_SET */
+#define SCRAMBLER_TYPE                         (0x1 << 9)
+#define HW_LINK_TRAINING_PATTERN               (0x1 << 8)
+#define SCRAMBLING_DISABLE                     (0x1 << 5)
+#define SCRAMBLING_ENABLE                      (0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK             (0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7            (0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2            (0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE          (0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK           (0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2           (0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1           (0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_NORMAL         (0x0 << 0)
+
+/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
+#define PRE_EMPHASIS_SET_MASK                  (0x3 << 3)
+#define PRE_EMPHASIS_SET_SHIFT                 (3)
+
+/* EXYNOS_DP_DEBUG_CTL */
+#define PLL_LOCK                               (0x1 << 4)
+#define F_PLL_LOCK                             (0x1 << 3)
+#define PLL_LOCK_CTRL                          (0x1 << 2)
+#define PN_INV                                 (0x1 << 0)
+
+/* EXYNOS_DP_PLL_CTL */
+#define DP_PLL_PD                              (0x1 << 7)
+#define DP_PLL_RESET                           (0x1 << 6)
+#define DP_PLL_LOOP_BIT_DEFAULT                        (0x1 << 4)
+#define DP_PLL_REF_BIT_1_1250V                 (0x5 << 0)
+#define DP_PLL_REF_BIT_1_2500V                 (0x7 << 0)
+
+/* EXYNOS_DP_PHY_PD */
+#define DP_PHY_PD                              (0x1 << 5)
+#define AUX_PD                                 (0x1 << 4)
+#define CH3_PD                                 (0x1 << 3)
+#define CH2_PD                                 (0x1 << 2)
+#define CH1_PD                                 (0x1 << 1)
+#define CH0_PD                                 (0x1 << 0)
+
+/* EXYNOS_DP_PHY_TEST */
+#define MACRO_RST                              (0x1 << 5)
+#define CH1_TEST                               (0x1 << 1)
+#define CH0_TEST                               (0x1 << 0)
+
+/* EXYNOS_DP_AUX_CH_STA */
+#define AUX_BUSY                               (0x1 << 4)
+#define AUX_STATUS_MASK                                (0xf << 0)
+
+/* EXYNOS_DP_AUX_CH_DEFER_CTL */
+#define DEFER_CTRL_EN                          (0x1 << 7)
+#define DEFER_COUNT(x)                         (((x) & 0x7f) << 0)
+
+/* EXYNOS_DP_AUX_RX_COMM */
+#define AUX_RX_COMM_I2C_DEFER                  (0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER                  (0x2 << 0)
+
+/* EXYNOS_DP_BUFFER_DATA_CTL */
+#define BUF_CLR                                        (0x1 << 7)
+#define BUF_DATA_COUNT(x)                      (((x) & 0x1f) << 0)
+
+/* EXYNOS_DP_AUX_CH_CTL_1 */
+#define AUX_LENGTH(x)                          (((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK                       (0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION             (0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION            (0x0 << 3)
+#define AUX_TX_COMM_MOT                                (0x1 << 2)
+#define AUX_TX_COMM_WRITE                      (0x0 << 0)
+#define AUX_TX_COMM_READ                       (0x1 << 0)
+
+/* EXYNOS_DP_AUX_ADDR_7_0 */
+#define AUX_ADDR_7_0(x)                                (((x) >> 0) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_15_8 */
+#define AUX_ADDR_15_8(x)                       (((x) >> 8) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_19_16 */
+#define AUX_ADDR_19_16(x)                      (((x) >> 16) & 0x0f)
+
+/* EXYNOS_DP_AUX_CH_CTL_2 */
+#define ADDR_ONLY                              (0x1 << 1)
+#define AUX_EN                                 (0x1 << 0)
+
+/* EXYNOS_DP_SOC_GENERAL_CTL */
+#define AUDIO_MODE_SPDIF_MODE                  (0x1 << 8)
+#define AUDIO_MODE_MASTER_MODE                 (0x0 << 8)
+#define MASTER_VIDEO_INTERLACE_EN              (0x1 << 4)
+#define VIDEO_MASTER_CLK_SEL                   (0x1 << 2)
+#define VIDEO_MASTER_MODE_EN                   (0x1 << 1)
+#define VIDEO_MODE_MASK                                (0x1 << 0)
+#define VIDEO_MODE_SLAVE_MODE                  (0x1 << 0)
+#define VIDEO_MODE_MASTER_MODE                 (0x0 << 0)
+
+#endif /* _EXYNOS_DP_REG_H */
index e082efb2fece3d7174592194f155946efcee03fe..9a16dbe121d11e3a24c7f72b6c55ca5db50319fb 100644 (file)
                                drm_connector)
 
 struct exynos_drm_connector {
-       struct drm_connector    drm_connector;
-       uint32_t                encoder_id;
-       struct exynos_drm_manager *manager;
-       uint32_t                dpms;
+       struct drm_connector            drm_connector;
+       uint32_t                        encoder_id;
+       struct exynos_drm_display       *display;
 };
 
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 {
        struct exynos_drm_connector *exynos_connector =
                                        to_exynos_connector(connector);
-       struct exynos_drm_manager *manager = exynos_connector->manager;
-       struct exynos_drm_display_ops *display_ops = manager->display_ops;
+       struct exynos_drm_display *display = exynos_connector->display;
        struct edid *edid = NULL;
        unsigned int count = 0;
        int ret;
 
-       if (!display_ops) {
-               DRM_DEBUG_KMS("display_ops is null.\n");
-               return 0;
-       }
-
        /*
         * if get_edid() exists then get_edid() callback of hdmi side
         * 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)
         * P.S. in case of lcd panel, count is always 1 if success
         * because lcd panel has only one mode.
         */
-       if (display_ops->get_edid) {
-               edid = display_ops->get_edid(manager->dev, connector);
+       if (display->ops->get_edid) {
+               edid = display->ops->get_edid(display, connector);
                if (IS_ERR_OR_NULL(edid)) {
                        ret = PTR_ERR(edid);
                        edid = NULL;
@@ -76,8 +69,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                        return 0;
                }
 
-               if (display_ops->get_panel)
-                       panel = display_ops->get_panel(manager->dev);
+               if (display->ops->get_panel)
+                       panel = display->ops->get_panel(display);
                else {
                        drm_mode_destroy(connector->dev, mode);
                        return 0;
@@ -106,20 +99,20 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 {
        struct exynos_drm_connector *exynos_connector =
                                        to_exynos_connector(connector);
-       struct exynos_drm_manager *manager = exynos_connector->manager;
-       struct exynos_drm_display_ops *display_ops = manager->display_ops;
+       struct exynos_drm_display *display = exynos_connector->display;
        int ret = MODE_BAD;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (display_ops && display_ops->check_mode)
-               if (!display_ops->check_mode(manager->dev, mode))
+       if (display->ops->check_mode)
+               if (!display->ops->check_mode(display, mode))
                        ret = MODE_OK;
 
        return ret;
 }
 
-struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *exynos_drm_best_encoder(
+               struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct exynos_drm_connector *exynos_connector =
@@ -146,48 +139,12 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
        .best_encoder   = exynos_drm_best_encoder,
 };
 
-void exynos_drm_display_power(struct drm_connector *connector, int mode)
-{
-       struct drm_encoder *encoder = exynos_drm_best_encoder(connector);
-       struct exynos_drm_connector *exynos_connector;
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-       struct exynos_drm_display_ops *display_ops = manager->display_ops;
-
-       exynos_connector = to_exynos_connector(connector);
-
-       if (exynos_connector->dpms == mode) {
-               DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
-               return;
-       }
-
-       if (display_ops && display_ops->power_on)
-               display_ops->power_on(manager->dev, mode);
-
-       exynos_connector->dpms = mode;
-}
-
-static void exynos_drm_connector_dpms(struct drm_connector *connector,
-                                       int mode)
-{
-       /*
-        * in case that drm_crtc_helper_set_mode() is called,
-        * encoder/crtc->funcs->dpms() will be just returned
-        * because they already were DRM_MODE_DPMS_ON so only
-        * exynos_drm_display_power() will be called.
-        */
-       drm_helper_connector_dpms(connector, mode);
-
-       exynos_drm_display_power(connector, mode);
-
-}
-
 static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
                                unsigned int max_width, unsigned int max_height)
 {
        struct exynos_drm_connector *exynos_connector =
                                        to_exynos_connector(connector);
-       struct exynos_drm_manager *manager = exynos_connector->manager;
-       struct exynos_drm_manager_ops *ops = manager->ops;
+       struct exynos_drm_display *display = exynos_connector->display;
        unsigned int width, height;
 
        width = max_width;
@@ -197,8 +154,8 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
         * if specific driver want to find desired_mode using maxmum
         * resolution then get max width and height from that driver.
         */
-       if (ops && ops->get_max_resol)
-               ops->get_max_resol(manager->dev, &width, &height);
+       if (display->ops->get_max_resol)
+               display->ops->get_max_resol(display, &width, &height);
 
        return drm_helper_probe_single_connector_modes(connector, width,
                                                        height);
@@ -210,13 +167,11 @@ exynos_drm_connector_detect(struct drm_connector *connector, bool force)
 {
        struct exynos_drm_connector *exynos_connector =
                                        to_exynos_connector(connector);
-       struct exynos_drm_manager *manager = exynos_connector->manager;
-       struct exynos_drm_display_ops *display_ops =
-                                       manager->display_ops;
+       struct exynos_drm_display *display = exynos_connector->display;
        enum drm_connector_status status = connector_status_disconnected;
 
-       if (display_ops && display_ops->is_connected) {
-               if (display_ops->is_connected(manager->dev))
+       if (display->ops->is_connected) {
+               if (display->ops->is_connected(display))
                        status = connector_status_connected;
                else
                        status = connector_status_disconnected;
@@ -236,7 +191,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
 }
 
 static struct drm_connector_funcs exynos_connector_funcs = {
-       .dpms           = exynos_drm_connector_dpms,
+       .dpms           = drm_helper_connector_dpms,
        .fill_modes     = exynos_drm_connector_fill_modes,
        .detect         = exynos_drm_connector_detect,
        .destroy        = exynos_drm_connector_destroy,
@@ -246,7 +201,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
                                                   struct drm_encoder *encoder)
 {
        struct exynos_drm_connector *exynos_connector;
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_display *display = exynos_drm_get_display(encoder);
        struct drm_connector *connector;
        int type;
        int err;
@@ -257,7 +212,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 
        connector = &exynos_connector->drm_connector;
 
-       switch (manager->display_ops->type) {
+       switch (display->type) {
        case EXYNOS_DISPLAY_TYPE_HDMI:
                type = DRM_MODE_CONNECTOR_HDMIA;
                connector->interlace_allowed = true;
@@ -280,8 +235,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
                goto err_connector;
 
        exynos_connector->encoder_id = encoder->base.id;
-       exynos_connector->manager = manager;
-       exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+       exynos_connector->display = display;
        connector->dpms = DRM_MODE_DPMS_OFF;
        connector->encoder = encoder;
 
index 547c6b590357609a2c4f1e6811cb018ea75b1cff..4eb20d78379a20777e65664f724770c9be015846 100644 (file)
@@ -17,8 +17,4 @@
 struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
                                                   struct drm_encoder *encoder);
 
-struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector);
-
-void exynos_drm_display_power(struct drm_connector *connector, int mode);
-
 #endif
index 1bef6dc774782efe81b4b2839c9fa09e9f264b4e..0e9e06ce36b860ae8fb5a91d40faf31d917b180a 100644 (file)
 
 #include <drm/drmP.h>
 #include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
 #include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
+static LIST_HEAD(exynos_drm_manager_list);
+static LIST_HEAD(exynos_drm_display_list);
 
 static int exynos_drm_create_enc_conn(struct drm_device *dev,
-                                       struct exynos_drm_subdrv *subdrv)
+                                       struct exynos_drm_display *display)
 {
        struct drm_encoder *encoder;
-       struct drm_connector *connector;
+       struct exynos_drm_manager *manager;
        int ret;
+       unsigned long possible_crtcs = 0;
 
-       subdrv->manager->dev = subdrv->dev;
+       /* Find possible crtcs for this display */
+       list_for_each_entry(manager, &exynos_drm_manager_list, list)
+               if (manager->type == display->type)
+                       possible_crtcs |= 1 << manager->pipe;
 
        /* create and initialize a encoder for this sub driver. */
-       encoder = exynos_drm_encoder_create(dev, subdrv->manager,
-                       (1 << MAX_CRTC) - 1);
+       encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
        if (!encoder) {
                DRM_ERROR("failed to create encoder\n");
                return -EFAULT;
        }
 
-       /*
-        * create and initialize a connector for this sub driver and
-        * attach the encoder created above to the connector.
-        */
-       connector = exynos_drm_connector_create(dev, encoder);
-       if (!connector) {
-               DRM_ERROR("failed to create connector\n");
-               ret = -EFAULT;
+       display->encoder = encoder;
+
+       ret = display->ops->create_connector(display, encoder);
+       if (ret) {
+               DRM_ERROR("failed to create connector ret = %d\n", ret);
                goto err_destroy_encoder;
        }
 
-       subdrv->encoder = encoder;
-       subdrv->connector = connector;
-
        return 0;
 
 err_destroy_encoder:
@@ -58,21 +57,6 @@ err_destroy_encoder:
        return ret;
 }
 
-static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
-{
-       if (subdrv->encoder) {
-               struct drm_encoder *encoder = subdrv->encoder;
-               encoder->funcs->destroy(encoder);
-               subdrv->encoder = NULL;
-       }
-
-       if (subdrv->connector) {
-               struct drm_connector *connector = subdrv->connector;
-               connector->funcs->destroy(connector);
-               subdrv->connector = NULL;
-       }
-}
-
 static int exynos_drm_subdrv_probe(struct drm_device *dev,
                                        struct exynos_drm_subdrv *subdrv)
 {
@@ -104,10 +88,98 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
                subdrv->remove(dev, subdrv->dev);
 }
 
+int exynos_drm_initialize_managers(struct drm_device *dev)
+{
+       struct exynos_drm_manager *manager, *n;
+       int ret, pipe = 0;
+
+       list_for_each_entry(manager, &exynos_drm_manager_list, list) {
+               if (manager->ops->initialize) {
+                       ret = manager->ops->initialize(manager, dev, pipe);
+                       if (ret) {
+                               DRM_ERROR("Mgr init [%d] failed with %d\n",
+                                               manager->type, ret);
+                               goto err;
+                       }
+               }
+
+               manager->drm_dev = dev;
+               manager->pipe = pipe++;
+
+               ret = exynos_drm_crtc_create(manager);
+               if (ret) {
+                       DRM_ERROR("CRTC create [%d] failed with %d\n",
+                                       manager->type, ret);
+                       goto err;
+               }
+       }
+       return 0;
+
+err:
+       list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) {
+               if (pipe-- > 0)
+                       exynos_drm_manager_unregister(manager);
+               else
+                       list_del(&manager->list);
+       }
+       return ret;
+}
+
+void exynos_drm_remove_managers(struct drm_device *dev)
+{
+       struct exynos_drm_manager *manager, *n;
+
+       list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list)
+               exynos_drm_manager_unregister(manager);
+}
+
+int exynos_drm_initialize_displays(struct drm_device *dev)
+{
+       struct exynos_drm_display *display, *n;
+       int ret, initialized = 0;
+
+       list_for_each_entry(display, &exynos_drm_display_list, list) {
+               if (display->ops->initialize) {
+                       ret = display->ops->initialize(display, dev);
+                       if (ret) {
+                               DRM_ERROR("Display init [%d] failed with %d\n",
+                                               display->type, ret);
+                               goto err;
+                       }
+               }
+
+               initialized++;
+
+               ret = exynos_drm_create_enc_conn(dev, display);
+               if (ret) {
+                       DRM_ERROR("Encoder create [%d] failed with %d\n",
+                                       display->type, ret);
+                       goto err;
+               }
+       }
+       return 0;
+
+err:
+       list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) {
+               if (initialized-- > 0)
+                       exynos_drm_display_unregister(display);
+               else
+                       list_del(&display->list);
+       }
+       return ret;
+}
+
+void exynos_drm_remove_displays(struct drm_device *dev)
+{
+       struct exynos_drm_display *display, *n;
+
+       list_for_each_entry_safe(display, n, &exynos_drm_display_list, list)
+               exynos_drm_display_unregister(display);
+}
+
 int exynos_drm_device_register(struct drm_device *dev)
 {
        struct exynos_drm_subdrv *subdrv, *n;
-       unsigned int fine_cnt = 0;
        int err;
 
        if (!dev)
@@ -120,30 +192,8 @@ int exynos_drm_device_register(struct drm_device *dev)
                        list_del(&subdrv->list);
                        continue;
                }
-
-               /*
-                * if manager is null then it means that this sub driver
-                * doesn't need encoder and connector.
-                */
-               if (!subdrv->manager) {
-                       fine_cnt++;
-                       continue;
-               }
-
-               err = exynos_drm_create_enc_conn(dev, subdrv);
-               if (err) {
-                       DRM_DEBUG("failed to create encoder and connector.\n");
-                       exynos_drm_subdrv_remove(dev, subdrv);
-                       list_del(&subdrv->list);
-                       continue;
-               }
-
-               fine_cnt++;
        }
 
-       if (!fine_cnt)
-               return -EINVAL;
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(exynos_drm_device_register);
@@ -159,13 +209,44 @@ int exynos_drm_device_unregister(struct drm_device *dev)
 
        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
                exynos_drm_subdrv_remove(dev, subdrv);
-               exynos_drm_destroy_enc_conn(subdrv);
        }
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
 
+int exynos_drm_manager_register(struct exynos_drm_manager *manager)
+{
+       BUG_ON(!manager->ops);
+       list_add_tail(&manager->list, &exynos_drm_manager_list);
+       return 0;
+}
+
+int exynos_drm_manager_unregister(struct exynos_drm_manager *manager)
+{
+       if (manager->ops->remove)
+               manager->ops->remove(manager);
+
+       list_del(&manager->list);
+       return 0;
+}
+
+int exynos_drm_display_register(struct exynos_drm_display *display)
+{
+       BUG_ON(!display->ops);
+       list_add_tail(&display->list, &exynos_drm_display_list);
+       return 0;
+}
+
+int exynos_drm_display_unregister(struct exynos_drm_display *display)
+{
+       if (display->ops->remove)
+               display->ops->remove(display);
+
+       list_del(&display->list);
+       return 0;
+}
+
 int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
 {
        if (!subdrv)
index 6f3400f3978a7544cf9138c4e2cd0d7dc41a7f85..e930d4fe29c71c2d82d2317bb6681ac8d3f39d6a 100644 (file)
@@ -33,6 +33,7 @@ enum exynos_crtc_mode {
  *
  * @drm_crtc: crtc object.
  * @drm_plane: pointer of private plane object for this crtc
+ * @manager: the manager associated with this crtc
  * @pipe: a crtc index created at load() with a new crtc object creation
  *     and the crtc object would be set to private->crtc array
  *     to get a crtc object corresponding to this pipe from private->crtc
@@ -46,6 +47,7 @@ enum exynos_crtc_mode {
 struct exynos_drm_crtc {
        struct drm_crtc                 drm_crtc;
        struct drm_plane                *plane;
+       struct exynos_drm_manager       *manager;
        unsigned int                    pipe;
        unsigned int                    dpms;
        enum exynos_crtc_mode           mode;
@@ -56,6 +58,7 @@ struct exynos_drm_crtc {
 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
 
        DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
 
@@ -71,7 +74,9 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
                drm_vblank_off(crtc->dev, exynos_crtc->pipe);
        }
 
-       exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
+       if (manager->ops->dpms)
+               manager->ops->dpms(manager, mode);
+
        exynos_crtc->dpms = mode;
 }
 
@@ -83,9 +88,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
 static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
 
        exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
        exynos_plane_commit(exynos_crtc->plane);
+
+       if (manager->ops->commit)
+               manager->ops->commit(manager);
+
        exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
 }
 
@@ -94,7 +105,12 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
                            const struct drm_display_mode *mode,
                            struct drm_display_mode *adjusted_mode)
 {
-       /* drm framework doesn't check NULL */
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
+
+       if (manager->ops->mode_fixup)
+               return manager->ops->mode_fixup(manager, mode, adjusted_mode);
+
        return true;
 }
 
@@ -104,10 +120,10 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
                          struct drm_framebuffer *old_fb)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
        struct drm_plane *plane = exynos_crtc->plane;
        unsigned int crtc_w;
        unsigned int crtc_h;
-       int pipe = exynos_crtc->pipe;
        int ret;
 
        /*
@@ -116,18 +132,19 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
         */
        memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
 
-       crtc_w = crtc->fb->width - x;
-       crtc_h = crtc->fb->height - y;
+       crtc_w = crtc->primary->fb->width - x;
+       crtc_h = crtc->primary->fb->height - y;
+
+       if (manager->ops->mode_set)
+               manager->ops->mode_set(manager, &crtc->mode);
 
-       ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
+       ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h,
                                    x, y, crtc_w, crtc_h);
        if (ret)
                return ret;
 
        plane->crtc = crtc;
-       plane->fb = crtc->fb;
-
-       exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe);
+       plane->fb = crtc->primary->fb;
 
        return 0;
 }
@@ -147,10 +164,10 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
                return -EPERM;
        }
 
-       crtc_w = crtc->fb->width - x;
-       crtc_h = crtc->fb->height - y;
+       crtc_w = crtc->primary->fb->width - x;
+       crtc_h = crtc->primary->fb->height - y;
 
-       ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
+       ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h,
                                    x, y, crtc_w, crtc_h);
        if (ret)
                return ret;
@@ -168,10 +185,19 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 
 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
 {
-       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+       struct drm_plane *plane;
+       int ret;
 
-       exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
        exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) {
+               if (plane->crtc != crtc)
+                       continue;
+
+               ret = plane->funcs->disable_plane(plane);
+               if (ret)
+                       DRM_ERROR("Failed to disable plane %d\n", ret);
+       }
 }
 
 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
@@ -192,7 +218,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct exynos_drm_private *dev_priv = dev->dev_private;
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-       struct drm_framebuffer *old_fb = crtc->fb;
+       struct drm_framebuffer *old_fb = crtc->primary->fb;
        int ret = -EINVAL;
 
        /* 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,
                atomic_set(&exynos_crtc->pending_flip, 1);
                spin_unlock_irq(&dev->event_lock);
 
-               crtc->fb = fb;
+               crtc->primary->fb = fb;
                ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
                                                    NULL);
                if (ret) {
-                       crtc->fb = old_fb;
+                       crtc->primary->fb = old_fb;
 
                        spin_lock_irq(&dev->event_lock);
                        drm_vblank_put(dev, exynos_crtc->pipe);
@@ -318,21 +344,24 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
        drm_object_attach_property(&crtc->base, prop, 0);
 }
 
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
+int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
 {
        struct exynos_drm_crtc *exynos_crtc;
-       struct exynos_drm_private *private = dev->dev_private;
+       struct exynos_drm_private *private = manager->drm_dev->dev_private;
        struct drm_crtc *crtc;
 
        exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
        if (!exynos_crtc)
                return -ENOMEM;
 
-       exynos_crtc->pipe = nr;
-       exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
        init_waitqueue_head(&exynos_crtc->pending_flip_queue);
        atomic_set(&exynos_crtc->pending_flip, 0);
-       exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true);
+
+       exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
+       exynos_crtc->manager = manager;
+       exynos_crtc->pipe = manager->pipe;
+       exynos_crtc->plane = exynos_plane_init(manager->drm_dev,
+                               1 << manager->pipe, true);
        if (!exynos_crtc->plane) {
                kfree(exynos_crtc);
                return -ENOMEM;
@@ -340,9 +369,9 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 
        crtc = &exynos_crtc->drm_crtc;
 
-       private->crtc[nr] = crtc;
+       private->crtc[manager->pipe] = crtc;
 
-       drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
+       drm_crtc_init(manager->drm_dev, crtc, &exynos_crtc_funcs);
        drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
 
        exynos_drm_crtc_attach_mode_property(crtc);
@@ -350,39 +379,41 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
        return 0;
 }
 
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
 {
        struct exynos_drm_private *private = dev->dev_private;
        struct exynos_drm_crtc *exynos_crtc =
-               to_exynos_crtc(private->crtc[crtc]);
+               to_exynos_crtc(private->crtc[pipe]);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
 
        if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
                return -EPERM;
 
-       exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
-                       exynos_drm_enable_vblank);
+       if (manager->ops->enable_vblank)
+               manager->ops->enable_vblank(manager);
 
        return 0;
 }
 
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
 {
        struct exynos_drm_private *private = dev->dev_private;
        struct exynos_drm_crtc *exynos_crtc =
-               to_exynos_crtc(private->crtc[crtc]);
+               to_exynos_crtc(private->crtc[pipe]);
+       struct exynos_drm_manager *manager = exynos_crtc->manager;
 
        if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
                return;
 
-       exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
-                       exynos_drm_disable_vblank);
+       if (manager->ops->disable_vblank)
+               manager->ops->disable_vblank(manager);
 }
 
-void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
 {
        struct exynos_drm_private *dev_priv = dev->dev_private;
        struct drm_pending_vblank_event *e, *t;
-       struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
+       struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
        unsigned long flags;
 
@@ -391,15 +422,71 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
        list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
                        base.link) {
                /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
+               if (pipe != e->pipe)
                        continue;
 
                list_del(&e->base.link);
                drm_send_vblank_event(dev, -1, e);
-               drm_vblank_put(dev, crtc);
+               drm_vblank_put(dev, pipe);
                atomic_set(&exynos_crtc->pending_flip, 0);
                wake_up(&exynos_crtc->pending_flip_queue);
        }
 
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
+
+void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
+                       struct exynos_drm_overlay *overlay)
+{
+       struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+       if (manager->ops->win_mode_set)
+               manager->ops->win_mode_set(manager, overlay);
+}
+
+void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
+{
+       struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+       if (manager->ops->win_commit)
+               manager->ops->win_commit(manager, zpos);
+}
+
+void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
+{
+       struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+       if (manager->ops->win_enable)
+               manager->ops->win_enable(manager, zpos);
+}
+
+void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
+{
+       struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+       if (manager->ops->win_disable)
+               manager->ops->win_disable(manager, zpos);
+}
+
+void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
+{
+       struct exynos_drm_manager *manager;
+       struct drm_device *dev = fb->dev;
+       struct drm_crtc *crtc;
+
+       /*
+        * make sure that overlay data are updated to real hardware
+        * for all encoders.
+        */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               manager = to_exynos_crtc(crtc)->manager;
+
+               /*
+                * wait for vblank interrupt
+                * - this makes sure that overlay data are updated to
+                *      real hardware.
+                */
+               if (manager->ops->wait_for_vblank)
+                       manager->ops->wait_for_vblank(manager);
+       }
+}
index 3e197e6ae7d938f23c98a88c66a09478aa97f60b..c27b66cc5d24cadc20e12d3427cd4dca3a10998c 100644 (file)
 #ifndef _EXYNOS_DRM_CRTC_H_
 #define _EXYNOS_DRM_CRTC_H_
 
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc);
+struct drm_device;
+struct drm_crtc;
+struct exynos_drm_manager;
+struct exynos_drm_overlay;
+
+int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
+
+void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
+                       struct exynos_drm_overlay *overlay);
+void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
+void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
+void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
 
 #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 (file)
index 0000000..2b09c7c
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Exynos DRM Parallel output support.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * Contacts: Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include "exynos_drm_drv.h"
+
+struct exynos_dpi {
+       struct device *dev;
+       struct device_node *panel_node;
+
+       struct drm_panel *panel;
+       struct drm_connector connector;
+       struct drm_encoder *encoder;
+
+       struct videomode *vm;
+       int dpms_mode;
+};
+
+#define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector)
+
+static enum drm_connector_status
+exynos_dpi_detect(struct drm_connector *connector, bool force)
+{
+       struct exynos_dpi *ctx = connector_to_dpi(connector);
+
+       /* panels supported only by boot-loader are always connected */
+       if (!ctx->panel_node)
+               return connector_status_connected;
+
+       if (!ctx->panel) {
+               ctx->panel = of_drm_find_panel(ctx->panel_node);
+               if (ctx->panel)
+                       drm_panel_attach(ctx->panel, &ctx->connector);
+       }
+
+       if (ctx->panel)
+               return connector_status_connected;
+
+       return connector_status_disconnected;
+}
+
+static void exynos_dpi_connector_destroy(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs exynos_dpi_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = exynos_dpi_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = exynos_dpi_connector_destroy,
+};
+
+static int exynos_dpi_get_modes(struct drm_connector *connector)
+{
+       struct exynos_dpi *ctx = connector_to_dpi(connector);
+
+       /* fimd timings gets precedence over panel modes */
+       if (ctx->vm) {
+               struct drm_display_mode *mode;
+
+               mode = drm_mode_create(connector->dev);
+               if (!mode) {
+                       DRM_ERROR("failed to create a new display mode\n");
+                       return 0;
+               }
+               drm_display_mode_from_videomode(ctx->vm, mode);
+               mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+               drm_mode_probed_add(connector, mode);
+               return 1;
+       }
+
+       if (ctx->panel)
+               return ctx->panel->funcs->get_modes(ctx->panel);
+
+       return 0;
+}
+
+static int exynos_dpi_mode_valid(struct drm_connector *connector,
+                                struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static struct drm_encoder *
+exynos_dpi_best_encoder(struct drm_connector *connector)
+{
+       struct exynos_dpi *ctx = connector_to_dpi(connector);
+
+       return ctx->encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
+       .get_modes = exynos_dpi_get_modes,
+       .mode_valid = exynos_dpi_mode_valid,
+       .best_encoder = exynos_dpi_best_encoder,
+};
+
+static int exynos_dpi_create_connector(struct exynos_drm_display *display,
+                                      struct drm_encoder *encoder)
+{
+       struct exynos_dpi *ctx = display->ctx;
+       struct drm_connector *connector = &ctx->connector;
+       int ret;
+
+       ctx->encoder = encoder;
+
+       if (ctx->panel_node)
+               connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+       else
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       ret = drm_connector_init(encoder->dev, connector,
+                                &exynos_dpi_connector_funcs,
+                                DRM_MODE_CONNECTOR_VGA);
+       if (ret) {
+               DRM_ERROR("failed to initialize connector with drm\n");
+               return ret;
+       }
+
+       drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
+       drm_sysfs_connector_add(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       return 0;
+}
+
+static void exynos_dpi_poweron(struct exynos_dpi *ctx)
+{
+       if (ctx->panel)
+               drm_panel_enable(ctx->panel);
+}
+
+static void exynos_dpi_poweroff(struct exynos_dpi *ctx)
+{
+       if (ctx->panel)
+               drm_panel_disable(ctx->panel);
+}
+
+static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode)
+{
+       struct exynos_dpi *ctx = display->ctx;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               if (ctx->dpms_mode != DRM_MODE_DPMS_ON)
+                               exynos_dpi_poweron(ctx);
+                       break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               if (ctx->dpms_mode == DRM_MODE_DPMS_ON)
+                       exynos_dpi_poweroff(ctx);
+               break;
+       default:
+               break;
+       };
+       ctx->dpms_mode = mode;
+}
+
+static struct exynos_drm_display_ops exynos_dpi_display_ops = {
+       .create_connector = exynos_dpi_create_connector,
+       .dpms = exynos_dpi_dpms
+};
+
+static struct exynos_drm_display exynos_dpi_display = {
+       .type = EXYNOS_DISPLAY_TYPE_LCD,
+       .ops = &exynos_dpi_display_ops,
+};
+
+/* of_* functions will be removed after merge of of_graph patches */
+static struct device_node *
+of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
+{
+       struct device_node *np;
+
+       for_each_child_of_node(parent, np) {
+               u32 r;
+
+               if (!np->name || of_node_cmp(np->name, name))
+                       continue;
+
+               if (of_property_read_u32(np, "reg", &r) < 0)
+                       r = 0;
+
+               if (reg == r)
+                       break;
+       }
+
+       return np;
+}
+
+static struct device_node *of_graph_get_port_by_reg(struct device_node *parent,
+                                                   u32 reg)
+{
+       struct device_node *ports, *port;
+
+       ports = of_get_child_by_name(parent, "ports");
+       if (ports)
+               parent = ports;
+
+       port = of_get_child_by_name_reg(parent, "port", reg);
+
+       of_node_put(ports);
+
+       return port;
+}
+
+static struct device_node *
+of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg)
+{
+       return of_get_child_by_name_reg(port, "endpoint", reg);
+}
+
+static struct device_node *
+of_graph_get_remote_port_parent(const struct device_node *node)
+{
+       struct device_node *np;
+       unsigned int depth;
+
+       np = of_parse_phandle(node, "remote-endpoint", 0);
+
+       /* Walk 3 levels up only if there is 'ports' node. */
+       for (depth = 3; depth && np; depth--) {
+               np = of_get_next_parent(np);
+               if (depth == 2 && of_node_cmp(np->name, "ports"))
+                       break;
+       }
+       return np;
+}
+
+enum {
+       FIMD_PORT_IN0,
+       FIMD_PORT_IN1,
+       FIMD_PORT_IN2,
+       FIMD_PORT_RGB,
+       FIMD_PORT_WRB,
+};
+
+static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev)
+{
+       struct device_node *np, *ep;
+
+       np = of_graph_get_port_by_reg(dev->of_node, FIMD_PORT_RGB);
+       if (!np)
+               return NULL;
+
+       ep = of_graph_get_endpoint_by_reg(np, 0);
+       of_node_put(np);
+       if (!ep)
+               return NULL;
+
+       np = of_graph_get_remote_port_parent(ep);
+       of_node_put(ep);
+
+       return np;
+}
+
+static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
+{
+       struct device *dev = ctx->dev;
+       struct device_node *dn = dev->of_node;
+       struct device_node *np;
+
+       ctx->panel_node = exynos_dpi_of_find_panel_node(dev);
+
+       np = of_get_child_by_name(dn, "display-timings");
+       if (np) {
+               struct videomode *vm;
+               int ret;
+
+               of_node_put(np);
+
+               vm = devm_kzalloc(dev, sizeof(*ctx->vm), GFP_KERNEL);
+               if (!vm)
+                       return -ENOMEM;
+
+               ret = of_get_videomode(dn, vm, 0);
+               if (ret < 0)
+                       return ret;
+
+               ctx->vm = vm;
+
+               return 0;
+       }
+
+       if (!ctx->panel_node)
+               return -EINVAL;
+
+       return 0;
+}
+
+int exynos_dpi_probe(struct device *dev)
+{
+       struct exynos_dpi *ctx;
+       int ret;
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->dev = dev;
+       exynos_dpi_display.ctx = ctx;
+       ctx->dpms_mode = DRM_MODE_DPMS_OFF;
+
+       ret = exynos_dpi_parse_dt(ctx);
+       if (ret < 0)
+               return ret;
+
+       exynos_drm_display_register(&exynos_dpi_display);
+
+       return 0;
+}
+
+int exynos_dpi_remove(struct device *dev)
+{
+       exynos_dpi_dpms(&exynos_dpi_display, DRM_MODE_DPMS_OFF);
+       exynos_drm_display_unregister(&exynos_dpi_display);
+
+       return 0;
+}
index 215131ab1dd2f2b65c707c6d367d50ec967c27d6..771c87e90a2f1a390df3e42ca82f0747bb8ccc94 100644 (file)
@@ -11,6 +11,7 @@
  * option) any later version.
  */
 
+#include <linux/pm_runtime.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -53,6 +54,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&private->pageflip_event_list);
+       dev_set_drvdata(dev->dev, dev);
        dev->dev_private = (void *)private;
 
        /*
@@ -64,38 +66,36 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
        ret = drm_create_iommu_mapping(dev);
        if (ret < 0) {
                DRM_ERROR("failed to create iommu mapping.\n");
-               goto err_crtc;
+               goto err_free_private;
        }
 
        drm_mode_config_init(dev);
 
-       /* init kms poll for handling hpd */
-       drm_kms_helper_poll_init(dev);
-
        exynos_drm_mode_config_init(dev);
 
-       /*
-        * EXYNOS4 is enough to have two CRTCs and each crtc would be used
-        * without dependency of hardware.
-        */
-       for (nr = 0; nr < MAX_CRTC; nr++) {
-               ret = exynos_drm_crtc_create(dev, nr);
-               if (ret)
-                       goto err_release_iommu_mapping;
-       }
+       ret = exynos_drm_initialize_managers(dev);
+       if (ret)
+               goto err_mode_config_cleanup;
 
        for (nr = 0; nr < MAX_PLANE; nr++) {
                struct drm_plane *plane;
-               unsigned int possible_crtcs = (1 << MAX_CRTC) - 1;
+               unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
 
                plane = exynos_plane_init(dev, possible_crtcs, false);
                if (!plane)
-                       goto err_release_iommu_mapping;
+                       goto err_manager_cleanup;
        }
 
+       ret = exynos_drm_initialize_displays(dev);
+       if (ret)
+               goto err_manager_cleanup;
+
+       /* init kms poll for handling hpd */
+       drm_kms_helper_poll_init(dev);
+
        ret = drm_vblank_init(dev, MAX_CRTC);
        if (ret)
-               goto err_release_iommu_mapping;
+               goto err_display_cleanup;
 
        /*
         * 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)
        /* setup possible_clones. */
        exynos_drm_encoder_setup(dev);
 
-       /*
-        * create and configure fb helper and also exynos specific
-        * fbdev object.
-        */
-       ret = exynos_drm_fbdev_init(dev);
-       if (ret) {
-               DRM_ERROR("failed to initialize drm fbdev\n");
-               goto err_drm_device;
-       }
-
        drm_vblank_offdelay = VBLANK_OFF_DELAY;
 
        platform_set_drvdata(dev->platformdev, dev);
 
+       /* force connectors detection */
+       drm_helper_hpd_irq_event(dev);
+
        return 0;
 
-err_drm_device:
-       exynos_drm_device_unregister(dev);
 err_vblank:
        drm_vblank_cleanup(dev);
-err_release_iommu_mapping:
-       drm_release_iommu_mapping(dev);
-err_crtc:
+err_display_cleanup:
+       exynos_drm_remove_displays(dev);
+err_manager_cleanup:
+       exynos_drm_remove_managers(dev);
+err_mode_config_cleanup:
        drm_mode_config_cleanup(dev);
+       drm_release_iommu_mapping(dev);
+err_free_private:
        kfree(private);
 
        return ret;
@@ -144,6 +139,8 @@ static int exynos_drm_unload(struct drm_device *dev)
        exynos_drm_device_unregister(dev);
        drm_vblank_cleanup(dev);
        drm_kms_helper_poll_fini(dev);
+       exynos_drm_remove_displays(dev);
+       exynos_drm_remove_managers(dev);
        drm_mode_config_cleanup(dev);
 
        drm_release_iommu_mapping(dev);
@@ -158,6 +155,41 @@ static const struct file_operations exynos_drm_gem_fops = {
        .mmap = exynos_drm_gem_mmap_buffer,
 };
 
+static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
+{
+       struct drm_connector *connector;
+
+       drm_modeset_lock_all(dev);
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               int old_dpms = connector->dpms;
+
+               if (connector->funcs->dpms)
+                       connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
+
+               /* Set the old mode back to the connector for resume */
+               connector->dpms = old_dpms;
+       }
+       drm_modeset_unlock_all(dev);
+
+       return 0;
+}
+
+static int exynos_drm_resume(struct drm_device *dev)
+{
+       struct drm_connector *connector;
+
+       drm_modeset_lock_all(dev);
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (connector->funcs->dpms)
+                       connector->funcs->dpms(connector, connector->dpms);
+       }
+
+       drm_helper_resume_force_mode(dev);
+       drm_modeset_unlock_all(dev);
+
+       return 0;
+}
+
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_exynos_file_private *file_priv;
@@ -172,20 +204,24 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 
        ret = exynos_drm_subdrv_open(dev, file);
        if (ret)
-               goto out;
+               goto err_file_priv_free;
 
        anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
                                        NULL, 0);
        if (IS_ERR(anon_filp)) {
                ret = PTR_ERR(anon_filp);
-               goto out;
+               goto err_subdrv_close;
        }
 
        anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
        file_priv->anon_filp = anon_filp;
 
        return ret;
-out:
+
+err_subdrv_close:
+       exynos_drm_subdrv_close(dev, file);
+
+err_file_priv_free:
        kfree(file_priv);
        file->driver_priv = NULL;
        return ret;
@@ -291,6 +327,8 @@ static struct drm_driver exynos_drm_driver = {
                                        DRIVER_GEM | DRIVER_PRIME,
        .load                   = exynos_drm_load,
        .unload                 = exynos_drm_unload,
+       .suspend                = exynos_drm_suspend,
+       .resume                 = exynos_drm_resume,
        .open                   = exynos_drm_open,
        .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
@@ -325,6 +363,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
        return drm_platform_init(&exynos_drm_driver, pdev);
 }
 
@@ -335,12 +376,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int exynos_drm_sys_suspend(struct device *dev)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+       pm_message_t message;
+
+       if (pm_runtime_suspended(dev))
+               return 0;
+
+       message.event = PM_EVENT_SUSPEND;
+       return exynos_drm_suspend(drm_dev, message);
+}
+
+static int exynos_drm_sys_resume(struct device *dev)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+       if (pm_runtime_suspended(dev))
+               return 0;
+
+       return exynos_drm_resume(drm_dev);
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int exynos_drm_runtime_suspend(struct device *dev)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+       pm_message_t message;
+
+       if (pm_runtime_suspended(dev))
+               return 0;
+
+       message.event = PM_EVENT_SUSPEND;
+       return exynos_drm_suspend(drm_dev, message);
+}
+
+static int exynos_drm_runtime_resume(struct device *dev)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+       if (!pm_runtime_suspended(dev))
+               return 0;
+
+       return exynos_drm_resume(drm_dev);
+}
+#endif
+
+static const struct dev_pm_ops exynos_drm_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
+       SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
+                       exynos_drm_runtime_resume, NULL)
+};
+
 static struct platform_driver exynos_drm_platform_driver = {
        .probe          = exynos_drm_platform_probe,
        .remove         = exynos_drm_platform_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "exynos-drm",
+               .pm     = &exynos_drm_pm_ops,
        },
 };
 
@@ -348,6 +444,12 @@ static int __init exynos_drm_init(void)
 {
        int ret;
 
+#ifdef CONFIG_DRM_EXYNOS_DP
+       ret = platform_driver_register(&dp_driver);
+       if (ret < 0)
+               goto out_dp;
+#endif
+
 #ifdef CONFIG_DRM_EXYNOS_FIMD
        ret = platform_driver_register(&fimd_driver);
        if (ret < 0)
@@ -361,13 +463,6 @@ static int __init exynos_drm_init(void)
        ret = platform_driver_register(&mixer_driver);
        if (ret < 0)
                goto out_mixer;
-       ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
-       if (ret < 0)
-               goto out_common_hdmi;
-
-       ret = exynos_platform_device_hdmi_register();
-       if (ret < 0)
-               goto out_common_hdmi_dev;
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_VIDI
@@ -460,10 +555,6 @@ out_vidi:
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_HDMI
-       exynos_platform_device_hdmi_unregister();
-out_common_hdmi_dev:
-       platform_driver_unregister(&exynos_drm_common_hdmi_driver);
-out_common_hdmi:
        platform_driver_unregister(&mixer_driver);
 out_mixer:
        platform_driver_unregister(&hdmi_driver);
@@ -473,6 +564,11 @@ out_hdmi:
 #ifdef CONFIG_DRM_EXYNOS_FIMD
        platform_driver_unregister(&fimd_driver);
 out_fimd:
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_DP
+       platform_driver_unregister(&dp_driver);
+out_dp:
 #endif
        return ret;
 }
@@ -505,8 +601,6 @@ static void __exit exynos_drm_exit(void)
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_HDMI
-       exynos_platform_device_hdmi_unregister();
-       platform_driver_unregister(&exynos_drm_common_hdmi_driver);
        platform_driver_unregister(&mixer_driver);
        platform_driver_unregister(&hdmi_driver);
 #endif
@@ -518,6 +612,10 @@ static void __exit exynos_drm_exit(void)
 #ifdef CONFIG_DRM_EXYNOS_FIMD
        platform_driver_unregister(&fimd_driver);
 #endif
+
+#ifdef CONFIG_DRM_EXYNOS_DP
+       platform_driver_unregister(&dp_driver);
+#endif
 }
 
 module_init(exynos_drm_init);
index 0eaf5a27e120e586129074446e816b902d7316f3..2d892f32e831624a532dde0f4fbdc3e75f388dfd 100644 (file)
@@ -53,22 +53,6 @@ enum exynos_drm_output_type {
        EXYNOS_DISPLAY_TYPE_VIDI,
 };
 
-/*
- * Exynos drm overlay ops structure.
- *
- * @mode_set: copy drm overlay info to hw specific overlay info.
- * @commit: apply hardware specific overlay data to registers.
- * @enable: enable hardware specific overlay.
- * @disable: disable hardware specific overlay.
- */
-struct exynos_drm_overlay_ops {
-       void (*mode_set)(struct device *subdrv_dev,
-                        struct exynos_drm_overlay *overlay);
-       void (*commit)(struct device *subdrv_dev, int zpos);
-       void (*enable)(struct device *subdrv_dev, int zpos);
-       void (*disable)(struct device *subdrv_dev, int zpos);
-};
-
 /*
  * Exynos drm common overlay structure.
  *
@@ -138,77 +122,110 @@ struct exynos_drm_overlay {
  * Exynos DRM Display Structure.
  *     - this structure is common to analog tv, digital tv and lcd panel.
  *
- * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
- * @is_connected: check for that display is connected or not.
- * @get_edid: get edid modes from display driver.
- * @get_panel: get panel object from display driver.
+ * @initialize: initializes the display with drm_dev
+ * @remove: cleans up the display for removal
+ * @mode_fixup: fix mode data comparing to hw specific display mode.
+ * @mode_set: convert drm_display_mode to hw specific display mode and
+ *           would be called by encoder->mode_set().
  * @check_mode: check if mode is valid or not.
- * @power_on: display device on or off.
+ * @dpms: display device on or off.
+ * @commit: apply changes to hw
  */
+struct exynos_drm_display;
 struct exynos_drm_display_ops {
+       int (*initialize)(struct exynos_drm_display *display,
+                               struct drm_device *drm_dev);
+       int (*create_connector)(struct exynos_drm_display *display,
+                               struct drm_encoder *encoder);
+       void (*remove)(struct exynos_drm_display *display);
+       void (*mode_fixup)(struct exynos_drm_display *display,
+                               struct drm_connector *connector,
+                               const struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode);
+       void (*mode_set)(struct exynos_drm_display *display,
+                               struct drm_display_mode *mode);
+       int (*check_mode)(struct exynos_drm_display *display,
+                               struct drm_display_mode *mode);
+       void (*dpms)(struct exynos_drm_display *display, int mode);
+       void (*commit)(struct exynos_drm_display *display);
+};
+
+/*
+ * Exynos drm display structure, maps 1:1 with an encoder/connector
+ *
+ * @list: the list entry for this manager
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @encoder: encoder object this display maps to
+ * @connector: connector object this display maps to
+ * @ops: pointer to callbacks for exynos drm specific functionality
+ * @ctx: A pointer to the display's implementation specific context
+ */
+struct exynos_drm_display {
+       struct list_head list;
        enum exynos_drm_output_type type;
-       bool (*is_connected)(struct device *dev);
-       struct edid *(*get_edid)(struct device *dev,
-                       struct drm_connector *connector);
-       void *(*get_panel)(struct device *dev);
-       int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
-       int (*power_on)(struct device *dev, int mode);
+       struct drm_encoder *encoder;
+       struct drm_connector *connector;
+       struct exynos_drm_display_ops *ops;
+       void *ctx;
 };
 
 /*
  * Exynos drm manager ops
  *
+ * @initialize: initializes the manager with drm_dev
+ * @remove: cleans up the manager for removal
  * @dpms: control device power.
- * @apply: set timing, vblank and overlay data to registers.
- * @mode_fixup: fix mode data comparing to hw specific display mode.
- * @mode_set: convert drm_display_mode to hw specific display mode and
- *           would be called by encoder->mode_set().
- * @get_max_resol: get maximum resolution to specific hardware.
+ * @mode_fixup: fix mode data before applying it
+ * @mode_set: set the given mode to the manager
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  * @wait_for_vblank: wait for vblank interrupt to make sure that
  *     hardware overlay is updated.
+ * @win_mode_set: copy drm overlay info to hw specific overlay info.
+ * @win_commit: apply hardware specific overlay data to registers.
+ * @win_enable: enable hardware specific overlay.
+ * @win_disable: disable hardware specific overlay.
  */
+struct exynos_drm_manager;
 struct exynos_drm_manager_ops {
-       void (*dpms)(struct device *subdrv_dev, int mode);
-       void (*apply)(struct device *subdrv_dev);
-       void (*mode_fixup)(struct device *subdrv_dev,
-                               struct drm_connector *connector,
+       int (*initialize)(struct exynos_drm_manager *mgr,
+                               struct drm_device *drm_dev, int pipe);
+       void (*remove)(struct exynos_drm_manager *mgr);
+       void (*dpms)(struct exynos_drm_manager *mgr, int mode);
+       bool (*mode_fixup)(struct exynos_drm_manager *mgr,
                                const struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode);
-       void (*mode_set)(struct device *subdrv_dev, void *mode);
-       void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width,
-                               unsigned int *height);
-       void (*commit)(struct device *subdrv_dev);
-       int (*enable_vblank)(struct device *subdrv_dev);
-       void (*disable_vblank)(struct device *subdrv_dev);
-       void (*wait_for_vblank)(struct device *subdrv_dev);
+       void (*mode_set)(struct exynos_drm_manager *mgr,
+                               const struct drm_display_mode *mode);
+       void (*commit)(struct exynos_drm_manager *mgr);
+       int (*enable_vblank)(struct exynos_drm_manager *mgr);
+       void (*disable_vblank)(struct exynos_drm_manager *mgr);
+       void (*wait_for_vblank)(struct exynos_drm_manager *mgr);
+       void (*win_mode_set)(struct exynos_drm_manager *mgr,
+                               struct exynos_drm_overlay *overlay);
+       void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
+       void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
+       void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
 };
 
 /*
- * Exynos drm common manager structure.
+ * Exynos drm common manager structure, maps 1:1 with a crtc
  *
- * @dev: pointer to device object for subdrv device driver.
- *     sub drivers such as display controller or hdmi driver,
- *     have their own device object.
- * @ops: pointer to callbacks for exynos drm specific framebuffer.
- *     these callbacks should be set by specific drivers such fimd
- *     or hdmi driver and are used to control hardware global registers.
- * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
- *     these callbacks should be set by specific drivers such fimd
- *     or hdmi driver and are used to control hardware overlay reigsters.
- * @display: pointer to callbacks for exynos drm specific framebuffer.
- *     these callbacks should be set by specific drivers such fimd
- *     or hdmi driver and are used to control display devices such as
- *     analog tv, digital tv and lcd panel and also get timing data for them.
+ * @list: the list entry for this manager
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @drm_dev: pointer to the drm device
+ * @pipe: the pipe number for this crtc/manager
+ * @ops: pointer to callbacks for exynos drm specific functionality
+ * @ctx: A pointer to the manager's implementation specific context
  */
 struct exynos_drm_manager {
-       struct device *dev;
+       struct list_head list;
+       enum exynos_drm_output_type type;
+       struct drm_device *drm_dev;
        int pipe;
        struct exynos_drm_manager_ops *ops;
-       struct exynos_drm_overlay_ops *overlay_ops;
-       struct exynos_drm_display_ops *display_ops;
+       void *ctx;
 };
 
 struct exynos_drm_g2d_private {
@@ -273,14 +290,11 @@ struct exynos_drm_private {
  *     by probe callback.
  * @open: this would be called with drm device file open.
  * @close: this would be called with drm device file close.
- * @encoder: encoder object owned by this sub driver.
- * @connector: connector object owned by this sub driver.
  */
 struct exynos_drm_subdrv {
        struct list_head list;
        struct device *dev;
        struct drm_device *drm_dev;
-       struct exynos_drm_manager *manager;
 
        int (*probe)(struct drm_device *drm_dev, struct device *dev);
        void (*remove)(struct drm_device *drm_dev, struct device *dev);
@@ -288,9 +302,6 @@ struct exynos_drm_subdrv {
                        struct drm_file *file);
        void (*close)(struct drm_device *drm_dev, struct device *dev,
                        struct drm_file *file);
-
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
 };
 
 /*
@@ -305,6 +316,16 @@ int exynos_drm_device_register(struct drm_device *dev);
  */
 int exynos_drm_device_unregister(struct drm_device *dev);
 
+int exynos_drm_initialize_managers(struct drm_device *dev);
+void exynos_drm_remove_managers(struct drm_device *dev);
+int exynos_drm_initialize_displays(struct drm_device *dev);
+void exynos_drm_remove_displays(struct drm_device *dev);
+
+int exynos_drm_manager_register(struct exynos_drm_manager *manager);
+int exynos_drm_manager_unregister(struct exynos_drm_manager *manager);
+int exynos_drm_display_register(struct exynos_drm_display *display);
+int exynos_drm_display_unregister(struct exynos_drm_display *display);
+
 /*
  * this function would be called by sub drivers such as display controller
  * or hdmi driver to register this sub driver object to exynos drm driver
@@ -340,6 +361,15 @@ int exynos_platform_device_ipp_register(void);
  */
 void exynos_platform_device_ipp_unregister(void);
 
+#ifdef CONFIG_DRM_EXYNOS_DPI
+int exynos_dpi_probe(struct device *dev);
+int exynos_dpi_remove(struct device *dev);
+#else
+static inline int exynos_dpi_probe(struct device *dev) { return 0; }
+static inline int exynos_dpi_remove(struct device *dev) { return 0; }
+#endif
+
+extern struct platform_driver dp_driver;
 extern struct platform_driver fimd_driver;
 extern struct platform_driver hdmi_driver;
 extern struct platform_driver mixer_driver;
index 06f1b2a09da7a1d2c1f4f556db86f299d872a081..7e282e3d603826cefb4f43d53a588dc3a2d55830 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
 
 #define to_exynos_encoder(x)   container_of(x, struct exynos_drm_encoder,\
                                drm_encoder)
  * exynos specific encoder structure.
  *
  * @drm_encoder: encoder object.
- * @manager: specific encoder has its own manager to control a hardware
- *     appropriately and we can access a hardware drawing on this manager.
- * @dpms: store the encoder dpms value.
- * @updated: indicate whether overlay data updating is needed or not.
+ * @display: the display structure that maps to this encoder
  */
 struct exynos_drm_encoder {
-       struct drm_crtc                 *old_crtc;
        struct drm_encoder              drm_encoder;
-       struct exynos_drm_manager       *manager;
-       int                             dpms;
-       bool                            updated;
+       struct exynos_drm_display       *display;
 };
 
-static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct drm_connector *connector;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (exynos_drm_best_encoder(connector) == encoder) {
-                       DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
-                                       connector->base.id, mode);
-
-                       exynos_drm_display_power(connector, mode);
-               }
-       }
-}
-
 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
        struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_display *display = exynos_encoder->display;
 
        DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
 
-       if (exynos_encoder->dpms == mode) {
-               DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
-               return;
-       }
-
-       mutex_lock(&dev->struct_mutex);
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               if (manager_ops && manager_ops->apply)
-                       if (!exynos_encoder->updated)
-                               manager_ops->apply(manager->dev);
-
-               exynos_drm_connector_power(encoder, mode);
-               exynos_encoder->dpms = mode;
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               exynos_drm_connector_power(encoder, mode);
-               exynos_encoder->dpms = mode;
-               exynos_encoder->updated = false;
-               break;
-       default:
-               DRM_ERROR("unspecified mode %d\n", mode);
-               break;
-       }
-
-       mutex_unlock(&dev->struct_mutex);
+       if (display->ops->dpms)
+               display->ops->dpms(display, mode);
 }
 
 static bool
@@ -100,87 +49,31 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode)
 {
        struct drm_device *dev = encoder->dev;
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_display *display = exynos_encoder->display;
        struct drm_connector *connector;
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->encoder == encoder)
-                       if (manager_ops && manager_ops->mode_fixup)
-                               manager_ops->mode_fixup(manager->dev, connector,
-                                                       mode, adjusted_mode);
+               if (connector->encoder != encoder)
+                       continue;
+
+               if (display->ops->mode_fixup)
+                       display->ops->mode_fixup(display, connector, mode,
+                                       adjusted_mode);
        }
 
        return true;
 }
 
-static void disable_plane_to_crtc(struct drm_device *dev,
-                                               struct drm_crtc *old_crtc,
-                                               struct drm_crtc *new_crtc)
-{
-       struct drm_plane *plane;
-
-       /*
-        * if old_crtc isn't same as encoder->crtc then it means that
-        * user changed crtc id to another one so the plane to old_crtc
-        * should be disabled and plane->crtc should be set to new_crtc
-        * (encoder->crtc)
-        */
-       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-               if (plane->crtc == old_crtc) {
-                       /*
-                        * do not change below call order.
-                        *
-                        * plane->funcs->disable_plane call checks
-                        * if encoder->crtc is same as plane->crtc and if same
-                        * then overlay_ops->disable callback will be called
-                        * to diasble current hw overlay so plane->crtc should
-                        * have new_crtc because new_crtc was set to
-                        * encoder->crtc in advance.
-                        */
-                       plane->crtc = new_crtc;
-                       plane->funcs->disable_plane(plane);
-               }
-       }
-}
-
 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
                                         struct drm_display_mode *mode,
                                         struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_connector *connector;
-       struct exynos_drm_manager *manager;
-       struct exynos_drm_manager_ops *manager_ops;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->encoder == encoder) {
-                       struct exynos_drm_encoder *exynos_encoder;
-
-                       exynos_encoder = to_exynos_encoder(encoder);
-
-                       if (exynos_encoder->old_crtc != encoder->crtc &&
-                                       exynos_encoder->old_crtc) {
-
-                               /*
-                                * disable a plane to old crtc and change
-                                * crtc of the plane to new one.
-                                */
-                               disable_plane_to_crtc(dev,
-                                               exynos_encoder->old_crtc,
-                                               encoder->crtc);
-                       }
-
-                       manager = exynos_drm_get_manager(encoder);
-                       manager_ops = manager->ops;
-
-                       if (manager_ops && manager_ops->mode_set)
-                               manager_ops->mode_set(manager->dev,
-                                                       adjusted_mode);
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_display *display = exynos_encoder->display;
 
-                       exynos_encoder->old_crtc = encoder->crtc;
-               }
-       }
+       if (display->ops->mode_set)
+               display->ops->mode_set(display, adjusted_mode);
 }
 
 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
@@ -191,53 +84,15 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
        struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-       struct exynos_drm_manager *manager = exynos_encoder->manager;
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
-
-       if (manager_ops && manager_ops->commit)
-               manager_ops->commit(manager->dev);
-
-       /*
-        * this will avoid one issue that overlay data is updated to
-        * real hardware two times.
-        * And this variable will be used to check if the data was
-        * already updated or not by exynos_drm_encoder_dpms function.
-        */
-       exynos_encoder->updated = true;
-
-       /*
-        * In case of setcrtc, there is no way to update encoder's dpms
-        * so update it here.
-        */
-       exynos_encoder->dpms = DRM_MODE_DPMS_ON;
-}
+       struct exynos_drm_display *display = exynos_encoder->display;
 
-void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
-{
-       struct exynos_drm_encoder *exynos_encoder;
-       struct exynos_drm_manager_ops *ops;
-       struct drm_device *dev = fb->dev;
-       struct drm_encoder *encoder;
+       if (display->ops->dpms)
+               display->ops->dpms(display, DRM_MODE_DPMS_ON);
 
-       /*
-        * make sure that overlay data are updated to real hardware
-        * for all encoders.
-        */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               exynos_encoder = to_exynos_encoder(encoder);
-               ops = exynos_encoder->manager->ops;
-
-               /*
-                * wait for vblank interrupt
-                * - this makes sure that overlay data are updated to
-                *      real hardware.
-                */
-               if (ops->wait_for_vblank)
-                       ops->wait_for_vblank(exynos_encoder->manager->dev);
-       }
+       if (display->ops->commit)
+               display->ops->commit(display);
 }
 
-
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
 {
        struct drm_plane *plane;
@@ -246,7 +101,7 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
        exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 
        /* all planes connected to this encoder should be also disabled. */
-       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+       drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
                if (plane->crtc == encoder->crtc)
                        plane->funcs->disable_plane(plane);
        }
@@ -263,10 +118,7 @@ static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
 
 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
 {
-       struct exynos_drm_encoder *exynos_encoder =
-               to_exynos_encoder(encoder);
-
-       exynos_encoder->manager->pipe = -1;
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
 
        drm_encoder_cleanup(encoder);
        kfree(exynos_encoder);
@@ -281,13 +133,12 @@ static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
        struct drm_encoder *clone;
        struct drm_device *dev = encoder->dev;
        struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-       struct exynos_drm_display_ops *display_ops =
-                               exynos_encoder->manager->display_ops;
+       struct exynos_drm_display *display = exynos_encoder->display;
        unsigned int clone_mask = 0;
        int cnt = 0;
 
        list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
-               switch (display_ops->type) {
+               switch (display->type) {
                case EXYNOS_DISPLAY_TYPE_LCD:
                case EXYNOS_DISPLAY_TYPE_HDMI:
                case EXYNOS_DISPLAY_TYPE_VIDI:
@@ -311,24 +162,20 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
 
 struct drm_encoder *
 exynos_drm_encoder_create(struct drm_device *dev,
-                          struct exynos_drm_manager *manager,
-                          unsigned int possible_crtcs)
+                          struct exynos_drm_display *display,
+                          unsigned long possible_crtcs)
 {
        struct drm_encoder *encoder;
        struct exynos_drm_encoder *exynos_encoder;
 
-       if (!manager || !possible_crtcs)
-               return NULL;
-
-       if (!manager->dev)
+       if (!possible_crtcs)
                return NULL;
 
        exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
        if (!exynos_encoder)
                return NULL;
 
-       exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
-       exynos_encoder->manager = manager;
+       exynos_encoder->display = display;
        encoder = &exynos_encoder->drm_encoder;
        encoder->possible_crtcs = possible_crtcs;
 
@@ -344,149 +191,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
        return encoder;
 }
 
-struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
-{
-       return to_exynos_encoder(encoder)->manager;
-}
-
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
-                           void (*fn)(struct drm_encoder *, void *))
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_encoder *encoder;
-       struct exynos_drm_private *private = dev->dev_private;
-       struct exynos_drm_manager *manager;
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               /*
-                * if crtc is detached from encoder, check pipe,
-                * otherwise check crtc attached to encoder
-                */
-               if (!encoder->crtc) {
-                       manager = to_exynos_encoder(encoder)->manager;
-                       if (manager->pipe < 0 ||
-                                       private->crtc[manager->pipe] != crtc)
-                               continue;
-               } else {
-                       if (encoder->crtc != crtc)
-                               continue;
-               }
-
-               fn(encoder, data);
-       }
-}
-
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
-       int crtc = *(int *)data;
-
-       if (manager->pipe != crtc)
-               return;
-
-       if (manager_ops->enable_vblank)
-               manager_ops->enable_vblank(manager->dev);
-}
-
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
-       int crtc = *(int *)data;
-
-       if (manager->pipe != crtc)
-               return;
-
-       if (manager_ops->disable_vblank)
-               manager_ops->disable_vblank(manager->dev);
-}
-
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-       struct exynos_drm_manager *manager = exynos_encoder->manager;
-       struct exynos_drm_manager_ops *manager_ops = manager->ops;
-       int mode = *(int *)data;
-
-       if (manager_ops && manager_ops->dpms)
-               manager_ops->dpms(manager->dev, mode);
-
-       /*
-        * if this condition is ok then it means that the crtc is already
-        * detached from encoder and last function for detaching is properly
-        * done, so clear pipe from manager to prevent repeated call.
-        */
-       if (mode > DRM_MODE_DPMS_ON) {
-               if (!encoder->crtc)
-                       manager->pipe = -1;
-       }
-}
-
-void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       int pipe = *(int *)data;
-
-       /*
-        * when crtc is detached from encoder, this pipe is used
-        * to select manager operation
-        */
-       manager->pipe = pipe;
-}
-
-void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
-       struct exynos_drm_overlay *overlay = data;
-
-       if (overlay_ops && overlay_ops->mode_set)
-               overlay_ops->mode_set(manager->dev, overlay);
-}
-
-void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
+struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder)
 {
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
-       int zpos = DEFAULT_ZPOS;
-
-       if (data)
-               zpos = *(int *)data;
-
-       if (overlay_ops && overlay_ops->commit)
-               overlay_ops->commit(manager->dev, zpos);
-}
-
-void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
-       int zpos = DEFAULT_ZPOS;
-
-       if (data)
-               zpos = *(int *)data;
-
-       if (overlay_ops && overlay_ops->enable)
-               overlay_ops->enable(manager->dev, zpos);
-}
-
-void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
-{
-       struct exynos_drm_manager *manager =
-               to_exynos_encoder(encoder)->manager;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
-       int zpos = DEFAULT_ZPOS;
-
-       if (data)
-               zpos = *(int *)data;
-
-       if (overlay_ops && overlay_ops->disable)
-               overlay_ops->disable(manager->dev, zpos);
+       return to_exynos_encoder(encoder)->display;
 }
index 89e2fb0770af12ba7405ba8b116edb831b67c4fd..b7a1620a7e79cfff9abff9eec3f283316f524249 100644 (file)
@@ -18,20 +18,8 @@ struct exynos_drm_manager;
 
 void exynos_drm_encoder_setup(struct drm_device *dev);
 struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
-                                              struct exynos_drm_manager *mgr,
-                                              unsigned int possible_crtcs);
-struct exynos_drm_manager *
-exynos_drm_get_manager(struct drm_encoder *encoder);
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
-                           void (*fn)(struct drm_encoder *, void *));
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb);
+                       struct exynos_drm_display *mgr,
+                       unsigned long possible_crtcs);
+struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder);
 
 #endif
index ea39e0ef2ae4c61d530bd2f7b729a26a6ad1e752..65a22cad7b36300811abf39b3a0d13020a479cc0 100644 (file)
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
+#include "exynos_drm_fbdev.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_iommu.h"
-#include "exynos_drm_encoder.h"
+#include "exynos_drm_crtc.h"
 
 #define to_exynos_fb(x)        container_of(x, struct exynos_drm_fb, fb)
 
@@ -71,7 +72,7 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
        unsigned int i;
 
        /* make sure that overlay data are updated before relesing fb. */
-       exynos_drm_encoder_complete_scanout(fb);
+       exynos_drm_crtc_complete_scanout(fb);
 
        drm_framebuffer_cleanup(fb);
 
@@ -300,6 +301,8 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev)
 
        if (fb_helper)
                drm_fb_helper_hotplug_event(fb_helper);
+       else
+               exynos_drm_fbdev_init(dev);
 }
 
 static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
index e7c2f2d07f193b0393052be2e1bf32921b804da9..5fa342e5f9633214ee45dcc70fd96f89b858c67f 100644 (file)
@@ -90,7 +90,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
        /* RGB formats use only one buffer */
        buffer = exynos_drm_fb_buffer(fb, 0);
        if (!buffer) {
-               DRM_LOG_KMS("buffer is null.\n");
+               DRM_DEBUG_KMS("buffer is null.\n");
                return -EFAULT;
        }
 
index a20440ce32e6c39ee450d926f668f5638df0cca8..40fd6ccfcd6f7595671d750b57ea44066ddf4b87 100644 (file)
@@ -62,7 +62,7 @@
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR     5
 
-#define get_fimd_context(dev)  platform_get_drvdata(to_platform_device(dev))
+#define get_fimd_manager(mgr)  platform_get_drvdata(to_platform_device(dev))
 
 struct fimd_driver_data {
        unsigned int timing_base;
@@ -105,20 +105,18 @@ struct fimd_win_data {
 };
 
 struct fimd_context {
-       struct exynos_drm_subdrv        subdrv;
-       int                             irq;
-       struct drm_crtc                 *crtc;
+       struct device                   *dev;
+       struct drm_device               *drm_dev;
        struct clk                      *bus_clk;
        struct clk                      *lcd_clk;
        void __iomem                    *regs;
+       struct drm_display_mode         mode;
        struct fimd_win_data            win_data[WINDOWS_NR];
-       unsigned int                    clkdiv;
        unsigned int                    default_win;
        unsigned long                   irq_flags;
-       u32                             vidcon0;
        u32                             vidcon1;
        bool                            suspended;
-       struct mutex                    lock;
+       int                             pipe;
        wait_queue_head_t               wait_vsync_queue;
        atomic_t                        wait_vsync_event;
 
@@ -145,153 +143,147 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
        return (struct fimd_driver_data *)of_id->data;
 }
 
-static bool fimd_display_is_connected(struct device *dev)
+static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
+                       struct drm_device *drm_dev, int pipe)
 {
-       /* TODO. */
+       struct fimd_context *ctx = mgr->ctx;
 
-       return true;
-}
+       ctx->drm_dev = drm_dev;
+       ctx->pipe = pipe;
 
-static void *fimd_get_panel(struct device *dev)
-{
-       struct fimd_context *ctx = get_fimd_context(dev);
+       /*
+        * enable drm irq mode.
+        * - with irq_enabled = true, we can use the vblank feature.
+        *
+        * P.S. note that we wouldn't use drm irq handler but
+        *      just specific driver own one instead because
+        *      drm framework supports only one irq handler.
+        */
+       drm_dev->irq_enabled = true;
 
-       return &ctx->panel;
-}
+       /*
+        * with vblank_disable_allowed = true, vblank interrupt will be disabled
+        * by drm timer once a current process gives up ownership of
+        * vblank event.(after drm_vblank_put function is called)
+        */
+       drm_dev->vblank_disable_allowed = true;
 
-static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
-{
-       /* TODO. */
+       /* attach this sub driver to iommu mapping if supported. */
+       if (is_drm_iommu_supported(ctx->drm_dev))
+               drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
 
        return 0;
 }
 
-static int fimd_display_power_on(struct device *dev, int mode)
+static void fimd_mgr_remove(struct exynos_drm_manager *mgr)
 {
-       /* TODO */
+       struct fimd_context *ctx = mgr->ctx;
 
-       return 0;
+       /* detach this sub driver from iommu mapping if supported. */
+       if (is_drm_iommu_supported(ctx->drm_dev))
+               drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
 }
 
-static struct exynos_drm_display_ops fimd_display_ops = {
-       .type = EXYNOS_DISPLAY_TYPE_LCD,
-       .is_connected = fimd_display_is_connected,
-       .get_panel = fimd_get_panel,
-       .check_mode = fimd_check_mode,
-       .power_on = fimd_display_power_on,
-};
-
-static void fimd_dpms(struct device *subdrv_dev, int mode)
+static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
+               const struct drm_display_mode *mode)
 {
-       struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+       unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
+       u32 clkdiv;
 
-       DRM_DEBUG_KMS("%d\n", mode);
+       /* Find the clock divider value that gets us closest to ideal_clk */
+       clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
 
-       mutex_lock(&ctx->lock);
+       return (clkdiv < 0x100) ? clkdiv : 0xff;
+}
 
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               /*
-                * enable fimd hardware only if suspended status.
-                *
-                * P.S. fimd_dpms function would be called at booting time so
-                * clk_enable could be called double time.
-                */
-               if (ctx->suspended)
-                       pm_runtime_get_sync(subdrv_dev);
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               if (!ctx->suspended)
-                       pm_runtime_put_sync(subdrv_dev);
-               break;
-       default:
-               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-               break;
-       }
+static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       if (adjusted_mode->vrefresh == 0)
+               adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
 
-       mutex_unlock(&ctx->lock);
+       return true;
 }
 
-static void fimd_apply(struct device *subdrv_dev)
+static void fimd_mode_set(struct exynos_drm_manager *mgr,
+               const struct drm_display_mode *in_mode)
 {
-       struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-       struct exynos_drm_manager *mgr = ctx->subdrv.manager;
-       struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
-       struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
-       struct fimd_win_data *win_data;
-       int i;
-
-       for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               if (win_data->enabled && (ovl_ops && ovl_ops->commit))
-                       ovl_ops->commit(subdrv_dev, i);
-       }
+       struct fimd_context *ctx = mgr->ctx;
 
-       if (mgr_ops && mgr_ops->commit)
-               mgr_ops->commit(subdrv_dev);
+       drm_mode_copy(&ctx->mode, in_mode);
 }
 
-static void fimd_commit(struct device *dev)
+static void fimd_commit(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
-       struct exynos_drm_panel_info *panel = &ctx->panel;
-       struct videomode *vm = &panel->vm;
+       struct fimd_context *ctx = mgr->ctx;
+       struct drm_display_mode *mode = &ctx->mode;
        struct fimd_driver_data *driver_data;
-       u32 val;
+       u32 val, clkdiv, vidcon1;
+       int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
 
        driver_data = ctx->driver_data;
        if (ctx->suspended)
                return;
 
-       /* setup polarity values from machine code. */
-       writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+       /* nothing to do if we haven't set the mode yet */
+       if (mode->htotal == 0 || mode->vtotal == 0)
+               return;
+
+       /* setup polarity values */
+       vidcon1 = ctx->vidcon1;
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               vidcon1 |= VIDCON1_INV_VSYNC;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               vidcon1 |= VIDCON1_INV_HSYNC;
+       writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
 
        /* setup vertical timing values. */
-       val = VIDTCON0_VBPD(vm->vback_porch - 1) |
-              VIDTCON0_VFPD(vm->vfront_porch - 1) |
-              VIDTCON0_VSPW(vm->vsync_len - 1);
+       vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+       vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
+       vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
+       val = VIDTCON0_VBPD(vbpd - 1) |
+               VIDTCON0_VFPD(vfpd - 1) |
+               VIDTCON0_VSPW(vsync_len - 1);
        writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
 
        /* setup horizontal timing values.  */
-       val = VIDTCON1_HBPD(vm->hback_porch - 1) |
-              VIDTCON1_HFPD(vm->hfront_porch - 1) |
-              VIDTCON1_HSPW(vm->hsync_len - 1);
+       hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+       hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
+       hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+
+       val = VIDTCON1_HBPD(hbpd - 1) |
+               VIDTCON1_HFPD(hfpd - 1) |
+               VIDTCON1_HSPW(hsync_len - 1);
        writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
 
        /* setup horizontal and vertical display size. */
-       val = VIDTCON2_LINEVAL(vm->vactive - 1) |
-              VIDTCON2_HOZVAL(vm->hactive - 1) |
-              VIDTCON2_LINEVAL_E(vm->vactive - 1) |
-              VIDTCON2_HOZVAL_E(vm->hactive - 1);
+       val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
+              VIDTCON2_HOZVAL(mode->hdisplay - 1) |
+              VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
+              VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
        writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
 
-       /* setup clock source, clock divider, enable dma. */
-       val = ctx->vidcon0;
-       val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
-       if (ctx->driver_data->has_clksel) {
-               val &= ~VIDCON0_CLKSEL_MASK;
-               val |= VIDCON0_CLKSEL_LCD;
-       }
-
-       if (ctx->clkdiv > 1)
-               val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
-       else
-               val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
-
        /*
         * fields of register with prefix '_F' would be updated
         * at vsync(same as dma start)
         */
-       val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+       val = VIDCON0_ENVID | VIDCON0_ENVID_F;
+
+       if (ctx->driver_data->has_clksel)
+               val |= VIDCON0_CLKSEL_LCD;
+
+       clkdiv = fimd_calc_clkdiv(ctx, mode);
+       if (clkdiv > 1)
+               val |= VIDCON0_CLKVAL_F(clkdiv - 1) | VIDCON0_CLKDIR;
+
        writel(val, ctx->regs + VIDCON0);
 }
 
-static int fimd_enable_vblank(struct device *dev)
+static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        u32 val;
 
        if (ctx->suspended)
@@ -314,9 +306,9 @@ static int fimd_enable_vblank(struct device *dev)
        return 0;
 }
 
-static void fimd_disable_vblank(struct device *dev)
+static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        u32 val;
 
        if (ctx->suspended)
@@ -332,9 +324,9 @@ static void fimd_disable_vblank(struct device *dev)
        }
 }
 
-static void fimd_wait_for_vblank(struct device *dev)
+static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
 
        if (ctx->suspended)
                return;
@@ -351,25 +343,16 @@ static void fimd_wait_for_vblank(struct device *dev)
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
-static struct exynos_drm_manager_ops fimd_manager_ops = {
-       .dpms = fimd_dpms,
-       .apply = fimd_apply,
-       .commit = fimd_commit,
-       .enable_vblank = fimd_enable_vblank,
-       .disable_vblank = fimd_disable_vblank,
-       .wait_for_vblank = fimd_wait_for_vblank,
-};
-
-static void fimd_win_mode_set(struct device *dev,
-                             struct exynos_drm_overlay *overlay)
+static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
+                       struct exynos_drm_overlay *overlay)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        struct fimd_win_data *win_data;
        int win;
        unsigned long offset;
 
        if (!overlay) {
-               dev_err(dev, "overlay is NULL\n");
+               DRM_ERROR("overlay is NULL\n");
                return;
        }
 
@@ -409,9 +392,8 @@ static void fimd_win_mode_set(struct device *dev,
                        overlay->fb_width, overlay->crtc_width);
 }
 
-static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
+static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
        struct fimd_win_data *win_data = &ctx->win_data[win];
        unsigned long val;
 
@@ -467,9 +449,8 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
        writel(val, ctx->regs + WINCON(win));
 }
 
-static void fimd_win_set_colkey(struct device *dev, unsigned int win)
+static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
        unsigned int keycon0 = 0, keycon1 = 0;
 
        keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
@@ -508,9 +489,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
        writel(val, ctx->regs + reg);
 }
 
-static void fimd_win_commit(struct device *dev, int zpos)
+static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        struct fimd_win_data *win_data;
        int win = zpos;
        unsigned long val, alpha, size;
@@ -528,6 +509,12 @@ static void fimd_win_commit(struct device *dev, int zpos)
 
        win_data = &ctx->win_data[win];
 
+       /* If suspended, enable this on resume */
+       if (ctx->suspended) {
+               win_data->resume = true;
+               return;
+       }
+
        /*
         * SHADOWCON/PRTCON register is used for enabling timing.
         *
@@ -605,11 +592,11 @@ static void fimd_win_commit(struct device *dev, int zpos)
                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
        }
 
-       fimd_win_set_pixfmt(dev, win);
+       fimd_win_set_pixfmt(ctx, win);
 
        /* hardware window 0 doesn't support color key. */
        if (win != 0)
-               fimd_win_set_colkey(dev, win);
+               fimd_win_set_colkey(ctx, win);
 
        /* wincon */
        val = readl(ctx->regs + WINCON(win));
@@ -628,9 +615,9 @@ static void fimd_win_commit(struct device *dev, int zpos)
        win_data->enabled = true;
 }
 
-static void fimd_win_disable(struct device *dev, int zpos)
+static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        struct fimd_win_data *win_data;
        int win = zpos;
        u32 val;
@@ -669,132 +656,6 @@ static void fimd_win_disable(struct device *dev, int zpos)
        win_data->enabled = false;
 }
 
-static struct exynos_drm_overlay_ops fimd_overlay_ops = {
-       .mode_set = fimd_win_mode_set,
-       .commit = fimd_win_commit,
-       .disable = fimd_win_disable,
-};
-
-static struct exynos_drm_manager fimd_manager = {
-       .pipe           = -1,
-       .ops            = &fimd_manager_ops,
-       .overlay_ops    = &fimd_overlay_ops,
-       .display_ops    = &fimd_display_ops,
-};
-
-static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
-{
-       struct fimd_context *ctx = (struct fimd_context *)dev_id;
-       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct drm_device *drm_dev = subdrv->drm_dev;
-       struct exynos_drm_manager *manager = subdrv->manager;
-       u32 val;
-
-       val = readl(ctx->regs + VIDINTCON1);
-
-       if (val & VIDINTCON1_INT_FRAME)
-               /* VSYNC interrupt */
-               writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
-
-       /* check the crtc is detached already from encoder */
-       if (manager->pipe < 0)
-               goto out;
-
-       drm_handle_vblank(drm_dev, manager->pipe);
-       exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
-
-       /* set wait vsync event to zero and wake up queue. */
-       if (atomic_read(&ctx->wait_vsync_event)) {
-               atomic_set(&ctx->wait_vsync_event, 0);
-               wake_up(&ctx->wait_vsync_queue);
-       }
-out:
-       return IRQ_HANDLED;
-}
-
-static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
-       /*
-        * enable drm irq mode.
-        * - with irq_enabled = true, we can use the vblank feature.
-        *
-        * P.S. note that we wouldn't use drm irq handler but
-        *      just specific driver own one instead because
-        *      drm framework supports only one irq handler.
-        */
-       drm_dev->irq_enabled = true;
-
-       /*
-        * with vblank_disable_allowed = true, vblank interrupt will be disabled
-        * by drm timer once a current process gives up ownership of
-        * vblank event.(after drm_vblank_put function is called)
-        */
-       drm_dev->vblank_disable_allowed = true;
-
-       /* attach this sub driver to iommu mapping if supported. */
-       if (is_drm_iommu_supported(drm_dev))
-               drm_iommu_attach_device(drm_dev, dev);
-
-       return 0;
-}
-
-static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-       /* detach this sub driver from iommu mapping if supported. */
-       if (is_drm_iommu_supported(drm_dev))
-               drm_iommu_detach_device(drm_dev, dev);
-}
-
-static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
-{
-       struct videomode *vm = &ctx->panel.vm;
-       unsigned long clk;
-
-       ctx->bus_clk = devm_clk_get(dev, "fimd");
-       if (IS_ERR(ctx->bus_clk)) {
-               dev_err(dev, "failed to get bus clock\n");
-               return PTR_ERR(ctx->bus_clk);
-       }
-
-       ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
-       if (IS_ERR(ctx->lcd_clk)) {
-               dev_err(dev, "failed to get lcd clock\n");
-               return PTR_ERR(ctx->lcd_clk);
-       }
-
-       clk = clk_get_rate(ctx->lcd_clk);
-       if (clk == 0) {
-               dev_err(dev, "error getting sclk_fimd clock rate\n");
-               return -EINVAL;
-       }
-
-       if (vm->pixelclock == 0) {
-               unsigned long c;
-               c = vm->hactive + vm->hback_porch + vm->hfront_porch +
-                   vm->hsync_len;
-               c *= vm->vactive + vm->vback_porch + vm->vfront_porch +
-                    vm->vsync_len;
-               vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE;
-               if (vm->pixelclock == 0) {
-                       dev_err(dev, "incorrect display timings\n");
-                       return -EINVAL;
-               }
-               dev_warn(dev, "pixel clock recalculated to %luHz (%dHz frame rate)\n",
-                        vm->pixelclock, FIMD_DEFAULT_FRAMERATE);
-       }
-       ctx->clkdiv = DIV_ROUND_UP(clk, vm->pixelclock);
-       if (ctx->clkdiv > 256) {
-               dev_warn(dev, "calculated pixel clock divider too high (%u), lowered to 256\n",
-                        ctx->clkdiv);
-               ctx->clkdiv = 256;
-       }
-       vm->pixelclock = clk / ctx->clkdiv;
-       DRM_DEBUG_KMS("pixel clock = %lu, clkdiv = %d\n", vm->pixelclock,
-                     ctx->clkdiv);
-
-       return 0;
-}
-
 static void fimd_clear_win(struct fimd_context *ctx, int win)
 {
        writel(0, ctx->regs + WINCON(win));
@@ -808,111 +669,190 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
        fimd_shadow_protect_win(ctx, win, false);
 }
 
-static int fimd_clock(struct fimd_context *ctx, bool enable)
+static void fimd_window_suspend(struct exynos_drm_manager *mgr)
 {
-       if (enable) {
-               int ret;
-
-               ret = clk_prepare_enable(ctx->bus_clk);
-               if (ret < 0)
-                       return ret;
+       struct fimd_context *ctx = mgr->ctx;
+       struct fimd_win_data *win_data;
+       int i;
 
-               ret = clk_prepare_enable(ctx->lcd_clk);
-               if  (ret < 0) {
-                       clk_disable_unprepare(ctx->bus_clk);
-                       return ret;
-               }
-       } else {
-               clk_disable_unprepare(ctx->lcd_clk);
-               clk_disable_unprepare(ctx->bus_clk);
+       for (i = 0; i < WINDOWS_NR; i++) {
+               win_data = &ctx->win_data[i];
+               win_data->resume = win_data->enabled;
+               if (win_data->enabled)
+                       fimd_win_disable(mgr, i);
        }
-
-       return 0;
+       fimd_wait_for_vblank(mgr);
 }
 
-static void fimd_window_suspend(struct device *dev)
+static void fimd_window_resume(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        struct fimd_win_data *win_data;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
                win_data = &ctx->win_data[i];
-               win_data->resume = win_data->enabled;
-               fimd_win_disable(dev, i);
+               win_data->enabled = win_data->resume;
+               win_data->resume = false;
        }
-       fimd_wait_for_vblank(dev);
 }
 
-static void fimd_window_resume(struct device *dev)
+static void fimd_apply(struct exynos_drm_manager *mgr)
 {
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct fimd_context *ctx = mgr->ctx;
        struct fimd_win_data *win_data;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
                win_data = &ctx->win_data[i];
-               win_data->enabled = win_data->resume;
-               win_data->resume = false;
+               if (win_data->enabled)
+                       fimd_win_commit(mgr, i);
        }
+
+       fimd_commit(mgr);
 }
 
-static int fimd_activate(struct fimd_context *ctx, bool enable)
+static int fimd_poweron(struct exynos_drm_manager *mgr)
 {
-       struct device *dev = ctx->subdrv.dev;
-       if (enable) {
-               int ret;
+       struct fimd_context *ctx = mgr->ctx;
+       int ret;
 
-               ret = fimd_clock(ctx, true);
-               if (ret < 0)
-                       return ret;
+       if (!ctx->suspended)
+               return 0;
 
-               ctx->suspended = false;
+       ctx->suspended = false;
 
-               /* if vblank was enabled status, enable it again. */
-               if (test_and_clear_bit(0, &ctx->irq_flags))
-                       fimd_enable_vblank(dev);
+       pm_runtime_get_sync(ctx->dev);
 
-               fimd_window_resume(dev);
-       } else {
-               fimd_window_suspend(dev);
+       ret = clk_prepare_enable(ctx->bus_clk);
+       if (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
+               goto bus_clk_err;
+       }
+
+       ret = clk_prepare_enable(ctx->lcd_clk);
+       if  (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
+               goto lcd_clk_err;
+       }
 
-               fimd_clock(ctx, false);
-               ctx->suspended = true;
+       /* if vblank was enabled status, enable it again. */
+       if (test_and_clear_bit(0, &ctx->irq_flags)) {
+               ret = fimd_enable_vblank(mgr);
+               if (ret) {
+                       DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
+                       goto enable_vblank_err;
+               }
        }
 
+       fimd_window_resume(mgr);
+
+       fimd_apply(mgr);
+
        return 0;
+
+enable_vblank_err:
+       clk_disable_unprepare(ctx->lcd_clk);
+lcd_clk_err:
+       clk_disable_unprepare(ctx->bus_clk);
+bus_clk_err:
+       ctx->suspended = true;
+       return ret;
 }
 
-static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev)
+static int fimd_poweroff(struct exynos_drm_manager *mgr)
 {
-       struct videomode *vm;
-       int ret;
+       struct fimd_context *ctx = mgr->ctx;
 
-       vm = &ctx->panel.vm;
-       ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE);
-       if (ret) {
-               DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
-               return ret;
-       }
+       if (ctx->suspended)
+               return 0;
 
-       if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
-               ctx->vidcon1 |= VIDCON1_INV_VSYNC;
-       if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
-               ctx->vidcon1 |= VIDCON1_INV_HSYNC;
-       if (vm->flags & DISPLAY_FLAGS_DE_LOW)
-               ctx->vidcon1 |= VIDCON1_INV_VDEN;
-       if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
-               ctx->vidcon1 |= VIDCON1_INV_VCLK;
+       /*
+        * We need to make sure that all windows are disabled before we
+        * suspend that connector. Otherwise we might try to scan from
+        * a destroyed buffer later.
+        */
+       fimd_window_suspend(mgr);
 
+       clk_disable_unprepare(ctx->lcd_clk);
+       clk_disable_unprepare(ctx->bus_clk);
+
+       pm_runtime_put_sync(ctx->dev);
+
+       ctx->suspended = true;
        return 0;
 }
 
+static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
+{
+       DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               fimd_poweron(mgr);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               fimd_poweroff(mgr);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
+       }
+}
+
+static struct exynos_drm_manager_ops fimd_manager_ops = {
+       .initialize = fimd_mgr_initialize,
+       .remove = fimd_mgr_remove,
+       .dpms = fimd_dpms,
+       .mode_fixup = fimd_mode_fixup,
+       .mode_set = fimd_mode_set,
+       .commit = fimd_commit,
+       .enable_vblank = fimd_enable_vblank,
+       .disable_vblank = fimd_disable_vblank,
+       .wait_for_vblank = fimd_wait_for_vblank,
+       .win_mode_set = fimd_win_mode_set,
+       .win_commit = fimd_win_commit,
+       .win_disable = fimd_win_disable,
+};
+
+static struct exynos_drm_manager fimd_manager = {
+       .type = EXYNOS_DISPLAY_TYPE_LCD,
+       .ops = &fimd_manager_ops,
+};
+
+static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
+{
+       struct fimd_context *ctx = (struct fimd_context *)dev_id;
+       u32 val;
+
+       val = readl(ctx->regs + VIDINTCON1);
+
+       if (val & VIDINTCON1_INT_FRAME)
+               /* VSYNC interrupt */
+               writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+
+       /* check the crtc is detached already from encoder */
+       if (ctx->pipe < 0 || !ctx->drm_dev)
+               goto out;
+
+       drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+       exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+
+       /* set wait vsync event to zero and wake up queue. */
+       if (atomic_read(&ctx->wait_vsync_event)) {
+               atomic_set(&ctx->wait_vsync_event, 0);
+               wake_up(&ctx->wait_vsync_queue);
+       }
+out:
+       return IRQ_HANDLED;
+}
+
 static int fimd_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimd_context *ctx;
-       struct exynos_drm_subdrv *subdrv;
        struct resource *res;
        int win;
        int ret = -EINVAL;
@@ -924,13 +864,25 @@ static int fimd_probe(struct platform_device *pdev)
        if (!ctx)
                return -ENOMEM;
 
-       ret = fimd_get_platform_data(ctx, dev);
-       if (ret)
-               return ret;
+       ctx->dev = dev;
+       ctx->suspended = true;
 
-       ret = fimd_configure_clocks(ctx, dev);
-       if (ret)
-               return ret;
+       if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
+               ctx->vidcon1 |= VIDCON1_INV_VDEN;
+       if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
+               ctx->vidcon1 |= VIDCON1_INV_VCLK;
+
+       ctx->bus_clk = devm_clk_get(dev, "fimd");
+       if (IS_ERR(ctx->bus_clk)) {
+               dev_err(dev, "failed to get bus clock\n");
+               return PTR_ERR(ctx->bus_clk);
+       }
+
+       ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
+       if (IS_ERR(ctx->lcd_clk)) {
+               dev_err(dev, "failed to get lcd clock\n");
+               return PTR_ERR(ctx->lcd_clk);
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -944,9 +896,7 @@ static int fimd_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       ctx->irq = res->start;
-
-       ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
+       ret = devm_request_irq(dev, res->start, fimd_irq_handler,
                                                        0, "drm_fimd", ctx);
        if (ret) {
                dev_err(dev, "irq request failed.\n");
@@ -957,112 +907,35 @@ static int fimd_probe(struct platform_device *pdev)
        init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
-       subdrv = &ctx->subdrv;
+       platform_set_drvdata(pdev, &fimd_manager);
 
-       subdrv->dev = dev;
-       subdrv->manager = &fimd_manager;
-       subdrv->probe = fimd_subdrv_probe;
-       subdrv->remove = fimd_subdrv_remove;
+       fimd_manager.ctx = ctx;
+       exynos_drm_manager_register(&fimd_manager);
 
-       mutex_init(&ctx->lock);
-
-       platform_set_drvdata(pdev, ctx);
+       exynos_dpi_probe(ctx->dev);
 
        pm_runtime_enable(dev);
-       pm_runtime_get_sync(dev);
 
        for (win = 0; win < WINDOWS_NR; win++)
                fimd_clear_win(ctx, win);
 
-       exynos_drm_subdrv_register(subdrv);
-
        return 0;
 }
 
 static int fimd_remove(struct platform_device *pdev)
 {
-       struct device *dev = &pdev->dev;
-       struct fimd_context *ctx = platform_get_drvdata(pdev);
-
-       exynos_drm_subdrv_unregister(&ctx->subdrv);
-
-       if (ctx->suspended)
-               goto out;
-
-       pm_runtime_set_suspended(dev);
-       pm_runtime_put_sync(dev);
-
-out:
-       pm_runtime_disable(dev);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int fimd_suspend(struct device *dev)
-{
-       struct fimd_context *ctx = get_fimd_context(dev);
+       struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
 
-       /*
-        * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
-        * called here, an error would be returned by that interface
-        * because the usage_count of pm runtime is more than 1.
-        */
-       if (!pm_runtime_suspended(dev))
-               return fimd_activate(ctx, false);
+       exynos_dpi_remove(&pdev->dev);
 
-       return 0;
-}
+       exynos_drm_manager_unregister(&fimd_manager);
 
-static int fimd_resume(struct device *dev)
-{
-       struct fimd_context *ctx = get_fimd_context(dev);
+       fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
 
-       /*
-        * if entered to sleep when lcd panel was on, the usage_count
-        * of pm runtime would still be 1 so in this case, fimd driver
-        * should be on directly not drawing on pm runtime interface.
-        */
-       if (!pm_runtime_suspended(dev)) {
-               int ret;
-
-               ret = fimd_activate(ctx, true);
-               if (ret < 0)
-                       return ret;
-
-               /*
-                * in case of dpms on(standby), fimd_apply function will
-                * be called by encoder's dpms callback to update fimd's
-                * registers but in case of sleep wakeup, it's not.
-                * so fimd_apply function should be called at here.
-                */
-               fimd_apply(dev);
-       }
+       pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int fimd_runtime_suspend(struct device *dev)
-{
-       struct fimd_context *ctx = get_fimd_context(dev);
-
-       return fimd_activate(ctx, false);
-}
-
-static int fimd_runtime_resume(struct device *dev)
-{
-       struct fimd_context *ctx = get_fimd_context(dev);
-
-       return fimd_activate(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops fimd_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
-       SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
-};
 
 struct platform_driver fimd_driver = {
        .probe          = fimd_probe,
@@ -1070,7 +943,6 @@ struct platform_driver fimd_driver = {
        .driver         = {
                .name   = "exynos4-fb",
                .owner  = THIS_MODULE,
-               .pm     = &fimd_pm_ops,
                .of_match_table = fimd_driver_dt_match,
        },
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
deleted file mode 100644 (file)
index 8548b97..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- *     Inki Dae <inki.dae@samsung.com>
- *     Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-#define to_context(dev)                platform_get_drvdata(to_platform_device(dev))
-#define to_subdrv(dev)         to_context(dev)
-#define get_ctx_from_subdrv(subdrv)    container_of(subdrv,\
-                                       struct drm_hdmi_context, subdrv);
-
-/* platform device pointer for common drm hdmi device. */
-static struct platform_device *exynos_drm_hdmi_pdev;
-
-/* Common hdmi subdrv needs to access the hdmi and mixer though context.
-* These should be initialied by the repective drivers */
-static struct exynos_drm_hdmi_context *hdmi_ctx;
-static struct exynos_drm_hdmi_context *mixer_ctx;
-
-/* these callback points shoud be set by specific drivers. */
-static struct exynos_hdmi_ops *hdmi_ops;
-static struct exynos_mixer_ops *mixer_ops;
-
-struct drm_hdmi_context {
-       struct exynos_drm_subdrv        subdrv;
-       struct exynos_drm_hdmi_context  *hdmi_ctx;
-       struct exynos_drm_hdmi_context  *mixer_ctx;
-
-       bool    enabled[MIXER_WIN_NR];
-};
-
-int exynos_platform_device_hdmi_register(void)
-{
-       struct platform_device *pdev;
-
-       if (exynos_drm_hdmi_pdev)
-               return -EEXIST;
-
-       pdev = platform_device_register_simple(
-                       "exynos-drm-hdmi", -1, NULL, 0);
-       if (IS_ERR(pdev))
-               return PTR_ERR(pdev);
-
-       exynos_drm_hdmi_pdev = pdev;
-
-       return 0;
-}
-
-void exynos_platform_device_hdmi_unregister(void)
-{
-       if (exynos_drm_hdmi_pdev) {
-               platform_device_unregister(exynos_drm_hdmi_pdev);
-               exynos_drm_hdmi_pdev = NULL;
-       }
-}
-
-void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)
-{
-       if (ctx)
-               hdmi_ctx = ctx;
-}
-
-void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
-{
-       if (ctx)
-               mixer_ctx = ctx;
-}
-
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
-{
-       if (ops)
-               hdmi_ops = ops;
-}
-
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
-{
-       if (ops)
-               mixer_ops = ops;
-}
-
-static bool drm_hdmi_is_connected(struct device *dev)
-{
-       struct drm_hdmi_context *ctx = to_context(dev);
-
-       if (hdmi_ops && hdmi_ops->is_connected)
-               return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
-
-       return false;
-}
-
-static struct edid *drm_hdmi_get_edid(struct device *dev,
-                       struct drm_connector *connector)
-{
-       struct drm_hdmi_context *ctx = to_context(dev);
-
-       if (hdmi_ops && hdmi_ops->get_edid)
-               return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
-
-       return NULL;
-}
-
-static int drm_hdmi_check_mode(struct device *dev,
-               struct drm_display_mode *mode)
-{
-       struct drm_hdmi_context *ctx = to_context(dev);
-       int ret = 0;
-
-       /*
-       * Both, mixer and hdmi should be able to handle the requested mode.
-       * If any of the two fails, return mode as BAD.
-       */
-
-       if (mixer_ops && mixer_ops->check_mode)
-               ret = mixer_ops->check_mode(ctx->mixer_ctx->ctx, mode);
-
-       if (ret)
-               return ret;
-
-       if (hdmi_ops && hdmi_ops->check_mode)
-               return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
-
-       return 0;
-}
-
-static int drm_hdmi_power_on(struct device *dev, int mode)
-{
-       struct drm_hdmi_context *ctx = to_context(dev);
-
-       if (hdmi_ops && hdmi_ops->power_on)
-               return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
-
-       return 0;
-}
-
-static struct exynos_drm_display_ops drm_hdmi_display_ops = {
-       .type = EXYNOS_DISPLAY_TYPE_HDMI,
-       .is_connected = drm_hdmi_is_connected,
-       .get_edid = drm_hdmi_get_edid,
-       .check_mode = drm_hdmi_check_mode,
-       .power_on = drm_hdmi_power_on,
-};
-
-static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct exynos_drm_manager *manager = subdrv->manager;
-
-       if (mixer_ops && mixer_ops->enable_vblank)
-               return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
-                                               manager->pipe);
-
-       return 0;
-}
-
-static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (mixer_ops && mixer_ops->disable_vblank)
-               return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (mixer_ops && mixer_ops->wait_for_vblank)
-               mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
-                               struct drm_connector *connector,
-                               const struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-       struct drm_display_mode *m;
-       int mode_ok;
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       mode_ok = drm_hdmi_check_mode(subdrv_dev, adjusted_mode);
-
-       /* just return if user desired mode exists. */
-       if (mode_ok == 0)
-               return;
-
-       /*
-        * otherwise, find the most suitable mode among modes and change it
-        * to adjusted_mode.
-        */
-       list_for_each_entry(m, &connector->modes, head) {
-               mode_ok = drm_hdmi_check_mode(subdrv_dev, m);
-
-               if (mode_ok == 0) {
-                       struct drm_mode_object base;
-                       struct list_head head;
-
-                       DRM_INFO("desired mode doesn't exist so\n");
-                       DRM_INFO("use the most suitable mode among modes.\n");
-
-                       DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
-                               m->hdisplay, m->vdisplay, m->vrefresh);
-
-                       /* preserve display mode header while copying. */
-                       head = adjusted_mode->head;
-                       base = adjusted_mode->base;
-                       memcpy(adjusted_mode, m, sizeof(*m));
-                       adjusted_mode->head = head;
-                       adjusted_mode->base = base;
-                       break;
-               }
-       }
-}
-
-static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (hdmi_ops && hdmi_ops->mode_set)
-               hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
-                               unsigned int *width, unsigned int *height)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (hdmi_ops && hdmi_ops->get_max_resol)
-               hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
-}
-
-static void drm_hdmi_commit(struct device *subdrv_dev)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (hdmi_ops && hdmi_ops->commit)
-               hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (mixer_ops && mixer_ops->dpms)
-               mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
-
-       if (hdmi_ops && hdmi_ops->dpms)
-               hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_apply(struct device *subdrv_dev)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-       int i;
-
-       for (i = 0; i < MIXER_WIN_NR; i++) {
-               if (!ctx->enabled[i])
-                       continue;
-               if (mixer_ops && mixer_ops->win_commit)
-                       mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
-       }
-
-       if (hdmi_ops && hdmi_ops->commit)
-               hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
-       .dpms = drm_hdmi_dpms,
-       .apply = drm_hdmi_apply,
-       .enable_vblank = drm_hdmi_enable_vblank,
-       .disable_vblank = drm_hdmi_disable_vblank,
-       .wait_for_vblank = drm_hdmi_wait_for_vblank,
-       .mode_fixup = drm_hdmi_mode_fixup,
-       .mode_set = drm_hdmi_mode_set,
-       .get_max_resol = drm_hdmi_get_max_resol,
-       .commit = drm_hdmi_commit,
-};
-
-static void drm_mixer_mode_set(struct device *subdrv_dev,
-               struct exynos_drm_overlay *overlay)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
-       if (mixer_ops && mixer_ops->win_mode_set)
-               mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
-}
-
-static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-       int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
-       if (win < 0 || win >= MIXER_WIN_NR) {
-               DRM_ERROR("mixer window[%d] is wrong\n", win);
-               return;
-       }
-
-       if (mixer_ops && mixer_ops->win_commit)
-               mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
-
-       ctx->enabled[win] = true;
-}
-
-static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
-{
-       struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-       int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
-       if (win < 0 || win >= MIXER_WIN_NR) {
-               DRM_ERROR("mixer window[%d] is wrong\n", win);
-               return;
-       }
-
-       if (mixer_ops && mixer_ops->win_disable)
-               mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
-
-       ctx->enabled[win] = false;
-}
-
-static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
-       .mode_set = drm_mixer_mode_set,
-       .commit = drm_mixer_commit,
-       .disable = drm_mixer_disable,
-};
-
-static struct exynos_drm_manager hdmi_manager = {
-       .pipe           = -1,
-       .ops            = &drm_hdmi_manager_ops,
-       .overlay_ops    = &drm_hdmi_overlay_ops,
-       .display_ops    = &drm_hdmi_display_ops,
-};
-
-static int hdmi_subdrv_probe(struct drm_device *drm_dev,
-               struct device *dev)
-{
-       struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
-       struct drm_hdmi_context *ctx;
-
-       if (!hdmi_ctx) {
-               DRM_ERROR("hdmi context not initialized.\n");
-               return -EFAULT;
-       }
-
-       if (!mixer_ctx) {
-               DRM_ERROR("mixer context not initialized.\n");
-               return -EFAULT;
-       }
-
-       ctx = get_ctx_from_subdrv(subdrv);
-
-       if (!ctx) {
-               DRM_ERROR("no drm hdmi context.\n");
-               return -EFAULT;
-       }
-
-       ctx->hdmi_ctx = hdmi_ctx;
-       ctx->mixer_ctx = mixer_ctx;
-
-       ctx->hdmi_ctx->drm_dev = drm_dev;
-       ctx->mixer_ctx->drm_dev = drm_dev;
-
-       if (mixer_ops->iommu_on)
-               mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
-
-       return 0;
-}
-
-static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-       struct drm_hdmi_context *ctx;
-       struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
-
-       ctx = get_ctx_from_subdrv(subdrv);
-
-       if (mixer_ops->iommu_on)
-               mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
-}
-
-static int exynos_drm_hdmi_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct exynos_drm_subdrv *subdrv;
-       struct drm_hdmi_context *ctx;
-
-       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
-
-       subdrv = &ctx->subdrv;
-
-       subdrv->dev = dev;
-       subdrv->manager = &hdmi_manager;
-       subdrv->probe = hdmi_subdrv_probe;
-       subdrv->remove = hdmi_subdrv_remove;
-
-       platform_set_drvdata(pdev, subdrv);
-
-       exynos_drm_subdrv_register(subdrv);
-
-       return 0;
-}
-
-static int exynos_drm_hdmi_remove(struct platform_device *pdev)
-{
-       struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-
-       exynos_drm_subdrv_unregister(&ctx->subdrv);
-
-       return 0;
-}
-
-struct platform_driver exynos_drm_common_hdmi_driver = {
-       .probe          = exynos_drm_hdmi_probe,
-       .remove         = exynos_drm_hdmi_remove,
-       .driver         = {
-               .name   = "exynos-drm-hdmi",
-               .owner  = THIS_MODULE,
-       },
-};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
deleted file mode 100644 (file)
index 724cab1..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* exynos_drm_hdmi.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef _EXYNOS_DRM_HDMI_H_
-#define _EXYNOS_DRM_HDMI_H_
-
-#define MIXER_WIN_NR           3
-#define MIXER_DEFAULT_WIN      0
-
-/*
- * exynos hdmi common context structure.
- *
- * @drm_dev: pointer to drm_device.
- * @ctx: pointer to the context of specific device driver.
- *     this context should be hdmi_context or mixer_context.
- */
-struct exynos_drm_hdmi_context {
-       struct drm_device       *drm_dev;
-       void                    *ctx;
-};
-
-struct exynos_hdmi_ops {
-       /* display */
-       bool (*is_connected)(void *ctx);
-       struct edid *(*get_edid)(void *ctx,
-                       struct drm_connector *connector);
-       int (*check_mode)(void *ctx, struct drm_display_mode *mode);
-       int (*power_on)(void *ctx, int mode);
-
-       /* manager */
-       void (*mode_set)(void *ctx, struct drm_display_mode *mode);
-       void (*get_max_resol)(void *ctx, unsigned int *width,
-                               unsigned int *height);
-       void (*commit)(void *ctx);
-       void (*dpms)(void *ctx, int mode);
-};
-
-struct exynos_mixer_ops {
-       /* manager */
-       int (*iommu_on)(void *ctx, bool enable);
-       int (*enable_vblank)(void *ctx, int pipe);
-       void (*disable_vblank)(void *ctx);
-       void (*wait_for_vblank)(void *ctx);
-       void (*dpms)(void *ctx, int mode);
-
-       /* overlay */
-       void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
-       void (*win_commit)(void *ctx, int zpos);
-       void (*win_disable)(void *ctx, int zpos);
-
-       /* display */
-       int (*check_mode)(void *ctx, struct drm_display_mode *mode);
-};
-
-void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
-void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx);
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
-#endif
index fcb0652e77d04975f005e885faf33c70e2b291ba..8371cbd7631d421365a194c9b3d936fd8b02a567 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <drm/exynos_drm.h>
 #include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_plane.h"
@@ -87,7 +87,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
                struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
 
                if (!buffer) {
-                       DRM_LOG_KMS("buffer is null\n");
+                       DRM_DEBUG_KMS("buffer is null\n");
                        return -EFAULT;
                }
 
@@ -139,7 +139,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
                        overlay->crtc_x, overlay->crtc_y,
                        overlay->crtc_width, overlay->crtc_height);
 
-       exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set);
+       exynos_drm_crtc_plane_mode_set(crtc, overlay);
 
        return 0;
 }
@@ -149,8 +149,7 @@ void exynos_plane_commit(struct drm_plane *plane)
        struct exynos_plane *exynos_plane = to_exynos_plane(plane);
        struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
 
-       exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-                       exynos_drm_encoder_plane_commit);
+       exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos);
 }
 
 void exynos_plane_dpms(struct drm_plane *plane, int mode)
@@ -162,17 +161,13 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
                if (exynos_plane->enabled)
                        return;
 
-               exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-                               exynos_drm_encoder_plane_enable);
-
+               exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos);
                exynos_plane->enabled = true;
        } else {
                if (!exynos_plane->enabled)
                        return;
 
-               exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-                               exynos_drm_encoder_plane_disable);
-
+               exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos);
                exynos_plane->enabled = false;
        }
 }
@@ -259,7 +254,7 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
 }
 
 struct drm_plane *exynos_plane_init(struct drm_device *dev,
-                                   unsigned int possible_crtcs, bool priv)
+                                   unsigned long possible_crtcs, bool priv)
 {
        struct exynos_plane *exynos_plane;
        int err;
index 88312458580d459946cd67a1f794a13929254374..84d464c90d3d34b095459e29304fb3aec1cf6a79 100644 (file)
@@ -17,4 +17,4 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 void exynos_plane_commit(struct drm_plane *plane);
 void exynos_plane_dpms(struct drm_plane *plane, int mode);
 struct drm_plane *exynos_plane_init(struct drm_device *dev,
-                                   unsigned int possible_crtcs, bool priv);
+                                   unsigned long possible_crtcs, bool priv);
index ddaaedde173d0814b5823e628bc1f61e07eae8d8..7afead9c3f30258b7869e69e0f2015d9c2921fca 100644 (file)
@@ -28,7 +28,9 @@
 /* vidi has totally three virtual windows. */
 #define WINDOWS_NR             3
 
-#define get_vidi_context(dev)  platform_get_drvdata(to_platform_device(dev))
+#define get_vidi_mgr(dev)      platform_get_drvdata(to_platform_device(dev))
+#define ctx_from_connector(c)  container_of(c, struct vidi_context, \
+                                       connector)
 
 struct vidi_win_data {
        unsigned int            offset_x;
@@ -45,8 +47,10 @@ struct vidi_win_data {
 };
 
 struct vidi_context {
-       struct exynos_drm_subdrv        subdrv;
+       struct drm_device               *drm_dev;
        struct drm_crtc                 *crtc;
+       struct drm_encoder              *encoder;
+       struct drm_connector            connector;
        struct vidi_win_data            win_data[WINDOWS_NR];
        struct edid                     *raw_edid;
        unsigned int                    clkdiv;
@@ -58,6 +62,7 @@ struct vidi_context {
        bool                            direct_vblank;
        struct work_struct              work;
        struct mutex                    lock;
+       int                             pipe;
 };
 
 static const char fake_edid_info[] = {
@@ -85,126 +90,34 @@ static const char fake_edid_info[] = {
        0x00, 0x00, 0x00, 0x06
 };
 
-static bool vidi_display_is_connected(struct device *dev)
+static void vidi_apply(struct exynos_drm_manager *mgr)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
-
-       /*
-        * connection request would come from user side
-        * to do hotplug through specific ioctl.
-        */
-       return ctx->connected ? true : false;
-}
-
-static struct edid *vidi_get_edid(struct device *dev,
-                       struct drm_connector *connector)
-{
-       struct vidi_context *ctx = get_vidi_context(dev);
-       struct edid *edid;
-
-       /*
-        * the edid data comes from user side and it would be set
-        * to ctx->raw_edid through specific ioctl.
-        */
-       if (!ctx->raw_edid) {
-               DRM_DEBUG_KMS("raw_edid is null.\n");
-               return ERR_PTR(-EFAULT);
-       }
-
-       edid = drm_edid_duplicate(ctx->raw_edid);
-       if (!edid) {
-               DRM_DEBUG_KMS("failed to allocate edid\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       return edid;
-}
-
-static void *vidi_get_panel(struct device *dev)
-{
-       /* TODO. */
-
-       return NULL;
-}
-
-static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
-{
-       /* TODO. */
-
-       return 0;
-}
-
-static int vidi_display_power_on(struct device *dev, int mode)
-{
-       /* TODO */
-
-       return 0;
-}
-
-static struct exynos_drm_display_ops vidi_display_ops = {
-       .type = EXYNOS_DISPLAY_TYPE_VIDI,
-       .is_connected = vidi_display_is_connected,
-       .get_edid = vidi_get_edid,
-       .get_panel = vidi_get_panel,
-       .check_mode = vidi_check_mode,
-       .power_on = vidi_display_power_on,
-};
-
-static void vidi_dpms(struct device *subdrv_dev, int mode)
-{
-       struct vidi_context *ctx = get_vidi_context(subdrv_dev);
-
-       DRM_DEBUG_KMS("%d\n", mode);
-
-       mutex_lock(&ctx->lock);
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               /* TODO. */
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               /* TODO. */
-               break;
-       default:
-               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-               break;
-       }
-
-       mutex_unlock(&ctx->lock);
-}
-
-static void vidi_apply(struct device *subdrv_dev)
-{
-       struct vidi_context *ctx = get_vidi_context(subdrv_dev);
-       struct exynos_drm_manager *mgr = ctx->subdrv.manager;
+       struct vidi_context *ctx = mgr->ctx;
        struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
-       struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
        struct vidi_win_data *win_data;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
                win_data = &ctx->win_data[i];
-               if (win_data->enabled && (ovl_ops && ovl_ops->commit))
-                       ovl_ops->commit(subdrv_dev, i);
+               if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
+                       mgr_ops->win_commit(mgr, i);
        }
 
        if (mgr_ops && mgr_ops->commit)
-               mgr_ops->commit(subdrv_dev);
+               mgr_ops->commit(mgr);
 }
 
-static void vidi_commit(struct device *dev)
+static void vidi_commit(struct exynos_drm_manager *mgr)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
 
        if (ctx->suspended)
                return;
 }
 
-static int vidi_enable_vblank(struct device *dev)
+static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
 
        if (ctx->suspended)
                return -EPERM;
@@ -217,16 +130,16 @@ static int vidi_enable_vblank(struct device *dev)
        /*
         * in case of page flip request, vidi_finish_pageflip function
         * will not be called because direct_vblank is true and then
-        * that function will be called by overlay_ops->commit callback
+        * that function will be called by manager_ops->win_commit callback
         */
        schedule_work(&ctx->work);
 
        return 0;
 }
 
-static void vidi_disable_vblank(struct device *dev)
+static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
 
        if (ctx->suspended)
                return;
@@ -235,24 +148,16 @@ static void vidi_disable_vblank(struct device *dev)
                ctx->vblank_on = false;
 }
 
-static struct exynos_drm_manager_ops vidi_manager_ops = {
-       .dpms = vidi_dpms,
-       .apply = vidi_apply,
-       .commit = vidi_commit,
-       .enable_vblank = vidi_enable_vblank,
-       .disable_vblank = vidi_disable_vblank,
-};
-
-static void vidi_win_mode_set(struct device *dev,
-                             struct exynos_drm_overlay *overlay)
+static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
+                       struct exynos_drm_overlay *overlay)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
        struct vidi_win_data *win_data;
        int win;
        unsigned long offset;
 
        if (!overlay) {
-               dev_err(dev, "overlay is NULL\n");
+               DRM_ERROR("overlay is NULL\n");
                return;
        }
 
@@ -296,9 +201,9 @@ static void vidi_win_mode_set(struct device *dev,
                        overlay->fb_width, overlay->crtc_width);
 }
 
-static void vidi_win_commit(struct device *dev, int zpos)
+static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
        struct vidi_win_data *win_data;
        int win = zpos;
 
@@ -321,9 +226,9 @@ static void vidi_win_commit(struct device *dev, int zpos)
                schedule_work(&ctx->work);
 }
 
-static void vidi_win_disable(struct device *dev, int zpos)
+static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct vidi_context *ctx = mgr->ctx;
        struct vidi_win_data *win_data;
        int win = zpos;
 
@@ -339,98 +244,132 @@ static void vidi_win_disable(struct device *dev, int zpos)
        /* TODO. */
 }
 
-static struct exynos_drm_overlay_ops vidi_overlay_ops = {
-       .mode_set = vidi_win_mode_set,
-       .commit = vidi_win_commit,
-       .disable = vidi_win_disable,
-};
+static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
+{
+       struct vidi_context *ctx = mgr->ctx;
 
-static struct exynos_drm_manager vidi_manager = {
-       .pipe           = -1,
-       .ops            = &vidi_manager_ops,
-       .overlay_ops    = &vidi_overlay_ops,
-       .display_ops    = &vidi_display_ops,
-};
+       DRM_DEBUG_KMS("%s\n", __FILE__);
 
-static void vidi_fake_vblank_handler(struct work_struct *work)
-{
-       struct vidi_context *ctx = container_of(work, struct vidi_context,
-                                       work);
-       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct exynos_drm_manager *manager = subdrv->manager;
+       if (enable != false && enable != true)
+               return -EINVAL;
 
-       if (manager->pipe < 0)
-               return;
+       if (enable) {
+               ctx->suspended = false;
 
-       /* refresh rate is about 50Hz. */
-       usleep_range(16000, 20000);
+               /* if vblank was enabled status, enable it again. */
+               if (test_and_clear_bit(0, &ctx->irq_flags))
+                       vidi_enable_vblank(mgr);
+
+               vidi_apply(mgr);
+       } else {
+               ctx->suspended = true;
+       }
+
+       return 0;
+}
+
+static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
+{
+       struct vidi_context *ctx = mgr->ctx;
+
+       DRM_DEBUG_KMS("%d\n", mode);
 
        mutex_lock(&ctx->lock);
 
-       if (ctx->direct_vblank) {
-               drm_handle_vblank(subdrv->drm_dev, manager->pipe);
-               ctx->direct_vblank = false;
-               mutex_unlock(&ctx->lock);
-               return;
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               vidi_power_on(mgr, true);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               vidi_power_on(mgr, false);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
        }
 
        mutex_unlock(&ctx->lock);
-
-       exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe);
 }
 
-static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
+                       struct drm_device *drm_dev, int pipe)
 {
+       struct vidi_context *ctx = mgr->ctx;
+
+       DRM_ERROR("vidi initialize ct=%p dev=%p pipe=%d\n", ctx, drm_dev, pipe);
+
+       ctx->drm_dev = drm_dev;
+       ctx->pipe = pipe;
+
        /*
         * enable drm irq mode.
-        * - with irq_enabled = true, we can use the vblank feature.
+        * - with irq_enabled = 1, we can use the vblank feature.
         *
         * P.S. note that we wouldn't use drm irq handler but
         *      just specific driver own one instead because
         *      drm framework supports only one irq handler.
         */
-       drm_dev->irq_enabled = true;
+       drm_dev->irq_enabled = 1;
 
        /*
-        * with vblank_disable_allowed = true, vblank interrupt will be disabled
+        * with vblank_disable_allowed = 1, vblank interrupt will be disabled
         * by drm timer once a current process gives up ownership of
         * vblank event.(after drm_vblank_put function is called)
         */
-       drm_dev->vblank_disable_allowed = true;
+       drm_dev->vblank_disable_allowed = 1;
 
        return 0;
 }
 
-static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-       /* TODO. */
-}
+static struct exynos_drm_manager_ops vidi_manager_ops = {
+       .initialize = vidi_mgr_initialize,
+       .dpms = vidi_dpms,
+       .commit = vidi_commit,
+       .enable_vblank = vidi_enable_vblank,
+       .disable_vblank = vidi_disable_vblank,
+       .win_mode_set = vidi_win_mode_set,
+       .win_commit = vidi_win_commit,
+       .win_disable = vidi_win_disable,
+};
 
-static int vidi_power_on(struct vidi_context *ctx, bool enable)
+static struct exynos_drm_manager vidi_manager = {
+       .type = EXYNOS_DISPLAY_TYPE_VIDI,
+       .ops = &vidi_manager_ops,
+};
+
+static void vidi_fake_vblank_handler(struct work_struct *work)
 {
-       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct device *dev = subdrv->dev;
+       struct vidi_context *ctx = container_of(work, struct vidi_context,
+                                       work);
 
-       if (enable) {
-               ctx->suspended = false;
+       if (ctx->pipe < 0)
+               return;
 
-               /* if vblank was enabled status, enable it again. */
-               if (test_and_clear_bit(0, &ctx->irq_flags))
-                       vidi_enable_vblank(dev);
+       /* refresh rate is about 50Hz. */
+       usleep_range(16000, 20000);
 
-               vidi_apply(dev);
-       } else {
-               ctx->suspended = true;
+       mutex_lock(&ctx->lock);
+
+       if (ctx->direct_vblank) {
+               drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+               ctx->direct_vblank = false;
+               mutex_unlock(&ctx->lock);
+               return;
        }
 
-       return 0;
+       mutex_unlock(&ctx->lock);
+
+       exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 }
 
 static int vidi_show_connection(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        int rc;
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+       struct vidi_context *ctx = mgr->ctx;
 
        mutex_lock(&ctx->lock);
 
@@ -445,7 +384,8 @@ static int vidi_store_connection(struct device *dev,
                                struct device_attribute *attr,
                                const char *buf, size_t len)
 {
-       struct vidi_context *ctx = get_vidi_context(dev);
+       struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+       struct vidi_context *ctx = mgr->ctx;
        int ret;
 
        ret = kstrtoint(buf, 0, &ctx->connected);
@@ -467,7 +407,7 @@ static int vidi_store_connection(struct device *dev,
 
        DRM_DEBUG_KMS("requested connection.\n");
 
-       drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
+       drm_helper_hpd_irq_event(ctx->drm_dev);
 
        return len;
 }
@@ -480,8 +420,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 {
        struct vidi_context *ctx = NULL;
        struct drm_encoder *encoder;
-       struct exynos_drm_manager *manager;
-       struct exynos_drm_display_ops *display_ops;
+       struct exynos_drm_display *display;
        struct drm_exynos_vidi_connection *vidi = data;
 
        if (!vidi) {
@@ -496,11 +435,10 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 
        list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list,
                                                                head) {
-               manager = exynos_drm_get_manager(encoder);
-               display_ops = manager->display_ops;
+               display = exynos_drm_get_display(encoder);
 
-               if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) {
-                       ctx = get_vidi_context(manager->dev);
+               if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) {
+                       ctx = display->ctx;
                        break;
                }
        }
@@ -539,16 +477,119 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
        }
 
        ctx->connected = vidi->connection;
-       drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
+       drm_helper_hpd_irq_event(ctx->drm_dev);
+
+       return 0;
+}
+
+static enum drm_connector_status vidi_detect(struct drm_connector *connector,
+                       bool force)
+{
+       struct vidi_context *ctx = ctx_from_connector(connector);
+
+       /*
+        * connection request would come from user side
+        * to do hotplug through specific ioctl.
+        */
+       return ctx->connected ? connector_status_connected :
+                       connector_status_disconnected;
+}
+
+static void vidi_connector_destroy(struct drm_connector *connector)
+{
+}
+
+static struct drm_connector_funcs vidi_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = vidi_detect,
+       .destroy = vidi_connector_destroy,
+};
+
+static int vidi_get_modes(struct drm_connector *connector)
+{
+       struct vidi_context *ctx = ctx_from_connector(connector);
+       struct edid *edid;
+       int edid_len;
+
+       /*
+        * the edid data comes from user side and it would be set
+        * to ctx->raw_edid through specific ioctl.
+        */
+       if (!ctx->raw_edid) {
+               DRM_DEBUG_KMS("raw_edid is null.\n");
+               return -EFAULT;
+       }
+
+       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
+       if (!edid) {
+               DRM_DEBUG_KMS("failed to allocate edid\n");
+               return -ENOMEM;
+       }
+
+       drm_mode_connector_update_edid_property(connector, edid);
+
+       return drm_add_edid_modes(connector, edid);
+}
+
+static int vidi_mode_valid(struct drm_connector *connector,
+                       struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
+{
+       struct vidi_context *ctx = ctx_from_connector(connector);
+
+       return ctx->encoder;
+}
+
+static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
+       .get_modes = vidi_get_modes,
+       .mode_valid = vidi_mode_valid,
+       .best_encoder = vidi_best_encoder,
+};
+
+static int vidi_create_connector(struct exynos_drm_display *display,
+                               struct drm_encoder *encoder)
+{
+       struct vidi_context *ctx = display->ctx;
+       struct drm_connector *connector = &ctx->connector;
+       int ret;
+
+       ctx->encoder = encoder;
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       ret = drm_connector_init(ctx->drm_dev, connector,
+                       &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
+               return ret;
+       }
+
+       drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
+       drm_sysfs_connector_add(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
 
+
+static struct exynos_drm_display_ops vidi_display_ops = {
+       .create_connector = vidi_create_connector,
+};
+
+static struct exynos_drm_display vidi_display = {
+       .type = EXYNOS_DISPLAY_TYPE_VIDI,
+       .ops = &vidi_display_ops,
+};
+
 static int vidi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct vidi_context *ctx;
-       struct exynos_drm_subdrv *subdrv;
        int ret;
 
        ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
@@ -559,21 +600,19 @@ static int vidi_probe(struct platform_device *pdev)
 
        INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
 
-       subdrv = &ctx->subdrv;
-       subdrv->dev = dev;
-       subdrv->manager = &vidi_manager;
-       subdrv->probe = vidi_subdrv_probe;
-       subdrv->remove = vidi_subdrv_remove;
+       vidi_manager.ctx = ctx;
+       vidi_display.ctx = ctx;
 
        mutex_init(&ctx->lock);
 
-       platform_set_drvdata(pdev, ctx);
+       platform_set_drvdata(pdev, &vidi_manager);
 
        ret = device_create_file(dev, &dev_attr_connection);
        if (ret < 0)
                DRM_INFO("failed to create connection sysfs.\n");
 
-       exynos_drm_subdrv_register(subdrv);
+       exynos_drm_manager_register(&vidi_manager);
+       exynos_drm_display_register(&vidi_display);
 
        return 0;
 }
@@ -582,7 +621,8 @@ static int vidi_remove(struct platform_device *pdev)
 {
        struct vidi_context *ctx = platform_get_drvdata(pdev);
 
-       exynos_drm_subdrv_unregister(&ctx->subdrv);
+       exynos_drm_display_unregister(&vidi_display);
+       exynos_drm_manager_unregister(&vidi_manager);
 
        if (ctx->raw_edid != (struct edid *)fake_edid_info) {
                kfree(ctx->raw_edid);
@@ -592,32 +632,11 @@ static int vidi_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int vidi_suspend(struct device *dev)
-{
-       struct vidi_context *ctx = get_vidi_context(dev);
-
-       return vidi_power_on(ctx, false);
-}
-
-static int vidi_resume(struct device *dev)
-{
-       struct vidi_context *ctx = get_vidi_context(dev);
-
-       return vidi_power_on(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops vidi_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
-};
-
 struct platform_driver vidi_driver = {
        .probe          = vidi_probe,
        .remove         = vidi_remove,
        .driver         = {
                .name   = "exynos-drm-vidi",
                .owner  = THIS_MODULE,
-               .pm     = &vidi_pm_ops,
        },
 };
index c021ddc1ffb4b4e982ac01874953dbb7239ddc31..9a6d652a3ef248127723ad6b011ad021411690c9 100644 (file)
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/i2c.h>
 #include <linux/of_gpio.h>
 #include <linux/hdmi.h>
 
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-#include "exynos_hdmi.h"
+#include "exynos_mixer.h"
 
 #include <linux/gpio.h>
 #include <media/s5p_hdmi.h>
 
-#define MAX_WIDTH              1920
-#define MAX_HEIGHT             1080
-#define get_hdmi_context(dev)  platform_get_drvdata(to_platform_device(dev))
+#define get_hdmi_display(dev)  platform_get_drvdata(to_platform_device(dev))
+#define ctx_from_connector(c)  container_of(c, struct hdmi_context, connector)
 
 /* AVI header and aspect ratio */
 #define HDMI_AVI_VERSION               0x02
 #define HDMI_AVI_LENGTH                0x0D
-#define AVI_PIC_ASPECT_RATIO_16_9      (2 << 4)
-#define AVI_SAME_AS_PIC_ASPECT_RATIO   8
 
 /* AUI header info */
 #define HDMI_AUI_VERSION       0x01
 #define HDMI_AUI_LENGTH        0x0A
+#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
+#define AVI_4_3_CENTER_RATIO   0x9
+#define AVI_16_9_CENTER_RATIO  0xa
 
 enum hdmi_type {
        HDMI_TYPE13,
        HDMI_TYPE14,
 };
 
+struct hdmi_driver_data {
+       unsigned int type;
+       unsigned int is_apb_phy:1;
+};
+
 struct hdmi_resources {
        struct clk                      *hdmi;
        struct clk                      *sclk_hdmi;
@@ -162,6 +166,7 @@ struct hdmi_v14_conf {
 struct hdmi_conf_regs {
        int pixel_clock;
        int cea_video_id;
+       enum hdmi_picture_aspect aspect_ratio;
        union {
                struct hdmi_v13_conf v13_conf;
                struct hdmi_v14_conf v14_conf;
@@ -171,16 +176,17 @@ struct hdmi_conf_regs {
 struct hdmi_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
+       struct drm_connector            connector;
+       struct drm_encoder              *encoder;
        bool                            hpd;
        bool                            powered;
        bool                            dvi_mode;
        struct mutex                    hdmi_mutex;
 
        void __iomem                    *regs;
-       void                            *parent_ctx;
        int                             irq;
 
-       struct i2c_client               *ddc_port;
+       struct i2c_adapter              *ddc_adpt;
        struct i2c_client               *hdmiphy_port;
 
        /* current hdmiphy conf regs */
@@ -198,6 +204,14 @@ struct hdmiphy_config {
        u8 conf[32];
 };
 
+struct hdmi_driver_data exynos4212_hdmi_driver_data = {
+       .type   = HDMI_TYPE14,
+};
+
+struct hdmi_driver_data exynos5_hdmi_driver_data = {
+       .type   = HDMI_TYPE14,
+};
+
 /* list of phy config settings */
 static const struct hdmiphy_config hdmiphy_v13_configs[] = {
        {
@@ -302,6 +316,24 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
                        0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
                },
        },
+       {
+               .pixel_clock = 71000000,
+               .conf = {
+                       0x01, 0x91, 0x1e, 0x15, 0x40, 0x3c, 0xce, 0x08,
+                       0x04, 0x20, 0xb2, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
+       },
+       {
+               .pixel_clock = 73250000,
+               .conf = {
+                       0x01, 0xd1, 0x1f, 0x15, 0x40, 0x18, 0xe9, 0x08,
+                       0x02, 0xa0, 0xb7, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
+       },
        {
                .pixel_clock = 74176000,
                .conf = {
@@ -329,6 +361,15 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
                        0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
                },
        },
+       {
+               .pixel_clock = 88750000,
+               .conf = {
+                       0x01, 0x91, 0x25, 0x17, 0x40, 0x30, 0xfe, 0x08,
+                       0x06, 0x20, 0xde, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x8a, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
+       },
        {
                .pixel_clock = 106500000,
                .conf = {
@@ -347,6 +388,24 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
                        0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
                },
        },
+       {
+               .pixel_clock = 115500000,
+               .conf = {
+                       0x01, 0xd1, 0x30, 0x1a, 0x40, 0x40, 0x10, 0x04,
+                       0x04, 0xa0, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+               },
+       },
+       {
+               .pixel_clock = 119000000,
+               .conf = {
+                       0x01, 0x91, 0x32, 0x14, 0x40, 0x60, 0xd8, 0x08,
+                       0x06, 0x20, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+               },
+       },
        {
                .pixel_clock = 146250000,
                .conf = {
@@ -668,7 +727,6 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 {
        u32 hdr_sum;
        u8 chksum;
-       u32 aspect_ratio;
        u32 mod;
        u32 vic;
 
@@ -697,10 +755,28 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
                        AVI_ACTIVE_FORMAT_VALID |
                        AVI_UNDERSCANNED_DISPLAY_VALID);
 
-               aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
-
-               hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
-                               AVI_SAME_AS_PIC_ASPECT_RATIO);
+               /*
+                * Set the aspect ratio as per the mode, mentioned in
+                * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
+                */
+               switch (hdata->mode_conf.aspect_ratio) {
+               case HDMI_PICTURE_ASPECT_4_3:
+                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
+                                       hdata->mode_conf.aspect_ratio |
+                                       AVI_4_3_CENTER_RATIO);
+                       break;
+               case HDMI_PICTURE_ASPECT_16_9:
+                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
+                                       hdata->mode_conf.aspect_ratio |
+                                       AVI_16_9_CENTER_RATIO);
+                       break;
+               case HDMI_PICTURE_ASPECT_NONE:
+               default:
+                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
+                                       hdata->mode_conf.aspect_ratio |
+                                       AVI_SAME_AS_PIC_ASPECT_RATIO);
+                       break;
+               }
 
                vic = hdata->mode_conf.cea_video_id;
                hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
@@ -728,31 +804,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
        }
 }
 
-static bool hdmi_is_connected(void *ctx)
+static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
+                               bool force)
 {
-       struct hdmi_context *hdata = ctx;
+       struct hdmi_context *hdata = ctx_from_connector(connector);
+
+       return hdata->hpd ? connector_status_connected :
+                       connector_status_disconnected;
+}
 
-       return hdata->hpd;
+static void hdmi_connector_destroy(struct drm_connector *connector)
+{
 }
 
-static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
+static struct drm_connector_funcs hdmi_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = hdmi_detect,
+       .destroy = hdmi_connector_destroy,
+};
+
+static int hdmi_get_modes(struct drm_connector *connector)
 {
-       struct edid *raw_edid;
-       struct hdmi_context *hdata = ctx;
+       struct hdmi_context *hdata = ctx_from_connector(connector);
+       struct edid *edid;
 
-       if (!hdata->ddc_port)
-               return ERR_PTR(-ENODEV);
+       if (!hdata->ddc_adpt)
+               return -ENODEV;
 
-       raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
-       if (!raw_edid)
-               return ERR_PTR(-ENODEV);
+       edid = drm_get_edid(connector, hdata->ddc_adpt);
+       if (!edid)
+               return -ENODEV;
 
-       hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
+       hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
        DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
                (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
-               raw_edid->width_cm, raw_edid->height_cm);
+               edid->width_cm, edid->height_cm);
 
-       return raw_edid;
+       drm_mode_connector_update_edid_property(connector, edid);
+
+       return drm_add_edid_modes(connector, edid);
 }
 
 static 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)
        return -EINVAL;
 }
 
-static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
+static int hdmi_mode_valid(struct drm_connector *connector,
+                       struct drm_display_mode *mode)
 {
-       struct hdmi_context *hdata = ctx;
+       struct hdmi_context *hdata = ctx_from_connector(connector);
        int ret;
 
        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)
                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
                false, mode->clock * 1000);
 
+       ret = mixer_check_mode(mode);
+       if (ret)
+               return MODE_BAD;
+
        ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
        if (ret < 0)
+               return MODE_BAD;
+
+       return MODE_OK;
+}
+
+static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
+{
+       struct hdmi_context *hdata = ctx_from_connector(connector);
+
+       return hdata->encoder;
+}
+
+static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
+       .get_modes = hdmi_get_modes,
+       .mode_valid = hdmi_mode_valid,
+       .best_encoder = hdmi_best_encoder,
+};
+
+static int hdmi_create_connector(struct exynos_drm_display *display,
+                       struct drm_encoder *encoder)
+{
+       struct hdmi_context *hdata = display->ctx;
+       struct drm_connector *connector = &hdata->connector;
+       int ret;
+
+       hdata->encoder = encoder;
+       connector->interlace_allowed = true;
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       ret = drm_connector_init(hdata->drm_dev, connector,
+                       &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
                return ret;
+       }
+
+       drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
+       drm_sysfs_connector_add(connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       return 0;
+}
+
+static int hdmi_initialize(struct exynos_drm_display *display,
+                       struct drm_device *drm_dev)
+{
+       struct hdmi_context *hdata = display->ctx;
+
+       hdata->drm_dev = drm_dev;
+
        return 0;
 }
 
+static void hdmi_mode_fixup(struct exynos_drm_display *display,
+                               struct drm_connector *connector,
+                               const struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
+{
+       struct drm_display_mode *m;
+       int mode_ok;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+       mode_ok = hdmi_mode_valid(connector, adjusted_mode);
+
+       /* just return if user desired mode exists. */
+       if (mode_ok == MODE_OK)
+               return;
+
+       /*
+        * otherwise, find the most suitable mode among modes and change it
+        * to adjusted_mode.
+        */
+       list_for_each_entry(m, &connector->modes, head) {
+               mode_ok = hdmi_mode_valid(connector, m);
+
+               if (mode_ok == MODE_OK) {
+                       DRM_INFO("desired mode doesn't exist so\n");
+                       DRM_INFO("use the most suitable mode among modes.\n");
+
+                       DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
+                               m->hdisplay, m->vdisplay, m->vrefresh);
+
+                       drm_mode_copy(adjusted_mode, m);
+                       break;
+               }
+       }
+}
+
 static void hdmi_set_acr(u32 freq, u8 *acr)
 {
        u32 n, cts;
@@ -1421,6 +1604,7 @@ static void hdmi_v13_mode_set(struct hdmi_context *hdata,
        hdata->mode_conf.cea_video_id =
                drm_match_cea_mode((struct drm_display_mode *)m);
        hdata->mode_conf.pixel_clock = m->clock * 1000;
+       hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
 
        hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
        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,
        hdata->mode_conf.cea_video_id =
                drm_match_cea_mode((struct drm_display_mode *)m);
        hdata->mode_conf.pixel_clock = m->clock * 1000;
+       hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
 
        hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
        hdmi_set_reg(core->v_line, 2, m->vtotal);
@@ -1618,9 +1803,10 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
        hdmi_set_reg(tg->tg_3d, 1, 0x0);
 }
 
-static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
+static void hdmi_mode_set(struct exynos_drm_display *display,
+                       struct drm_display_mode *mode)
 {
-       struct hdmi_context *hdata = ctx;
+       struct hdmi_context *hdata = display->ctx;
        struct drm_display_mode *m = mode;
 
        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)
                hdmi_v14_mode_set(hdata, mode);
 }
 
-static void hdmi_get_max_resol(void *ctx, unsigned int *width,
-                                       unsigned int *height)
-{
-       *width = MAX_WIDTH;
-       *height = MAX_HEIGHT;
-}
-
-static void hdmi_commit(void *ctx)
+static void hdmi_commit(struct exynos_drm_display *display)
 {
-       struct hdmi_context *hdata = ctx;
+       struct hdmi_context *hdata = display->ctx;
 
        mutex_lock(&hdata->hdmi_mutex);
        if (!hdata->powered) {
@@ -1655,8 +1834,9 @@ static void hdmi_commit(void *ctx)
        hdmi_conf_apply(hdata);
 }
 
-static void hdmi_poweron(struct hdmi_context *hdata)
+static void hdmi_poweron(struct exynos_drm_display *display)
 {
+       struct hdmi_context *hdata = display->ctx;
        struct hdmi_resources *res = &hdata->res;
 
        mutex_lock(&hdata->hdmi_mutex);
@@ -1669,6 +1849,8 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 
        mutex_unlock(&hdata->hdmi_mutex);
 
+       pm_runtime_get_sync(hdata->dev);
+
        if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
                DRM_DEBUG_KMS("failed to enable regulator bulk\n");
 
@@ -1677,10 +1859,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
        clk_prepare_enable(res->sclk_hdmi);
 
        hdmiphy_poweron(hdata);
+       hdmi_commit(display);
 }
 
-static void hdmi_poweroff(struct hdmi_context *hdata)
+static void hdmi_poweroff(struct exynos_drm_display *display)
 {
+       struct hdmi_context *hdata = display->ctx;
        struct hdmi_resources *res = &hdata->res;
 
        mutex_lock(&hdata->hdmi_mutex);
@@ -1700,30 +1884,27 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
        clk_disable_unprepare(res->hdmiphy);
        regulator_bulk_disable(res->regul_count, res->regul_bulk);
 
-       mutex_lock(&hdata->hdmi_mutex);
+       pm_runtime_put_sync(hdata->dev);
 
+       mutex_lock(&hdata->hdmi_mutex);
        hdata->powered = false;
 
 out:
        mutex_unlock(&hdata->hdmi_mutex);
 }
 
-static void hdmi_dpms(void *ctx, int mode)
+static void hdmi_dpms(struct exynos_drm_display *display, int mode)
 {
-       struct hdmi_context *hdata = ctx;
-
        DRM_DEBUG_KMS("mode %d\n", mode);
 
        switch (mode) {
        case DRM_MODE_DPMS_ON:
-               if (pm_runtime_suspended(hdata->dev))
-                       pm_runtime_get_sync(hdata->dev);
+               hdmi_poweron(display);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
-               if (!pm_runtime_suspended(hdata->dev))
-                       pm_runtime_put_sync(hdata->dev);
+               hdmi_poweroff(display);
                break;
        default:
                DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -1731,30 +1912,30 @@ static void hdmi_dpms(void *ctx, int mode)
        }
 }
 
-static struct exynos_hdmi_ops hdmi_ops = {
-       /* display */
-       .is_connected   = hdmi_is_connected,
-       .get_edid       = hdmi_get_edid,
-       .check_mode     = hdmi_check_mode,
-
-       /* manager */
+static struct exynos_drm_display_ops hdmi_display_ops = {
+       .initialize     = hdmi_initialize,
+       .create_connector = hdmi_create_connector,
+       .mode_fixup     = hdmi_mode_fixup,
        .mode_set       = hdmi_mode_set,
-       .get_max_resol  = hdmi_get_max_resol,
-       .commit         = hdmi_commit,
        .dpms           = hdmi_dpms,
+       .commit         = hdmi_commit,
+};
+
+static struct exynos_drm_display hdmi_display = {
+       .type = EXYNOS_DISPLAY_TYPE_HDMI,
+       .ops = &hdmi_display_ops,
 };
 
 static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 {
-       struct exynos_drm_hdmi_context *ctx = arg;
-       struct hdmi_context *hdata = ctx->ctx;
+       struct hdmi_context *hdata = arg;
 
        mutex_lock(&hdata->hdmi_mutex);
        hdata->hpd = gpio_get_value(hdata->hpd_gpio);
        mutex_unlock(&hdata->hdmi_mutex);
 
-       if (ctx->drm_dev)
-               drm_helper_hpd_irq_event(ctx->drm_dev);
+       if (hdata->drm_dev)
+               drm_helper_hpd_irq_event(hdata->drm_dev);
 
        return IRQ_HANDLED;
 }
@@ -1830,20 +2011,6 @@ fail:
        return -ENODEV;
 }
 
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc)
-{
-       if (ddc)
-               hdmi_ddc = ddc;
-}
-
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
-{
-       if (hdmiphy)
-               hdmi_hdmiphy = hdmiphy;
-}
-
 static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
                                        (struct device *dev)
 {
@@ -1871,10 +2038,10 @@ err_data:
 static struct of_device_id hdmi_match_types[] = {
        {
                .compatible = "samsung,exynos5-hdmi",
-               .data   = (void *)HDMI_TYPE14,
+               .data = &exynos5_hdmi_driver_data,
        }, {
                .compatible = "samsung,exynos4212-hdmi",
-               .data   = (void *)HDMI_TYPE14,
+               .data = &exynos4212_hdmi_driver_data,
        }, {
                /* end node */
        }
@@ -1883,11 +2050,12 @@ static struct of_device_id hdmi_match_types[] = {
 static int hdmi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx;
        struct hdmi_context *hdata;
        struct s5p_hdmi_platform_data *pdata;
        struct resource *res;
        const struct of_device_id *match;
+       struct device_node *ddc_node, *phy_node;
+       struct hdmi_driver_data *drv_data;
        int ret;
 
         if (!dev->of_node)
@@ -1897,25 +2065,20 @@ static int hdmi_probe(struct platform_device *pdev)
        if (!pdata)
                return -EINVAL;
 
-       drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
-       if (!drm_hdmi_ctx)
-               return -ENOMEM;
-
        hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
        if (!hdata)
                return -ENOMEM;
 
        mutex_init(&hdata->hdmi_mutex);
 
-       drm_hdmi_ctx->ctx = (void *)hdata;
-       hdata->parent_ctx = (void *)drm_hdmi_ctx;
-
-       platform_set_drvdata(pdev, drm_hdmi_ctx);
+       platform_set_drvdata(pdev, &hdmi_display);
 
        match = of_match_node(hdmi_match_types, dev->of_node);
        if (!match)
                return -ENODEV;
-       hdata->type = (enum hdmi_type)match->data;
+
+       drv_data = (struct hdmi_driver_data *)match->data;
+       hdata->type = drv_data->type;
 
        hdata->hpd_gpio = pdata->hpd_gpio;
        hdata->dev = dev;
@@ -1938,21 +2101,34 @@ static int hdmi_probe(struct platform_device *pdev)
        }
 
        /* DDC i2c driver */
-       if (i2c_add_driver(&ddc_driver)) {
-               DRM_ERROR("failed to register ddc i2c driver\n");
-               return -ENOENT;
+       ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+       if (!ddc_node) {
+               DRM_ERROR("Failed to find ddc node in device tree\n");
+               return -ENODEV;
+       }
+       hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
+       if (!hdata->ddc_adpt) {
+               DRM_ERROR("Failed to get ddc i2c adapter by node\n");
+               return -ENODEV;
        }
 
-       hdata->ddc_port = hdmi_ddc;
+       /* Not support APB PHY yet. */
+       if (drv_data->is_apb_phy)
+               return -EPERM;
 
        /* hdmiphy i2c driver */
-       if (i2c_add_driver(&hdmiphy_driver)) {
-               DRM_ERROR("failed to register hdmiphy i2c driver\n");
-               ret = -ENOENT;
+       phy_node = of_parse_phandle(dev->of_node, "phy", 0);
+       if (!phy_node) {
+               DRM_ERROR("Failed to find hdmiphy node in device tree\n");
+               ret = -ENODEV;
+               goto err_ddc;
+       }
+       hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
+       if (!hdata->hdmiphy_port) {
+               DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
+               ret = -ENODEV;
                goto err_ddc;
        }
-
-       hdata->hdmiphy_port = hdmi_hdmiphy;
 
        hdata->irq = gpio_to_irq(hdata->hpd_gpio);
        if (hdata->irq < 0) {
@@ -1966,119 +2142,45 @@ static int hdmi_probe(struct platform_device *pdev)
        ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
                        hdmi_irq_thread, IRQF_TRIGGER_RISING |
                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                       "hdmi", drm_hdmi_ctx);
+                       "hdmi", hdata);
        if (ret) {
                DRM_ERROR("failed to register hdmi interrupt\n");
                goto err_hdmiphy;
        }
 
-       /* Attach HDMI Driver to common hdmi. */
-       exynos_hdmi_drv_attach(drm_hdmi_ctx);
-
-       /* register specific callbacks to common hdmi. */
-       exynos_hdmi_ops_register(&hdmi_ops);
-
        pm_runtime_enable(dev);
 
+       hdmi_display.ctx = hdata;
+       exynos_drm_display_register(&hdmi_display);
+
        return 0;
 
 err_hdmiphy:
-       i2c_del_driver(&hdmiphy_driver);
+       put_device(&hdata->hdmiphy_port->dev);
 err_ddc:
-       i2c_del_driver(&ddc_driver);
+       put_device(&hdata->ddc_adpt->dev);
        return ret;
 }
 
 static int hdmi_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       struct exynos_drm_display *display = get_hdmi_display(dev);
+       struct hdmi_context *hdata = display->ctx;
 
-       pm_runtime_disable(dev);
-
-       /* hdmiphy i2c driver */
-       i2c_del_driver(&hdmiphy_driver);
-       /* DDC i2c driver */
-       i2c_del_driver(&ddc_driver);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int hdmi_suspend(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-       struct hdmi_context *hdata = ctx->ctx;
-
-       disable_irq(hdata->irq);
-
-       hdata->hpd = false;
-       if (ctx->drm_dev)
-               drm_helper_hpd_irq_event(ctx->drm_dev);
-
-       if (pm_runtime_suspended(dev)) {
-               DRM_DEBUG_KMS("Already suspended\n");
-               return 0;
-       }
-
-       hdmi_poweroff(hdata);
+       put_device(&hdata->hdmiphy_port->dev);
+       put_device(&hdata->ddc_adpt->dev);
+       pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
 
-static int hdmi_resume(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-       struct hdmi_context *hdata = ctx->ctx;
-
-       hdata->hpd = gpio_get_value(hdata->hpd_gpio);
-
-       enable_irq(hdata->irq);
-
-       if (!pm_runtime_suspended(dev)) {
-               DRM_DEBUG_KMS("Already resumed\n");
-               return 0;
-       }
-
-       hdmi_poweron(hdata);
-
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int hdmi_runtime_suspend(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-       struct hdmi_context *hdata = ctx->ctx;
-
-       hdmi_poweroff(hdata);
-
-       return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-       struct hdmi_context *hdata = ctx->ctx;
-
-       hdmi_poweron(hdata);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops hdmi_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
-       SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
-};
-
 struct platform_driver hdmi_driver = {
        .probe          = hdmi_probe,
        .remove         = hdmi_remove,
        .driver         = {
                .name   = "exynos-hdmi",
                .owner  = THIS_MODULE,
-               .pm     = &hdmi_pm_ops,
                .of_match_table = hdmi_match_types,
        },
 };
index 2dfa48c76f54644d1c7efd6fb6e52bedacc02e70..ce288818d2c0f727cd56e70fd1d367ad7e050f4c 100644 (file)
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
-#include "exynos_drm_hdmi.h"
 #include "exynos_drm_iommu.h"
+#include "exynos_mixer.h"
 
-#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
+#define get_mixer_manager(dev) platform_get_drvdata(to_platform_device(dev))
+
+#define MIXER_WIN_NR           3
+#define MIXER_DEFAULT_WIN      0
 
 struct hdmi_win_data {
        dma_addr_t              dma_addr;
@@ -82,6 +85,7 @@ enum mixer_version_id {
 };
 
 struct mixer_context {
+       struct platform_device *pdev;
        struct device           *dev;
        struct drm_device       *drm_dev;
        int                     pipe;
@@ -94,7 +98,6 @@ struct mixer_context {
        struct mixer_resources  mixer_res;
        struct hdmi_win_data    win_data[MIXER_WIN_NR];
        enum mixer_version_id   mxr_ver;
-       void                    *parent_ctx;
        wait_queue_head_t       wait_vsync_queue;
        atomic_t                wait_vsync_event;
 };
@@ -685,31 +688,196 @@ static void mixer_win_reset(struct mixer_context *ctx)
        spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
-static int mixer_iommu_on(void *ctx, bool enable)
+static irqreturn_t mixer_irq_handler(int irq, void *arg)
+{
+       struct mixer_context *ctx = arg;
+       struct mixer_resources *res = &ctx->mixer_res;
+       u32 val, base, shadow;
+
+       spin_lock(&res->reg_slock);
+
+       /* read interrupt status for handling and clearing flags for VSYNC */
+       val = mixer_reg_read(res, MXR_INT_STATUS);
+
+       /* handling VSYNC */
+       if (val & MXR_INT_STATUS_VSYNC) {
+               /* interlace scan need to check shadow register */
+               if (ctx->interlace) {
+                       base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
+                       shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
+                       if (base != shadow)
+                               goto out;
+
+                       base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
+                       shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
+                       if (base != shadow)
+                               goto out;
+               }
+
+               drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+               exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+
+               /* set wait vsync event to zero and wake up queue. */
+               if (atomic_read(&ctx->wait_vsync_event)) {
+                       atomic_set(&ctx->wait_vsync_event, 0);
+                       wake_up(&ctx->wait_vsync_queue);
+               }
+       }
+
+out:
+       /* clear interrupts */
+       if (~val & MXR_INT_EN_VSYNC) {
+               /* vsync interrupt use different bit for read and clear */
+               val &= ~MXR_INT_EN_VSYNC;
+               val |= MXR_INT_CLEAR_VSYNC;
+       }
+       mixer_reg_write(res, MXR_INT_STATUS, val);
+
+       spin_unlock(&res->reg_slock);
+
+       return IRQ_HANDLED;
+}
+
+static int mixer_resources_init(struct mixer_context *mixer_ctx)
 {
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx;
-       struct mixer_context *mdata = ctx;
-       struct drm_device *drm_dev;
+       struct device *dev = &mixer_ctx->pdev->dev;
+       struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
+       struct resource *res;
+       int ret;
 
-       drm_hdmi_ctx = mdata->parent_ctx;
-       drm_dev = drm_hdmi_ctx->drm_dev;
+       spin_lock_init(&mixer_res->reg_slock);
 
-       if (is_drm_iommu_supported(drm_dev)) {
-               if (enable)
-                       return drm_iommu_attach_device(drm_dev, mdata->dev);
+       mixer_res->mixer = devm_clk_get(dev, "mixer");
+       if (IS_ERR(mixer_res->mixer)) {
+               dev_err(dev, "failed to get clock 'mixer'\n");
+               return -ENODEV;
+       }
 
-               drm_iommu_detach_device(drm_dev, mdata->dev);
+       mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
+       if (IS_ERR(mixer_res->sclk_hdmi)) {
+               dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+               return -ENODEV;
+       }
+       res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "get memory resource failed.\n");
+               return -ENXIO;
        }
+
+       mixer_res->mixer_regs = devm_ioremap(dev, res->start,
+                                                       resource_size(res));
+       if (mixer_res->mixer_regs == NULL) {
+               dev_err(dev, "register mapping failed.\n");
+               return -ENXIO;
+       }
+
+       res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(dev, "get interrupt resource failed.\n");
+               return -ENXIO;
+       }
+
+       ret = devm_request_irq(dev, res->start, mixer_irq_handler,
+                                               0, "drm_mixer", mixer_ctx);
+       if (ret) {
+               dev_err(dev, "request interrupt failed.\n");
+               return ret;
+       }
+       mixer_res->irq = res->start;
+
        return 0;
 }
 
-static int mixer_enable_vblank(void *ctx, int pipe)
+static int vp_resources_init(struct mixer_context *mixer_ctx)
 {
-       struct mixer_context *mixer_ctx = ctx;
-       struct mixer_resources *res = &mixer_ctx->mixer_res;
+       struct device *dev = &mixer_ctx->pdev->dev;
+       struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
+       struct resource *res;
+
+       mixer_res->vp = devm_clk_get(dev, "vp");
+       if (IS_ERR(mixer_res->vp)) {
+               dev_err(dev, "failed to get clock 'vp'\n");
+               return -ENODEV;
+       }
+       mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
+       if (IS_ERR(mixer_res->sclk_mixer)) {
+               dev_err(dev, "failed to get clock 'sclk_mixer'\n");
+               return -ENODEV;
+       }
+       mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
+       if (IS_ERR(mixer_res->sclk_dac)) {
+               dev_err(dev, "failed to get clock 'sclk_dac'\n");
+               return -ENODEV;
+       }
+
+       if (mixer_res->sclk_hdmi)
+               clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
+
+       res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
+       if (res == NULL) {
+               dev_err(dev, "get memory resource failed.\n");
+               return -ENXIO;
+       }
 
+       mixer_res->vp_regs = devm_ioremap(dev, res->start,
+                                                       resource_size(res));
+       if (mixer_res->vp_regs == NULL) {
+               dev_err(dev, "register mapping failed.\n");
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static int mixer_initialize(struct exynos_drm_manager *mgr,
+                       struct drm_device *drm_dev, int pipe)
+{
+       int ret;
+       struct mixer_context *mixer_ctx = mgr->ctx;
+
+       mixer_ctx->drm_dev = drm_dev;
        mixer_ctx->pipe = pipe;
 
+       /* acquire resources: regs, irqs, clocks */
+       ret = mixer_resources_init(mixer_ctx);
+       if (ret) {
+               DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
+               return ret;
+       }
+
+       if (mixer_ctx->vp_enabled) {
+               /* acquire vp resources: regs, irqs, clocks */
+               ret = vp_resources_init(mixer_ctx);
+               if (ret) {
+                       DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
+               return 0;
+
+       return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
+}
+
+static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
+{
+       struct mixer_context *mixer_ctx = mgr->ctx;
+
+       if (is_drm_iommu_supported(mixer_ctx->drm_dev))
+               drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
+}
+
+static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
+{
+       struct mixer_context *mixer_ctx = mgr->ctx;
+       struct mixer_resources *res = &mixer_ctx->mixer_res;
+
+       if (!mixer_ctx->powered) {
+               mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
+               return 0;
+       }
+
        /* enable vsync interrupt */
        mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
                        MXR_INT_EN_VSYNC);
@@ -717,19 +885,19 @@ static int mixer_enable_vblank(void *ctx, int pipe)
        return 0;
 }
 
-static void mixer_disable_vblank(void *ctx)
+static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
 {
-       struct mixer_context *mixer_ctx = ctx;
+       struct mixer_context *mixer_ctx = mgr->ctx;
        struct mixer_resources *res = &mixer_ctx->mixer_res;
 
        /* disable vsync interrupt */
        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
-static void mixer_win_mode_set(void *ctx,
-                             struct exynos_drm_overlay *overlay)
+static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
+                       struct exynos_drm_overlay *overlay)
 {
-       struct mixer_context *mixer_ctx = ctx;
+       struct mixer_context *mixer_ctx = mgr->ctx;
        struct hdmi_win_data *win_data;
        int win;
 
@@ -778,9 +946,10 @@ static void mixer_win_mode_set(void *ctx,
        win_data->scan_flags = overlay->scan_flag;
 }
 
-static void mixer_win_commit(void *ctx, int win)
+static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct mixer_context *mixer_ctx = ctx;
+       struct mixer_context *mixer_ctx = mgr->ctx;
+       int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 
        DRM_DEBUG_KMS("win: %d\n", win);
 
@@ -799,10 +968,11 @@ static void mixer_win_commit(void *ctx, int win)
        mixer_ctx->win_data[win].enabled = true;
 }
 
-static void mixer_win_disable(void *ctx, int win)
+static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-       struct mixer_context *mixer_ctx = ctx;
+       struct mixer_context *mixer_ctx = mgr->ctx;
        struct mixer_resources *res = &mixer_ctx->mixer_res;
+       int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
        unsigned long flags;
 
        DRM_DEBUG_KMS("win: %d\n", win);
@@ -826,32 +996,9 @@ static void mixer_win_disable(void *ctx, int win)
        mixer_ctx->win_data[win].enabled = false;
 }
 
-static int mixer_check_mode(void *ctx, struct drm_display_mode *mode)
+static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
 {
-       struct mixer_context *mixer_ctx = ctx;
-       u32 w, h;
-
-       w = mode->hdisplay;
-       h = mode->vdisplay;
-
-       DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
-               mode->hdisplay, mode->vdisplay, mode->vrefresh,
-               (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
-
-       if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16 ||
-               mixer_ctx->mxr_ver == MXR_VER_128_0_0_184)
-               return 0;
-
-       if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
-               (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
-               (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
-               return 0;
-
-       return -EINVAL;
-}
-static void mixer_wait_for_vblank(void *ctx)
-{
-       struct mixer_context *mixer_ctx = ctx;
+       struct mixer_context *mixer_ctx = mgr->ctx;
 
        mutex_lock(&mixer_ctx->mixer_mutex);
        if (!mixer_ctx->powered) {
@@ -872,21 +1019,23 @@ static void mixer_wait_for_vblank(void *ctx)
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
-static void mixer_window_suspend(struct mixer_context *ctx)
+static void mixer_window_suspend(struct exynos_drm_manager *mgr)
 {
+       struct mixer_context *ctx = mgr->ctx;
        struct hdmi_win_data *win_data;
        int i;
 
        for (i = 0; i < MIXER_WIN_NR; i++) {
                win_data = &ctx->win_data[i];
                win_data->resume = win_data->enabled;
-               mixer_win_disable(ctx, i);
+               mixer_win_disable(mgr, i);
        }
-       mixer_wait_for_vblank(ctx);
+       mixer_wait_for_vblank(mgr);
 }
 
-static void mixer_window_resume(struct mixer_context *ctx)
+static void mixer_window_resume(struct exynos_drm_manager *mgr)
 {
+       struct mixer_context *ctx = mgr->ctx;
        struct hdmi_win_data *win_data;
        int i;
 
@@ -894,11 +1043,14 @@ static void mixer_window_resume(struct mixer_context *ctx)
                win_data = &ctx->win_data[i];
                win_data->enabled = win_data->resume;
                win_data->resume = false;
+               if (win_data->enabled)
+                       mixer_win_commit(mgr, i);
        }
 }
 
-static void mixer_poweron(struct mixer_context *ctx)
+static void mixer_poweron(struct exynos_drm_manager *mgr)
 {
+       struct mixer_context *ctx = mgr->ctx;
        struct mixer_resources *res = &ctx->mixer_res;
 
        mutex_lock(&ctx->mixer_mutex);
@@ -909,6 +1061,8 @@ static void mixer_poweron(struct mixer_context *ctx)
        ctx->powered = true;
        mutex_unlock(&ctx->mixer_mutex);
 
+       pm_runtime_get_sync(ctx->dev);
+
        clk_prepare_enable(res->mixer);
        if (ctx->vp_enabled) {
                clk_prepare_enable(res->vp);
@@ -918,11 +1072,12 @@ static void mixer_poweron(struct mixer_context *ctx)
        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
        mixer_win_reset(ctx);
 
-       mixer_window_resume(ctx);
+       mixer_window_resume(mgr);
 }
 
-static void mixer_poweroff(struct mixer_context *ctx)
+static void mixer_poweroff(struct exynos_drm_manager *mgr)
 {
+       struct mixer_context *ctx = mgr->ctx;
        struct mixer_resources *res = &ctx->mixer_res;
 
        mutex_lock(&ctx->mixer_mutex);
@@ -930,7 +1085,7 @@ static void mixer_poweroff(struct mixer_context *ctx)
                goto out;
        mutex_unlock(&ctx->mixer_mutex);
 
-       mixer_window_suspend(ctx);
+       mixer_window_suspend(mgr);
 
        ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
 
@@ -940,6 +1095,8 @@ static void mixer_poweroff(struct mixer_context *ctx)
                clk_disable_unprepare(res->sclk_mixer);
        }
 
+       pm_runtime_put_sync(ctx->dev);
+
        mutex_lock(&ctx->mixer_mutex);
        ctx->powered = false;
 
@@ -947,20 +1104,16 @@ out:
        mutex_unlock(&ctx->mixer_mutex);
 }
 
-static void mixer_dpms(void *ctx, int mode)
+static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-       struct mixer_context *mixer_ctx = ctx;
-
        switch (mode) {
        case DRM_MODE_DPMS_ON:
-               if (pm_runtime_suspended(mixer_ctx->dev))
-                       pm_runtime_get_sync(mixer_ctx->dev);
+               mixer_poweron(mgr);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
-               if (!pm_runtime_suspended(mixer_ctx->dev))
-                       pm_runtime_put_sync(mixer_ctx->dev);
+               mixer_poweroff(mgr);
                break;
        default:
                DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -968,169 +1121,42 @@ static void mixer_dpms(void *ctx, int mode)
        }
 }
 
-static struct exynos_mixer_ops mixer_ops = {
-       /* manager */
-       .iommu_on               = mixer_iommu_on,
-       .enable_vblank          = mixer_enable_vblank,
-       .disable_vblank         = mixer_disable_vblank,
-       .wait_for_vblank        = mixer_wait_for_vblank,
-       .dpms                   = mixer_dpms,
-
-       /* overlay */
-       .win_mode_set           = mixer_win_mode_set,
-       .win_commit             = mixer_win_commit,
-       .win_disable            = mixer_win_disable,
-
-       /* display */
-       .check_mode             = mixer_check_mode,
-};
-
-static irqreturn_t mixer_irq_handler(int irq, void *arg)
-{
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
-       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-       struct mixer_resources *res = &ctx->mixer_res;
-       u32 val, base, shadow;
-
-       spin_lock(&res->reg_slock);
-
-       /* read interrupt status for handling and clearing flags for VSYNC */
-       val = mixer_reg_read(res, MXR_INT_STATUS);
-
-       /* handling VSYNC */
-       if (val & MXR_INT_STATUS_VSYNC) {
-               /* interlace scan need to check shadow register */
-               if (ctx->interlace) {
-                       base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
-                       shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
-                       if (base != shadow)
-                               goto out;
-
-                       base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
-                       shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
-                       if (base != shadow)
-                               goto out;
-               }
-
-               drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
-               exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
-                               ctx->pipe);
-
-               /* set wait vsync event to zero and wake up queue. */
-               if (atomic_read(&ctx->wait_vsync_event)) {
-                       atomic_set(&ctx->wait_vsync_event, 0);
-                       wake_up(&ctx->wait_vsync_queue);
-               }
-       }
-
-out:
-       /* clear interrupts */
-       if (~val & MXR_INT_EN_VSYNC) {
-               /* vsync interrupt use different bit for read and clear */
-               val &= ~MXR_INT_EN_VSYNC;
-               val |= MXR_INT_CLEAR_VSYNC;
-       }
-       mixer_reg_write(res, MXR_INT_STATUS, val);
-
-       spin_unlock(&res->reg_slock);
-
-       return IRQ_HANDLED;
-}
-
-static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
-                               struct platform_device *pdev)
+/* Only valid for Mixer version 16.0.33.0 */
+int mixer_check_mode(struct drm_display_mode *mode)
 {
-       struct mixer_context *mixer_ctx = ctx->ctx;
-       struct device *dev = &pdev->dev;
-       struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
-       struct resource *res;
-       int ret;
-
-       spin_lock_init(&mixer_res->reg_slock);
-
-       mixer_res->mixer = devm_clk_get(dev, "mixer");
-       if (IS_ERR(mixer_res->mixer)) {
-               dev_err(dev, "failed to get clock 'mixer'\n");
-               return -ENODEV;
-       }
-
-       mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
-       if (IS_ERR(mixer_res->sclk_hdmi)) {
-               dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
-               return -ENODEV;
-       }
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(dev, "get memory resource failed.\n");
-               return -ENXIO;
-       }
+       u32 w, h;
 
-       mixer_res->mixer_regs = devm_ioremap(dev, res->start,
-                                                       resource_size(res));
-       if (mixer_res->mixer_regs == NULL) {
-               dev_err(dev, "register mapping failed.\n");
-               return -ENXIO;
-       }
+       w = mode->hdisplay;
+       h = mode->vdisplay;
 
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (res == NULL) {
-               dev_err(dev, "get interrupt resource failed.\n");
-               return -ENXIO;
-       }
+       DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
+               mode->hdisplay, mode->vdisplay, mode->vrefresh,
+               (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
 
-       ret = devm_request_irq(dev, res->start, mixer_irq_handler,
-                                                       0, "drm_mixer", ctx);
-       if (ret) {
-               dev_err(dev, "request interrupt failed.\n");
-               return ret;
-       }
-       mixer_res->irq = res->start;
+       if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
+               (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
+               (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
+               return 0;
 
-       return 0;
+       return -EINVAL;
 }
 
-static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
-                            struct platform_device *pdev)
-{
-       struct mixer_context *mixer_ctx = ctx->ctx;
-       struct device *dev = &pdev->dev;
-       struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
-       struct resource *res;
-
-       mixer_res->vp = devm_clk_get(dev, "vp");
-       if (IS_ERR(mixer_res->vp)) {
-               dev_err(dev, "failed to get clock 'vp'\n");
-               return -ENODEV;
-       }
-       mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
-       if (IS_ERR(mixer_res->sclk_mixer)) {
-               dev_err(dev, "failed to get clock 'sclk_mixer'\n");
-               return -ENODEV;
-       }
-       mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
-       if (IS_ERR(mixer_res->sclk_dac)) {
-               dev_err(dev, "failed to get clock 'sclk_dac'\n");
-               return -ENODEV;
-       }
-
-       if (mixer_res->sclk_hdmi)
-               clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (res == NULL) {
-               dev_err(dev, "get memory resource failed.\n");
-               return -ENXIO;
-       }
-
-       mixer_res->vp_regs = devm_ioremap(dev, res->start,
-                                                       resource_size(res));
-       if (mixer_res->vp_regs == NULL) {
-               dev_err(dev, "register mapping failed.\n");
-               return -ENXIO;
-       }
+static struct exynos_drm_manager_ops mixer_manager_ops = {
+       .initialize             = mixer_initialize,
+       .remove                 = mixer_mgr_remove,
+       .dpms                   = mixer_dpms,
+       .enable_vblank          = mixer_enable_vblank,
+       .disable_vblank         = mixer_disable_vblank,
+       .wait_for_vblank        = mixer_wait_for_vblank,
+       .win_mode_set           = mixer_win_mode_set,
+       .win_commit             = mixer_win_commit,
+       .win_disable            = mixer_win_disable,
+};
 
-       return 0;
-}
+static struct exynos_drm_manager mixer_manager = {
+       .type                   = EXYNOS_DISPLAY_TYPE_HDMI,
+       .ops                    = &mixer_manager_ops,
+};
 
 static struct mixer_drv_data exynos5420_mxr_drv_data = {
        .version = MXR_VER_128_0_0_184,
@@ -1177,21 +1203,16 @@ static struct of_device_id mixer_match_types[] = {
 static int mixer_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx;
        struct mixer_context *ctx;
        struct mixer_drv_data *drv;
-       int ret;
 
        dev_info(dev, "probe start\n");
 
-       drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
-                                                               GFP_KERNEL);
-       if (!drm_hdmi_ctx)
-               return -ENOMEM;
-
-       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx) {
+               DRM_ERROR("failed to alloc mixer context.\n");
                return -ENOMEM;
+       }
 
        mutex_init(&ctx->mixer_mutex);
 
@@ -1204,46 +1225,20 @@ static int mixer_probe(struct platform_device *pdev)
                        platform_get_device_id(pdev)->driver_data;
        }
 
+       ctx->pdev = pdev;
        ctx->dev = dev;
-       ctx->parent_ctx = (void *)drm_hdmi_ctx;
-       drm_hdmi_ctx->ctx = (void *)ctx;
        ctx->vp_enabled = drv->is_vp_enabled;
        ctx->mxr_ver = drv->version;
        init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
-       platform_set_drvdata(pdev, drm_hdmi_ctx);
-
-       /* acquire resources: regs, irqs, clocks */
-       ret = mixer_resources_init(drm_hdmi_ctx, pdev);
-       if (ret) {
-               DRM_ERROR("mixer_resources_init failed\n");
-               goto fail;
-       }
-
-       if (ctx->vp_enabled) {
-               /* acquire vp resources: regs, irqs, clocks */
-               ret = vp_resources_init(drm_hdmi_ctx, pdev);
-               if (ret) {
-                       DRM_ERROR("vp_resources_init failed\n");
-                       goto fail;
-               }
-       }
-
-       /* attach mixer driver to common hdmi. */
-       exynos_mixer_drv_attach(drm_hdmi_ctx);
-
-       /* register specific callback point to common hdmi. */
-       exynos_mixer_ops_register(&mixer_ops);
+       mixer_manager.ctx = ctx;
+       platform_set_drvdata(pdev, &mixer_manager);
+       exynos_drm_manager_register(&mixer_manager);
 
        pm_runtime_enable(dev);
 
        return 0;
-
-
-fail:
-       dev_info(dev, "probe failed\n");
-       return ret;
 }
 
 static int mixer_remove(struct platform_device *pdev)
@@ -1255,70 +1250,10 @@ static int mixer_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int mixer_suspend(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
-       if (pm_runtime_suspended(dev)) {
-               DRM_DEBUG_KMS("Already suspended\n");
-               return 0;
-       }
-
-       mixer_poweroff(ctx);
-
-       return 0;
-}
-
-static int mixer_resume(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
-       if (!pm_runtime_suspended(dev)) {
-               DRM_DEBUG_KMS("Already resumed\n");
-               return 0;
-       }
-
-       mixer_poweron(ctx);
-
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int mixer_runtime_suspend(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
-       mixer_poweroff(ctx);
-
-       return 0;
-}
-
-static int mixer_runtime_resume(struct device *dev)
-{
-       struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
-       mixer_poweron(ctx);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops mixer_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
-       SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
-};
-
 struct platform_driver mixer_driver = {
        .driver = {
                .name = "exynos-mixer",
                .owner = THIS_MODULE,
-               .pm = &mixer_pm_ops,
                .of_match_table = mixer_match_types,
        },
        .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 (file)
index 0000000..3811e41
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _EXYNOS_MIXER_H_
+#define _EXYNOS_MIXER_H_
+
+/* This function returns 0 if the given timing is valid for the mixer */
+int mixer_check_mode(struct drm_display_mode *mode);
+
+#endif
index e9064dd9045dec0aeb784a945237662b0e37ca1b..b1531557637662af7c0e3bc576602514f3701d63 100644 (file)
@@ -13,9 +13,11 @@ gma500_gfx-y += \
          intel_i2c.o \
          intel_gmbus.o \
          mmu.o \
+         blitter.o \
          power.o \
          psb_drv.o \
          gma_display.o \
+         gma_device.o \
          psb_intel_display.o \
          psb_intel_lvds.o \
          psb_intel_modes.o \
diff --git a/drivers/gpu/drm/gma500/blitter.c b/drivers/gpu/drm/gma500/blitter.c
new file mode 100644 (file)
index 0000000..9cd54a6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Patrik Jakobsson
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * Authors: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+ */
+
+#include "psb_drv.h"
+
+#include "blitter.h"
+#include "psb_reg.h"
+
+/* Wait for the blitter to be completely idle */
+int gma_blt_wait_idle(struct drm_psb_private *dev_priv)
+{
+       unsigned long stop = jiffies + HZ;
+       int busy = 1;
+
+       /* NOP for Cedarview */
+       if (IS_CDV(dev_priv->dev))
+               return 0;
+
+       /* First do a quick check */
+       if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
+           ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
+               return 0;
+
+       do {
+               busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+       } while (busy && !time_after_eq(jiffies, stop));
+
+       if (busy)
+               return -EBUSY;
+
+       do {
+               busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+                       _PSB_C2B_STATUS_BUSY) != 0);
+       } while (busy && !time_after_eq(jiffies, stop));
+
+       /* If still busy, we probably have a hang */
+       return (busy) ? -EBUSY : 0;
+}
diff --git a/drivers/gpu/drm/gma500/blitter.h b/drivers/gpu/drm/gma500/blitter.h
new file mode 100644 (file)
index 0000000..b83648d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014, Patrik Jakobsson
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * Authors: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+ */
+
+#ifndef __BLITTER_H
+#define __BLITTER_H
+
+extern int gma_blt_wait_idle(struct drm_psb_private *dev_priv);
+
+#endif
index 5a9a6a3063a8a603a73422f8f08b5ceaf30d8e82..3531f90e53d043e4ec6ae473570389a24b1fd6c3 100644 (file)
@@ -26,6 +26,7 @@
 #include "psb_intel_reg.h"
 #include "intel_bios.h"
 #include "cdv_device.h"
+#include "gma_device.h"
 
 #define VGA_SR_INDEX           0x3c4
 #define VGA_SR_DATA            0x3c5
@@ -426,43 +427,6 @@ static int cdv_power_up(struct drm_device *dev)
        return 0;
 }
 
-/* FIXME ? - shared with Poulsbo */
-static void cdv_get_core_freq(struct drm_device *dev)
-{
-       uint32_t clock;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-       pci_read_config_dword(pci_root, 0xD4, &clock);
-       pci_dev_put(pci_root);
-
-       switch (clock & 0x07) {
-       case 0:
-               dev_priv->core_freq = 100;
-               break;
-       case 1:
-               dev_priv->core_freq = 133;
-               break;
-       case 2:
-               dev_priv->core_freq = 150;
-               break;
-       case 3:
-               dev_priv->core_freq = 178;
-               break;
-       case 4:
-               dev_priv->core_freq = 200;
-               break;
-       case 5:
-       case 6:
-       case 7:
-               dev_priv->core_freq = 266;
-               break;
-       default:
-               dev_priv->core_freq = 0;
-       }
-}
-
 static void cdv_hotplug_work_func(struct work_struct *work)
 {
         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)
        if (pci_enable_msi(dev->pdev))
                dev_warn(dev->dev, "Enabling MSI failed!\n");
        dev_priv->regmap = cdv_regmap;
-       cdv_get_core_freq(dev);
+       gma_get_core_freq(dev);
        psb_intel_opregion_init(dev);
        psb_intel_init_bios(dev);
        cdv_hotplug_enable(dev, false);
index 661af492173d44f4861be750f42a93b13402b59e..c18268cd516ef5798d06824a6b0b436011ef3438 100644 (file)
@@ -81,13 +81,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
-                                const struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
 static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode)
@@ -224,7 +217,7 @@ static int cdv_intel_crt_set_property(struct drm_connector *connector,
 
 static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
        .dpms = cdv_intel_crt_dpms,
-       .mode_fixup = cdv_intel_crt_mode_fixup,
+       .mode_fixup = gma_encoder_mode_fixup,
        .prepare = gma_encoder_prepare,
        .commit = gma_encoder_commit,
        .mode_set = cdv_intel_crt_mode_set,
index 8fbfa06da62d867d8b70d944a7e195388ab36848..66727328832d7563f6e1dc42bc67ea6b48809ee2 100644 (file)
@@ -412,8 +412,11 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
                                  int refclk,
                                  struct gma_clock_t *best_clock)
 {
+       struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
        struct gma_clock_t clock;
-       if (refclk == 27000) {
+
+       switch (refclk) {
+       case 27000:
                if (target < 200000) {
                        clock.p1 = 2;
                        clock.p2 = 10;
@@ -427,7 +430,9 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
                        clock.m1 = 0;
                        clock.m2 = 98;
                }
-       } else if (refclk == 100000) {
+               break;
+
+       case 100000:
                if (target < 200000) {
                        clock.p1 = 2;
                        clock.p2 = 10;
@@ -441,12 +446,13 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
                        clock.m1 = 0;
                        clock.m2 = 133;
                }
-       } else
+               break;
+
+       default:
                return false;
-       clock.m = clock.m2 + 2;
-       clock.p = clock.p1 * clock.p2;
-       clock.vco = (refclk * clock.m) / clock.n;
-       clock.dot = clock.vco / clock.p;
+       }
+
+       gma_crtc->clock_funcs->clock(refclk, &clock);
        memcpy(best_clock, &clock, sizeof(struct gma_clock_t));
        return true;
 }
@@ -463,54 +469,11 @@ static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
        crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        gma_crtc = to_gma_crtc(crtc);
 
-       if (crtc->fb == NULL || !gma_crtc->active)
+       if (crtc->primary->fb == NULL || !gma_crtc->active)
                return false;
        return true;
 }
 
-static bool cdv_intel_single_pipe_active (struct drm_device *dev)
-{
-       uint32_t pipe_enabled = 0;
-
-       if (cdv_intel_pipe_enabled(dev, 0))
-               pipe_enabled |= FIFO_PIPEA;
-
-       if (cdv_intel_pipe_enabled(dev, 1))
-               pipe_enabled |= FIFO_PIPEB;
-
-
-       DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled);
-
-       if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB)
-               return true;
-       else
-               return false;
-}
-
-static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc)
-{
-       struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
-
-       if (gma_crtc->pipe != 1)
-               return false;
-
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct gma_encoder *gma_encoder =
-                                       gma_attached_encoder(connector);
-
-               if (!connector->encoder
-                   || connector->encoder->crtc != crtc)
-                       continue;
-
-               if (gma_encoder->type == INTEL_OUTPUT_LVDS)
-                       return true;
-       }
-
-       return false;
-}
-
 void cdv_disable_sr(struct drm_device *dev)
 {
        if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
@@ -535,8 +498,10 @@ void cdv_disable_sr(struct drm_device *dev)
 void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
+       struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
 
-       if (cdv_intel_single_pipe_active(dev)) {
+       /* Is only one pipe enabled? */
+       if (cdv_intel_pipe_enabled(dev, 0) ^ cdv_intel_pipe_enabled(dev, 1)) {
                u32 fw;
 
                fw = REG_READ(DSPFW1);
@@ -557,7 +522,9 @@ void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
 
                /* ignore FW4 */
 
-               if (is_pipeb_lvds(dev, crtc)) {
+               /* Is pipe b lvds ? */
+               if (gma_crtc->pipe == 1 &&
+                   gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
                        REG_WRITE(DSPFW5, 0x00040330);
                } else {
                        fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) |
index 0490ce36b53fd9237e754de7877f51f3aaffee97..9ff30c2efadbf99c8901bf0fe26f22cea73f63b5 100644 (file)
@@ -1693,7 +1693,7 @@ done:
                struct drm_crtc *crtc = encoder->base.crtc;
                drm_crtc_helper_set_mode(crtc, &crtc->mode,
                                         crtc->x, crtc->y,
-                                        crtc->fb);
+                                        crtc->primary->fb);
        }
 
        return 0;
index 1c0d723b8d2424339b74b706d9c258a974264a37..b99084b3f706e0e50d35330ab6accc9a0fcaf08f 100644 (file)
@@ -89,13 +89,6 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
        REG_READ(hdmi_priv->hdmi_reg);
 }
 
-static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
-                                 const struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
 static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -199,7 +192,7 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
                    crtc->saved_mode.vdisplay != 0) {
                        if (centre) {
                                if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
-                                           encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+                                           encoder->crtc->x, encoder->crtc->y, encoder->crtc->primary->fb))
                                        return -1;
                        } else {
                                struct drm_encoder_helper_funcs *helpers
@@ -262,7 +255,7 @@ static void cdv_hdmi_destroy(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
        .dpms = cdv_hdmi_dpms,
-       .mode_fixup = cdv_hdmi_mode_fixup,
+       .mode_fixup = gma_encoder_mode_fixup,
        .prepare = gma_encoder_prepare,
        .mode_set = cdv_hdmi_mode_set,
        .commit = gma_encoder_commit,
index 20e08e65d46ccfecdf06dd03c150347c14c0f327..8ecc920fc26d1c3f8f331004305180aab88413d4 100644 (file)
@@ -494,7 +494,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
                                                      &crtc->saved_mode,
                                                      encoder->crtc->x,
                                                      encoder->crtc->y,
-                                                     encoder->crtc->fb))
+                                                     encoder->crtc->primary->fb))
                                return -1;
                }
        } else if (!strcmp(property->name, "backlight") && encoder) {
@@ -712,6 +712,7 @@ void cdv_intel_lvds_init(struct drm_device *dev,
         * Attempt to get the fixed panel mode from DDC.  Assume that the
         * preferred mode is the right one.
         */
+       mutex_lock(&dev->mode_config.mutex);
        psb_intel_ddc_get_modes(connector,
                                &gma_encoder->ddc_bus->adapter);
        list_for_each_entry(scan, &connector->probed_modes, head) {
@@ -772,10 +773,12 @@ void cdv_intel_lvds_init(struct drm_device *dev,
        }
 
 out:
+       mutex_unlock(&dev->mode_config.mutex);
        drm_sysfs_connector_add(connector);
        return;
 
 failed_find:
+       mutex_unlock(&dev->mode_config.mutex);
        printk(KERN_ERR "Failed find\n");
        if (gma_encoder->ddc_bus)
                psb_intel_i2c_destroy(gma_encoder->ddc_bus);
index 94b3fec22c280475dfe1f08d43cf00ed1ca571d2..e7fcc148f333ed56de86a92b14bcc0297fd798ff 100644 (file)
@@ -319,7 +319,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 {
        struct gtt_range *backing;
        /* Begin by trying to use stolen memory backing */
-       backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
+       backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1, PAGE_SIZE);
        if (backing) {
                drm_gem_private_object_init(dev, &backing->gem, aligned_size);
                return backing;
index e2db48a81ed0147738b27baaa76d663b29cc0f1a..c707fa6fca85bac195b824c7dcdb885074161f9a 100644 (file)
@@ -62,9 +62,6 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
        int ret = 0;
        struct drm_gem_object *obj;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        mutex_lock(&dev->struct_mutex);
 
        /* GEM does all our handle to object mapping */
@@ -98,8 +95,8 @@ unlock:
  *     it so that userspace can speak about it. This does the core work
  *     for the various methods that do/will create GEM objects for things
  */
-static int psb_gem_create(struct drm_file *file,
-       struct drm_device *dev, uint64_t size, uint32_t *handlep)
+int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size,
+                  u32 *handlep, int stolen, u32 align)
 {
        struct gtt_range *r;
        int ret;
@@ -109,7 +106,7 @@ static int psb_gem_create(struct drm_file *file,
 
        /* Allocate our object - for now a direct gtt range which is not
           stolen memory backed */
-       r = psb_gtt_alloc_range(dev, size, "gem", 0);
+       r = psb_gtt_alloc_range(dev, size, "gem", 0, PAGE_SIZE);
        if (r == NULL) {
                dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
                return -ENOSPC;
@@ -153,7 +150,8 @@ int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 {
        args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
        args->size = args->pitch * args->height;
-       return psb_gem_create(file, dev, args->size, &args->handle);
+       return psb_gem_create(file, dev, args->size, &args->handle, 0,
+                             PAGE_SIZE);
 }
 
 /**
@@ -229,47 +227,3 @@ fail:
                return VM_FAULT_SIGBUS;
        }
 }
-
-static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
-                                               int size, u32 *handle)
-{
-       struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
-       if (gtt == NULL)
-               return -ENOMEM;
-
-       drm_gem_private_object_init(dev, &gtt->gem, size);
-       if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
-               return 0;
-
-       drm_gem_object_release(&gtt->gem);
-       psb_gtt_free_range(dev, gtt);
-       return -ENOMEM;
-}
-
-/*
- *     GEM interfaces for our specific client
- */
-int psb_gem_create_ioctl(struct drm_device *dev, void *data,
-                                       struct drm_file *file)
-{
-       struct drm_psb_gem_create *args = data;
-       int ret;
-       if (args->flags & GMA_GEM_CREATE_STOLEN) {
-               ret = psb_gem_create_stolen(file, dev, args->size,
-                                                       &args->handle);
-               if (ret == 0)
-                       return 0;
-               /* Fall throguh */
-               args->flags &= ~GMA_GEM_CREATE_STOLEN;
-       }
-       return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
-                                       struct drm_file *file)
-{
-       struct drm_psb_gem_mmap *args = data;
-       return dev->driver->dumb_map_offset(file, dev,
-                                               args->handle, &args->offset);
-}
-
diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h
new file mode 100644 (file)
index 0000000..1381c51
--- /dev/null
@@ -0,0 +1,21 @@
+/**************************************************************************
+ * Copyright (c) 2014 Patrik Jakobsson
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ **************************************************************************/
+
+#ifndef _GEM_H
+#define _GEM_H
+
+extern int psb_gem_create(struct drm_file *file, struct drm_device *dev,
+                         u64 size, u32 *handlep, int stolen, u32 align);
+#endif
diff --git a/drivers/gpu/drm/gma500/gma_device.c b/drivers/gpu/drm/gma500/gma_device.c
new file mode 100644 (file)
index 0000000..4a295f9
--- /dev/null
@@ -0,0 +1,56 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+void gma_get_core_freq(struct drm_device *dev)
+{
+       uint32_t clock;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+       /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+       pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+       pci_read_config_dword(pci_root, 0xD4, &clock);
+       pci_dev_put(pci_root);
+
+       switch (clock & 0x07) {
+       case 0:
+               dev_priv->core_freq = 100;
+               break;
+       case 1:
+               dev_priv->core_freq = 133;
+               break;
+       case 2:
+               dev_priv->core_freq = 150;
+               break;
+       case 3:
+               dev_priv->core_freq = 178;
+               break;
+       case 4:
+               dev_priv->core_freq = 200;
+               break;
+       case 5:
+       case 6:
+       case 7:
+               dev_priv->core_freq = 266;
+               break;
+       default:
+               dev_priv->core_freq = 0;
+       }
+}
diff --git a/drivers/gpu/drm/gma500/gma_device.h b/drivers/gpu/drm/gma500/gma_device.h
new file mode 100644 (file)
index 0000000..e1dbb00
--- /dev/null
@@ -0,0 +1,21 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ **************************************************************************/
+
+#ifndef _GMA_DEVICE_H
+#define _GMA_DEVICE_H
+
+extern void gma_get_core_freq(struct drm_device *dev);
+
+#endif
index 386de2c9dc8649f449580a062d4d91c62fd3a733..9bb9bddd881a701a4cf387bf31874455d7e9da76 100644 (file)
@@ -59,7 +59,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_device *dev = crtc->dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+       struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
        int pipe = gma_crtc->pipe;
        const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
@@ -70,7 +70,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return 0;
 
        /* no fb bound */
-       if (!crtc->fb) {
+       if (!crtc->primary->fb) {
                dev_err(dev->dev, "No FB bound\n");
                goto gma_pipe_cleaner;
        }
@@ -81,19 +81,19 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        if (ret < 0)
                goto gma_pipe_set_base_exit;
        start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+       offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
 
-       REG_WRITE(map->stride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
 
        dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                dspcntr |= DISPPLANE_8BPP;
                break;
        case 16:
-               if (crtc->fb->depth == 15)
+               if (crtc->primary->fb->depth == 15)
                        dspcntr |= DISPPLANE_15_16BPP;
                else
                        dspcntr |= DISPPLANE_16BPP;
@@ -485,6 +485,13 @@ int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        return 0;
 }
 
+bool gma_encoder_mode_fixup(struct drm_encoder *encoder,
+                           const struct drm_display_mode *mode,
+                           struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
 bool gma_crtc_mode_fixup(struct drm_crtc *crtc,
                         const struct drm_display_mode *mode,
                         struct drm_display_mode *adjusted_mode)
@@ -511,8 +518,8 @@ void gma_crtc_disable(struct drm_crtc *crtc)
 
        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
-       if (crtc->fb) {
-               gt = to_psb_fb(crtc->fb)->gtt;
+       if (crtc->primary->fb) {
+               gt = to_psb_fb(crtc->primary->fb)->gtt;
                psb_gtt_unpin(gt);
        }
 }
index 78b9f986a6e5edf7bbc29615bdf0be356961a689..ed569d8a6af3cb53dc8a90031d2e98bd87fbf4e7 100644 (file)
@@ -90,6 +90,9 @@ extern void gma_crtc_restore(struct drm_crtc *crtc);
 extern void gma_encoder_prepare(struct drm_encoder *encoder);
 extern void gma_encoder_commit(struct drm_encoder *encoder);
 extern void gma_encoder_destroy(struct drm_encoder *encoder);
+extern bool gma_encoder_mode_fixup(struct drm_encoder *encoder,
+                                  const struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted_mode);
 
 /* Common clock related functions */
 extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk);
index 2db731f00930d7b28d85e124744423c8a37dd8b4..592d205a0089c0b71922a8453914b5b26aa2ec35 100644 (file)
@@ -22,6 +22,7 @@
 #include <drm/drmP.h>
 #include <linux/shmem_fs.h>
 #include "psb_drv.h"
+#include "blitter.h"
 
 
 /*
@@ -105,11 +106,13 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
 
        /* Write our page entries into the GTT itself */
        for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        /* 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,
  *     page table entries with the dummy page. This is protected via the gtt
  *     mutex which the caller must hold.
  */
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        u32 __iomem *gtt_slot;
@@ -137,7 +140,8 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
        WARN_ON(r->stolen);
 
        gtt_slot = psb_gtt_entry(dev, r);
-       pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
+       pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page),
+                              PSB_MMU_CACHED_MEMORY);
 
        for (i = 0; i < r->npage; i++)
                iowrite32(pte, gtt_slot++);
@@ -176,11 +180,13 @@ void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
        gtt_slot = psb_gtt_entry(dev, r);
 
        for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        ioread32(gtt_slot - 1);
@@ -240,6 +246,7 @@ int psb_gtt_pin(struct gtt_range *gt)
        int ret = 0;
        struct drm_device *dev = gt->gem.dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 gpu_base = dev_priv->gtt.gatt_start;
 
        mutex_lock(&dev_priv->gtt_mutex);
 
@@ -252,6 +259,9 @@ int psb_gtt_pin(struct gtt_range *gt)
                        psb_gtt_detach_pages(gt);
                        goto out;
                }
+               psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu),
+                                    gt->pages, (gpu_base + gt->offset),
+                                    gt->npage, 0, 0, PSB_MMU_CACHED_MEMORY);
        }
        gt->in_gart++;
 out:
@@ -274,16 +284,30 @@ void psb_gtt_unpin(struct gtt_range *gt)
 {
        struct drm_device *dev = gt->gem.dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 gpu_base = dev_priv->gtt.gatt_start;
+       int ret;
 
+       /* While holding the gtt_mutex no new blits can be initiated */
        mutex_lock(&dev_priv->gtt_mutex);
 
+       /* Wait for any possible usage of the memory to be finished */
+       ret = gma_blt_wait_idle(dev_priv);
+       if (ret) {
+               DRM_ERROR("Failed to idle the blitter, unpin failed!");
+               goto out;
+       }
+
        WARN_ON(!gt->in_gart);
 
        gt->in_gart--;
        if (gt->in_gart == 0 && gt->stolen == 0) {
+               psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu),
+                                    (gpu_base + gt->offset), gt->npage, 0, 0);
                psb_gtt_remove(dev, gt);
                psb_gtt_detach_pages(gt);
        }
+
+out:
        mutex_unlock(&dev_priv->gtt_mutex);
 }
 
@@ -306,7 +330,7 @@ void psb_gtt_unpin(struct gtt_range *gt)
  *     as in use.
  */
 struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-                                               const char *name, int backed)
+                                     const char *name, int backed, u32 align)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gtt_range *gt;
@@ -334,7 +358,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
        /* Ensure this is set for non GEM objects */
        gt->gem.dev = dev;
        ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
-                               len, start, end, PAGE_SIZE, NULL, NULL);
+                               len, start, end, align, NULL, NULL);
        if (ret == 0) {
                gt->offset = gt->resource.start - r->start;
                return gt;
@@ -497,6 +521,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        if (!resume)
                dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
                                                 stolen_size);
+
        if (!dev_priv->vram_addr) {
                dev_err(dev->dev, "Failure to map stolen base.\n");
                ret = -ENOMEM;
@@ -512,7 +537,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
                num_pages, pfn_base << PAGE_SHIFT, 0);
        for (i = 0; i < num_pages; ++i) {
-               pte = psb_gtt_mask_pte(pfn_base + i, 0);
+               pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, dev_priv->gtt_map + i);
        }
 
@@ -521,7 +546,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
         */
 
        pfn_base = page_to_pfn(dev_priv->scratch_page);
-       pte = psb_gtt_mask_pte(pfn_base, 0);
+       pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY);
        for (; i < gtt_pages; ++i)
                iowrite32(pte, dev_priv->gtt_map + i);
 
index 6191d10acf33286f9f768e57aad30c59ef49bbfc..f5860a739bd8551fa60868b09ab61bb74b4c0edf 100644 (file)
@@ -53,7 +53,8 @@ struct gtt_range {
 };
 
 extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-                                               const char *name, int backed);
+                                            const char *name, int backed,
+                                            u32 align);
 extern void psb_gtt_kref_put(struct gtt_range *gt);
 extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
 extern int psb_gtt_pin(struct gtt_range *gt);
index 860a4ee9baaf0a124574726b7554c58e85de7785..6e91b20ce2e500fd766103ce1d11403a4257f383 100644 (file)
@@ -287,7 +287,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
                                                &gma_crtc->saved_mode,
                                                encoder->crtc->x,
                                                encoder->crtc->y,
-                                               encoder->crtc->fb))
+                                               encoder->crtc->primary->fb))
                                        goto set_prop_error;
                        } else {
                                struct drm_encoder_helper_funcs *funcs =
index 321c00a944e9278479e29d588ac0ebb0bea2c707..8cc8a5abbc7bdd0852c1747f3b7924c0650e924d 100644 (file)
@@ -166,7 +166,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_device *dev = crtc->dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+       struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
        int pipe = gma_crtc->pipe;
        const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
@@ -178,12 +178,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
 
        /* no fb bound */
-       if (!crtc->fb) {
+       if (!crtc->primary->fb) {
                dev_dbg(dev->dev, "No FB bound\n");
                return 0;
        }
 
-       ret = check_fb(crtc->fb);
+       ret = check_fb(crtc->primary->fb);
        if (ret)
                return ret;
 
@@ -196,18 +196,18 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return 0;
 
        start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+       offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
 
-       REG_WRITE(map->stride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
        dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                dspcntr |= DISPPLANE_8BPP;
                break;
        case 16:
-               if (crtc->fb->depth == 15)
+               if (crtc->primary->fb->depth == 15)
                        dspcntr |= DISPPLANE_15_16BPP;
                else
                        dspcntr |= DISPPLANE_16BPP;
@@ -700,7 +700,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
        }
 #endif
 
-       ret = check_fb(crtc->fb);
+       ret = check_fb(crtc->primary->fb);
        if (ret)
                return ret;
 
index 49bac41beefb3251ecc6a63f04e86d0d36de9974..3e14a9b3525286de73fffc3c82cb2af838a9ac79 100644 (file)
@@ -18,6 +18,7 @@
 #include <drm/drmP.h>
 #include "psb_drv.h"
 #include "psb_reg.h"
+#include "mmu.h"
 
 /*
  * Code for the SGX MMU:
  * but on average it should be fast.
  */
 
-struct psb_mmu_driver {
-       /* protects driver- and pd structures. Always take in read mode
-        * before taking the page table spinlock.
-        */
-       struct rw_semaphore sem;
-
-       /* protects page tables, directory tables and pt tables.
-        * and pt structures.
-        */
-       spinlock_t lock;
-
-       atomic_t needs_tlbflush;
-
-       uint8_t __iomem *register_map;
-       struct psb_mmu_pd *default_pd;
-       /*uint32_t bif_ctrl;*/
-       int has_clflush;
-       int clflush_add;
-       unsigned long clflush_mask;
-
-       struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
-       struct psb_mmu_pd *pd;
-       uint32_t index;
-       uint32_t count;
-       struct page *p;
-       uint32_t *v;
-};
-
-struct psb_mmu_pd {
-       struct psb_mmu_driver *driver;
-       int hw_context;
-       struct psb_mmu_pt **tables;
-       struct page *p;
-       struct page *dummy_pt;
-       struct page *dummy_page;
-       uint32_t pd_mask;
-       uint32_t invalid_pde;
-       uint32_t invalid_pte;
-};
-
 static inline uint32_t psb_mmu_pt_index(uint32_t offset)
 {
        return (offset >> PSB_PTE_SHIFT) & 0x3FF;
@@ -102,13 +58,13 @@ static inline uint32_t psb_mmu_pd_index(uint32_t offset)
        return offset >> PSB_PDE_SHIFT;
 }
 
+#if defined(CONFIG_X86)
 static inline void psb_clflush(void *addr)
 {
        __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
 }
 
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
-                                  void *addr)
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr)
 {
        if (!driver->has_clflush)
                return;
@@ -117,62 +73,77 @@ static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
        psb_clflush(addr);
        mb();
 }
+#else
 
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
-{
-       uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
-       uint32_t clflush_count = PAGE_SIZE / clflush_add;
-       int i;
-       uint8_t *clf;
-
-       clf = kmap_atomic(page);
-       mb();
-       for (i = 0; i < clflush_count; ++i) {
-               psb_clflush(clf);
-               clf += clflush_add;
-       }
-       mb();
-       kunmap_atomic(clf);
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr)
+{;
 }
 
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
-                               struct page *page[], unsigned long num_pages)
-{
-       int i;
-
-       if (!driver->has_clflush)
-               return ;
+#endif
 
-       for (i = 0; i < num_pages; i++)
-               psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
-                                   int force)
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, int force)
 {
+       struct drm_device *dev = driver->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       if (atomic_read(&driver->needs_tlbflush) || force) {
+               uint32_t val = PSB_RSGX32(PSB_CR_BIF_CTRL);
+               PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+
+               /* Make sure data cache is turned off before enabling it */
+               wmb();
+               PSB_WSGX32(val & ~_PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+               (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
+               if (driver->msvdx_mmu_invaldc)
+                       atomic_set(driver->msvdx_mmu_invaldc, 1);
+       }
        atomic_set(&driver->needs_tlbflush, 0);
 }
 
+#if 0
 static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
 {
        down_write(&driver->sem);
        psb_mmu_flush_pd_locked(driver, force);
        up_write(&driver->sem);
 }
+#endif
 
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+void psb_mmu_flush(struct psb_mmu_driver *driver)
 {
-       if (rc_prot)
-               down_write(&driver->sem);
-       if (rc_prot)
-               up_write(&driver->sem);
+       struct drm_device *dev = driver->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t val;
+
+       down_write(&driver->sem);
+       val = PSB_RSGX32(PSB_CR_BIF_CTRL);
+       if (atomic_read(&driver->needs_tlbflush))
+               PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+       else
+               PSB_WSGX32(val | _PSB_CB_CTRL_FLUSH, PSB_CR_BIF_CTRL);
+
+       /* Make sure data cache is turned off and MMU is flushed before
+          restoring bank interface control register */
+       wmb();
+       PSB_WSGX32(val & ~(_PSB_CB_CTRL_FLUSH | _PSB_CB_CTRL_INVALDC),
+                  PSB_CR_BIF_CTRL);
+       (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+       atomic_set(&driver->needs_tlbflush, 0);
+       if (driver->msvdx_mmu_invaldc)
+               atomic_set(driver->msvdx_mmu_invaldc, 1);
+       up_write(&driver->sem);
 }
 
 void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
 {
-       /*ttm_tt_cache_flush(&pd->p, 1);*/
-       psb_pages_clflush(pd->driver, &pd->p, 1);
+       struct drm_device *dev = pd->driver->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t offset = (hw_context == 0) ? PSB_CR_BIF_DIR_LIST_BASE0 :
+                         PSB_CR_BIF_DIR_LIST_BASE1 + hw_context * 4;
+
        down_write(&pd->driver->sem);
+       PSB_WSGX32(page_to_pfn(pd->p) << PAGE_SHIFT, offset);
        wmb();
        psb_mmu_flush_pd_locked(pd->driver, 1);
        pd->hw_context = hw_context;
@@ -183,7 +154,6 @@ void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
 static inline unsigned long psb_pd_addr_end(unsigned long addr,
                                            unsigned long end)
 {
-
        addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
        return (addr < end) ? addr : end;
 }
@@ -223,12 +193,10 @@ struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
                goto out_err3;
 
        if (!trap_pagefaults) {
-               pd->invalid_pde =
-                   psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
-                                    invalid_type);
-               pd->invalid_pte =
-                   psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
-                                    invalid_type);
+               pd->invalid_pde = psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+                                                  invalid_type);
+               pd->invalid_pte = psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+                                                  invalid_type);
        } else {
                pd->invalid_pde = 0;
                pd->invalid_pte = 0;
@@ -279,12 +247,16 @@ static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
 void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
 {
        struct psb_mmu_driver *driver = pd->driver;
+       struct drm_device *dev = driver->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_mmu_pt *pt;
        int i;
 
        down_write(&driver->sem);
-       if (pd->hw_context != -1)
+       if (pd->hw_context != -1) {
+               PSB_WSGX32(0, PSB_CR_BIF_DIR_LIST_BASE0 + pd->hw_context * 4);
                psb_mmu_flush_pd_locked(driver, 1);
+       }
 
        /* Should take the spinlock here, but we don't need to do that
           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)
        for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
                *ptes++ = pd->invalid_pte;
 
-
+#if defined(CONFIG_X86)
        if (pd->driver->has_clflush && pd->hw_context != -1) {
                mb();
                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)
                }
                mb();
        }
-
+#endif
        kunmap_atomic(v);
        spin_unlock(lock);
 
@@ -351,7 +323,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
        return pt;
 }
 
-static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
                                             unsigned long addr)
 {
        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,
                kunmap_atomic((void *) v);
 
                if (pd->hw_context != -1) {
-                       psb_mmu_clflush(pd->driver, (void *) &v[index]);
+                       psb_mmu_clflush(pd->driver, (void *)&v[index]);
                        atomic_set(&pd->driver->needs_tlbflush, 1);
                }
        }
@@ -420,8 +392,7 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
                pd->tables[pt->index] = NULL;
 
                if (pd->hw_context != -1) {
-                       psb_mmu_clflush(pd->driver,
-                                       (void *) &v[pt->index]);
+                       psb_mmu_clflush(pd->driver, (void *)&v[pt->index]);
                        atomic_set(&pd->driver->needs_tlbflush, 1);
                }
                kunmap_atomic(pt->v);
@@ -432,8 +403,8 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
        spin_unlock(&pd->driver->lock);
 }
 
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
-                                  unsigned long addr, uint32_t pte)
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, unsigned long addr,
+                                  uint32_t pte)
 {
        pt->v[psb_mmu_pt_index(addr)] = pte;
 }
@@ -444,69 +415,50 @@ static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
        pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
 }
 
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
-                       uint32_t mmu_offset, uint32_t gtt_start,
-                       uint32_t gtt_pages)
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
 {
-       uint32_t *v;
-       uint32_t start = psb_mmu_pd_index(mmu_offset);
-       struct psb_mmu_driver *driver = pd->driver;
-       int num_pages = gtt_pages;
+       struct psb_mmu_pd *pd;
 
        down_read(&driver->sem);
-       spin_lock(&driver->lock);
-
-       v = kmap_atomic(pd->p);
-       v += start;
-
-       while (gtt_pages--) {
-               *v++ = gtt_start | pd->pd_mask;
-               gtt_start += PAGE_SIZE;
-       }
-
-       /*ttm_tt_cache_flush(&pd->p, num_pages);*/
-       psb_pages_clflush(pd->driver, &pd->p, num_pages);
-       kunmap_atomic(v);
-       spin_unlock(&driver->lock);
-
-       if (pd->hw_context != -1)
-               atomic_set(&pd->driver->needs_tlbflush, 1);
+       pd = driver->default_pd;
+       up_read(&driver->sem);
 
-       up_read(&pd->driver->sem);
-       psb_mmu_flush_pd(pd->driver, 0);
+       return pd;
 }
 
-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
 {
        struct psb_mmu_pd *pd;
 
-       /* down_read(&driver->sem); */
-       pd = driver->default_pd;
-       /* up_read(&driver->sem); */
-
-       return pd;
+       pd = psb_mmu_get_default_pd(driver);
+       return page_to_pfn(pd->p) << PAGE_SHIFT;
 }
 
 void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
 {
+       struct drm_device *dev = driver->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       PSB_WSGX32(driver->bif_ctrl, PSB_CR_BIF_CTRL);
        psb_mmu_free_pagedir(driver->default_pd);
        kfree(driver);
 }
 
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-                                       int trap_pagefaults,
-                                       int invalid_type,
-                                       struct drm_psb_private *dev_priv)
+struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
+                                          int trap_pagefaults,
+                                          int invalid_type,
+                                          atomic_t *msvdx_mmu_invaldc)
 {
        struct psb_mmu_driver *driver;
+       struct drm_psb_private *dev_priv = dev->dev_private;
 
        driver = kmalloc(sizeof(*driver), GFP_KERNEL);
 
        if (!driver)
                return NULL;
-       driver->dev_priv = dev_priv;
 
+       driver->dev = dev;
        driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
                                              invalid_type);
        if (!driver->default_pd)
@@ -515,17 +467,24 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
        spin_lock_init(&driver->lock);
        init_rwsem(&driver->sem);
        down_write(&driver->sem);
-       driver->register_map = registers;
        atomic_set(&driver->needs_tlbflush, 1);
+       driver->msvdx_mmu_invaldc = msvdx_mmu_invaldc;
+
+       driver->bif_ctrl = PSB_RSGX32(PSB_CR_BIF_CTRL);
+       PSB_WSGX32(driver->bif_ctrl | _PSB_CB_CTRL_CLEAR_FAULT,
+                  PSB_CR_BIF_CTRL);
+       PSB_WSGX32(driver->bif_ctrl & ~_PSB_CB_CTRL_CLEAR_FAULT,
+                  PSB_CR_BIF_CTRL);
 
        driver->has_clflush = 0;
 
+#if defined(CONFIG_X86)
        if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
                uint32_t tfms, misc, cap0, cap4, clflush_size;
 
                /*
-                * clflush size is determined at kernel setup for x86_64
-                *  but not for i386. We have to do it here.
+                * clflush size is determined at kernel setup for x86_64 but not
+                * for i386. We have to do it here.
                 */
 
                cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
@@ -536,6 +495,7 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
                driver->clflush_mask = driver->clflush_add - 1;
                driver->clflush_mask = ~driver->clflush_mask;
        }
+#endif
 
        up_write(&driver->sem);
        return driver;
@@ -545,9 +505,9 @@ out_err1:
        return NULL;
 }
 
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
-                              unsigned long address, uint32_t num_pages,
-                              uint32_t desired_tile_stride,
+#if defined(CONFIG_X86)
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address,
+                              uint32_t num_pages, uint32_t desired_tile_stride,
                               uint32_t hw_tile_stride)
 {
        struct psb_mmu_pt *pt;
@@ -561,11 +521,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
        unsigned long clflush_add = pd->driver->clflush_add;
        unsigned long clflush_mask = pd->driver->clflush_mask;
 
-       if (!pd->driver->has_clflush) {
-               /*ttm_tt_cache_flush(&pd->p, num_pages);*/
-               psb_pages_clflush(pd->driver, &pd->p, num_pages);
+       if (!pd->driver->has_clflush)
                return;
-       }
 
        if (hw_tile_stride)
                rows = num_pages / desired_tile_stride;
@@ -586,10 +543,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
                        if (!pt)
                                continue;
                        do {
-                               psb_clflush(&pt->v
-                                           [psb_mmu_pt_index(addr)]);
-                       } while (addr +=
-                                clflush_add,
+                               psb_clflush(&pt->v[psb_mmu_pt_index(addr)]);
+                       } while (addr += clflush_add,
                                 (addr & clflush_mask) < next);
 
                        psb_mmu_pt_unmap_unlock(pt);
@@ -598,6 +553,14 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
        }
        mb();
 }
+#else
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address,
+                              uint32_t num_pages, uint32_t desired_tile_stride,
+                              uint32_t hw_tile_stride)
+{
+       drm_ttm_cache_flush();
+}
+#endif
 
 void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
                                 unsigned long address, uint32_t num_pages)
@@ -633,7 +596,7 @@ out:
        up_read(&pd->driver->sem);
 
        if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 0);
+               psb_mmu_flush(pd->driver);
 
        return;
 }
@@ -660,7 +623,7 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
        add = desired_tile_stride << PAGE_SHIFT;
        row_add = hw_tile_stride << PAGE_SHIFT;
 
-       /* down_read(&pd->driver->sem); */
+       down_read(&pd->driver->sem);
 
        /* Make sure we only need to flush this processor's cache */
 
@@ -688,10 +651,10 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
                psb_mmu_flush_ptes(pd, f_address, num_pages,
                                   desired_tile_stride, hw_tile_stride);
 
-       /* up_read(&pd->driver->sem); */
+       up_read(&pd->driver->sem);
 
        if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 0);
+               psb_mmu_flush(pd->driver);
 }
 
 int 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,
        unsigned long end;
        unsigned long next;
        unsigned long f_address = address;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        down_read(&pd->driver->sem);
 
@@ -726,6 +689,7 @@ int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
                psb_mmu_pt_unmap_unlock(pt);
 
        } while (addr = next, next != end);
+       ret = 0;
 
 out:
        if (pd->hw_context != -1)
@@ -734,15 +698,15 @@ out:
        up_read(&pd->driver->sem);
 
        if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 1);
+               psb_mmu_flush(pd->driver);
 
-       return ret;
+       return 0;
 }
 
 int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
                         unsigned long address, uint32_t num_pages,
-                        uint32_t desired_tile_stride,
-                        uint32_t hw_tile_stride, int type)
+                        uint32_t desired_tile_stride, uint32_t hw_tile_stride,
+                        int type)
 {
        struct psb_mmu_pt *pt;
        uint32_t rows = 1;
@@ -754,7 +718,7 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
        unsigned long add;
        unsigned long row_add;
        unsigned long f_address = address;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        if (hw_tile_stride) {
                if (num_pages % desired_tile_stride != 0)
@@ -777,14 +741,11 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
                do {
                        next = psb_pd_addr_end(addr, end);
                        pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-                       if (!pt) {
-                               ret = -ENOMEM;
+                       if (!pt)
                                goto out;
-                       }
                        do {
-                               pte =
-                                   psb_mmu_mask_pte(page_to_pfn(*pages++),
-                                                    type);
+                               pte = psb_mmu_mask_pte(page_to_pfn(*pages++),
+                                                      type);
                                psb_mmu_set_pte(pt, addr, pte);
                                pt->count++;
                        } while (addr += PAGE_SIZE, addr < next);
@@ -794,6 +755,8 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
 
                address += row_add;
        }
+
+       ret = 0;
 out:
        if (pd->hw_context != -1)
                psb_mmu_flush_ptes(pd, f_address, num_pages,
@@ -802,7 +765,7 @@ out:
        up_read(&pd->driver->sem);
 
        if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 1);
+               psb_mmu_flush(pd->driver);
 
        return ret;
 }
diff --git a/drivers/gpu/drm/gma500/mmu.h b/drivers/gpu/drm/gma500/mmu.h
new file mode 100644 (file)
index 0000000..e89abec
--- /dev/null
@@ -0,0 +1,93 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ **************************************************************************/
+
+#ifndef __MMU_H
+#define __MMU_H
+
+struct psb_mmu_driver {
+       /* protects driver- and pd structures. Always take in read mode
+        * before taking the page table spinlock.
+        */
+       struct rw_semaphore sem;
+
+       /* protects page tables, directory tables and pt tables.
+        * and pt structures.
+        */
+       spinlock_t lock;
+
+       atomic_t needs_tlbflush;
+       atomic_t *msvdx_mmu_invaldc;
+       struct psb_mmu_pd *default_pd;
+       uint32_t bif_ctrl;
+       int has_clflush;
+       int clflush_add;
+       unsigned long clflush_mask;
+
+       struct drm_device *dev;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+       struct psb_mmu_pd *pd;
+       uint32_t index;
+       uint32_t count;
+       struct page *p;
+       uint32_t *v;
+};
+
+struct psb_mmu_pd {
+       struct psb_mmu_driver *driver;
+       int hw_context;
+       struct psb_mmu_pt **tables;
+       struct page *p;
+       struct page *dummy_pt;
+       struct page *dummy_page;
+       uint32_t pd_mask;
+       uint32_t invalid_pde;
+       uint32_t invalid_pte;
+};
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
+                                                 int trap_pagefaults,
+                                                 int invalid_type,
+                                                 atomic_t *msvdx_mmu_invaldc);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+                                                *driver);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+                                          int trap_pagefaults,
+                                          int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+                                       unsigned long address,
+                                       uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+                                      uint32_t start_pfn,
+                                      unsigned long address,
+                                      uint32_t num_pages, int type);
+extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+                                 unsigned long *pfn);
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+                               unsigned long address, uint32_t num_pages,
+                               uint32_t desired_tile_stride,
+                               uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+                                unsigned long address, uint32_t num_pages,
+                                uint32_t desired_tile_stride,
+                                uint32_t hw_tile_stride);
+
+#endif
index 8195e859210741cdd37ef00b0d8c6f2aa1070227..2de216c2374f34482f43008e20fab3eaffbb2e2b 100644 (file)
@@ -599,7 +599,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+       struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
        int pipe = gma_crtc->pipe;
        const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
@@ -608,7 +608,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
        int ret = 0;
 
        /* no fb bound */
-       if (!crtc->fb) {
+       if (!crtc->primary->fb) {
                dev_dbg(dev->dev, "No FB bound\n");
                return 0;
        }
@@ -617,19 +617,19 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
                return 0;
 
        start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+       offset = y * crtc->primary->fb->pitches[0] + x * (crtc->primary->fb->bits_per_pixel / 8);
 
-       REG_WRITE(map->stride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
 
        dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                dspcntr |= DISPPLANE_8BPP;
                break;
        case 16:
-               if (crtc->fb->depth == 15)
+               if (crtc->primary->fb->depth == 15)
                        dspcntr |= DISPPLANE_15_16BPP;
                else
                        dspcntr |= DISPPLANE_16BPP;
index 38153143ed8ca222cd9d169ebaa885a7a57d4bfe..cf018ddcc5a646caf91d027d4cd79343d6e7c124 100644 (file)
@@ -523,13 +523,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder,
-                                const struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
 static enum drm_connector_status
 oaktrail_hdmi_detect(struct drm_connector *connector, bool force)
 {
@@ -608,7 +601,7 @@ static void oaktrail_hdmi_destroy(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = {
        .dpms = oaktrail_hdmi_dpms,
-       .mode_fixup = oaktrail_hdmi_mode_fixup,
+       .mode_fixup = gma_encoder_mode_fixup,
        .prepare = gma_encoder_prepare,
        .mode_set = oaktrail_hdmi_mode_set,
        .commit = gma_encoder_commit,
index 5e0697862736e8372c0ac5342e3d5b5b852be930..9b099468a5dbb496d0892f8c465131522aae7d9a 100644 (file)
@@ -359,6 +359,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
         *    if closed, act like it's not there for now
         */
 
+       mutex_lock(&dev->mode_config.mutex);
        i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
        if (i2c_adap == NULL)
                dev_err(dev->dev, "No ddc adapter available!\n");
@@ -401,10 +402,14 @@ void oaktrail_lvds_init(struct drm_device *dev,
        }
 
 out:
+       mutex_unlock(&dev->mode_config.mutex);
+
        drm_sysfs_connector_add(connector);
        return;
 
 failed_find:
+       mutex_unlock(&dev->mode_config.mutex);
+
        dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
        if (gma_encoder->ddc_bus)
                psb_intel_i2c_destroy(gma_encoder->ddc_bus);
index 13ec6283bf597481e83089226ed13dfc35fbc37f..ab696ca7eeecc8544df4a9db2a1c74d00797bc9f 100644 (file)
@@ -173,10 +173,13 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
        return 0;
 }
 
-void psb_intel_opregion_asle_intr(struct drm_device *dev)
+static void psb_intel_opregion_asle_work(struct work_struct *work)
 {
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct psb_intel_opregion *opregion =
+               container_of(work, struct psb_intel_opregion, asle_work);
+       struct drm_psb_private *dev_priv =
+               container_of(opregion, struct drm_psb_private, opregion);
+       struct opregion_asle *asle = opregion->asle;
        u32 asle_stat = 0;
        u32 asle_req;
 
@@ -190,9 +193,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev)
        }
 
        if (asle_req & ASLE_SET_BACKLIGHT)
-               asle_stat |= asle_set_backlight(dev, asle->bclp);
+               asle_stat |= asle_set_backlight(dev_priv->dev, asle->bclp);
 
        asle->aslc = asle_stat;
+
+}
+
+void psb_intel_opregion_asle_intr(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->opregion.asle)
+               schedule_work(&dev_priv->opregion.asle_work);
 }
 
 #define ASLE_ALS_EN    (1<<0)
@@ -282,6 +294,8 @@ void psb_intel_opregion_fini(struct drm_device *dev)
                unregister_acpi_notifier(&psb_intel_opregion_notifier);
        }
 
+       cancel_work_sync(&opregion->asle_work);
+
        /* just clear all opregion memory pointers now */
        iounmap(opregion->header);
        opregion->header = NULL;
@@ -304,6 +318,9 @@ int psb_intel_opregion_setup(struct drm_device *dev)
                DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
                return -ENOTSUPP;
        }
+
+       INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);
+
        DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
        base = acpi_os_ioremap(opregion_phy, 8*1024);
        if (!base)
index 23fb33f1471baf0a77f8de33f4200d7961546e8f..07df7d4eea7282911fb6d1d7ce1e699541babd7b 100644 (file)
@@ -26,6 +26,7 @@
 #include "psb_intel_reg.h"
 #include "intel_bios.h"
 #include "psb_device.h"
+#include "gma_device.h"
 
 static int psb_output_init(struct drm_device *dev)
 {
@@ -257,45 +258,6 @@ static int psb_power_up(struct drm_device *dev)
        return 0;
 }
 
-static void psb_get_core_freq(struct drm_device *dev)
-{
-       uint32_t clock;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
-       /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
-       pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-       pci_read_config_dword(pci_root, 0xD4, &clock);
-       pci_dev_put(pci_root);
-
-       switch (clock & 0x07) {
-       case 0:
-               dev_priv->core_freq = 100;
-               break;
-       case 1:
-               dev_priv->core_freq = 133;
-               break;
-       case 2:
-               dev_priv->core_freq = 150;
-               break;
-       case 3:
-               dev_priv->core_freq = 178;
-               break;
-       case 4:
-               dev_priv->core_freq = 200;
-               break;
-       case 5:
-       case 6:
-       case 7:
-               dev_priv->core_freq = 266;
-               break;
-       default:
-               dev_priv->core_freq = 0;
-       }
-}
-
 /* Poulsbo */
 static const struct psb_offset psb_regmap[2] = {
        {
@@ -352,7 +314,7 @@ static int psb_chip_setup(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        dev_priv->regmap = psb_regmap;
-       psb_get_core_freq(dev);
+       gma_get_core_freq(dev);
        gma_intel_setup_gmbus(dev);
        psb_intel_opregion_init(dev);
        psb_intel_init_bios(dev);
index 1199180667c98af81093ff073948f2bf52aacbbc..b686e56646ebd4b8abe6ba53582dd4e595484f29 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include <drm/gma_drm.h>
 #include "psb_drv.h"
 #include "framebuffer.h"
 #include "psb_reg.h"
 #include <acpi/video.h>
 #include <linux/module.h>
 
-static int drm_psb_trap_pagefaults;
-
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
-
+static struct drm_driver driver;
+static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 
+/*
+ * The table below contains a mapping of the PCI vendor ID and the PCI Device ID
+ * to the different groups of PowerVR 5-series chip designs
+ *
+ * 0x8086 = Intel Corporation
+ *
+ * PowerVR SGX535    - Poulsbo    - Intel GMA 500, Intel Atom Z5xx
+ * PowerVR SGX535    - Moorestown - Intel GMA 600
+ * PowerVR SGX535    - Oaktrail   - Intel GMA 600, Intel Atom Z6xx, E6xx
+ * PowerVR SGX540    - Medfield   - Intel Atom Z2460
+ * PowerVR SGX544MP2 - Medfield   -
+ * PowerVR SGX545    - Cedartrail - Intel GMA 3600, Intel Atom D2500, N2600
+ * PowerVR SGX545    - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700,
+ *                                  N2800
+ */
 static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
        { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
        { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
 #if defined(CONFIG_DRM_GMA600)
-       { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-       /* Atom E620 */
-       { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+       { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
 #endif
 #if defined(CONFIG_DRM_MEDFIELD)
-       {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+       { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
+       { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops },
 #endif
 #if defined(CONFIG_DRM_GMA3600)
-       { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+       { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
 #endif
        { 0, }
 };
@@ -95,59 +103,10 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 /*
  * Standard IOCTLs.
  */
-
-#define DRM_IOCTL_GMA_ADB      \
-               DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_GMA_MODE_OPERATION   \
-               DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
-                        struct drm_psb_mode_operation_arg)
-#define DRM_IOCTL_GMA_STOLEN_MEMORY    \
-               DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
-                        struct drm_psb_stolen_memory_arg)
-#define DRM_IOCTL_GMA_GAMMA    \
-               DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
-                        struct drm_psb_dpst_lut_arg)
-#define DRM_IOCTL_GMA_DPST_BL  \
-               DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
-                        uint32_t)
-#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID    \
-               DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
-                        struct drm_psb_get_pipe_from_crtc_id_arg)
-#define DRM_IOCTL_GMA_GEM_CREATE       \
-               DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
-                        struct drm_psb_gem_create)
-#define DRM_IOCTL_GMA_GEM_MMAP \
-               DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
-                        struct drm_psb_gem_mmap)
-
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
-                                  struct drm_file *file_priv);
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv);
-
 static const struct drm_ioctl_desc psb_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
-                     DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl,
-                     DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID,
-                                       psb_intel_get_pipe_from_crtc_id, 0),
-       DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl,
-                                               DRM_UNLOCKED | DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl,
-                                               DRM_UNLOCKED | DRM_AUTH),
 };
 
-static void psb_lastclose(struct drm_device *dev)
+static void psb_driver_lastclose(struct drm_device *dev)
 {
        int ret;
        struct drm_psb_private *dev_priv = dev->dev_private;
@@ -169,19 +128,14 @@ static int psb_do_init(struct drm_device *dev)
 
        uint32_t stolen_gtt;
 
-       int ret = -ENOMEM;
-
        if (pg->mmu_gatt_start & 0x0FFFFFFF) {
                dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
-               ret = -EINVAL;
-               goto out_err;
+               return -EINVAL;
        }
 
-
        stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
        stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       stolen_gtt =
-           (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+       stolen_gtt = (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
 
        dev_priv->gatt_free_offset = pg->mmu_gatt_start +
            (stolen_gtt << PAGE_SHIFT) * 1024;
@@ -192,23 +146,26 @@ static int psb_do_init(struct drm_device *dev)
        PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
        PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
        PSB_RSGX32(PSB_CR_BIF_BANK1);
-       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
-                                                       PSB_CR_BIF_CTRL);
+
+       /* Do not bypass any MMU access, let them pagefault instead */
+       PSB_WSGX32((PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_MMU_ER_MASK),
+                  PSB_CR_BIF_CTRL);
+       PSB_RSGX32(PSB_CR_BIF_CTRL);
+
        psb_spank(dev_priv);
 
        /* mmu_gatt ?? */
        PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+       PSB_RSGX32(PSB_CR_BIF_TWOD_REQ_BASE); /* Post */
+
        return 0;
-out_err:
-       return ret;
 }
 
 static int psb_driver_unload(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
 
-       /* Kill vblank etc here */
-
+       /* TODO: Kill vblank etc here */
 
        if (dev_priv) {
                if (dev_priv->backlight_device)
@@ -268,8 +225,7 @@ static int psb_driver_unload(struct drm_device *dev)
        return 0;
 }
 
-
-static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+static int psb_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_psb_private *dev_priv;
        unsigned long resource_start, resource_len;
@@ -277,15 +233,19 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        int ret = -ENOMEM;
        struct drm_connector *connector;
        struct gma_encoder *gma_encoder;
+       struct psb_gtt *pg;
 
+       /* allocating and initializing driver private data */
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
                return -ENOMEM;
 
-       dev_priv->ops = (struct psb_ops *)chipset;
+       dev_priv->ops = (struct psb_ops *)flags;
        dev_priv->dev = dev;
        dev->dev_private = (void *) dev_priv;
 
+       pg = &dev_priv->gtt;
+
        pci_set_master(dev->pdev);
 
        dev_priv->num_pipe = dev_priv->ops->pipes;
@@ -347,9 +307,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        if (ret)
                goto out_err;
 
-       dev_priv->mmu = psb_mmu_driver_init((void *)0,
-                                       drm_psb_trap_pagefaults, 0,
-                                       dev_priv);
+       dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0);
        if (!dev_priv->mmu)
                goto out_err;
 
@@ -357,18 +315,27 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        if (!dev_priv->pf_pd)
                goto out_err;
 
-       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
-       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
-
        ret = psb_do_init(dev);
        if (ret)
                return ret;
 
+       /* Add stolen memory to SGX MMU */
+       down_read(&pg->sem);
+       ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd(dev_priv->mmu),
+                                         dev_priv->stolen_base >> PAGE_SHIFT,
+                                         pg->gatt_start,
+                                         pg->stolen_size >> PAGE_SHIFT, 0);
+       up_read(&pg->sem);
+
+       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
        PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
        PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
 
        acpi_video_register();
 
+       /* Setup vertical blanking handling */
        ret = drm_vblank_init(dev, dev_priv->num_pipe);
        if (ret)
                goto out_err;
@@ -390,9 +357,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        drm_irq_install(dev);
 
        dev->vblank_disable_allowed = true;
-
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-
        dev->driver->get_vblank_counter = psb_get_vblank_counter;
 
        psb_modeset_init(dev);
@@ -416,11 +381,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
                return ret;
        psb_intel_opregion_enable_asle(dev);
 #if 0
-       /*enable runtime pm at last*/
+       /* Enable runtime pm at last */
        pm_runtime_enable(&dev->pdev->dev);
        pm_runtime_set_active(&dev->pdev->dev);
 #endif
-       /*Intel drm driver load is done, continue doing pvr load*/
+       /* Intel drm driver load is done, continue doing pvr load */
        return 0;
 out_err:
        psb_driver_unload(dev);
@@ -442,161 +407,6 @@ static inline void get_brightness(struct backlight_device *bd)
 #endif
 }
 
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       uint32_t *arg = data;
-
-       dev_priv->blc_adj2 = *arg;
-       get_brightness(dev_priv->backlight_device);
-       return 0;
-}
-
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       uint32_t *arg = data;
-
-       dev_priv->blc_adj1 = *arg;
-       get_brightness(dev_priv->backlight_device);
-       return 0;
-}
-
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       struct drm_psb_dpst_lut_arg *lut_arg = data;
-       struct drm_mode_object *obj;
-       struct drm_crtc *crtc;
-       struct drm_connector *connector;
-       struct gma_crtc *gma_crtc;
-       int i = 0;
-       int32_t obj_id;
-
-       obj_id = lut_arg->output_id;
-       obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
-       if (!obj) {
-               dev_dbg(dev->dev, "Invalid Connector object.\n");
-               return -ENOENT;
-       }
-
-       connector = obj_to_connector(obj);
-       crtc = connector->encoder->crtc;
-       gma_crtc = to_gma_crtc(crtc);
-
-       for (i = 0; i < 256; i++)
-               gma_crtc->lut_adj[i] = lut_arg->lut[i];
-
-       gma_crtc_load_lut(crtc);
-
-       return 0;
-}
-
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       uint32_t obj_id;
-       uint16_t op;
-       struct drm_mode_modeinfo *umode;
-       struct drm_display_mode *mode = NULL;
-       struct drm_psb_mode_operation_arg *arg;
-       struct drm_mode_object *obj;
-       struct drm_connector *connector;
-       struct drm_connector_helper_funcs *connector_funcs;
-       int ret = 0;
-       int resp = MODE_OK;
-
-       arg = (struct drm_psb_mode_operation_arg *)data;
-       obj_id = arg->obj_id;
-       op = arg->operation;
-
-       switch (op) {
-       case PSB_MODE_OPERATION_MODE_VALID:
-               umode = &arg->mode;
-
-               drm_modeset_lock_all(dev);
-
-               obj = drm_mode_object_find(dev, obj_id,
-                                       DRM_MODE_OBJECT_CONNECTOR);
-               if (!obj) {
-                       ret = -ENOENT;
-                       goto mode_op_out;
-               }
-
-               connector = obj_to_connector(obj);
-
-               mode = drm_mode_create(dev);
-               if (!mode) {
-                       ret = -ENOMEM;
-                       goto mode_op_out;
-               }
-
-               /* drm_crtc_convert_umode(mode, umode); */
-               {
-                       mode->clock = umode->clock;
-                       mode->hdisplay = umode->hdisplay;
-                       mode->hsync_start = umode->hsync_start;
-                       mode->hsync_end = umode->hsync_end;
-                       mode->htotal = umode->htotal;
-                       mode->hskew = umode->hskew;
-                       mode->vdisplay = umode->vdisplay;
-                       mode->vsync_start = umode->vsync_start;
-                       mode->vsync_end = umode->vsync_end;
-                       mode->vtotal = umode->vtotal;
-                       mode->vscan = umode->vscan;
-                       mode->vrefresh = umode->vrefresh;
-                       mode->flags = umode->flags;
-                       mode->type = umode->type;
-                       strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
-                       mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
-               }
-
-               connector_funcs = (struct drm_connector_helper_funcs *)
-                                  connector->helper_private;
-
-               if (connector_funcs->mode_valid) {
-                       resp = connector_funcs->mode_valid(connector, mode);
-                       arg->data = resp;
-               }
-
-               /*do some clean up work*/
-               if (mode)
-                       drm_mode_destroy(dev, mode);
-mode_op_out:
-               drm_modeset_unlock_all(dev);
-               return ret;
-
-       default:
-               dev_dbg(dev->dev, "Unsupported psb mode operation\n");
-               return -EOPNOTSUPP;
-       }
-
-       return 0;
-}
-
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
-                                  struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       struct drm_psb_stolen_memory_arg *arg = data;
-
-       arg->base = dev_priv->stolen_base;
-       arg->size = dev_priv->vram_stolen_size;
-
-       return 0;
-}
-
-static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
-{
-       return 0;
-}
-
-static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
 static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
                               unsigned long arg)
 {
@@ -614,15 +424,21 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
        /* FIXME: do we need to wrap the other side of this */
 }
 
-
-/* When a client dies:
+/*
+ * When a client dies:
  *    - Check for and clean up flipped page state
  */
 static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
 {
 }
 
-static void psb_remove(struct pci_dev *pdev)
+static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+
+static void psb_pci_remove(struct pci_dev *pdev)
 {
        struct drm_device *dev = pci_get_drvdata(pdev);
        drm_put_dev(dev);
@@ -657,11 +473,12 @@ static const struct file_operations psb_gem_fops = {
 
 static struct drm_driver driver = {
        .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
-                          DRIVER_MODESET | DRIVER_GEM ,
+                          DRIVER_MODESET | DRIVER_GEM,
        .load = psb_driver_load,
        .unload = psb_driver_unload,
+       .lastclose = psb_driver_lastclose,
+       .preclose = psb_driver_preclose,
 
-       .ioctls = psb_ioctls,
        .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
        .device_is_agp = psb_driver_device_is_agp,
        .irq_preinstall = psb_irq_preinstall,
@@ -671,40 +488,31 @@ static struct drm_driver driver = {
        .enable_vblank = psb_enable_vblank,
        .disable_vblank = psb_disable_vblank,
        .get_vblank_counter = psb_get_vblank_counter,
-       .lastclose = psb_lastclose,
-       .open = psb_driver_open,
-       .preclose = psb_driver_preclose,
-       .postclose = psb_driver_close,
 
        .gem_free_object = psb_gem_free_object,
        .gem_vm_ops = &psb_gem_vm_ops,
+
        .dumb_create = psb_gem_dumb_create,
        .dumb_map_offset = psb_gem_dumb_map_gtt,
        .dumb_destroy = drm_gem_dumb_destroy,
+       .ioctls = psb_ioctls,
        .fops = &psb_gem_fops,
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
-       .date = PSB_DRM_DRIVER_DATE,
-       .major = PSB_DRM_DRIVER_MAJOR,
-       .minor = PSB_DRM_DRIVER_MINOR,
-       .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL
 };
 
 static struct pci_driver psb_pci_driver = {
        .name = DRIVER_NAME,
        .id_table = pciidlist,
-       .probe = psb_probe,
-       .remove = psb_remove,
-       .driver = {
-               .pm = &psb_pm_ops,
-       }
+       .probe = psb_pci_probe,
+       .remove = psb_pci_remove,
+       .driver.pm = &psb_pm_ops,
 };
 
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       return drm_get_pci_dev(pdev, ent, &driver);
-}
-
 static int __init psb_init(void)
 {
        return drm_pci_init(&driver, &psb_pci_driver);
@@ -718,6 +526,6 @@ static void __exit psb_exit(void)
 late_initcall(psb_init);
 module_exit(psb_exit);
 
-MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
+MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE(DRIVER_LICENSE);
index 5ad6a03e477eae63aa8cc635981887febca71ac1..55ebe2bd88dd75972b10c5cae18ed44cb3a50fd7 100644 (file)
 #include "power.h"
 #include "opregion.h"
 #include "oaktrail.h"
+#include "mmu.h"
+
+#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
+#define DRIVER_LICENSE "GPL"
+
+#define DRIVER_NAME "gma500"
+#define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650"
+#define DRIVER_DATE "20140314"
+
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
 
 /* Append new drm mode definition here, align with libdrm definition */
 #define DRM_MODE_SCALE_NO_SCALE        2
@@ -49,21 +61,7 @@ enum {
 #define IS_MFLD(dev) (((dev)->pdev->device & 0xfff8) == 0x0130)
 #define IS_CDV(dev) (((dev)->pdev->device & 0xfff0) == 0x0be0)
 
-/*
- * Driver definitions
- */
-
-#define DRIVER_NAME "gma500"
-#define DRIVER_DESC "DRM driver for the Intel GMA500"
-
-#define PSB_DRM_DRIVER_DATE "2011-06-06"
-#define PSB_DRM_DRIVER_MAJOR 1
-#define PSB_DRM_DRIVER_MINOR 0
-#define PSB_DRM_DRIVER_PATCHLEVEL 0
-
-/*
- *     Hardware offsets
- */
+/* Hardware offsets */
 #define PSB_VDC_OFFSET          0x00000000
 #define PSB_VDC_SIZE            0x000080000
 #define MRST_MMIO_SIZE          0x0000C0000
@@ -71,16 +69,14 @@ enum {
 #define PSB_SGX_SIZE            0x8000
 #define PSB_SGX_OFFSET          0x00040000
 #define MRST_SGX_OFFSET                 0x00080000
-/*
- *     PCI resource identifiers
- */
+
+/* PCI resource identifiers */
 #define PSB_MMIO_RESOURCE       0
 #define PSB_AUX_RESOURCE        0
 #define PSB_GATT_RESOURCE       2
 #define PSB_GTT_RESOURCE        3
-/*
- *     PCI configuration
- */
+
+/* PCI configuration */
 #define PSB_GMCH_CTRL           0x52
 #define PSB_BSM                         0x5C
 #define _PSB_GMCH_ENABLED       0x4
@@ -88,37 +84,29 @@ enum {
 #define _PSB_PGETBL_ENABLED     0x00000001
 #define PSB_SGX_2D_SLAVE_PORT   0x4000
 
-/* To get rid of */
+/* TODO: To get rid of */
 #define PSB_TT_PRIV0_LIMIT      (256*1024*1024)
 #define PSB_TT_PRIV0_PLIMIT     (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
 
-/*
- *     SGX side MMU definitions (these can probably go)
- */
+/* SGX side MMU definitions (these can probably go) */
 
-/*
- *     Flags for external memory type field.
- */
+/* Flags for external memory type field */
 #define PSB_MMU_CACHED_MEMORY    0x0001        /* Bind to MMU only */
 #define PSB_MMU_RO_MEMORY        0x0002        /* MMU RO memory */
 #define PSB_MMU_WO_MEMORY        0x0004        /* MMU WO memory */
-/*
- *     PTE's and PDE's
- */
+
+/* PTE's and PDE's */
 #define PSB_PDE_MASK             0x003FFFFF
 #define PSB_PDE_SHIFT            22
 #define PSB_PTE_SHIFT            12
-/*
- *     Cache control
- */
+
+/* Cache control */
 #define PSB_PTE_VALID            0x0001        /* PTE / PDE valid */
 #define PSB_PTE_WO               0x0002        /* Write only */
 #define PSB_PTE_RO               0x0004        /* Read only */
 #define PSB_PTE_CACHED           0x0008        /* CPU cache coherent */
 
-/*
- *     VDC registers and bits
- */
+/* VDC registers and bits */
 #define PSB_MSVDX_CLOCKGATING    0x2064
 #define PSB_TOPAZ_CLOCKGATING    0x2068
 #define PSB_HWSTAM               0x2098
@@ -265,6 +253,7 @@ struct psb_intel_opregion {
        struct opregion_asle *asle;
        void *vbt;
        u32 __iomem *lid_state;
+       struct work_struct asle_work;
 };
 
 struct sdvo_device_mapping {
@@ -283,10 +272,7 @@ struct intel_gmbus {
        u32 reg0;
 };
 
-/*
- *     Register offset maps
- */
-
+/* Register offset maps */
 struct psb_offset {
        u32     fp0;
        u32     fp1;
@@ -320,9 +306,7 @@ struct psb_offset {
  *     update the register cache instead.
  */
 
-/*
- *     Common status for pipes.
- */
+/* Common status for pipes */
 struct psb_pipe {
        u32     fp0;
        u32     fp1;
@@ -482,35 +466,24 @@ struct drm_psb_private {
        struct psb_mmu_driver *mmu;
        struct psb_mmu_pd *pf_pd;
 
-       /*
-        * Register base
-        */
-
+       /* Register base */
        uint8_t __iomem *sgx_reg;
        uint8_t __iomem *vdc_reg;
        uint8_t __iomem *aux_reg; /* Auxillary vdc pipe regs */
        uint32_t gatt_free_offset;
 
-       /*
-        * Fencing / irq.
-        */
-
+       /* Fencing / irq */
        uint32_t vdc_irq_mask;
        uint32_t pipestat[PSB_NUM_PIPE];
 
        spinlock_t irqmask_lock;
 
-       /*
-        * Power
-        */
-
+       /* Power */
        bool suspended;
        bool display_power;
        int display_count;
 
-       /*
-        * Modesetting
-        */
+       /* Modesetting */
        struct psb_intel_mode_device mode_dev;
        bool modeset;   /* true if we have done the mode_device setup */
 
@@ -518,15 +491,10 @@ struct drm_psb_private {
        struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
        uint32_t num_pipe;
 
-       /*
-        * OSPM info (Power management base) (can go ?)
-        */
+       /* OSPM info (Power management base) (TODO: can go ?) */
        uint32_t ospm_base;
 
-       /*
-        * Sizes info
-        */
-
+       /* Sizes info */
        u32 fuse_reg_value;
        u32 video_device_fuse;
 
@@ -546,9 +514,7 @@ struct drm_psb_private {
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
-       /*
-        * LVDS info
-        */
+       /* LVDS info */
        int backlight_duty_cycle;       /* restore backlight to this value */
        bool panel_wants_dither;
        struct drm_display_mode *panel_fixed_mode;
@@ -582,34 +548,23 @@ struct drm_psb_private {
        /* Oaktrail HDMI state */
        struct oaktrail_hdmi_dev *hdmi_priv;
        
-       /*
-        * Register state
-        */
-
+       /* Register state */
        struct psb_save_area regs;
 
        /* MSI reg save */
        uint32_t msi_addr;
        uint32_t msi_data;
 
-       /*
-        * Hotplug handling
-        */
-
+       /* Hotplug handling */
        struct work_struct hotplug_work;
 
-       /*
-        * LID-Switch
-        */
+       /* LID-Switch */
        spinlock_t lid_lock;
        struct timer_list lid_timer;
        struct psb_intel_opregion opregion;
        u32 lid_last_state;
 
-       /*
-        * Watchdog
-        */
-
+       /* Watchdog */
        uint32_t apm_reg;
        uint16_t apm_base;
 
@@ -629,9 +584,7 @@ struct drm_psb_private {
        /* 2D acceleration */
        spinlock_t lock_2d;
 
-       /*
-        * Panel brightness
-        */
+       /* Panel brightness */
        int brightness;
        int brightness_adjusted;
 
@@ -664,10 +617,7 @@ struct drm_psb_private {
 };
 
 
-/*
- *     Operations for each board type
- */
+/* Operations for each board type */
 struct psb_ops {
        const char *name;
        unsigned int accel_2d:1;
@@ -713,8 +663,6 @@ struct psb_ops {
 
 
 
-struct psb_mmu_driver;
-
 extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
 extern int drm_pick_crtcs(struct drm_device *dev);
 
@@ -723,52 +671,7 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
        return (struct drm_psb_private *) dev->dev_private;
 }
 
-/*
- * MMU stuff.
- */
-
-extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-                                       int trap_pagefaults,
-                                       int invalid_type,
-                                       struct drm_psb_private *dev_priv);
-extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
-extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
-                                                *driver);
-extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
-                              uint32_t gtt_start, uint32_t gtt_pages);
-extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
-                                          int trap_pagefaults,
-                                          int invalid_type);
-extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
-extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
-extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
-                                       unsigned long address,
-                                       uint32_t num_pages);
-extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
-                                      uint32_t start_pfn,
-                                      unsigned long address,
-                                      uint32_t num_pages, int type);
-extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
-                                 unsigned long *pfn);
-
-/*
- * Enable / disable MMU for different requestors.
- */
-
-
-extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
-extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
-                               unsigned long address, uint32_t num_pages,
-                               uint32_t desired_tile_stride,
-                               uint32_t hw_tile_stride, int type);
-extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
-                                unsigned long address, uint32_t num_pages,
-                                uint32_t desired_tile_stride,
-                                uint32_t hw_tile_stride);
-/*
- *psb_irq.c
- */
-
+/* psb_irq.c */
 extern irqreturn_t psb_irq_handler(int irq, void *arg);
 extern int psb_irq_enable_dpst(struct drm_device *dev);
 extern 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);
 
 extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
 
-/*
- * framebuffer.c
- */
+/* framebuffer.c */
 extern int psbfb_probed(struct drm_device *dev);
 extern int psbfb_remove(struct drm_device *dev,
                        struct drm_framebuffer *fb);
-/*
- * accel_2d.c
- */
+/* accel_2d.c */
 extern void psbfb_copyarea(struct fb_info *info,
                                        const struct fb_copyarea *region);
 extern int psbfb_sync(struct fb_info *info);
 extern void psb_spank(struct drm_psb_private *dev_priv);
 
-/*
- * psb_reset.c
- */
-
+/* psb_reset.c */
 extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
 extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
 extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
@@ -867,9 +763,7 @@ extern const struct psb_ops mdfld_chip_ops;
 /* cdv_device.c */
 extern const struct psb_ops cdv_chip_ops;
 
-/*
- * Debug print bits setting
- */
+/* Debug print bits setting */
 #define PSB_D_GENERAL (1 << 0)
 #define PSB_D_INIT    (1 << 1)
 #define PSB_D_IRQ     (1 << 2)
@@ -885,10 +779,7 @@ extern const struct psb_ops cdv_chip_ops;
 
 extern int drm_idle_check_interval;
 
-/*
- *     Utilities
- */
-
+/* Utilities */
 static inline u32 MRST_MSG_READ32(uint port, uint offset)
 {
        int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
index c8841ac6c8f1908bf0af3a058c5d3a423a4f97ca..87b50ba64ed40aa640e74ec37e90e4008c0875e7 100644 (file)
@@ -120,7 +120,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
        const struct gma_limit_t *limit;
 
        /* No scan out no play */
-       if (crtc->fb == NULL) {
+       if (crtc->primary->fb == NULL) {
                crtc_funcs->mode_set_base(crtc, x, y, old_fb);
                return 0;
        }
@@ -469,7 +469,8 @@ static void psb_intel_cursor_init(struct drm_device *dev,
                /* Allocate 4 pages of stolen mem for a hardware cursor. That
                 * is enough for the 64 x 64 ARGB cursors we support.
                 */
-               cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1);
+               cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1,
+                                               PAGE_SIZE);
                if (!cursor_gt) {
                        gma_crtc->cursor_gt = NULL;
                        goto out;
@@ -554,33 +555,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
        gma_crtc->active = true;
 }
 
-int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
-       struct drm_mode_object *drmmode_obj;
-       struct gma_crtc *crtc;
-
-       if (!dev_priv) {
-               dev_err(dev->dev, "called with no initialization\n");
-               return -EINVAL;
-       }
-
-       drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
-                       DRM_MODE_OBJECT_CRTC);
-
-       if (!drmmode_obj) {
-               dev_err(dev->dev, "no such CRTC id\n");
-               return -ENOENT;
-       }
-
-       crtc = to_gma_crtc(obj_to_crtc(drmmode_obj));
-       pipe_from_crtc_id->pipe = crtc->pipe;
-
-       return 0;
-}
-
 struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
 {
        struct drm_crtc *crtc = NULL;
index dc2c8eb030faeaf29f4bd7d32c87c803ab846e30..336bd3aa1a066868af57f131c3260629abdb27c0 100644 (file)
@@ -238,8 +238,6 @@ static inline struct gma_encoder *gma_attached_encoder(
 
 extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
                                                    struct drm_crtc *crtc);
-extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
 extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
                                                 int pipe);
 extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
index 32342f6990d964ddb6c798fc9159b5f5d4870b1a..d7778d0472c18569cbd89fbd9c70b5aa3f3a913b 100644 (file)
@@ -614,7 +614,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
                                                      &crtc->saved_mode,
                                                      encoder->crtc->x,
                                                      encoder->crtc->y,
-                                                     encoder->crtc->fb))
+                                                     encoder->crtc->primary->fb))
                                goto set_prop_error;
                }
        } else if (!strcmp(property->name, "backlight")) {
@@ -777,6 +777,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
         * Attempt to get the fixed panel mode from DDC.  Assume that the
         * preferred mode is the right one.
         */
+       mutex_lock(&dev->mode_config.mutex);
        psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter);
        list_for_each_entry(scan, &connector->probed_modes, head) {
                if (scan->type & DRM_MODE_TYPE_PREFERRED) {
@@ -827,10 +828,12 @@ void psb_intel_lvds_init(struct drm_device *dev,
         * actually having one.
         */
 out:
+       mutex_unlock(&dev->mode_config.mutex);
        drm_sysfs_connector_add(connector);
        return;
 
 failed_find:
+       mutex_unlock(&dev->mode_config.mutex);
        if (lvds_priv->ddc_bus)
                psb_intel_i2c_destroy(lvds_priv->ddc_bus);
 failed_ddc:
index 07d3a9e6d79b5e5deab9a36220063eb55789ab0f..deeb0829b1298d29130f51e7bad4bf4a415c6adc 100644 (file)
@@ -406,18 +406,18 @@ static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8
        DRM_DEBUG_KMS("%s: W: %02X ",
                                SDVO_NAME(psb_intel_sdvo), cmd);
        for (i = 0; i < args_len; i++)
-               DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
+               DRM_DEBUG_KMS("%02X ", ((u8 *)args)[i]);
        for (; i < 8; i++)
-               DRM_LOG_KMS("   ");
+               DRM_DEBUG_KMS("   ");
        for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
                if (cmd == sdvo_cmd_names[i].cmd) {
-                       DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
+                       DRM_DEBUG_KMS("(%s)", sdvo_cmd_names[i].name);
                        break;
                }
        }
        if (i == ARRAY_SIZE(sdvo_cmd_names))
-               DRM_LOG_KMS("(%02X)", cmd);
-       DRM_LOG_KMS("\n");
+               DRM_DEBUG_KMS("(%02X)", cmd);
+       DRM_DEBUG_KMS("\n");
 }
 
 static const char *cmd_status_names[] = {
@@ -512,9 +512,9 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
        }
 
        if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-               DRM_LOG_KMS("(%s)", cmd_status_names[status]);
+               DRM_DEBUG_KMS("(%s)", cmd_status_names[status]);
        else
-               DRM_LOG_KMS("(??? %d)", status);
+               DRM_DEBUG_KMS("(??? %d)", status);
 
        if (status != SDVO_CMD_STATUS_SUCCESS)
                goto log_fail;
@@ -525,13 +525,13 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
                                          SDVO_I2C_RETURN_0 + i,
                                          &((u8 *)response)[i]))
                        goto log_fail;
-               DRM_LOG_KMS(" %02X", ((u8 *)response)[i]);
+               DRM_DEBUG_KMS(" %02X", ((u8 *)response)[i]);
        }
-       DRM_LOG_KMS("\n");
+       DRM_DEBUG_KMS("\n");
        return true;
 
 log_fail:
-       DRM_LOG_KMS("... failed\n");
+       DRM_DEBUG_KMS("... failed\n");
        return false;
 }
 
@@ -1844,7 +1844,7 @@ done:
        if (psb_intel_sdvo->base.base.crtc) {
                struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
                drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-                                        crtc->y, crtc->fb);
+                                        crtc->y, crtc->primary->fb);
        }
 
        return 0;
index f883f9e4c5240ee923cbaabb3c57b88472983431..624eb36511c5dc226e4cb0817eb1322fc3011326 100644 (file)
@@ -200,11 +200,64 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
                mid_pipe_event_handler(dev, 1);
 }
 
+/*
+ * SGX interrupt handler
+ */
+static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 val, addr;
+       int error = false;
+
+       if (stat_1 & _PSB_CE_TWOD_COMPLETE)
+               val = PSB_RSGX32(PSB_CR_2D_BLIT_STATUS);
+
+       if (stat_2 & _PSB_CE2_BIF_REQUESTER_FAULT) {
+               val = PSB_RSGX32(PSB_CR_BIF_INT_STAT);
+               addr = PSB_RSGX32(PSB_CR_BIF_FAULT);
+               if (val) {
+                       if (val & _PSB_CBI_STAT_PF_N_RW)
+                               DRM_ERROR("SGX MMU page fault:");
+                       else
+                               DRM_ERROR("SGX MMU read / write protection fault:");
+
+                       if (val & _PSB_CBI_STAT_FAULT_CACHE)
+                               DRM_ERROR("\tCache requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_TA)
+                               DRM_ERROR("\tTA requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_VDM)
+                               DRM_ERROR("\tVDM requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_2D)
+                               DRM_ERROR("\t2D requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_PBE)
+                               DRM_ERROR("\tPBE requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_TSP)
+                               DRM_ERROR("\tTSP requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_ISP)
+                               DRM_ERROR("\tISP requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_USSEPDS)
+                               DRM_ERROR("\tUSSEPDS requestor");
+                       if (val & _PSB_CBI_STAT_FAULT_HOST)
+                               DRM_ERROR("\tHost requestor");
+
+                       DRM_ERROR("\tMMU failing address is 0x%08x.\n",
+                                 (unsigned int)addr);
+                       error = true;
+               }
+       }
+
+       /* Clear bits */
+       PSB_WSGX32(stat_1, PSB_CR_EVENT_HOST_CLEAR);
+       PSB_WSGX32(stat_2, PSB_CR_EVENT_HOST_CLEAR2);
+       PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2);
+}
+
 irqreturn_t psb_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct drm_psb_private *dev_priv = dev->dev_private;
        uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0;
+       u32 sgx_stat_1, sgx_stat_2;
        int handled = 0;
 
        spin_lock(&dev_priv->irqmask_lock);
@@ -233,14 +286,9 @@ irqreturn_t psb_irq_handler(int irq, void *arg)
        }
 
        if (sgx_int) {
-               /* Not expected - we have it masked, shut it up */
-               u32 s, s2;
-               s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
-               s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
-               PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
-               PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
-               /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
-                  we may as well poll even if we add that ! */
+               sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS);
+               sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
+               psb_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2);
                handled = 1;
        }
 
@@ -269,8 +317,13 @@ void psb_irq_preinstall(struct drm_device *dev)
 
        spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
-       if (gma_power_is_on(dev))
+       if (gma_power_is_on(dev)) {
                PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+               PSB_WVDC32(0x00000000, PSB_INT_MASK_R);
+               PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+               PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
+               PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);
+       }
        if (dev->vblank[0].enabled)
                dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
        if (dev->vblank[1].enabled)
@@ -286,7 +339,7 @@ void psb_irq_preinstall(struct drm_device *dev)
        /* Revisit this area - want per device masks ? */
        if (dev_priv->ops->hotplug)
                dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC;
-       dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE;
+       dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE | _PSB_IRQ_SGX_FLAG;
 
        /* This register is safe even if display island is off */
        PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
@@ -295,12 +348,16 @@ void psb_irq_preinstall(struct drm_device *dev)
 
 int psb_irq_postinstall(struct drm_device *dev)
 {
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
+       /* Enable 2D and MMU fault interrupts */
+       PSB_WSGX32(_PSB_CE2_BIF_REQUESTER_FAULT, PSB_CR_EVENT_HOST_ENABLE2);
+       PSB_WSGX32(_PSB_CE_TWOD_COMPLETE, PSB_CR_EVENT_HOST_ENABLE);
+       PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /* Post */
+
        /* This register is safe even if display island is off */
        PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
        PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
index af42e94f68467534f3879965c930c0c47610690d..a0f5bdd694919a86206ab210e5eb30827d297232 100644 (file)
@@ -340,9 +340,9 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
        for (i = 0; i < CH7xxx_NUM_REGS; i++) {
                uint8_t val;
                if ((i % 8) == 0)
-                       DRM_LOG_KMS("\n %02X: ", i);
+                       DRM_DEBUG_KMS("\n %02X: ", i);
                ch7xxx_readb(dvo, i, &val);
-               DRM_LOG_KMS("%02X ", val);
+               DRM_DEBUG_KMS("%02X ", val);
        }
 }
 
index baaf65bf0bdd1a1430b565fce6c60302c4f95a2f..0f1865d7d4d8412918e99cbf92841ba85d0ec5d8 100644 (file)
@@ -377,41 +377,41 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo)
        uint16_t val;
 
        ivch_read(dvo, VR00, &val);
-       DRM_LOG_KMS("VR00: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR00: 0x%04x\n", val);
        ivch_read(dvo, VR01, &val);
-       DRM_LOG_KMS("VR01: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR01: 0x%04x\n", val);
        ivch_read(dvo, VR30, &val);
-       DRM_LOG_KMS("VR30: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR30: 0x%04x\n", val);
        ivch_read(dvo, VR40, &val);
-       DRM_LOG_KMS("VR40: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR40: 0x%04x\n", val);
 
        /* GPIO registers */
        ivch_read(dvo, VR80, &val);
-       DRM_LOG_KMS("VR80: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR80: 0x%04x\n", val);
        ivch_read(dvo, VR81, &val);
-       DRM_LOG_KMS("VR81: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR81: 0x%04x\n", val);
        ivch_read(dvo, VR82, &val);
-       DRM_LOG_KMS("VR82: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR82: 0x%04x\n", val);
        ivch_read(dvo, VR83, &val);
-       DRM_LOG_KMS("VR83: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR83: 0x%04x\n", val);
        ivch_read(dvo, VR84, &val);
-       DRM_LOG_KMS("VR84: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR84: 0x%04x\n", val);
        ivch_read(dvo, VR85, &val);
-       DRM_LOG_KMS("VR85: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR85: 0x%04x\n", val);
        ivch_read(dvo, VR86, &val);
-       DRM_LOG_KMS("VR86: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR86: 0x%04x\n", val);
        ivch_read(dvo, VR87, &val);
-       DRM_LOG_KMS("VR87: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR87: 0x%04x\n", val);
        ivch_read(dvo, VR88, &val);
-       DRM_LOG_KMS("VR88: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR88: 0x%04x\n", val);
 
        /* Scratch register 0 - AIM Panel type */
        ivch_read(dvo, VR8E, &val);
-       DRM_LOG_KMS("VR8E: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR8E: 0x%04x\n", val);
 
        /* Scratch register 1 - Status register */
        ivch_read(dvo, VR8F, &val);
-       DRM_LOG_KMS("VR8F: 0x%04x\n", val);
+       DRM_DEBUG_KMS("VR8F: 0x%04x\n", val);
 }
 
 static void ivch_destroy(struct intel_dvo_device *dvo)
index 954acb2c7021d8eb9a90fe1e49ea5bc806f1f344..8155ded79079dfdee1b513299a499efe054c20d4 100644 (file)
@@ -490,15 +490,15 @@ static void ns2501_dump_regs(struct intel_dvo_device *dvo)
        uint8_t val;
 
        ns2501_readb(dvo, NS2501_FREQ_LO, &val);
-       DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
+       DRM_DEBUG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
        ns2501_readb(dvo, NS2501_FREQ_HI, &val);
-       DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
+       DRM_DEBUG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
        ns2501_readb(dvo, NS2501_REG8, &val);
-       DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
+       DRM_DEBUG_KMS("NS2501_REG8: 0x%02x\n", val);
        ns2501_readb(dvo, NS2501_REG9, &val);
-       DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
+       DRM_DEBUG_KMS("NS2501_REG9: 0x%02x\n", val);
        ns2501_readb(dvo, NS2501_REGC, &val);
-       DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
+       DRM_DEBUG_KMS("NS2501_REGC: 0x%02x\n", val);
 }
 
 static void ns2501_destroy(struct intel_dvo_device *dvo)
index 4debd32e3e4ce195e201b8869170a2533a7fd73e..7b3e9e9362003461951dfa737809f8ac916db47e 100644 (file)
@@ -246,15 +246,15 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo)
        uint8_t val;
 
        sil164_readb(dvo, SIL164_FREQ_LO, &val);
-       DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
+       DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
        sil164_readb(dvo, SIL164_FREQ_HI, &val);
-       DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
+       DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
        sil164_readb(dvo, SIL164_REG8, &val);
-       DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val);
+       DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val);
        sil164_readb(dvo, SIL164_REG9, &val);
-       DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val);
+       DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val);
        sil164_readb(dvo, SIL164_REGC, &val);
-       DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);
+       DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val);
 }
 
 static void sil164_destroy(struct intel_dvo_device *dvo)
index e17f1b07e915f924244032bc77c3ba2a5919adc8..12ea4b16469277d971f78a5b194079d67dcb7781 100644 (file)
@@ -267,33 +267,33 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo)
        uint8_t val, val2;
 
        tfp410_readb(dvo, TFP410_REV, &val);
-       DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_REV: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_CTL_1, &val);
-       DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_CTL1: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_CTL_2, &val);
-       DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_CTL2: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_CTL_3, &val);
-       DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_CTL3: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_USERCFG, &val);
-       DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_USERCFG: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_DE_DLY, &val);
-       DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_DE_CTL, &val);
-       DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_DE_TOP, &val);
-       DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
+       DRM_DEBUG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
        tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
        tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
-       DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
+       DRM_DEBUG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
        tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
        tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
-       DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
+       DRM_DEBUG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
        tfp410_readb(dvo, TFP410_H_RES_LO, &val);
        tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
-       DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
+       DRM_DEBUG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
        tfp410_readb(dvo, TFP410_V_RES_LO, &val);
        tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
-       DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
+       DRM_DEBUG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
 }
 
 static void tfp410_destroy(struct intel_dvo_device *dvo)
index 0eaed44aee6d946bb8c2433b4c0d399f1ef321e0..4cf6d020d5135e3da688e5c1f586c362189b5629 100644 (file)
@@ -405,7 +405,7 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
                        DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n",
                                         *cmd,
                                         length,
-                                        batch_end - cmd);
+                                        (unsigned long)(batch_end - cmd));
                        ret = -EINVAL;
                        break;
                }
index 049dcb5256d1e1851dd4f06a568eca36507ec936..d04786db962712fc364fe41aa340fb54a884995a 100644 (file)
@@ -2203,8 +2203,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
        struct intel_encoder *intel_encoder;
 
        seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
-                  crtc->fb->base.id, crtc->x, crtc->y,
-                  crtc->fb->width, crtc->fb->height);
+                  crtc->primary->fb->base.id, crtc->x, crtc->y,
+                  crtc->primary->fb->width, crtc->primary->fb->height);
        for_each_encoder_on_crtc(dev, crtc, intel_encoder)
                intel_encoder_info(m, intel_crtc, intel_encoder);
 }
index acf1ab3ff0d982be8d98b58ee65e682b30a9ecd7..acebe511e4efa04f409e45b0bd83c0e54ee00ab3 100644 (file)
@@ -2368,8 +2368,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
        } else {
                int dspaddr = DSPADDR(intel_crtc->plane);
                stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
-                                                       crtc->y * crtc->fb->pitches[0] +
-                                                       crtc->x * crtc->fb->bits_per_pixel/8);
+                                                       crtc->y * crtc->primary->fb->pitches[0] +
+                                                       crtc->x * crtc->primary->fb->bits_per_pixel/8);
        }
 
        spin_unlock_irqrestore(&dev->event_lock, flags);
index 7be5984431bb6252e62cd99263f480944e8e713b..6332383abae9ab64cbddd517ed397ebfe729cce6 100644 (file)
@@ -741,10 +741,10 @@ bool intel_crtc_active(struct drm_crtc *crtc)
         * We can ditch the adjusted_mode.crtc_clock check as soon
         * as Haswell has gained clock readout/fastboot support.
         *
-        * We can ditch the crtc->fb check as soon as we can
+        * We can ditch the crtc->primary->fb check as soon as we can
         * properly reconstruct framebuffers.
         */
-       return intel_crtc->active && crtc->fb &&
+       return intel_crtc->active && crtc->primary->fb &&
                intel_crtc->config.adjusted_mode.crtc_clock;
 }
 
@@ -2086,17 +2086,17 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
 
        if (plane_config->tiled) {
                obj->tiling_mode = I915_TILING_X;
-               obj->stride = crtc->base.fb->pitches[0];
+               obj->stride = crtc->base.primary->fb->pitches[0];
        }
 
-       mode_cmd.pixel_format = crtc->base.fb->pixel_format;
-       mode_cmd.width = crtc->base.fb->width;
-       mode_cmd.height = crtc->base.fb->height;
-       mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
+       mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
+       mode_cmd.width = crtc->base.primary->fb->width;
+       mode_cmd.height = crtc->base.primary->fb->height;
+       mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
 
        mutex_lock(&dev->struct_mutex);
 
-       if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
+       if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.primary->fb),
                                   &mode_cmd, obj)) {
                DRM_DEBUG_KMS("intel fb init failed\n");
                goto out_unref_obj;
@@ -2121,14 +2121,14 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
        struct intel_crtc *i;
        struct intel_framebuffer *fb;
 
-       if (!intel_crtc->base.fb)
+       if (!intel_crtc->base.primary->fb)
                return;
 
        if (intel_alloc_plane_obj(intel_crtc, plane_config))
                return;
 
-       kfree(intel_crtc->base.fb);
-       intel_crtc->base.fb = NULL;
+       kfree(intel_crtc->base.primary->fb);
+       intel_crtc->base.primary->fb = NULL;
 
        /*
         * 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,
                if (c == &intel_crtc->base)
                        continue;
 
-               if (!i->active || !c->fb)
+               if (!i->active || !c->primary->fb)
                        continue;
 
-               fb = to_intel_framebuffer(c->fb);
+               fb = to_intel_framebuffer(c->primary->fb);
                if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
-                       drm_framebuffer_reference(c->fb);
-                       intel_crtc->base.fb = c->fb;
+                       drm_framebuffer_reference(c->primary->fb);
+                       intel_crtc->base.primary->fb = c->primary->fb;
                        break;
                }
        }
@@ -2396,11 +2396,11 @@ void intel_display_handle_reset(struct drm_device *dev)
                /*
                 * FIXME: Once we have proper support for primary planes (and
                 * disabling them without disabling the entire crtc) allow again
-                * a NULL crtc->fb.
+                * a NULL crtc->primary->fb.
                 */
-               if (intel_crtc->active && crtc->fb)
+               if (intel_crtc->active && crtc->primary->fb)
                        dev_priv->display.update_primary_plane(crtc,
-                                                              crtc->fb,
+                                                              crtc->primary->fb,
                                                               crtc->x,
                                                               crtc->y);
                mutex_unlock(&crtc->mutex);
@@ -2527,8 +2527,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return ret;
        }
 
-       old_fb = crtc->fb;
-       crtc->fb = fb;
+       old_fb = crtc->primary->fb;
+       crtc->primary->fb = fb;
        crtc->x = x;
        crtc->y = y;
 
@@ -3122,7 +3122,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (crtc->fb == NULL)
+       if (crtc->primary->fb == NULL)
                return;
 
        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)
                   !intel_crtc_has_pending_flip(crtc));
 
        mutex_lock(&dev->struct_mutex);
-       intel_finish_fb(crtc->fb);
+       intel_finish_fb(crtc->primary->fb);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -3536,22 +3536,28 @@ static void intel_enable_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       struct drm_plane *plane;
        struct intel_plane *intel_plane;
 
-       list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+       drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
+               intel_plane = to_intel_plane(plane);
                if (intel_plane->pipe == pipe)
                        intel_plane_restore(&intel_plane->base);
+       }
 }
 
 static void intel_disable_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       struct drm_plane *plane;
        struct intel_plane *intel_plane;
 
-       list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+       drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
+               intel_plane = to_intel_plane(plane);
                if (intel_plane->pipe == pipe)
                        intel_plane_disable(&intel_plane->base);
+       }
 }
 
 void hsw_enable_ips(struct intel_crtc *crtc)
@@ -4573,11 +4579,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
        assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
        assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
 
-       if (crtc->fb) {
+       if (crtc->primary->fb) {
                mutex_lock(&dev->struct_mutex);
-               intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+               intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
-               crtc->fb = NULL;
+               crtc->primary->fb = NULL;
        }
 
        /* Update computed state. */
@@ -5728,8 +5734,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
        int fourcc, pixel_format;
        int aligned_height;
 
-       crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
-       if (!crtc->base.fb) {
+       crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
+       if (!crtc->base.primary->fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
                return;
        }
@@ -5742,8 +5748,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
 
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = intel_format_to_fourcc(pixel_format);
-       crtc->base.fb->pixel_format = fourcc;
-       crtc->base.fb->bits_per_pixel =
+       crtc->base.primary->fb->pixel_format = fourcc;
+       crtc->base.primary->fb->bits_per_pixel =
                drm_format_plane_cpp(fourcc, 0) * 8;
 
        if (INTEL_INFO(dev)->gen >= 4) {
@@ -5758,23 +5764,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
        plane_config->base = base;
 
        val = I915_READ(PIPESRC(pipe));
-       crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
-       crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
+       crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
+       crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
 
        val = I915_READ(DSPSTRIDE(pipe));
-       crtc->base.fb->pitches[0] = val & 0xffffff80;
+       crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
 
-       aligned_height = intel_align_height(dev, crtc->base.fb->height,
+       aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
                                            plane_config->tiled);
 
-       plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
+       plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
                                   aligned_height, PAGE_SIZE);
 
        DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-                     pipe, plane, crtc->base.fb->width,
-                     crtc->base.fb->height,
-                     crtc->base.fb->bits_per_pixel, base,
-                     crtc->base.fb->pitches[0],
+                     pipe, plane, crtc->base.primary->fb->width,
+                     crtc->base.primary->fb->height,
+                     crtc->base.primary->fb->bits_per_pixel, base,
+                     crtc->base.primary->fb->pitches[0],
                      plane_config->size);
 
 }
@@ -6736,8 +6742,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
        int fourcc, pixel_format;
        int aligned_height;
 
-       crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
-       if (!crtc->base.fb) {
+       crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
+       if (!crtc->base.primary->fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
                return;
        }
@@ -6750,8 +6756,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
 
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = intel_format_to_fourcc(pixel_format);
-       crtc->base.fb->pixel_format = fourcc;
-       crtc->base.fb->bits_per_pixel =
+       crtc->base.primary->fb->pixel_format = fourcc;
+       crtc->base.primary->fb->bits_per_pixel =
                drm_format_plane_cpp(fourcc, 0) * 8;
 
        base = I915_READ(DSPSURF(plane)) & 0xfffff000;
@@ -6766,23 +6772,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
        plane_config->base = base;
 
        val = I915_READ(PIPESRC(pipe));
-       crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
-       crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
+       crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
+       crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
 
        val = I915_READ(DSPSTRIDE(pipe));
-       crtc->base.fb->pitches[0] = val & 0xffffff80;
+       crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
 
-       aligned_height = intel_align_height(dev, crtc->base.fb->height,
+       aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
                                            plane_config->tiled);
 
-       plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
+       plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
                                   aligned_height, PAGE_SIZE);
 
        DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-                     pipe, plane, crtc->base.fb->width,
-                     crtc->base.fb->height,
-                     crtc->base.fb->bits_per_pixel, base,
-                     crtc->base.fb->pitches[0],
+                     pipe, plane, crtc->base.primary->fb->width,
+                     crtc->base.primary->fb->height,
+                     crtc->base.primary->fb->bits_per_pixel, base,
+                     crtc->base.primary->fb->pitches[0],
                      plane_config->size);
 }
 
@@ -8435,7 +8441,7 @@ void intel_mark_idle(struct drm_device *dev)
                goto out;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (!crtc->fb)
+               if (!crtc->primary->fb)
                        continue;
 
                intel_decrease_pllclock(crtc);
@@ -8458,10 +8464,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
                return;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (!crtc->fb)
+               if (!crtc->primary->fb)
                        continue;
 
-               if (to_intel_framebuffer(crtc->fb)->obj != obj)
+               if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
                        continue;
 
                intel_increase_pllclock(crtc);
@@ -8889,7 +8895,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *old_fb = crtc->fb;
+       struct drm_framebuffer *old_fb = crtc->primary->fb;
        struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
@@ -8897,7 +8903,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        int ret;
 
        /* Can't change pixel format via MI display flips. */
-       if (fb->pixel_format != crtc->fb->pixel_format)
+       if (fb->pixel_format != crtc->primary->fb->pixel_format)
                return -EINVAL;
 
        /*
@@ -8905,8 +8911,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
         * Note that pitch changes could also affect these register.
         */
        if (INTEL_INFO(dev)->gen > 3 &&
-           (fb->offsets[0] != crtc->fb->offsets[0] ||
-            fb->pitches[0] != crtc->fb->pitches[0]))
+           (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
+            fb->pitches[0] != crtc->primary->fb->pitches[0]))
                return -EINVAL;
 
        if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -8949,7 +8955,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        drm_gem_object_reference(&work->old_fb_obj->base);
        drm_gem_object_reference(&obj->base);
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        work->pending_flip_obj = obj;
 
@@ -8972,7 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
-       crtc->fb = old_fb;
+       crtc->primary->fb = old_fb;
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
@@ -10013,7 +10019,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
 
 void intel_crtc_restore_mode(struct drm_crtc *crtc)
 {
-       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
+       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
 }
 
 #undef for_each_intel_crtc_masked
@@ -10137,9 +10143,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
         * and then just flip_or_move it */
        if (is_crtc_connector_off(set)) {
                config->mode_changed = true;
-       } else if (set->crtc->fb != set->fb) {
+       } else if (set->crtc->primary->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
-               if (set->crtc->fb == NULL) {
+               if (set->crtc->primary->fb == NULL) {
                        struct intel_crtc *intel_crtc =
                                to_intel_crtc(set->crtc);
 
@@ -10153,7 +10159,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
                } else if (set->fb == NULL) {
                        config->mode_changed = true;
                } else if (set->fb->pixel_format !=
-                          set->crtc->fb->pixel_format) {
+                          set->crtc->primary->fb->pixel_format) {
                        config->mode_changed = true;
                } else {
                        config->fb_changed = true;
@@ -10366,7 +10372,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
        save_set.mode = &set->crtc->mode;
        save_set.x = set->crtc->x;
        save_set.y = set->crtc->y;
-       save_set.fb = set->crtc->fb;
+       save_set.fb = set->crtc->primary->fb;
 
        /* Compute whether we need a full modeset, only an fb base update or no
         * change at all. In the future we might also check whether only the
@@ -11720,7 +11726,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                                dev_priv->pipe_to_crtc_mapping[pipe];
 
                        __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
-                                        crtc->fb);
+                                        crtc->primary->fb);
                }
        } else {
                intel_modeset_update_staged_output_state(dev);
@@ -11745,15 +11751,15 @@ void intel_modeset_gem_init(struct drm_device *dev)
         */
        mutex_lock(&dev->struct_mutex);
        list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
-               if (!c->fb)
+               if (!c->primary->fb)
                        continue;
 
-               fb = to_intel_framebuffer(c->fb);
+               fb = to_intel_framebuffer(c->primary->fb);
                if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
                        DRM_ERROR("failed to pin boot fb on pipe %d\n",
                                  to_intel_crtc(c)->pipe);
-                       drm_framebuffer_unreference(c->fb);
-                       c->fb = NULL;
+                       drm_framebuffer_unreference(c->primary->fb);
+                       c->primary->fb = NULL;
                }
        }
        mutex_unlock(&dev->struct_mutex);
@@ -11792,7 +11798,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
-               if (!crtc->fb)
+               if (!crtc->primary->fb)
                        continue;
 
                intel_increase_pllclock(crtc);
index bbb1327644d48b923bcf1e99a8087929095667ef..5ce5e5be7e8826d430eb1ba7c2da9a864279eff2 100644 (file)
@@ -1634,7 +1634,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = dig_port->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->primary->fb)->obj;
        struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 
        dev_priv->psr.source_ok = false;
@@ -1667,7 +1667,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
                return false;
        }
 
-       obj = to_intel_framebuffer(crtc->fb)->obj;
+       obj = to_intel_framebuffer(crtc->primary->fb)->obj;
        if (obj->tiling_mode != I915_TILING_X ||
            obj->fence_reg == I915_FENCE_REG_NONE) {
                DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
@@ -3646,6 +3646,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        /* We now know it's not a ghost, init power sequence regs. */
        intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
 
+       mutex_lock(&dev->mode_config.mutex);
        edid = drm_get_edid(connector, &intel_dp->aux.ddc);
        if (edid) {
                if (drm_add_edid_modes(connector, edid)) {
@@ -3676,6 +3677,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                if (fixed_mode)
                        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
        }
+       mutex_unlock(&dev->mode_config.mutex);
 
        intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
        intel_panel_setup_backlight(connector);
index d6d78c86c232b006906d5e7f4dbc9aabc943afb6..2b1d42dbfe13c4462457e61e8b274025aff8b49c 100644 (file)
@@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                intel_crtc = to_intel_crtc(crtc);
 
-               if (!intel_crtc->active || !crtc->fb) {
+               if (!intel_crtc->active || !crtc->primary->fb) {
                        DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
                                      pipe_name(intel_crtc->pipe));
                        continue;
@@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
                        DRM_DEBUG_KMS("found possible fb from plane %c\n",
                                      pipe_name(intel_crtc->pipe));
                        plane_config = &intel_crtc->plane_config;
-                       fb = to_intel_framebuffer(crtc->fb);
+                       fb = to_intel_framebuffer(crtc->primary->fb);
                        max_size = plane_config->size;
                }
        }
@@ -560,7 +560,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
                if (!intel_crtc->active)
                        continue;
 
-               WARN(!crtc->fb,
+               WARN(!crtc->primary->fb,
                     "re-used BIOS config but lost an fb on crtc %d\n",
                     crtc->base.id);
        }
index ef5e5661efb21f3ade3da94e52ac47f1c86af5fc..f1ecf916474a93e3a18dd604991a8915309d83cb 100644 (file)
@@ -1002,6 +1002,7 @@ void intel_lvds_init(struct drm_device *dev)
         * Attempt to get the fixed panel mode from DDC.  Assume that the
         * preferred mode is the right one.
         */
+       mutex_lock(&dev->mode_config.mutex);
        edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
        if (edid) {
                if (drm_add_edid_modes(connector, edid)) {
@@ -1095,6 +1096,8 @@ void intel_lvds_init(struct drm_device *dev)
                goto failed;
 
 out:
+       mutex_unlock(&dev->mode_config.mutex);
+
        lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
        DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
                      lvds_encoder->is_dual_link ? "dual" : "single");
@@ -1123,6 +1126,8 @@ out:
        return;
 
 failed:
+       mutex_unlock(&dev->mode_config.mutex);
+
        DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
        drm_connector_cleanup(connector);
        drm_encoder_cleanup(encoder);
index 312961a8472e304313d4714684a7cb7cf9f3a6a0..623cd328b19663b065b557f3cc2d5b557fcddade 100644 (file)
@@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay,
 {
        u32 key = overlay->color_key;
 
-       switch (overlay->crtc->base.fb->bits_per_pixel) {
+       switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
        case 8:
                iowrite32(0, &regs->DCLRKV);
                iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
                break;
 
        case 16:
-               if (overlay->crtc->base.fb->depth == 15) {
+               if (overlay->crtc->base.primary->fb->depth == 15) {
                        iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
                        iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
                                  &regs->DCLRKM);
index fd68f93671bba7d02fb95eb116156b97f713edcf..6e73125fc78299978497da884edfb59af5b29612 100644 (file)
@@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -336,11 +336,11 @@ static void intel_fbc_work_fn(struct work_struct *__work)
                /* Double check that we haven't switched fb without cancelling
                 * the prior work.
                 */
-               if (work->crtc->fb == work->fb) {
+               if (work->crtc->primary->fb == work->fb) {
                        dev_priv->display.enable_fbc(work->crtc);
 
                        dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
-                       dev_priv->fbc.fb_id = work->crtc->fb->base.id;
+                       dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
                        dev_priv->fbc.y = work->crtc->y;
                }
 
@@ -393,7 +393,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc)
        }
 
        work->crtc = crtc;
-       work->fb = crtc->fb;
+       work->fb = crtc->primary->fb;
        INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
        dev_priv->fbc.fbc_work = work;
@@ -499,14 +499,14 @@ void intel_update_fbc(struct drm_device *dev)
                }
        }
 
-       if (!crtc || crtc->fb == NULL) {
+       if (!crtc || crtc->primary->fb == NULL) {
                if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
                        DRM_DEBUG_KMS("no output, disabling\n");
                goto out_disable;
        }
 
        intel_crtc = to_intel_crtc(crtc);
-       fb = crtc->fb;
+       fb = crtc->primary->fb;
        intel_fb = to_intel_framebuffer(fb);
        obj = intel_fb->obj;
        adjusted_mode = &intel_crtc->config.adjusted_mode;
@@ -1041,7 +1041,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
        crtc = single_enabled_crtc(dev);
        if (crtc) {
                const struct drm_display_mode *adjusted_mode;
-               int pixel_size = crtc->fb->bits_per_pixel / 8;
+               int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
                int clock;
 
                adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
@@ -1121,7 +1121,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        clock = adjusted_mode->crtc_clock;
        htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
+       pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 
        /* Use the small buffer method to calculate plane watermark */
        entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
@@ -1208,7 +1208,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
        clock = adjusted_mode->crtc_clock;
        htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
+       pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 
        line_time_us = max(htotal * 1000 / clock, 1);
        line_count = (latency_ns / line_time_us + 1000) / 1000;
@@ -1247,7 +1247,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
                return false;
 
        clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-       pixel_size = crtc->fb->bits_per_pixel / 8;      /* BPP */
+       pixel_size = crtc->primary->fb->bits_per_pixel / 8;     /* BPP */
 
        entries = (clock / 1000) * pixel_size;
        *plane_prec_mult = (entries > 256) ?
@@ -1439,7 +1439,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                int clock = adjusted_mode->crtc_clock;
                int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-               int pixel_size = crtc->fb->bits_per_pixel / 8;
+               int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
                int entries;
 
@@ -1512,7 +1512,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        crtc = intel_get_crtc_for_plane(dev, 0);
        if (intel_crtc_active(crtc)) {
                const struct drm_display_mode *adjusted_mode;
-               int cpp = crtc->fb->bits_per_pixel / 8;
+               int cpp = crtc->primary->fb->bits_per_pixel / 8;
                if (IS_GEN2(dev))
                        cpp = 4;
 
@@ -1528,7 +1528,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        crtc = intel_get_crtc_for_plane(dev, 1);
        if (intel_crtc_active(crtc)) {
                const struct drm_display_mode *adjusted_mode;
-               int cpp = crtc->fb->bits_per_pixel / 8;
+               int cpp = crtc->primary->fb->bits_per_pixel / 8;
                if (IS_GEN2(dev))
                        cpp = 4;
 
@@ -1565,7 +1565,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                int clock = adjusted_mode->crtc_clock;
                int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
-               int pixel_size = enabled->fb->bits_per_pixel / 8;
+               int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
                int entries;
 
@@ -2117,7 +2117,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
        if (p->active) {
                p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
                p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
-               p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
+               p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
                p->cur.bytes_per_pixel = 4;
                p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
                p->cur.horiz_pixels = 64;
@@ -2129,7 +2129,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                config->num_pipes_active += intel_crtc_active(crtc);
 
-       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+       drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
                struct intel_plane *intel_plane = to_intel_plane(plane);
 
                if (intel_plane->pipe == pipe)
index 968374776db9c32e2545b2409acc88322fe3f3f9..a034ed408252eb08e57e166ba6afed4a50931e31 100644 (file)
@@ -29,7 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
        struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        int i;
 
        if (!crtc->enabled)
@@ -742,7 +742,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
                mgag200_bo_unreserve(bo);
        }
 
-       mga_fb = to_mga_framebuffer(crtc->fb);
+       mga_fb = to_mga_framebuffer(crtc->primary->fb);
        obj = mga_fb->obj;
        bo = gem_to_mga_bo(obj);
 
@@ -805,7 +805,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                /* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
        };
 
-       bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
+       bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
 
        switch (mdev->type) {
        case G200_SE_A:
@@ -843,12 +843,12 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                break;
        }
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
                break;
        case 16:
-               if (crtc->fb->depth == 15)
+               if (crtc->primary->fb->depth == 15)
                        dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
                else
                        dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
@@ -896,8 +896,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
        WREG_SEQ(3, 0);
        WREG_SEQ(4, 0xe);
 
-       pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
-       if (crtc->fb->bits_per_pixel == 24)
+       pitch = crtc->primary->fb->pitches[0] / (crtc->primary->fb->bits_per_pixel / 8);
+       if (crtc->primary->fb->bits_per_pixel == 24)
                pitch = (pitch * 3) >> (4 - bppshift);
        else
                pitch = pitch >> (4 - bppshift);
@@ -974,7 +974,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                ((vdisplay & 0xc00) >> 7) |
                ((vsyncstart & 0xc00) >> 5) |
                ((vdisplay & 0x400) >> 3);
-       if (crtc->fb->bits_per_pixel == 24)
+       if (crtc->primary->fb->bits_per_pixel == 24)
                ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
        else
                ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
@@ -1034,9 +1034,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                        u32 bpp;
                        u32 mb;
 
-                       if (crtc->fb->bits_per_pixel > 16)
+                       if (crtc->primary->fb->bits_per_pixel > 16)
                                bpp = 32;
-                       else if (crtc->fb->bits_per_pixel > 8)
+                       else if (crtc->primary->fb->bits_per_pixel > 8)
                                bpp = 16;
                        else
                                bpp = 8;
@@ -1277,8 +1277,8 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
        int ret;
        DRM_DEBUG_KMS("\n");
        mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->fb) {
-               struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
+       if (crtc->primary->fb) {
+               struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);
                struct drm_gem_object *obj = mga_fb->obj;
                struct mgag200_bo *bo = gem_to_mga_bo(obj);
                ret = mgag200_bo_reserve(bo, false);
@@ -1287,7 +1287,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
                mgag200_bo_push_sysram(bo);
                mgag200_bo_unreserve(bo);
        }
-       crtc->fb = NULL;
+       crtc->primary->fb = NULL;
 }
 
 /* These provide the minimum set of functions required to handle a CRTC */
index 84c5b13b33c9ed2649a58d2a9d499d6d22ba0a21..3e6c0f3ed592a6b746610b9b6dd1986e50e1ace7 100644 (file)
@@ -120,7 +120,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
 
        /* grab reference to incoming scanout fb: */
        drm_framebuffer_reference(new_fb);
-       mdp4_crtc->base.fb = new_fb;
+       mdp4_crtc->base.primary->fb = new_fb;
        mdp4_crtc->fb = new_fb;
 
        if (old_fb)
@@ -182,7 +182,7 @@ static void pageflip_cb(struct msm_fence_cb *cb)
        struct mdp4_crtc *mdp4_crtc =
                container_of(cb, struct mdp4_crtc, pageflip_cb);
        struct drm_crtc *crtc = &mdp4_crtc->base;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
 
        if (!fb)
                return;
@@ -348,14 +348,14 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
                        mode->type, mode->flags);
 
        /* grab extra ref for update_scanout() */
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
-       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
+       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
        if (ret) {
-               drm_framebuffer_unreference(crtc->fb);
+               drm_framebuffer_unreference(crtc->primary->fb);
                dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
                                mdp4_crtc->name, ret);
                return ret;
@@ -368,7 +368,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
        /* take data from pipe: */
        mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
        mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
-                       crtc->fb->pitches[0]);
+                       crtc->primary->fb->pitches[0]);
        mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
                        MDP4_DMA_DST_SIZE_WIDTH(0) |
                        MDP4_DMA_DST_SIZE_HEIGHT(0));
@@ -378,7 +378,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
                        MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
                        MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
        mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
-                       crtc->fb->pitches[0]);
+                       crtc->primary->fb->pitches[0]);
 
        mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
 
@@ -388,8 +388,8 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
                mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
        }
 
-       update_fb(crtc, crtc->fb);
-       update_scanout(crtc, crtc->fb);
+       update_fb(crtc, crtc->primary->fb);
+       update_scanout(crtc, crtc->primary->fb);
 
        return 0;
 }
@@ -420,19 +420,19 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        int ret;
 
        /* grab extra ref for update_scanout() */
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
-       ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
+       ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
        if (ret) {
-               drm_framebuffer_unreference(crtc->fb);
+               drm_framebuffer_unreference(crtc->primary->fb);
                return ret;
        }
 
-       update_fb(crtc, crtc->fb);
-       update_scanout(crtc, crtc->fb);
+       update_fb(crtc, crtc->primary->fb);
+       update_scanout(crtc, crtc->primary->fb);
 
        return 0;
 }
@@ -740,6 +740,9 @@ void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
 
 void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
 {
+       /* don't actually detatch our primary plane: */
+       if (to_mdp4_crtc(crtc)->plane == plane)
+               return;
        set_attach(crtc, mdp4_plane_pipe(plane), NULL);
 }
 
@@ -791,7 +794,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 
        INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
 
-       drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
+       drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp4_crtc_funcs);
        drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
 
        mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
index 1e893dd13859817ae33e199b99f0810c59c49732..66f33dba1ebb3e520f3a2bfa1e4473eaeaacd7ba 100644 (file)
@@ -222,6 +222,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
        struct drm_plane *plane = NULL;
        struct mdp4_plane *mdp4_plane;
        int ret;
+       enum drm_plane_type type;
 
        mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
        if (!mdp4_plane) {
@@ -237,9 +238,10 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
        mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats,
                        ARRAY_SIZE(mdp4_plane->formats));
 
-       drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
-                       mdp4_plane->formats, mdp4_plane->nformats,
-                       private_plane);
+       type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+       drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
+                                mdp4_plane->formats, mdp4_plane->nformats,
+                                type);
 
        mdp4_plane_install_properties(plane, &plane->base);
 
index f2794021f086f53fc509dea1f3136cf4facfe27d..6ea10bdb6e8fc60d7691ba5ff6338177023e94ac 100644 (file)
@@ -102,7 +102,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
 
        /* grab reference to incoming scanout fb: */
        drm_framebuffer_reference(new_fb);
-       mdp5_crtc->base.fb = new_fb;
+       mdp5_crtc->base.primary->fb = new_fb;
        mdp5_crtc->fb = new_fb;
 
        if (old_fb)
@@ -289,14 +289,14 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
                        mode->type, mode->flags);
 
        /* grab extra ref for update_scanout() */
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
-       ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
+       ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
        if (ret) {
-               drm_framebuffer_unreference(crtc->fb);
+               drm_framebuffer_unreference(crtc->primary->fb);
                dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
                                mdp5_crtc->name, ret);
                return ret;
@@ -306,8 +306,8 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
                        MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
                        MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
 
-       update_fb(crtc, crtc->fb);
-       update_scanout(crtc, crtc->fb);
+       update_fb(crtc, crtc->primary->fb);
+       update_scanout(crtc, crtc->primary->fb);
 
        return 0;
 }
@@ -338,19 +338,19 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        int ret;
 
        /* grab extra ref for update_scanout() */
-       drm_framebuffer_reference(crtc->fb);
+       drm_framebuffer_reference(crtc->primary->fb);
 
-       ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
+       ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
        if (ret) {
-               drm_framebuffer_unreference(crtc->fb);
+               drm_framebuffer_unreference(crtc->primary->fb);
                return ret;
        }
 
-       update_fb(crtc, crtc->fb);
-       update_scanout(crtc, crtc->fb);
+       update_fb(crtc, crtc->primary->fb);
+       update_scanout(crtc, crtc->primary->fb);
 
        return 0;
 }
@@ -524,6 +524,9 @@ void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
 
 void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
 {
+       /* don't actually detatch our primary plane: */
+       if (to_mdp5_crtc(crtc)->plane == plane)
+               return;
        set_attach(crtc, mdp5_plane_pipe(plane), NULL);
 }
 
@@ -559,7 +562,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 
        INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
 
-       drm_crtc_init(dev, crtc, &mdp5_crtc_funcs);
+       drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs);
        drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
 
        mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
index 0ac8bb5e7e85ef08760ca2fce41ec67558b4415b..47f7bbb9c15ace7bec2606c7d550f30e480c20b1 100644 (file)
@@ -358,6 +358,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
        struct drm_plane *plane = NULL;
        struct mdp5_plane *mdp5_plane;
        int ret;
+       enum drm_plane_type type;
 
        mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
        if (!mdp5_plane) {
@@ -373,9 +374,10 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
        mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
                        ARRAY_SIZE(mdp5_plane->formats));
 
-       drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
-                       mdp5_plane->formats, mdp5_plane->nformats,
-                       private_plane);
+       type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+       drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
+                                mdp5_plane->formats, mdp5_plane->nformats,
+                                type);
 
        mdp5_plane_install_properties(plane, &plane->base);
 
index d310c195bdfed1d467abbd1f5933da703e207e13..b7d216264775511bcb807566047d9c69db26ff31 100644 (file)
@@ -48,6 +48,7 @@ nouveau-y += core/subdev/bios/therm.o
 nouveau-y += core/subdev/bios/vmap.o
 nouveau-y += core/subdev/bios/volt.o
 nouveau-y += core/subdev/bios/xpio.o
+nouveau-y += core/subdev/bios/P0260.o
 nouveau-y += core/subdev/bus/hwsq.o
 nouveau-y += core/subdev/bus/nv04.o
 nouveau-y += core/subdev/bus/nv31.o
@@ -77,6 +78,7 @@ nouveau-y += core/subdev/devinit/nv98.o
 nouveau-y += core/subdev/devinit/nva3.o
 nouveau-y += core/subdev/devinit/nvaf.o
 nouveau-y += core/subdev/devinit/nvc0.o
+nouveau-y += core/subdev/devinit/gm107.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
 nouveau-y += core/subdev/fb/nv10.o
@@ -100,6 +102,7 @@ nouveau-y += core/subdev/fb/nvaa.o
 nouveau-y += core/subdev/fb/nvaf.o
 nouveau-y += core/subdev/fb/nvc0.o
 nouveau-y += core/subdev/fb/nve0.o
+nouveau-y += core/subdev/fb/gm107.o
 nouveau-y += core/subdev/fb/ramnv04.o
 nouveau-y += core/subdev/fb/ramnv10.o
 nouveau-y += core/subdev/fb/ramnv1a.o
@@ -114,6 +117,7 @@ nouveau-y += core/subdev/fb/ramnva3.o
 nouveau-y += core/subdev/fb/ramnvaa.o
 nouveau-y += core/subdev/fb/ramnvc0.o
 nouveau-y += core/subdev/fb/ramnve0.o
+nouveau-y += core/subdev/fb/ramgm107.o
 nouveau-y += core/subdev/fb/sddr3.o
 nouveau-y += core/subdev/fb/gddr5.o
 nouveau-y += core/subdev/gpio/base.o
@@ -136,7 +140,8 @@ nouveau-y += core/subdev/instmem/base.o
 nouveau-y += core/subdev/instmem/nv04.o
 nouveau-y += core/subdev/instmem/nv40.o
 nouveau-y += core/subdev/instmem/nv50.o
-nouveau-y += core/subdev/ltcg/nvc0.o
+nouveau-y += core/subdev/ltcg/gf100.o
+nouveau-y += core/subdev/ltcg/gm107.o
 nouveau-y += core/subdev/mc/base.o
 nouveau-y += core/subdev/mc/nv04.o
 nouveau-y += core/subdev/mc/nv40.o
@@ -170,6 +175,7 @@ nouveau-y += core/subdev/therm/nva3.o
 nouveau-y += core/subdev/therm/nvd0.o
 nouveau-y += core/subdev/timer/base.o
 nouveau-y += core/subdev/timer/nv04.o
+nouveau-y += core/subdev/timer/gk20a.o
 nouveau-y += core/subdev/vm/base.o
 nouveau-y += core/subdev/vm/nv04.o
 nouveau-y += core/subdev/vm/nv41.o
@@ -206,6 +212,7 @@ nouveau-y += core/engine/device/nv40.o
 nouveau-y += core/engine/device/nv50.o
 nouveau-y += core/engine/device/nvc0.o
 nouveau-y += core/engine/device/nve0.o
+nouveau-y += core/engine/device/gm100.o
 nouveau-y += core/engine/disp/base.o
 nouveau-y += core/engine/disp/nv04.o
 nouveau-y += core/engine/disp/nv50.o
@@ -216,6 +223,7 @@ nouveau-y += core/engine/disp/nva3.o
 nouveau-y += core/engine/disp/nvd0.o
 nouveau-y += core/engine/disp/nve0.o
 nouveau-y += core/engine/disp/nvf0.o
+nouveau-y += core/engine/disp/gm107.o
 nouveau-y += core/engine/disp/dacnv50.o
 nouveau-y += core/engine/disp/dport.o
 nouveau-y += core/engine/disp/hdanva3.o
@@ -242,13 +250,14 @@ nouveau-y += core/engine/graph/ctxnv40.o
 nouveau-y += core/engine/graph/ctxnv50.o
 nouveau-y += core/engine/graph/ctxnvc0.o
 nouveau-y += core/engine/graph/ctxnvc1.o
-nouveau-y += core/engine/graph/ctxnvc3.o
+nouveau-y += core/engine/graph/ctxnvc4.o
 nouveau-y += core/engine/graph/ctxnvc8.o
 nouveau-y += core/engine/graph/ctxnvd7.o
 nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
 nouveau-y += core/engine/graph/ctxnvf0.o
 nouveau-y += core/engine/graph/ctxnv108.o
+nouveau-y += core/engine/graph/ctxgm107.o
 nouveau-y += core/engine/graph/nv04.o
 nouveau-y += core/engine/graph/nv10.o
 nouveau-y += core/engine/graph/nv20.o
@@ -261,13 +270,14 @@ nouveau-y += core/engine/graph/nv40.o
 nouveau-y += core/engine/graph/nv50.o
 nouveau-y += core/engine/graph/nvc0.o
 nouveau-y += core/engine/graph/nvc1.o
-nouveau-y += core/engine/graph/nvc3.o
+nouveau-y += core/engine/graph/nvc4.o
 nouveau-y += core/engine/graph/nvc8.o
 nouveau-y += core/engine/graph/nvd7.o
 nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
 nouveau-y += core/engine/graph/nvf0.o
 nouveau-y += core/engine/graph/nv108.o
+nouveau-y += core/engine/graph/gm107.o
 nouveau-y += core/engine/mpeg/nv31.o
 nouveau-y += core/engine/mpeg/nv40.o
 nouveau-y += core/engine/mpeg/nv44.o
index 1ce95a8709df7763ad24f93f9cb21b61e44e34aa..0594a599f6fb1d9aafbacdb6fa5ae2178b30e4ea 100644 (file)
@@ -167,7 +167,7 @@ int
 nouveau_namedb_create_(struct nouveau_object *parent,
                       struct nouveau_object *engine,
                       struct nouveau_oclass *oclass, u32 pclass,
-                      struct nouveau_oclass *sclass, u32 engcls,
+                      struct nouveau_oclass *sclass, u64 engcls,
                       int length, void **pobject)
 {
        struct nouveau_namedb *namedb;
index 313380ce632df1b9f1b9eef0915ef14deade0162..dee5d1235e9bb6701e0b5214da3482d5d334fbfb 100644 (file)
@@ -49,7 +49,7 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
 
        mask = nv_parent(parent)->engine;
        while (mask) {
-               int i = ffsll(mask) - 1;
+               int i = __ffs64(mask);
 
                if (nv_iclass(parent, NV_CLIENT_CLASS))
                        engine = nv_engine(nv_client(parent)->device);
index dd01c6c435d6e2e01ecb92ccbd57cf09e7346660..18c8c7245b73b2b1e12ec3fe921266621763f8ee 100644 (file)
@@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       mmio_base = pci_resource_start(device->pdev, 0);
-       mmio_size = pci_resource_len(device->pdev, 0);
+       mmio_base = nv_device_resource_start(device, 0);
+       mmio_size = nv_device_resource_len(device, 0);
 
        /* translate api disable mask into internal mapping */
        disable = args->debug0;
@@ -185,6 +185,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                        case 0x0e0:
                        case 0x0f0:
                        case 0x100: device->card_type = NV_E0; break;
+                       case 0x110: device->card_type = GM100; break;
                        default:
                                break;
                        }
@@ -208,6 +209,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                case NV_C0:
                case NV_D0: ret = nvc0_identify(device); break;
                case NV_E0: ret = nve0_identify(device); break;
+               case GM100: ret = gm100_identify(device); break;
                default:
                        ret = -EINVAL;
                        break;
@@ -446,6 +448,72 @@ nouveau_device_dtor(struct nouveau_object *object)
        nouveau_engine_destroy(&device->base);
 }
 
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
+{
+       if (nv_device_is_pci(device)) {
+               return pci_resource_start(device->pdev, bar);
+       } else {
+               struct resource *res;
+               res = platform_get_resource(device->platformdev,
+                                           IORESOURCE_MEM, bar);
+               if (!res)
+                       return 0;
+               return res->start;
+       }
+}
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
+{
+       if (nv_device_is_pci(device)) {
+               return pci_resource_len(device->pdev, bar);
+       } else {
+               struct resource *res;
+               res = platform_get_resource(device->platformdev,
+                                           IORESOURCE_MEM, bar);
+               if (!res)
+                       return 0;
+               return resource_size(res);
+       }
+}
+
+dma_addr_t
+nv_device_map_page(struct nouveau_device *device, struct page *page)
+{
+       dma_addr_t ret;
+
+       if (nv_device_is_pci(device)) {
+               ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
+                                  PCI_DMA_BIDIRECTIONAL);
+               if (pci_dma_mapping_error(device->pdev, ret))
+                       ret = 0;
+       } else {
+               ret = page_to_phys(page);
+       }
+
+       return ret;
+}
+
+void
+nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
+{
+       if (nv_device_is_pci(device))
+               pci_unmap_page(device->pdev, addr, PAGE_SIZE,
+                              PCI_DMA_BIDIRECTIONAL);
+}
+
+int
+nv_device_get_irq(struct nouveau_device *device, bool stall)
+{
+       if (nv_device_is_pci(device)) {
+               return device->pdev->irq;
+       } else {
+               return platform_get_irq_byname(device->platformdev,
+                                              stall ? "stall" : "nonstall");
+       }
+}
+
 static struct nouveau_oclass
 nouveau_device_oclass = {
        .handle = NV_ENGINE(DEVICE, 0x00),
@@ -457,8 +525,8 @@ nouveau_device_oclass = {
 };
 
 int
-nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
-                      const char *cfg, const char *dbg,
+nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
+                      const char *sname, const char *cfg, const char *dbg,
                       int length, void **pobject)
 {
        struct nouveau_device *device;
@@ -476,7 +544,14 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
        if (ret)
                goto done;
 
-       device->pdev = pdev;
+       switch (type) {
+       case NOUVEAU_BUS_PCI:
+               device->pdev = dev;
+               break;
+       case NOUVEAU_BUS_PLATFORM:
+               device->platformdev = dev;
+               break;
+       }
        device->handle = name;
        device->cfgopt = cfg;
        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 (file)
index 0000000..d258c21
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/mxm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/ltcg.h>
+#include <subdev/ibus.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/pwr.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+#include <engine/copy.h>
+#include <engine/bsp.h>
+#include <engine/vp.h>
+#include <engine/ppp.h>
+#include <engine/perfmon.h>
+
+int
+gm100_identify(struct nouveau_device *device)
+{
+       switch (device->chipset) {
+       case 0x117:
+               device->cname = "GM107";
+               device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
+               device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+#if 0
+               device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
+#endif
+               device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm107_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
+               device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gm107_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
+#if 0
+               device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
+               device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
+#endif
+               device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  gm107_graph_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  gm107_disp_oclass;
+               device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
+#if 0
+               device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
+#endif
+               device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+#if 0
+               device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
+               device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
+               device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
+#endif
+               break;
+       default:
+               nv_fatal(device, "unknown Maxwell chipset\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
index 32113b08c4d5fb16e401e871ec65080d61a63e7c..0a51ff4e9e00547b4649f43b2eadf55f86d44300 100644 (file)
@@ -60,7 +60,7 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x05:
                device->cname = "NV05";
@@ -78,7 +78,7 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        default:
                nv_fatal(device, "unknown RIVA chipset\n");
index 744f15d7e1315a6a3b9406f364d0a8bf78231cd5..e008de8b51b01927468c3f465c11ee9cd4b0c932 100644 (file)
@@ -60,7 +60,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x15:
                device->cname = "NV15";
@@ -79,7 +79,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x16:
                device->cname = "NV16";
@@ -98,7 +98,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x1a:
                device->cname = "nForce";
@@ -117,7 +117,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x11:
                device->cname = "NV11";
@@ -136,7 +136,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x17:
                device->cname = "NV17";
@@ -155,7 +155,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x1f:
                device->cname = "nForce2";
@@ -174,7 +174,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x18:
                device->cname = "NV18";
@@ -193,7 +193,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        default:
                nv_fatal(device, "unknown Celsius chipset\n");
index 27ba61fb271045c1efa9acd2982c48ce7b60f278..7b629a3aed059649e5b64b071370b9781e2b75d5 100644 (file)
@@ -63,7 +63,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv20_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x25:
                device->cname = "NV25";
@@ -82,7 +82,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x28:
                device->cname = "NV28";
@@ -101,7 +101,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x2a:
                device->cname = "NV2A";
@@ -120,7 +120,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv2a_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        default:
                nv_fatal(device, "unknown Kelvin chipset\n");
index fd47ace67543cd15f6be3c6b6799aefe497e4dcf..7dfddd5a1908fc517ac2e2f47359b787a08ec615 100644 (file)
@@ -63,7 +63,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x35:
                device->cname = "NV35";
@@ -82,7 +82,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x31:
                device->cname = "NV31";
@@ -102,7 +102,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x36:
                device->cname = "NV36";
@@ -122,7 +122,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        case 0x34:
                device->cname = "NV34";
@@ -142,7 +142,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv34_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                break;
        default:
                nv_fatal(device, "unknown Rankine chipset\n");
index 08b88591ed6036924c76d51efcf0d1d32c91210e..7c1ce6cf4f1f6ba931260d52cf2ea0000c61bfc5 100644 (file)
@@ -70,7 +70,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x41:
@@ -93,7 +93,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x42:
@@ -116,7 +116,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x43:
@@ -139,7 +139,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x45:
@@ -162,7 +162,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x47:
@@ -185,7 +185,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x49:
@@ -208,7 +208,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x4b:
@@ -231,7 +231,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x44:
@@ -254,7 +254,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x46:
@@ -277,7 +277,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x4a:
@@ -300,7 +300,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x4c:
@@ -323,7 +323,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x4e:
@@ -346,7 +346,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x63:
@@ -369,7 +369,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x67:
@@ -392,7 +392,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        case 0x68:
@@ -415,7 +415,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;
                break;
        default:
index 81d5c26643d50dcff2067abdf0f2bb7a227621ad..66499fa0f7589000a2ddfd263cddf5037c592c4f 100644 (file)
@@ -79,7 +79,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv50_mpeg_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv50_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv50_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv50_perfmon_oclass;
                break;
        case 0x84:
@@ -107,7 +107,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0x86:
@@ -135,7 +135,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0x92:
@@ -163,7 +163,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0x94:
@@ -191,7 +191,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0x96:
@@ -219,7 +219,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0x98:
@@ -247,7 +247,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0xa0:
@@ -275,7 +275,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva0_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0xaa:
@@ -303,7 +303,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0xac:
@@ -331,7 +331,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;
                break;
        case 0xa3:
@@ -361,7 +361,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;
                break;
        case 0xa5:
@@ -390,7 +390,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;
                break;
        case 0xa8:
@@ -419,7 +419,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;
                break;
        case 0xaf:
@@ -448,7 +448,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;
                break;
        default:
index b7d66b59f43d4c7cc3ea0c733f809f966c37aa3d..2075b3027052c349f7b714036c2cf358d43871ae 100644 (file)
@@ -70,7 +70,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -86,7 +86,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xc4:
@@ -102,7 +102,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -112,13 +112,13 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xc3:
@@ -134,7 +134,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -144,12 +144,12 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xce:
@@ -165,7 +165,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -175,13 +175,13 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xcf:
@@ -197,7 +197,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -207,13 +207,13 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xc1:
@@ -229,7 +229,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -244,7 +244,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xc8:
@@ -260,7 +260,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -276,7 +276,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xd9:
@@ -292,7 +292,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -307,7 +307,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nvd0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nvd0_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        case 0xd7:
@@ -323,7 +323,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -336,7 +336,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nvd0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nvd0_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
        default:
index 987edbc30a0917cc2db2a035c749f42c5818b5b9..9784cbf8a9d20d2cf7d9706ca0fa5a571a720d74 100644 (file)
@@ -70,7 +70,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -81,7 +81,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
@@ -103,7 +103,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -114,7 +114,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
@@ -136,7 +136,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -147,7 +147,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
@@ -169,7 +169,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -180,7 +180,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
@@ -204,7 +204,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
@@ -215,7 +215,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass;
-               device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
index 1bd4c63369c16f96fd30762c1faaddb60acdf337..3ca2d25b7f5e023b917dbd4dd246cd8e3fe64031 100644 (file)
@@ -273,7 +273,7 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
                .outp = outp,
                .head = head,
        }, *dp = &_dp;
-       const u32 bw_list[] = { 270000, 162000, 0 };
+       const u32 bw_list[] = { 540000, 270000, 162000, 0 };
        const u32 *link_bw = bw_list;
        u8  hdr, cnt, len;
        u32 data;
@@ -312,6 +312,14 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
                ERR("failed to read DPCD\n");
        }
 
+       /* bring capabilities within encoder limits */
+       if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
+               dp->dpcd[2] &= ~0x1f;
+               dp->dpcd[2] |= dp->outp->dpconf.link_nr;
+       }
+       if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
+               dp->dpcd[1] = dp->outp->dpconf.link_bw;
+
        /* adjust required bandwidth for 8B/10B coding overhead */
        datarate = (datarate / 8) * 10;
 
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 (file)
index 0000000..cf6f596
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/software.h>
+#include <engine/disp.h>
+
+#include <core/class.h>
+
+#include "nv50.h"
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
+static struct nouveau_oclass
+gm107_disp_sclass[] = {
+       { GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
+       { GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
+       { GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
+       { GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
+       { GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+       {}
+};
+
+static struct nouveau_oclass
+gm107_disp_base_oclass[] = {
+       { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+       {}
+};
+
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
+static int
+gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       struct nv50_disp_priv *priv;
+       int heads = nv_rd32(parent, 0x022448);
+       int ret;
+
+       ret = nouveau_disp_create(parent, engine, oclass, heads,
+                                 "PDISP", "display", &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       nv_engine(priv)->sclass = gm107_disp_base_oclass;
+       nv_engine(priv)->cclass = &nv50_disp_cclass;
+       nv_subdev(priv)->intr = nvd0_disp_intr;
+       INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
+       priv->sclass = gm107_disp_sclass;
+       priv->head.nr = heads;
+       priv->dac.nr = 3;
+       priv->sor.nr = 4;
+       priv->dac.power = nv50_dac_power;
+       priv->dac.sense = nv50_dac_sense;
+       priv->sor.power = nv50_sor_power;
+       priv->sor.hda_eld = nvd0_hda_eld;
+       priv->sor.hdmi = nvd0_hdmi_ctrl;
+       priv->sor.dp = &nvd0_sor_dp_func;
+       return 0;
+}
+
+struct nouveau_oclass *
+gm107_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x07),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gm107_disp_ctor,
+               .dtor = _nouveau_disp_dtor,
+               .init = _nouveau_disp_init,
+               .fini = _nouveau_disp_fini,
+       },
+       .mthd.core = &nve0_disp_mast_mthd_chan,
+       .mthd.base = &nvd0_disp_sync_mthd_chan,
+       .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+       .mthd.prev = -0x020000,
+}.base.base;
index 7cf8b13486326fdcf64066cb368203668024d11a..6c89af7928892e0a80a99ae5e8960996d81babae 100644 (file)
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include <engine/disp.h>
+#include "priv.h"
 
 #include <core/event.h>
 #include <core/class.h>
@@ -138,13 +138,13 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nv04_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_disp_oclass = &(struct nouveau_disp_impl) {
+       .base.handle = NV_ENGINE(DISP, 0x04),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+}.base;
index 9ad722e4e087007df76e77473c5a5f98ce24be74..9a0cab9c3adbc5b4a58b92bbb2939952d896bd49 100644 (file)
@@ -26,8 +26,7 @@
 #include <core/parent.h>
 #include <core/handle.h>
 #include <core/class.h>
-
-#include <engine/disp.h>
+#include <core/enum.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -227,6 +226,177 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)
  * EVO master channel object
  ******************************************************************************/
 
+static void
+nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c,
+                   const struct nv50_disp_mthd_list *list, int inst)
+{
+       struct nouveau_object *disp = nv_object(priv);
+       int i;
+
+       for (i = 0; list->data[i].mthd; i++) {
+               if (list->data[i].addr) {
+                       u32 next = nv_rd32(priv, list->data[i].addr + base + 0);
+                       u32 prev = nv_rd32(priv, list->data[i].addr + base + c);
+                       u32 mthd = list->data[i].mthd + (list->mthd * inst);
+                       const char *name = list->data[i].name;
+                       char mods[16];
+
+                       if (prev != next)
+                               snprintf(mods, sizeof(mods), "-> 0x%08x", next);
+                       else
+                               snprintf(mods, sizeof(mods), "%13c", ' ');
+
+                       nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n",
+                                  mthd, prev, mods, name ? " // " : "",
+                                  name ? name : "");
+               }
+       }
+}
+
+void
+nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head,
+                   const struct nv50_disp_mthd_chan *chan)
+{
+       struct nouveau_object *disp = nv_object(priv);
+       const struct nv50_disp_impl *impl = (void *)disp->oclass;
+       const struct nv50_disp_mthd_list *list;
+       int i, j;
+
+       if (debug > nv_subdev(priv)->debug)
+               return;
+
+       for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
+               u32 base = head * chan->addr;
+               for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
+                       const char *cname = chan->name;
+                       const char *sname = "";
+                       char cname_[16], sname_[16];
+
+                       if (chan->addr) {
+                               snprintf(cname_, sizeof(cname_), "%s %d",
+                                        chan->name, head);
+                               cname = cname_;
+                       }
+
+                       if (chan->data[i].nr > 1) {
+                               snprintf(sname_, sizeof(sname_), " - %s %d",
+                                        chan->data[i].name, j);
+                               sname = sname_;
+                       }
+
+                       nv_printk_(disp, debug, "%s%s:\n", cname, sname);
+                       nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev,
+                                           list, j);
+               }
+       }
+}
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x610bb8 },
+               { 0x0088, 0x610b9c },
+               { 0x008c, 0x000000 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_dac = {
+       .mthd = 0x0080,
+       .addr = 0x000008,
+       .data = {
+               { 0x0400, 0x610b58 },
+               { 0x0404, 0x610bdc },
+               { 0x0420, 0x610828 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_sor = {
+       .mthd = 0x0040,
+       .addr = 0x000008,
+       .data = {
+               { 0x0600, 0x610b70 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_pior = {
+       .mthd = 0x0040,
+       .addr = 0x000008,
+       .data = {
+               { 0x0700, 0x610b80 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_head = {
+       .mthd = 0x0400,
+       .addr = 0x000540,
+       .data = {
+               { 0x0800, 0x610ad8 },
+               { 0x0804, 0x610ad0 },
+               { 0x0808, 0x610a48 },
+               { 0x080c, 0x610a78 },
+               { 0x0810, 0x610ac0 },
+               { 0x0814, 0x610af8 },
+               { 0x0818, 0x610b00 },
+               { 0x081c, 0x610ae8 },
+               { 0x0820, 0x610af0 },
+               { 0x0824, 0x610b08 },
+               { 0x0828, 0x610b10 },
+               { 0x082c, 0x610a68 },
+               { 0x0830, 0x610a60 },
+               { 0x0834, 0x000000 },
+               { 0x0838, 0x610a40 },
+               { 0x0840, 0x610a24 },
+               { 0x0844, 0x610a2c },
+               { 0x0848, 0x610aa8 },
+               { 0x084c, 0x610ab0 },
+               { 0x0860, 0x610a84 },
+               { 0x0864, 0x610a90 },
+               { 0x0868, 0x610b18 },
+               { 0x086c, 0x610b20 },
+               { 0x0870, 0x610ac8 },
+               { 0x0874, 0x610a38 },
+               { 0x0880, 0x610a58 },
+               { 0x0884, 0x610a9c },
+               { 0x08a0, 0x610a70 },
+               { 0x08a4, 0x610a50 },
+               { 0x08a8, 0x610ae0 },
+               { 0x08c0, 0x610b28 },
+               { 0x08c4, 0x610b30 },
+               { 0x08c8, 0x610b40 },
+               { 0x08d4, 0x610b38 },
+               { 0x08d8, 0x610b48 },
+               { 0x08dc, 0x610b50 },
+               { 0x0900, 0x610a18 },
+               { 0x0904, 0x610ab8 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_mast_mthd_chan = {
+       .name = "Core",
+       .addr = 0x000000,
+       .data = {
+               { "Global", 1, &nv50_disp_mast_mthd_base },
+               {    "DAC", 3, &nv50_disp_mast_mthd_dac  },
+               {    "SOR", 2, &nv50_disp_mast_mthd_sor  },
+               {   "PIOR", 3, &nv50_disp_mast_mthd_pior },
+               {   "HEAD", 2, &nv50_disp_mast_mthd_head },
+               {}
+       }
+};
+
 static int
 nv50_disp_mast_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -323,6 +493,56 @@ nv50_disp_mast_ofuncs = {
  * EVO sync channel objects
  ******************************************************************************/
 
+static const struct nv50_disp_mthd_list
+nv50_disp_sync_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x0008c4 },
+               { 0x0088, 0x0008d0 },
+               { 0x008c, 0x0008dc },
+               { 0x0090, 0x0008e4 },
+               { 0x0094, 0x610884 },
+               { 0x00a0, 0x6108a0 },
+               { 0x00a4, 0x610878 },
+               { 0x00c0, 0x61086c },
+               { 0x00e0, 0x610858 },
+               { 0x00e4, 0x610860 },
+               { 0x00e8, 0x6108ac },
+               { 0x00ec, 0x6108b4 },
+               { 0x0100, 0x610894 },
+               { 0x0110, 0x6108bc },
+               { 0x0114, 0x61088c },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_sync_mthd_image = {
+       .mthd = 0x0400,
+       .addr = 0x000000,
+       .data = {
+               { 0x0800, 0x6108f0 },
+               { 0x0804, 0x6108fc },
+               { 0x0808, 0x61090c },
+               { 0x080c, 0x610914 },
+               { 0x0810, 0x610904 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_sync_mthd_chan = {
+       .name = "Base",
+       .addr = 0x000540,
+       .data = {
+               { "Global", 1, &nv50_disp_sync_mthd_base },
+               {  "Image", 2, &nv50_disp_sync_mthd_image },
+               {}
+       }
+};
+
 static int
 nv50_disp_sync_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -362,6 +582,44 @@ nv50_disp_sync_ofuncs = {
  * EVO overlay channel objects
  ******************************************************************************/
 
+const struct nv50_disp_mthd_list
+nv50_disp_ovly_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x0009a0 },
+               { 0x0088, 0x0009c0 },
+               { 0x008c, 0x0009c8 },
+               { 0x0090, 0x6109b4 },
+               { 0x0094, 0x610970 },
+               { 0x00a0, 0x610998 },
+               { 0x00a4, 0x610964 },
+               { 0x00c0, 0x610958 },
+               { 0x00e0, 0x6109a8 },
+               { 0x00e4, 0x6109d0 },
+               { 0x00e8, 0x6109d8 },
+               { 0x0100, 0x61094c },
+               { 0x0104, 0x610984 },
+               { 0x0108, 0x61098c },
+               { 0x0800, 0x6109f8 },
+               { 0x0808, 0x610a08 },
+               { 0x080c, 0x610a10 },
+               { 0x0810, 0x610a00 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_ovly_mthd_chan = {
+       .name = "Overlay",
+       .addr = 0x000540,
+       .data = {
+               { "Global", 1, &nv50_disp_ovly_mthd_base },
+               {}
+       }
+};
+
 static int
 nv50_disp_ovly_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -782,25 +1040,78 @@ nv50_disp_cclass = {
  * Display engine implementation
  ******************************************************************************/
 
-static void
-nv50_disp_intr_error(struct nv50_disp_priv *priv)
-{
-       u32 channels = (nv_rd32(priv, 0x610020) & 0x001f0000) >> 16;
-       u32 addr, data;
-       int chid;
-
-       for (chid = 0; chid < 5; chid++) {
-               if (!(channels & (1 << chid)))
-                       continue;
+static const struct nouveau_enum
+nv50_disp_intr_error_type[] = {
+       { 3, "ILLEGAL_MTHD" },
+       { 4, "INVALID_VALUE" },
+       { 5, "INVALID_STATE" },
+       { 7, "INVALID_HANDLE" },
+       {}
+};
 
-               nv_wr32(priv, 0x610020, 0x00010000 << chid);
-               addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
-               data = nv_rd32(priv, 0x610084 + (chid * 0x08));
-               nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
+static const struct nouveau_enum
+nv50_disp_intr_error_code[] = {
+       { 0x00, "" },
+       {}
+};
 
-               nv_error(priv, "chid %d mthd 0x%04x data 0x%08x 0x%08x\n",
-                        chid, addr & 0xffc, data, addr);
+static void
+nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
+{
+       struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+       u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
+       u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
+       u32 code = (addr & 0x00ff0000) >> 16;
+       u32 type = (addr & 0x00007000) >> 12;
+       u32 mthd = (addr & 0x00000ffc);
+       const struct nouveau_enum *ec, *et;
+       char ecunk[6], etunk[6];
+
+       et = nouveau_enum_find(nv50_disp_intr_error_type, type);
+       if (!et)
+               snprintf(etunk, sizeof(etunk), "UNK%02X", type);
+
+       ec = nouveau_enum_find(nv50_disp_intr_error_code, code);
+       if (!ec)
+               snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);
+
+       nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
+                et ? et->name : etunk, ec ? ec->name : ecunk,
+                chid, mthd, data);
+
+       if (chid == 0) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+                                           impl->mthd.core);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 2) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+                                           impl->mthd.base);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 4) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
+                                           impl->mthd.ovly);
+                       break;
+               default:
+                       break;
+               }
        }
+
+       nv_wr32(priv, 0x610020, 0x00010000 << chid);
+       nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
 }
 
 static u16
@@ -1241,12 +1552,14 @@ nv50_disp_intr_supervisor(struct work_struct *work)
 {
        struct nv50_disp_priv *priv =
                container_of(work, struct nv50_disp_priv, supervisor);
+       struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
        u32 super = nv_rd32(priv, 0x610030);
        int head;
 
        nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
 
        if (priv->super & 0x00000010) {
+               nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(super & (0x00000020 << head)))
                                continue;
@@ -1290,9 +1603,10 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
        u32 intr0 = nv_rd32(priv, 0x610020);
        u32 intr1 = nv_rd32(priv, 0x610024);
 
-       if (intr0 & 0x001f0000) {
-               nv50_disp_intr_error(priv);
-               intr0 &= ~0x001f0000;
+       while (intr0 & 0x001f0000) {
+               u32 chid = __ffs(intr0 & 0x001f0000) - 16;
+               nv50_disp_intr_error(priv, chid);
+               intr0 &= ~(0x00010000 << chid);
        }
 
        if (intr1 & 0x00000004) {
@@ -1346,13 +1660,17 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nv50_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x50),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nv50_disp_mast_mthd_chan,
+       .mthd.base = &nv50_disp_sync_mthd_chan,
+       .mthd.ovly = &nv50_disp_ovly_mthd_chan,
+       .mthd.prev = 0x000004,
+}.base.base;
index d31d426ea1f6327c96d77e21210d0b792ba87505..48d59db47f0d00eae37445ee3c22fc658895266d 100644 (file)
@@ -8,9 +8,19 @@
 #include <core/event.h>
 
 #include <engine/dmaobj.h>
-#include <engine/disp.h>
 
 #include "dport.h"
+#include "priv.h"
+
+struct nv50_disp_impl {
+       struct nouveau_disp_impl base;
+       struct {
+               const struct nv50_disp_mthd_chan *core;
+               const struct nv50_disp_mthd_chan *base;
+               const struct nv50_disp_mthd_chan *ovly;
+               int prev;
+       } mthd;
+};
 
 struct nv50_disp_priv {
        struct nouveau_disp base;
@@ -124,21 +134,60 @@ struct nv50_disp_pioc {
        struct nv50_disp_chan base;
 };
 
+struct nv50_disp_mthd_list {
+       u32 mthd;
+       u32 addr;
+       struct {
+               u32 mthd;
+               u32 addr;
+               const char *name;
+       } data[];
+};
+
+struct nv50_disp_mthd_chan {
+       const char *name;
+       u32 addr;
+       struct {
+               const char *name;
+               int nr;
+               const struct nv50_disp_mthd_list *mthd;
+       } data[];
+};
+
 extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
 extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
 extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
 extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
 extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
 extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
 extern struct nouveau_oclass nv50_disp_cclass;
+void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
+                        const struct nv50_disp_mthd_chan *);
 void nv50_disp_intr_supervisor(struct work_struct *);
 void nv50_disp_intr(struct nouveau_subdev *);
 
+extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
+extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
+extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
+extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
+extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
 extern struct nouveau_omthds nv84_disp_base_omthds[];
 
+extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
+
 extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
 extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
+extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
 extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
 extern struct nouveau_omthds nvd0_disp_base_omthds[];
@@ -147,4 +196,7 @@ extern struct nouveau_oclass nvd0_disp_cclass;
 void nvd0_disp_intr_supervisor(struct work_struct *);
 void nvd0_disp_intr(struct nouveau_subdev *);
 
+extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
+extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;
+
 #endif
index ef9ce300a496e0dc1c5baae4c5f1a041d112ea2a..98c5b19bc2b06d25643bd904905cc834ef7b8661 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+const struct nv50_disp_mthd_list
+nv84_disp_mast_mthd_dac = {
+       .mthd = 0x0080,
+       .addr = 0x000008,
+       .data = {
+               { 0x0400, 0x610b58 },
+               { 0x0404, 0x610bdc },
+               { 0x0420, 0x610bc4 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nv84_disp_mast_mthd_head = {
+       .mthd = 0x0400,
+       .addr = 0x000540,
+       .data = {
+               { 0x0800, 0x610ad8 },
+               { 0x0804, 0x610ad0 },
+               { 0x0808, 0x610a48 },
+               { 0x080c, 0x610a78 },
+               { 0x0810, 0x610ac0 },
+               { 0x0814, 0x610af8 },
+               { 0x0818, 0x610b00 },
+               { 0x081c, 0x610ae8 },
+               { 0x0820, 0x610af0 },
+               { 0x0824, 0x610b08 },
+               { 0x0828, 0x610b10 },
+               { 0x082c, 0x610a68 },
+               { 0x0830, 0x610a60 },
+               { 0x0834, 0x000000 },
+               { 0x0838, 0x610a40 },
+               { 0x0840, 0x610a24 },
+               { 0x0844, 0x610a2c },
+               { 0x0848, 0x610aa8 },
+               { 0x084c, 0x610ab0 },
+               { 0x085c, 0x610c5c },
+               { 0x0860, 0x610a84 },
+               { 0x0864, 0x610a90 },
+               { 0x0868, 0x610b18 },
+               { 0x086c, 0x610b20 },
+               { 0x0870, 0x610ac8 },
+               { 0x0874, 0x610a38 },
+               { 0x0878, 0x610c50 },
+               { 0x0880, 0x610a58 },
+               { 0x0884, 0x610a9c },
+               { 0x089c, 0x610c68 },
+               { 0x08a0, 0x610a70 },
+               { 0x08a4, 0x610a50 },
+               { 0x08a8, 0x610ae0 },
+               { 0x08c0, 0x610b28 },
+               { 0x08c4, 0x610b30 },
+               { 0x08c8, 0x610b40 },
+               { 0x08d4, 0x610b38 },
+               { 0x08d8, 0x610b48 },
+               { 0x08dc, 0x610b50 },
+               { 0x0900, 0x610a18 },
+               { 0x0904, 0x610ab8 },
+               { 0x0910, 0x610c70 },
+               { 0x0914, 0x610c78 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_mast_mthd_chan = {
+       .name = "Core",
+       .addr = 0x000000,
+       .data = {
+               { "Global", 1, &nv50_disp_mast_mthd_base },
+               {    "DAC", 3, &nv84_disp_mast_mthd_dac  },
+               {    "SOR", 2, &nv50_disp_mast_mthd_sor  },
+               {   "PIOR", 3, &nv50_disp_mast_mthd_pior },
+               {   "HEAD", 2, &nv84_disp_mast_mthd_head },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * EVO sync channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nv84_disp_sync_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x0008c4 },
+               { 0x0088, 0x0008d0 },
+               { 0x008c, 0x0008dc },
+               { 0x0090, 0x0008e4 },
+               { 0x0094, 0x610884 },
+               { 0x00a0, 0x6108a0 },
+               { 0x00a4, 0x610878 },
+               { 0x00c0, 0x61086c },
+               { 0x00c4, 0x610800 },
+               { 0x00c8, 0x61080c },
+               { 0x00cc, 0x610818 },
+               { 0x00e0, 0x610858 },
+               { 0x00e4, 0x610860 },
+               { 0x00e8, 0x6108ac },
+               { 0x00ec, 0x6108b4 },
+               { 0x00fc, 0x610824 },
+               { 0x0100, 0x610894 },
+               { 0x0104, 0x61082c },
+               { 0x0110, 0x6108bc },
+               { 0x0114, 0x61088c },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_sync_mthd_chan = {
+       .name = "Base",
+       .addr = 0x000540,
+       .data = {
+               { "Global", 1, &nv84_disp_sync_mthd_base },
+               {  "Image", 2, &nv50_disp_sync_mthd_image },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nv84_disp_ovly_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x6109a0 },
+               { 0x0088, 0x6109c0 },
+               { 0x008c, 0x6109c8 },
+               { 0x0090, 0x6109b4 },
+               { 0x0094, 0x610970 },
+               { 0x00a0, 0x610998 },
+               { 0x00a4, 0x610964 },
+               { 0x00c0, 0x610958 },
+               { 0x00e0, 0x6109a8 },
+               { 0x00e4, 0x6109d0 },
+               { 0x00e8, 0x6109d8 },
+               { 0x0100, 0x61094c },
+               { 0x0104, 0x610984 },
+               { 0x0108, 0x61098c },
+               { 0x0800, 0x6109f8 },
+               { 0x0808, 0x610a08 },
+               { 0x080c, 0x610a10 },
+               { 0x0810, 0x610a00 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_ovly_mthd_chan = {
+       .name = "Overlay",
+       .addr = 0x000540,
+       .data = {
+               { "Global", 1, &nv84_disp_ovly_mthd_base },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nv84_disp_sclass[] = {
        { NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -59,6 +232,10 @@ nv84_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -91,13 +268,17 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nv84_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x82),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv84_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x82),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv84_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nv84_disp_mast_mthd_chan,
+       .mthd.base = &nv84_disp_sync_mthd_chan,
+       .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+       .mthd.prev = 0x000004,
+}.base.base;
index a518543c00ab624f8df1b4fd22e66293943b8f02..6844061c7e0450afc2de82c1d4e6aa111ebab6b5 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+const struct nv50_disp_mthd_list
+nv94_disp_mast_mthd_sor = {
+       .mthd = 0x0040,
+       .addr = 0x000008,
+       .data = {
+               { 0x0600, 0x610794 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nv94_disp_mast_mthd_chan = {
+       .name = "Core",
+       .addr = 0x000000,
+       .data = {
+               { "Global", 1, &nv50_disp_mast_mthd_base },
+               {    "DAC", 3, &nv84_disp_mast_mthd_dac  },
+               {    "SOR", 4, &nv94_disp_mast_mthd_sor  },
+               {   "PIOR", 3, &nv50_disp_mast_mthd_pior },
+               {   "HEAD", 2, &nv84_disp_mast_mthd_head },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nv94_disp_sclass[] = {
        { NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -59,6 +91,10 @@ nv94_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -92,13 +128,17 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nv94_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x88),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv94_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x88),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv94_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nv94_disp_mast_mthd_chan,
+       .mthd.base = &nv84_disp_sync_mthd_chan,
+       .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+       .mthd.prev = 0x000004,
+}.base.base;
index 6cf8eefac3686bbd806225bdd21a1ff9b77ab0d6..88c96241c02a1a2fba69c67c3acadaffb5d498dc 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nva0_disp_ovly_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x000000 },
+               { 0x0084, 0x6109a0 },
+               { 0x0088, 0x6109c0 },
+               { 0x008c, 0x6109c8 },
+               { 0x0090, 0x6109b4 },
+               { 0x0094, 0x610970 },
+               { 0x00a0, 0x610998 },
+               { 0x00a4, 0x610964 },
+               { 0x00b0, 0x610c98 },
+               { 0x00b4, 0x610ca4 },
+               { 0x00b8, 0x610cac },
+               { 0x00c0, 0x610958 },
+               { 0x00e0, 0x6109a8 },
+               { 0x00e4, 0x6109d0 },
+               { 0x00e8, 0x6109d8 },
+               { 0x0100, 0x61094c },
+               { 0x0104, 0x610984 },
+               { 0x0108, 0x61098c },
+               { 0x0800, 0x6109f8 },
+               { 0x0808, 0x610a08 },
+               { 0x080c, 0x610a10 },
+               { 0x0810, 0x610a00 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nva0_disp_ovly_mthd_chan = {
+       .name = "Overlay",
+       .addr = 0x000540,
+       .data = {
+               { "Global", 1, &nva0_disp_ovly_mthd_base },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nva0_disp_sclass[] = {
        { NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -45,6 +94,10 @@ nva0_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +130,17 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nva0_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x83),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nva0_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x83),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nva0_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nv84_disp_mast_mthd_chan,
+       .mthd.base = &nv84_disp_sync_mthd_chan,
+       .mthd.ovly = &nva0_disp_ovly_mthd_chan,
+       .mthd.prev = 0x000004,
+}.base.base;
index 6ad6dcece43bde52062c5c4563662586dfaef7d6..46cb2ce0e82a99a8995a6e24bb33dd3c55284780 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nva3_disp_sclass[] = {
        { NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -60,6 +64,10 @@ nva3_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -94,13 +102,17 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nva3_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x85),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nva3_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x85),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nva3_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nv94_disp_mast_mthd_chan,
+       .mthd.base = &nv84_disp_sync_mthd_chan,
+       .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+       .mthd.prev = 0x000004,
+}.base.base;
index 1c5e4e8b2c822b37a140932d5b5378d5d2deb309..7762665ad8fdb5b461680ee84b7b224b77a5d4d5 100644 (file)
@@ -124,6 +124,146 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
  * EVO master channel object
  ******************************************************************************/
 
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x660080 },
+               { 0x0084, 0x660084 },
+               { 0x0088, 0x660088 },
+               { 0x008c, 0x000000 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_dac = {
+       .mthd = 0x0020,
+       .addr = 0x000020,
+       .data = {
+               { 0x0180, 0x660180 },
+               { 0x0184, 0x660184 },
+               { 0x0188, 0x660188 },
+               { 0x0190, 0x660190 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_sor = {
+       .mthd = 0x0020,
+       .addr = 0x000020,
+       .data = {
+               { 0x0200, 0x660200 },
+               { 0x0204, 0x660204 },
+               { 0x0208, 0x660208 },
+               { 0x0210, 0x660210 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_pior = {
+       .mthd = 0x0020,
+       .addr = 0x000020,
+       .data = {
+               { 0x0300, 0x660300 },
+               { 0x0304, 0x660304 },
+               { 0x0308, 0x660308 },
+               { 0x0310, 0x660310 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_head = {
+       .mthd = 0x0300,
+       .addr = 0x000300,
+       .data = {
+               { 0x0400, 0x660400 },
+               { 0x0404, 0x660404 },
+               { 0x0408, 0x660408 },
+               { 0x040c, 0x66040c },
+               { 0x0410, 0x660410 },
+               { 0x0414, 0x660414 },
+               { 0x0418, 0x660418 },
+               { 0x041c, 0x66041c },
+               { 0x0420, 0x660420 },
+               { 0x0424, 0x660424 },
+               { 0x0428, 0x660428 },
+               { 0x042c, 0x66042c },
+               { 0x0430, 0x660430 },
+               { 0x0434, 0x660434 },
+               { 0x0438, 0x660438 },
+               { 0x0440, 0x660440 },
+               { 0x0444, 0x660444 },
+               { 0x0448, 0x660448 },
+               { 0x044c, 0x66044c },
+               { 0x0450, 0x660450 },
+               { 0x0454, 0x660454 },
+               { 0x0458, 0x660458 },
+               { 0x045c, 0x66045c },
+               { 0x0460, 0x660460 },
+               { 0x0468, 0x660468 },
+               { 0x046c, 0x66046c },
+               { 0x0470, 0x660470 },
+               { 0x0474, 0x660474 },
+               { 0x0480, 0x660480 },
+               { 0x0484, 0x660484 },
+               { 0x048c, 0x66048c },
+               { 0x0490, 0x660490 },
+               { 0x0494, 0x660494 },
+               { 0x0498, 0x660498 },
+               { 0x04b0, 0x6604b0 },
+               { 0x04b8, 0x6604b8 },
+               { 0x04bc, 0x6604bc },
+               { 0x04c0, 0x6604c0 },
+               { 0x04c4, 0x6604c4 },
+               { 0x04c8, 0x6604c8 },
+               { 0x04d0, 0x6604d0 },
+               { 0x04d4, 0x6604d4 },
+               { 0x04e0, 0x6604e0 },
+               { 0x04e4, 0x6604e4 },
+               { 0x04e8, 0x6604e8 },
+               { 0x04ec, 0x6604ec },
+               { 0x04f0, 0x6604f0 },
+               { 0x04f4, 0x6604f4 },
+               { 0x04f8, 0x6604f8 },
+               { 0x04fc, 0x6604fc },
+               { 0x0500, 0x660500 },
+               { 0x0504, 0x660504 },
+               { 0x0508, 0x660508 },
+               { 0x050c, 0x66050c },
+               { 0x0510, 0x660510 },
+               { 0x0514, 0x660514 },
+               { 0x0518, 0x660518 },
+               { 0x051c, 0x66051c },
+               { 0x052c, 0x66052c },
+               { 0x0530, 0x660530 },
+               { 0x054c, 0x66054c },
+               { 0x0550, 0x660550 },
+               { 0x0554, 0x660554 },
+               { 0x0558, 0x660558 },
+               { 0x055c, 0x66055c },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nvd0_disp_mast_mthd_chan = {
+       .name = "Core",
+       .addr = 0x000000,
+       .data = {
+               { "Global", 1, &nvd0_disp_mast_mthd_base },
+               {    "DAC", 3, &nvd0_disp_mast_mthd_dac  },
+               {    "SOR", 8, &nvd0_disp_mast_mthd_sor  },
+               {   "PIOR", 4, &nvd0_disp_mast_mthd_pior },
+               {   "HEAD", 4, &nvd0_disp_mast_mthd_head },
+               {}
+       }
+};
+
 static int
 nvd0_disp_mast_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -216,6 +356,81 @@ nvd0_disp_mast_ofuncs = {
  * EVO sync channel objects
  ******************************************************************************/
 
+static const struct nv50_disp_mthd_list
+nvd0_disp_sync_mthd_base = {
+       .mthd = 0x0000,
+       .addr = 0x000000,
+       .data = {
+               { 0x0080, 0x661080 },
+               { 0x0084, 0x661084 },
+               { 0x0088, 0x661088 },
+               { 0x008c, 0x66108c },
+               { 0x0090, 0x661090 },
+               { 0x0094, 0x661094 },
+               { 0x00a0, 0x6610a0 },
+               { 0x00a4, 0x6610a4 },
+               { 0x00c0, 0x6610c0 },
+               { 0x00c4, 0x6610c4 },
+               { 0x00c8, 0x6610c8 },
+               { 0x00cc, 0x6610cc },
+               { 0x00e0, 0x6610e0 },
+               { 0x00e4, 0x6610e4 },
+               { 0x00e8, 0x6610e8 },
+               { 0x00ec, 0x6610ec },
+               { 0x00fc, 0x6610fc },
+               { 0x0100, 0x661100 },
+               { 0x0104, 0x661104 },
+               { 0x0108, 0x661108 },
+               { 0x010c, 0x66110c },
+               { 0x0110, 0x661110 },
+               { 0x0114, 0x661114 },
+               { 0x0118, 0x661118 },
+               { 0x011c, 0x66111c },
+               { 0x0130, 0x661130 },
+               { 0x0134, 0x661134 },
+               { 0x0138, 0x661138 },
+               { 0x013c, 0x66113c },
+               { 0x0140, 0x661140 },
+               { 0x0144, 0x661144 },
+               { 0x0148, 0x661148 },
+               { 0x014c, 0x66114c },
+               { 0x0150, 0x661150 },
+               { 0x0154, 0x661154 },
+               { 0x0158, 0x661158 },
+               { 0x015c, 0x66115c },
+               { 0x0160, 0x661160 },
+               { 0x0164, 0x661164 },
+               { 0x0168, 0x661168 },
+               { 0x016c, 0x66116c },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_list
+nvd0_disp_sync_mthd_image = {
+       .mthd = 0x0400,
+       .addr = 0x000400,
+       .data = {
+               { 0x0400, 0x661400 },
+               { 0x0404, 0x661404 },
+               { 0x0408, 0x661408 },
+               { 0x040c, 0x66140c },
+               { 0x0410, 0x661410 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nvd0_disp_sync_mthd_chan = {
+       .name = "Base",
+       .addr = 0x001000,
+       .data = {
+               { "Global", 1, &nvd0_disp_sync_mthd_base },
+               {  "Image", 2, &nvd0_disp_sync_mthd_image },
+               {}
+       }
+};
+
 static int
 nvd0_disp_sync_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -256,6 +471,68 @@ nvd0_disp_sync_ofuncs = {
  * EVO overlay channel objects
  ******************************************************************************/
 
+static const struct nv50_disp_mthd_list
+nvd0_disp_ovly_mthd_base = {
+       .mthd = 0x0000,
+       .data = {
+               { 0x0080, 0x665080 },
+               { 0x0084, 0x665084 },
+               { 0x0088, 0x665088 },
+               { 0x008c, 0x66508c },
+               { 0x0090, 0x665090 },
+               { 0x0094, 0x665094 },
+               { 0x00a0, 0x6650a0 },
+               { 0x00a4, 0x6650a4 },
+               { 0x00b0, 0x6650b0 },
+               { 0x00b4, 0x6650b4 },
+               { 0x00b8, 0x6650b8 },
+               { 0x00c0, 0x6650c0 },
+               { 0x00e0, 0x6650e0 },
+               { 0x00e4, 0x6650e4 },
+               { 0x00e8, 0x6650e8 },
+               { 0x0100, 0x665100 },
+               { 0x0104, 0x665104 },
+               { 0x0108, 0x665108 },
+               { 0x010c, 0x66510c },
+               { 0x0110, 0x665110 },
+               { 0x0118, 0x665118 },
+               { 0x011c, 0x66511c },
+               { 0x0120, 0x665120 },
+               { 0x0124, 0x665124 },
+               { 0x0130, 0x665130 },
+               { 0x0134, 0x665134 },
+               { 0x0138, 0x665138 },
+               { 0x013c, 0x66513c },
+               { 0x0140, 0x665140 },
+               { 0x0144, 0x665144 },
+               { 0x0148, 0x665148 },
+               { 0x014c, 0x66514c },
+               { 0x0150, 0x665150 },
+               { 0x0154, 0x665154 },
+               { 0x0158, 0x665158 },
+               { 0x015c, 0x66515c },
+               { 0x0160, 0x665160 },
+               { 0x0164, 0x665164 },
+               { 0x0168, 0x665168 },
+               { 0x016c, 0x66516c },
+               { 0x0400, 0x665400 },
+               { 0x0408, 0x665408 },
+               { 0x040c, 0x66540c },
+               { 0x0410, 0x665410 },
+               {}
+       }
+};
+
+static const struct nv50_disp_mthd_chan
+nvd0_disp_ovly_mthd_chan = {
+       .name = "Overlay",
+       .addr = 0x001000,
+       .data = {
+               { "Global", 1, &nvd0_disp_ovly_mthd_base },
+               {}
+       }
+};
+
 static int
 nvd0_disp_ovly_ctor(struct nouveau_object *parent,
                    struct nouveau_object *engine,
@@ -897,19 +1174,22 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
 {
        struct nv50_disp_priv *priv =
                container_of(work, struct nv50_disp_priv, supervisor);
+       struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
        u32 mask[4];
        int head;
 
-       nv_debug(priv, "supervisor %08x\n", priv->super);
+       nv_debug(priv, "supervisor %d\n", ffs(priv->super));
        for (head = 0; head < priv->head.nr; head++) {
                mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800));
                nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]);
        }
 
        if (priv->super & 0x00000001) {
+               nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(mask[head] & 0x00001000))
                                continue;
+                       nv_debug(priv, "supervisor 1.0 - head %d\n", head);
                        nvd0_disp_intr_unk1_0(priv, head);
                }
        } else
@@ -917,16 +1197,19 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(mask[head] & 0x00001000))
                                continue;
+                       nv_debug(priv, "supervisor 2.0 - head %d\n", head);
                        nvd0_disp_intr_unk2_0(priv, head);
                }
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(mask[head] & 0x00010000))
                                continue;
+                       nv_debug(priv, "supervisor 2.1 - head %d\n", head);
                        nvd0_disp_intr_unk2_1(priv, head);
                }
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(mask[head] & 0x00001000))
                                continue;
+                       nv_debug(priv, "supervisor 2.2 - head %d\n", head);
                        nvd0_disp_intr_unk2_2(priv, head);
                }
        } else
@@ -934,6 +1217,7 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
                for (head = 0; head < priv->head.nr; head++) {
                        if (!(mask[head] & 0x00001000))
                                continue;
+                       nv_debug(priv, "supervisor 3.0 - head %d\n", head);
                        nvd0_disp_intr_unk4_0(priv, head);
                }
        }
@@ -943,6 +1227,53 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
        nv_wr32(priv, 0x6101d0, 0x80000000);
 }
 
+static void
+nvd0_disp_intr_error(struct nv50_disp_priv *priv, int chid)
+{
+       const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+       u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
+       u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
+       u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
+
+       nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
+                      "0x%08x 0x%08x\n",
+                chid, (mthd & 0x0000ffc), data, mthd, unkn);
+
+       if (chid == 0) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+                                           impl->mthd.core);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 4) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+                                           impl->mthd.base);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 8) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5,
+                                           impl->mthd.ovly);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       nv_wr32(priv, 0x61009c, (1 << chid));
+       nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
+}
+
 void
 nvd0_disp_intr(struct nouveau_subdev *subdev)
 {
@@ -959,18 +1290,8 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
        if (intr & 0x00000002) {
                u32 stat = nv_rd32(priv, 0x61009c);
                int chid = ffs(stat) - 1;
-               if (chid >= 0) {
-                       u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
-                       u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
-                       u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
-
-                       nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
-                                      "0x%08x 0x%08x\n",
-                                chid, (mthd & 0x0000ffc), data, mthd, unkn);
-                       nv_wr32(priv, 0x61009c, (1 << chid));
-                       nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
-               }
-
+               if (chid >= 0)
+                       nvd0_disp_intr_error(priv, chid);
                intr &= ~0x00000002;
        }
 
@@ -1035,13 +1356,17 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nvd0_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x90),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvd0_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x90),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvd0_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nvd0_disp_mast_mthd_chan,
+       .mthd.base = &nvd0_disp_sync_mthd_chan,
+       .mthd.ovly = &nvd0_disp_ovly_mthd_chan,
+       .mthd.prev = -0x020000,
+}.base.base;
index ab63f32c00b2478d2cb0a2ebd062f946d394044d..44e0b8f34c1a8fc8d15fa019598be533e87df713 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nve0_disp_mast_mthd_head = {
+       .mthd = 0x0300,
+       .addr = 0x000300,
+       .data = {
+               { 0x0400, 0x660400 },
+               { 0x0404, 0x660404 },
+               { 0x0408, 0x660408 },
+               { 0x040c, 0x66040c },
+               { 0x0410, 0x660410 },
+               { 0x0414, 0x660414 },
+               { 0x0418, 0x660418 },
+               { 0x041c, 0x66041c },
+               { 0x0420, 0x660420 },
+               { 0x0424, 0x660424 },
+               { 0x0428, 0x660428 },
+               { 0x042c, 0x66042c },
+               { 0x0430, 0x660430 },
+               { 0x0434, 0x660434 },
+               { 0x0438, 0x660438 },
+               { 0x0440, 0x660440 },
+               { 0x0444, 0x660444 },
+               { 0x0448, 0x660448 },
+               { 0x044c, 0x66044c },
+               { 0x0450, 0x660450 },
+               { 0x0454, 0x660454 },
+               { 0x0458, 0x660458 },
+               { 0x045c, 0x66045c },
+               { 0x0460, 0x660460 },
+               { 0x0468, 0x660468 },
+               { 0x046c, 0x66046c },
+               { 0x0470, 0x660470 },
+               { 0x0474, 0x660474 },
+               { 0x047c, 0x66047c },
+               { 0x0480, 0x660480 },
+               { 0x0484, 0x660484 },
+               { 0x0488, 0x660488 },
+               { 0x048c, 0x66048c },
+               { 0x0490, 0x660490 },
+               { 0x0494, 0x660494 },
+               { 0x0498, 0x660498 },
+               { 0x04a0, 0x6604a0 },
+               { 0x04b0, 0x6604b0 },
+               { 0x04b8, 0x6604b8 },
+               { 0x04bc, 0x6604bc },
+               { 0x04c0, 0x6604c0 },
+               { 0x04c4, 0x6604c4 },
+               { 0x04c8, 0x6604c8 },
+               { 0x04d0, 0x6604d0 },
+               { 0x04d4, 0x6604d4 },
+               { 0x04e0, 0x6604e0 },
+               { 0x04e4, 0x6604e4 },
+               { 0x04e8, 0x6604e8 },
+               { 0x04ec, 0x6604ec },
+               { 0x04f0, 0x6604f0 },
+               { 0x04f4, 0x6604f4 },
+               { 0x04f8, 0x6604f8 },
+               { 0x04fc, 0x6604fc },
+               { 0x0500, 0x660500 },
+               { 0x0504, 0x660504 },
+               { 0x0508, 0x660508 },
+               { 0x050c, 0x66050c },
+               { 0x0510, 0x660510 },
+               { 0x0514, 0x660514 },
+               { 0x0518, 0x660518 },
+               { 0x051c, 0x66051c },
+               { 0x0520, 0x660520 },
+               { 0x0524, 0x660524 },
+               { 0x052c, 0x66052c },
+               { 0x0530, 0x660530 },
+               { 0x054c, 0x66054c },
+               { 0x0550, 0x660550 },
+               { 0x0554, 0x660554 },
+               { 0x0558, 0x660558 },
+               { 0x055c, 0x66055c },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nve0_disp_mast_mthd_chan = {
+       .name = "Core",
+       .addr = 0x000000,
+       .data = {
+               { "Global", 1, &nvd0_disp_mast_mthd_base },
+               {    "DAC", 3, &nvd0_disp_mast_mthd_dac  },
+               {    "SOR", 8, &nvd0_disp_mast_mthd_sor  },
+               {   "PIOR", 4, &nvd0_disp_mast_mthd_pior },
+               {   "HEAD", 4, &nve0_disp_mast_mthd_head },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nve0_disp_ovly_mthd_base = {
+       .mthd = 0x0000,
+       .data = {
+               { 0x0080, 0x665080 },
+               { 0x0084, 0x665084 },
+               { 0x0088, 0x665088 },
+               { 0x008c, 0x66508c },
+               { 0x0090, 0x665090 },
+               { 0x0094, 0x665094 },
+               { 0x00a0, 0x6650a0 },
+               { 0x00a4, 0x6650a4 },
+               { 0x00b0, 0x6650b0 },
+               { 0x00b4, 0x6650b4 },
+               { 0x00b8, 0x6650b8 },
+               { 0x00c0, 0x6650c0 },
+               { 0x00c4, 0x6650c4 },
+               { 0x00e0, 0x6650e0 },
+               { 0x00e4, 0x6650e4 },
+               { 0x00e8, 0x6650e8 },
+               { 0x0100, 0x665100 },
+               { 0x0104, 0x665104 },
+               { 0x0108, 0x665108 },
+               { 0x010c, 0x66510c },
+               { 0x0110, 0x665110 },
+               { 0x0118, 0x665118 },
+               { 0x011c, 0x66511c },
+               { 0x0120, 0x665120 },
+               { 0x0124, 0x665124 },
+               { 0x0130, 0x665130 },
+               { 0x0134, 0x665134 },
+               { 0x0138, 0x665138 },
+               { 0x013c, 0x66513c },
+               { 0x0140, 0x665140 },
+               { 0x0144, 0x665144 },
+               { 0x0148, 0x665148 },
+               { 0x014c, 0x66514c },
+               { 0x0150, 0x665150 },
+               { 0x0154, 0x665154 },
+               { 0x0158, 0x665158 },
+               { 0x015c, 0x66515c },
+               { 0x0160, 0x665160 },
+               { 0x0164, 0x665164 },
+               { 0x0168, 0x665168 },
+               { 0x016c, 0x66516c },
+               { 0x0400, 0x665400 },
+               { 0x0404, 0x665404 },
+               { 0x0408, 0x665408 },
+               { 0x040c, 0x66540c },
+               { 0x0410, 0x665410 },
+               {}
+       }
+};
+
+const struct nv50_disp_mthd_chan
+nve0_disp_ovly_mthd_chan = {
+       .name = "Overlay",
+       .addr = 0x001000,
+       .data = {
+               { "Global", 1, &nve0_disp_ovly_mthd_base },
+               {}
+       }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nve0_disp_sclass[] = {
        { NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
@@ -45,6 +214,10 @@ nve0_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +250,17 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nve0_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x91),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nve0_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x91),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nve0_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nve0_disp_mast_mthd_chan,
+       .mthd.base = &nvd0_disp_sync_mthd_chan,
+       .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+       .mthd.prev = -0x020000,
+}.base.base;
index 05fee10e0c975a166fec5b68d98d6e53cd1fae55..482585d375fa564ec2ff4e1bcbb7b87e2b15efe8 100644 (file)
 
 #include "nv50.h"
 
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
 static struct nouveau_oclass
 nvf0_disp_sclass[] = {
        { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
@@ -45,6 +49,10 @@ nvf0_disp_base_oclass[] = {
        {}
 };
 
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
 static int
 nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
               struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,13 +85,17 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nouveau_oclass
-nvf0_disp_oclass = {
-       .handle = NV_ENGINE(DISP, 0x92),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvf0_disp_oclass = &(struct nv50_disp_impl) {
+       .base.base.handle = NV_ENGINE(DISP, 0x92),
+       .base.base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvf0_disp_ctor,
                .dtor = _nouveau_disp_dtor,
                .init = _nouveau_disp_init,
                .fini = _nouveau_disp_fini,
        },
-};
+       .mthd.core = &nve0_disp_mast_mthd_chan,
+       .mthd.base = &nvd0_disp_sync_mthd_chan,
+       .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+       .mthd.prev = -0x020000,
+}.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 (file)
index 0000000..cc3c7a4
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __NVKM_DISP_PRIV_H__
+#define __NVKM_DISP_PRIV_H__
+
+#include <engine/disp.h>
+
+struct nouveau_disp_impl {
+       struct nouveau_oclass base;
+};
+
+#endif
index 944e73ac485cf7d9e058af20554ec51d1dfd7f96..1cfb3bb9013154ebdd9189ea85b635023d84cd8f 100644 (file)
@@ -53,6 +53,9 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
                case NVF0_DISP_MAST_CLASS:
                case NVF0_DISP_SYNC_CLASS:
                case NVF0_DISP_OVLY_CLASS:
+               case GM107_DISP_MAST_CLASS:
+               case GM107_DISP_SYNC_CLASS:
+               case GM107_DISP_OVLY_CLASS:
                        break;
                default:
                        return -EINVAL;
index 5e077e4ed7f6aa23d0e8ed3fde50ad58c2fd99d7..2914646c87094868e41e9ee38db9e2eb881f20b8 100644 (file)
@@ -119,7 +119,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x",
                         device->chipset, falcon->addr >> 12);
 
-               ret = request_firmware(&fw, name, &device->pdev->dev);
+               ret = request_firmware(&fw, name, nv_device_base(device));
                if (ret == 0) {
                        falcon->code.data = vmemdup(fw->data, fw->size);
                        falcon->code.size = fw->size;
@@ -138,7 +138,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd",
                         device->chipset, falcon->addr >> 12);
 
-               ret = request_firmware(&fw, name, &device->pdev->dev);
+               ret = request_firmware(&fw, name, nv_device_base(device));
                if (ret) {
                        nv_error(falcon, "unable to load firmware data\n");
                        return ret;
@@ -153,7 +153,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc",
                         device->chipset, falcon->addr >> 12);
 
-               ret = request_firmware(&fw, name, &device->pdev->dev);
+               ret = request_firmware(&fw, name, nv_device_base(device));
                if (ret) {
                        nv_error(falcon, "unable to load firmware code\n");
                        return ret;
index d3ec436d9cb5f249eff5e7146f842d325980ff8e..6f9041ced9a2b131ad0e571091b4383757b3e085 100644 (file)
@@ -86,7 +86,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
        }
 
        /* map fifo control registers */
-       chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr +
+       chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
                             (chan->chid * size), size);
        if (!chan->user)
                return -EFAULT;
index b22a33f0702dd0159ed01f79edb00b7349f6b561..fa1e719872b769c79a959efc7b6a62321ebad552 100644 (file)
 
 struct nvc0_fifo_priv {
        struct nouveau_fifo base;
-       struct nouveau_gpuobj *playlist[2];
-       int cur_playlist;
+
+       struct work_struct fault;
+       u64 mask;
+
+       struct {
+               struct nouveau_gpuobj *mem[2];
+               int active;
+               wait_queue_head_t wait;
+       } runlist;
+
        struct {
                struct nouveau_gpuobj *mem;
                struct nouveau_vma bar;
@@ -58,6 +66,11 @@ struct nvc0_fifo_base {
 
 struct nvc0_fifo_chan {
        struct nouveau_fifo_chan base;
+       enum {
+               STOPPED,
+               RUNNING,
+               KILLED
+       } state;
 };
 
 /*******************************************************************************
@@ -65,29 +78,33 @@ struct nvc0_fifo_chan {
  ******************************************************************************/
 
 static void
-nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
+nvc0_fifo_runlist_update(struct nvc0_fifo_priv *priv)
 {
        struct nouveau_bar *bar = nouveau_bar(priv);
        struct nouveau_gpuobj *cur;
        int i, p;
 
        mutex_lock(&nv_subdev(priv)->mutex);
-       cur = priv->playlist[priv->cur_playlist];
-       priv->cur_playlist = !priv->cur_playlist;
+       cur = priv->runlist.mem[priv->runlist.active];
+       priv->runlist.active = !priv->runlist.active;
 
        for (i = 0, p = 0; i < 128; i++) {
-               if (!(nv_rd32(priv, 0x003004 + (i * 8)) & 1))
-                       continue;
-               nv_wo32(cur, p + 0, i);
-               nv_wo32(cur, p + 4, 0x00000004);
-               p += 8;
+               struct nvc0_fifo_chan *chan = (void *)priv->base.channel[i];
+               if (chan && chan->state == RUNNING) {
+                       nv_wo32(cur, p + 0, i);
+                       nv_wo32(cur, p + 4, 0x00000004);
+                       p += 8;
+               }
        }
        bar->flush(bar);
 
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3));
-       if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000))
-               nv_error(priv, "playlist update failed\n");
+
+       if (wait_event_timeout(priv->runlist.wait,
+                              !(nv_rd32(priv, 0x00227c) & 0x00100000),
+                              msecs_to_jiffies(2000)) == 0)
+               nv_error(priv, "runlist update timeout\n");
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
@@ -239,30 +256,32 @@ nvc0_fifo_chan_init(struct nouveau_object *object)
                return ret;
 
        nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12);
-       nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001);
-       nvc0_fifo_playlist_update(priv);
+
+       if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
+               nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001);
+               nvc0_fifo_runlist_update(priv);
+       }
+
        return 0;
 }
 
+static void nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv);
+
 static int
 nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
 {
        struct nvc0_fifo_priv *priv = (void *)object->engine;
        struct nvc0_fifo_chan *chan = (void *)object;
        u32 chid = chan->base.chid;
-       u32 mask, engine;
 
-       nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
-       nvc0_fifo_playlist_update(priv);
-       mask = nv_rd32(priv, 0x0025a4);
-       for (engine = 0; mask && engine < 16; engine++) {
-               if (!(mask & (1 << engine)))
-                       continue;
-               nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000);
-               mask &= ~(1 << engine);
+       if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
+               nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
+               nvc0_fifo_runlist_update(priv);
        }
-       nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
 
+       nvc0_fifo_intr_engine(priv);
+
+       nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
        return nouveau_fifo_channel_fini(&chan->base, suspend);
 }
 
@@ -345,11 +364,177 @@ nvc0_fifo_cclass = {
  * PFIFO engine
  ******************************************************************************/
 
-static const struct nouveau_enum nvc0_fifo_fault_unit[] = {
+static inline int
+nvc0_fifo_engidx(struct nvc0_fifo_priv *priv, u32 engn)
+{
+       switch (engn) {
+       case NVDEV_ENGINE_GR   : engn = 0; break;
+       case NVDEV_ENGINE_BSP  : engn = 1; break;
+       case NVDEV_ENGINE_PPP  : engn = 2; break;
+       case NVDEV_ENGINE_VP   : engn = 3; break;
+       case NVDEV_ENGINE_COPY0: engn = 4; break;
+       case NVDEV_ENGINE_COPY1: engn = 5; break;
+       default:
+               return -1;
+       }
+
+       return engn;
+}
+
+static inline struct nouveau_engine *
+nvc0_fifo_engine(struct nvc0_fifo_priv *priv, u32 engn)
+{
+       switch (engn) {
+       case 0: engn = NVDEV_ENGINE_GR; break;
+       case 1: engn = NVDEV_ENGINE_BSP; break;
+       case 2: engn = NVDEV_ENGINE_PPP; break;
+       case 3: engn = NVDEV_ENGINE_VP; break;
+       case 4: engn = NVDEV_ENGINE_COPY0; break;
+       case 5: engn = NVDEV_ENGINE_COPY1; break;
+       default:
+               return NULL;
+       }
+
+       return nouveau_engine(priv, engn);
+}
+
+static void
+nvc0_fifo_recover_work(struct work_struct *work)
+{
+       struct nvc0_fifo_priv *priv = container_of(work, typeof(*priv), fault);
+       struct nouveau_object *engine;
+       unsigned long flags;
+       u32 engn, engm = 0;
+       u64 mask, todo;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       mask = priv->mask;
+       priv->mask = 0ULL;
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+
+       for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
+               engm |= 1 << nvc0_fifo_engidx(priv, engn);
+       nv_mask(priv, 0x002630, engm, engm);
+
+       for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
+               if ((engine = (void *)nouveau_engine(priv, engn))) {
+                       nv_ofuncs(engine)->fini(engine, false);
+                       WARN_ON(nv_ofuncs(engine)->init(engine));
+               }
+       }
+
+       nvc0_fifo_runlist_update(priv);
+       nv_wr32(priv, 0x00262c, engm);
+       nv_mask(priv, 0x002630, engm, 0x00000000);
+}
+
+static void
+nvc0_fifo_recover(struct nvc0_fifo_priv *priv, struct nouveau_engine *engine,
+                 struct nvc0_fifo_chan *chan)
+{
+       struct nouveau_object *engobj = nv_object(engine);
+       u32 chid = chan->base.chid;
+       unsigned long flags;
+
+       nv_error(priv, "%s engine fault on channel %d, recovering...\n",
+                      nv_subdev(engine)->name, chid);
+
+       nv_mask(priv, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
+       chan->state = KILLED;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       priv->mask |= 1ULL << nv_engidx(engobj);
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+       schedule_work(&priv->fault);
+}
+
+static int
+nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
+{
+       struct nvc0_fifo_chan *chan = NULL;
+       struct nouveau_handle *bind;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       if (likely(chid >= priv->base.min && chid <= priv->base.max))
+               chan = (void *)priv->base.channel[chid];
+       if (unlikely(!chan))
+               goto out;
+
+       bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
+       if (likely(bind)) {
+               if (!mthd || !nv_call(bind->object, mthd, data))
+                       ret = 0;
+               nouveau_namedb_put(bind);
+       }
+
+out:
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+       return ret;
+}
+
+static const struct nouveau_enum
+nvc0_fifo_sched_reason[] = {
+       { 0x0a, "CTXSW_TIMEOUT" },
+       {}
+};
+
+static void
+nvc0_fifo_intr_sched_ctxsw(struct nvc0_fifo_priv *priv)
+{
+       struct nouveau_engine *engine;
+       struct nvc0_fifo_chan *chan;
+       u32 engn;
+
+       for (engn = 0; engn < 6; engn++) {
+               u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04));
+               u32 busy = (stat & 0x80000000);
+               u32 save = (stat & 0x00100000); /* maybe? */
+               u32 unk0 = (stat & 0x00040000);
+               u32 unk1 = (stat & 0x00001000);
+               u32 chid = (stat & 0x0000007f);
+               (void)save;
+
+               if (busy && unk0 && unk1) {
+                       if (!(chan = (void *)priv->base.channel[chid]))
+                               continue;
+                       if (!(engine = nvc0_fifo_engine(priv, engn)))
+                               continue;
+                       nvc0_fifo_recover(priv, engine, chan);
+               }
+       }
+}
+
+static void
+nvc0_fifo_intr_sched(struct nvc0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x00254c);
+       u32 code = intr & 0x000000ff;
+       const struct nouveau_enum *en;
+       char enunk[6] = "";
+
+       en = nouveau_enum_find(nvc0_fifo_sched_reason, code);
+       if (!en)
+               snprintf(enunk, sizeof(enunk), "UNK%02x", code);
+
+       nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk);
+
+       switch (code) {
+       case 0x0a:
+               nvc0_fifo_intr_sched_ctxsw(priv);
+               break;
+       default:
+               break;
+       }
+}
+
+static const struct nouveau_enum
+nvc0_fifo_fault_engine[] = {
        { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR },
-       { 0x03, "PEEPHOLE" },
-       { 0x04, "BAR1" },
-       { 0x05, "BAR3" },
+       { 0x03, "PEEPHOLE", NULL, NVDEV_ENGINE_IFB },
+       { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
+       { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
        { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO },
        { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP },
        { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP },
@@ -361,7 +546,8 @@ static const struct nouveau_enum nvc0_fifo_fault_unit[] = {
        {}
 };
 
-static const struct nouveau_enum nvc0_fifo_fault_reason[] = {
+static const struct nouveau_enum
+nvc0_fifo_fault_reason[] = {
        { 0x00, "PT_NOT_PRESENT" },
        { 0x01, "PT_TOO_SHORT" },
        { 0x02, "PAGE_NOT_PRESENT" },
@@ -374,7 +560,8 @@ static const struct nouveau_enum nvc0_fifo_fault_reason[] = {
        {}
 };
 
-static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
+static const struct nouveau_enum
+nvc0_fifo_fault_hubclient[] = {
        { 0x01, "PCOPY0" },
        { 0x02, "PCOPY1" },
        { 0x04, "DISPATCH" },
@@ -392,7 +579,8 @@ static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
        {}
 };
 
-static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
+static const struct nouveau_enum
+nvc0_fifo_fault_gpcclient[] = {
        { 0x01, "TEX" },
        { 0x0c, "ESETUP" },
        { 0x0e, "CTXCTL" },
@@ -400,92 +588,92 @@ static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
        {}
 };
 
-static const struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = {
-/*     { 0x00008000, "" }      seen with null ib push */
-       { 0x00200000, "ILLEGAL_MTHD" },
-       { 0x00800000, "EMPTY_SUBC" },
-       {}
-};
-
 static void
-nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit)
+nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)
 {
        u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10));
        u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10));
        u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));
        u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10));
+       u32 gpc    = (stat & 0x1f000000) >> 24;
        u32 client = (stat & 0x00001f00) >> 8;
-       const struct nouveau_enum *en;
-       struct nouveau_engine *engine;
-       struct nouveau_object *engctx = NULL;
-
-       switch (unit) {
-       case 3: /* PEEPHOLE */
-               nv_mask(priv, 0x001718, 0x00000000, 0x00000000);
-               break;
-       case 4: /* BAR1 */
-               nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
-               break;
-       case 5: /* BAR3 */
-               nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
-               break;
-       default:
-               break;
+       u32 write  = (stat & 0x00000080);
+       u32 hub    = (stat & 0x00000040);
+       u32 reason = (stat & 0x0000000f);
+       struct nouveau_object *engctx = NULL, *object;
+       struct nouveau_engine *engine = NULL;
+       const struct nouveau_enum *er, *eu, *ec;
+       char erunk[6] = "";
+       char euunk[6] = "";
+       char ecunk[6] = "";
+       char gpcid[3] = "";
+
+       er = nouveau_enum_find(nvc0_fifo_fault_reason, reason);
+       if (!er)
+               snprintf(erunk, sizeof(erunk), "UNK%02X", reason);
+
+       eu = nouveau_enum_find(nvc0_fifo_fault_engine, unit);
+       if (eu) {
+               switch (eu->data2) {
+               case NVDEV_SUBDEV_BAR:
+                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+                       break;
+               case NVDEV_SUBDEV_INSTMEM:
+                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+                       break;
+               case NVDEV_ENGINE_IFB:
+                       nv_mask(priv, 0x001718, 0x00000000, 0x00000000);
+                       break;
+               default:
+                       engine = nouveau_engine(priv, eu->data2);
+                       if (engine)
+                               engctx = nouveau_engctx_get(engine, inst);
+                       break;
+               }
+       } else {
+               snprintf(euunk, sizeof(euunk), "UNK%02x", unit);
        }
 
-       nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ?
-                "write" : "read", (u64)vahi << 32 | valo);
-       nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
-       pr_cont("] from ");
-       en = nouveau_enum_print(nvc0_fifo_fault_unit, unit);
-       if (stat & 0x00000040) {
-               pr_cont("/");
-               nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
+       if (hub) {
+               ec = nouveau_enum_find(nvc0_fifo_fault_hubclient, client);
        } else {
-               pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24);
-               nouveau_enum_print(nvc0_fifo_fault_gpcclient, client);
+               ec = nouveau_enum_find(nvc0_fifo_fault_gpcclient, client);
+               snprintf(gpcid, sizeof(gpcid), "%d", gpc);
        }
 
-       if (en && en->data2) {
-               engine = nouveau_engine(priv, en->data2);
-               if (engine)
-                       engctx = nouveau_engctx_get(engine, inst);
-
+       if (!ec)
+               snprintf(ecunk, sizeof(ecunk), "UNK%02x", client);
+
+       nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on "
+                      "channel 0x%010llx [%s]\n", write ? "write" : "read",
+                (u64)vahi << 32 | valo, er ? er->name : erunk,
+                eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/",
+                ec ? ec->name : ecunk, (u64)inst << 12,
+                nouveau_client_name(engctx));
+
+       object = engctx;
+       while (object) {
+               switch (nv_mclass(object)) {
+               case NVC0_CHANNEL_IND_CLASS:
+                       nvc0_fifo_recover(priv, engine, (void *)object);
+                       break;
+               }
+               object = object->parent;
        }
-       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
-                       nouveau_client_name(engctx));
 
        nouveau_engctx_put(engctx);
 }
 
-static int
-nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
-{
-       struct nvc0_fifo_chan *chan = NULL;
-       struct nouveau_handle *bind;
-       unsigned long flags;
-       int ret = -EINVAL;
-
-       spin_lock_irqsave(&priv->base.lock, flags);
-       if (likely(chid >= priv->base.min && chid <= priv->base.max))
-               chan = (void *)priv->base.channel[chid];
-       if (unlikely(!chan))
-               goto out;
-
-       bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
-       if (likely(bind)) {
-               if (!mthd || !nv_call(bind->object, mthd, data))
-                       ret = 0;
-               nouveau_namedb_put(bind);
-       }
-
-out:
-       spin_unlock_irqrestore(&priv->base.lock, flags);
-       return ret;
-}
+static const struct nouveau_bitfield
+nvc0_fifo_pbdma_intr[] = {
+/*     { 0x00008000, "" }      seen with null ib push */
+       { 0x00200000, "ILLEGAL_MTHD" },
+       { 0x00800000, "EMPTY_SUBC" },
+       {}
+};
 
 static void
-nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
+nvc0_fifo_intr_pbdma(struct nvc0_fifo_priv *priv, int unit)
 {
        u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
        u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -501,11 +689,11 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
        }
 
        if (show) {
-               nv_error(priv, "SUBFIFO%d:", unit);
-               nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show);
+               nv_error(priv, "PBDMA%d:", unit);
+               nouveau_bitfield_print(nvc0_fifo_pbdma_intr, show);
                pr_cont("\n");
                nv_error(priv,
-                        "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
+                        "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
                         unit, chid,
                         nouveau_client_name_for_fifo_chid(&priv->base, chid),
                         subc, mthd, data);
@@ -515,6 +703,56 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
        nv_wr32(priv, 0x040108 + (unit * 0x2000), stat);
 }
 
+static void
+nvc0_fifo_intr_runlist(struct nvc0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x002a00);
+
+       if (intr & 0x10000000) {
+               wake_up(&priv->runlist.wait);
+               nv_wr32(priv, 0x002a00, 0x10000000);
+               intr &= ~0x10000000;
+       }
+
+       if (intr) {
+               nv_error(priv, "RUNLIST 0x%08x\n", intr);
+               nv_wr32(priv, 0x002a00, intr);
+       }
+}
+
+static void
+nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
+{
+       u32 intr = nv_rd32(priv, 0x0025a8 + (engn * 0x04));
+       u32 inte = nv_rd32(priv, 0x002628);
+       u32 unkn;
+
+       for (unkn = 0; unkn < 8; unkn++) {
+               u32 ints = (intr >> (unkn * 0x04)) & inte;
+               if (ints & 0x1) {
+                       nouveau_event_trigger(priv->base.uevent, 0);
+                       ints &= ~1;
+               }
+               if (ints) {
+                       nv_error(priv, "ENGINE %d %d %01x", engn, unkn, ints);
+                       nv_mask(priv, 0x002628, ints, 0);
+               }
+       }
+
+       nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
+}
+
+static void
+nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv)
+{
+       u32 mask = nv_rd32(priv, 0x0025a4);
+       while (mask) {
+               u32 unit = __ffs(mask);
+               nvc0_fifo_intr_engine_unit(priv, unit);
+               mask &= ~(1 << unit);
+       }
+}
+
 static void
 nvc0_fifo_intr(struct nouveau_subdev *subdev)
 {
@@ -530,8 +768,7 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x00000100) {
-               u32 intr = nv_rd32(priv, 0x00254c);
-               nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr);
+               nvc0_fifo_intr_sched(priv);
                nv_wr32(priv, 0x002100, 0x00000100);
                stat &= ~0x00000100;
        }
@@ -551,52 +788,41 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x10000000) {
-               u32 units = nv_rd32(priv, 0x00259c);
-               u32 u = units;
-
-               while (u) {
-                       int i = ffs(u) - 1;
-                       nvc0_fifo_isr_vm_fault(priv, i);
-                       u &= ~(1 << i);
+               u32 mask = nv_rd32(priv, 0x00259c);
+               while (mask) {
+                       u32 unit = __ffs(mask);
+                       nvc0_fifo_intr_fault(priv, unit);
+                       nv_wr32(priv, 0x00259c, (1 << unit));
+                       mask &= ~(1 << unit);
                }
-
-               nv_wr32(priv, 0x00259c, units);
                stat &= ~0x10000000;
        }
 
        if (stat & 0x20000000) {
-               u32 units = nv_rd32(priv, 0x0025a0);
-               u32 u = units;
-
-               while (u) {
-                       int i = ffs(u) - 1;
-                       nvc0_fifo_isr_subfifo_intr(priv, i);
-                       u &= ~(1 << i);
+               u32 mask = nv_rd32(priv, 0x0025a0);
+               while (mask) {
+                       u32 unit = __ffs(mask);
+                       nvc0_fifo_intr_pbdma(priv, unit);
+                       nv_wr32(priv, 0x0025a0, (1 << unit));
+                       mask &= ~(1 << unit);
                }
-
-               nv_wr32(priv, 0x0025a0, units);
                stat &= ~0x20000000;
        }
 
        if (stat & 0x40000000) {
-               u32 intr0 = nv_rd32(priv, 0x0025a4);
-               u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000);
-               nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n",
-                              intr0, intr1);
+               nvc0_fifo_intr_runlist(priv);
                stat &= ~0x40000000;
        }
 
        if (stat & 0x80000000) {
-               u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000);
-               nouveau_event_trigger(priv->base.uevent, 0);
-               nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr);
+               nvc0_fifo_intr_engine(priv);
                stat &= ~0x80000000;
        }
 
        if (stat) {
-               nv_fatal(priv, "unhandled status 0x%08x\n", stat);
+               nv_error(priv, "INTR 0x%08x\n", stat);
+               nv_mask(priv, 0x002140, stat, 0x00000000);
                nv_wr32(priv, 0x002100, stat);
-               nv_wr32(priv, 0x002140, 0);
        }
 }
 
@@ -627,16 +853,20 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       INIT_WORK(&priv->fault, nvc0_fifo_recover_work);
+
        ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
-                               &priv->playlist[0]);
+                               &priv->runlist.mem[0]);
        if (ret)
                return ret;
 
        ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
-                               &priv->playlist[1]);
+                               &priv->runlist.mem[1]);
        if (ret)
                return ret;
 
+       init_waitqueue_head(&priv->runlist.wait);
+
        ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0,
                                &priv->user.mem);
        if (ret)
@@ -665,8 +895,8 @@ nvc0_fifo_dtor(struct nouveau_object *object)
 
        nouveau_gpuobj_unmap(&priv->user.bar);
        nouveau_gpuobj_ref(NULL, &priv->user.mem);
-       nouveau_gpuobj_ref(NULL, &priv->playlist[1]);
-       nouveau_gpuobj_ref(NULL, &priv->playlist[0]);
+       nouveau_gpuobj_ref(NULL, &priv->runlist.mem[0]);
+       nouveau_gpuobj_ref(NULL, &priv->runlist.mem[1]);
 
        nouveau_fifo_destroy(&priv->base);
 }
@@ -685,9 +915,9 @@ nvc0_fifo_init(struct nouveau_object *object)
        nv_wr32(priv, 0x002204, 0xffffffff);
 
        priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204));
-       nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr);
+       nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr);
 
-       /* assign engines to subfifos */
+       /* assign engines to PBDMAs */
        if (priv->spoon_nr >= 3) {
                nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */
                nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */
@@ -697,7 +927,7 @@ nvc0_fifo_init(struct nouveau_object *object)
                nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */
        }
 
-       /* PSUBFIFO[n] */
+       /* PBDMA[n] */
        for (i = 0; i < priv->spoon_nr; i++) {
                nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
                nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
@@ -707,10 +937,9 @@ nvc0_fifo_init(struct nouveau_object *object)
        nv_mask(priv, 0x002200, 0x00000001, 0x00000001);
        nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
 
-       nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
        nv_wr32(priv, 0x002100, 0xffffffff);
-       nv_wr32(priv, 0x002140, 0x3fffffff);
-       nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */
+       nv_wr32(priv, 0x002140, 0x7fffffff);
+       nv_wr32(priv, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
        return 0;
 }
 
index 54c1b5b471cdfa5682a83587a1d490455d6828c1..a9a1a9c9f9f292648bf294eb358f0bc8ec232015 100644 (file)
@@ -60,10 +60,15 @@ static const struct {
 struct nve0_fifo_engn {
        struct nouveau_gpuobj *runlist[2];
        int cur_runlist;
+       wait_queue_head_t wait;
 };
 
 struct nve0_fifo_priv {
        struct nouveau_fifo base;
+
+       struct work_struct fault;
+       u64 mask;
+
        struct nve0_fifo_engn engine[FIFO_ENGINE_NR];
        struct {
                struct nouveau_gpuobj *mem;
@@ -81,6 +86,11 @@ struct nve0_fifo_base {
 struct nve0_fifo_chan {
        struct nouveau_fifo_chan base;
        u32 engine;
+       enum {
+               STOPPED,
+               RUNNING,
+               KILLED
+       } state;
 };
 
 /*******************************************************************************
@@ -93,7 +103,6 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
        struct nouveau_bar *bar = nouveau_bar(priv);
        struct nve0_fifo_engn *engn = &priv->engine[engine];
        struct nouveau_gpuobj *cur;
-       u32 match = (engine << 16) | 0x00000001;
        int i, p;
 
        mutex_lock(&nv_subdev(priv)->mutex);
@@ -101,18 +110,21 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
        engn->cur_runlist = !engn->cur_runlist;
 
        for (i = 0, p = 0; i < priv->base.max; i++) {
-               u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001;
-               if (ctrl != match)
-                       continue;
-               nv_wo32(cur, p + 0, i);
-               nv_wo32(cur, p + 4, 0x00000000);
-               p += 8;
+               struct nve0_fifo_chan *chan = (void *)priv->base.channel[i];
+               if (chan && chan->state == RUNNING && chan->engine == engine) {
+                       nv_wo32(cur, p + 0, i);
+                       nv_wo32(cur, p + 4, 0x00000000);
+                       p += 8;
+               }
        }
        bar->flush(bar);
 
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
-       if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000))
+
+       if (wait_event_timeout(engn->wait, !(nv_rd32(priv, 0x002284 +
+                              (engine * 0x08)) & 0x00100000),
+                               msecs_to_jiffies(2000)) == 0)
                nv_error(priv, "runlist %d update timeout\n", engine);
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
@@ -129,9 +141,11 @@ nve0_fifo_context_attach(struct nouveau_object *parent,
 
        switch (nv_engidx(object->engine)) {
        case NVDEV_ENGINE_SW   :
+               return 0;
        case NVDEV_ENGINE_COPY0:
        case NVDEV_ENGINE_COPY1:
        case NVDEV_ENGINE_COPY2:
+               nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
                return 0;
        case NVDEV_ENGINE_GR   : addr = 0x0210; break;
        case NVDEV_ENGINE_BSP  : addr = 0x0270; break;
@@ -279,9 +293,13 @@ nve0_fifo_chan_init(struct nouveau_object *object)
 
        nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
-       nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
-       nve0_fifo_runlist_update(priv, chan->engine);
-       nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+
+       if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
+               nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+               nve0_fifo_runlist_update(priv, chan->engine);
+               nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+       }
+
        return 0;
 }
 
@@ -292,10 +310,12 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
        struct nve0_fifo_chan *chan = (void *)object;
        u32 chid = chan->base.chid;
 
-       nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
-       nve0_fifo_runlist_update(priv, chan->engine);
-       nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
+       if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
+               nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
+               nve0_fifo_runlist_update(priv, chan->engine);
+       }
 
+       nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
        return nouveau_fifo_channel_fini(&chan->base, suspend);
 }
 
@@ -377,14 +397,211 @@ nve0_fifo_cclass = {
  * PFIFO engine
  ******************************************************************************/
 
-static const struct nouveau_enum nve0_fifo_sched_reason[] = {
+static inline int
+nve0_fifo_engidx(struct nve0_fifo_priv *priv, u32 engn)
+{
+       switch (engn) {
+       case NVDEV_ENGINE_GR   :
+       case NVDEV_ENGINE_COPY2: engn = 0; break;
+       case NVDEV_ENGINE_BSP  : engn = 1; break;
+       case NVDEV_ENGINE_PPP  : engn = 2; break;
+       case NVDEV_ENGINE_VP   : engn = 3; break;
+       case NVDEV_ENGINE_COPY0: engn = 4; break;
+       case NVDEV_ENGINE_COPY1: engn = 5; break;
+       case NVDEV_ENGINE_VENC : engn = 6; break;
+       default:
+               return -1;
+       }
+
+       return engn;
+}
+
+static inline struct nouveau_engine *
+nve0_fifo_engine(struct nve0_fifo_priv *priv, u32 engn)
+{
+       if (engn >= ARRAY_SIZE(fifo_engine))
+               return NULL;
+       return nouveau_engine(priv, fifo_engine[engn].subdev);
+}
+
+static void
+nve0_fifo_recover_work(struct work_struct *work)
+{
+       struct nve0_fifo_priv *priv = container_of(work, typeof(*priv), fault);
+       struct nouveau_object *engine;
+       unsigned long flags;
+       u32 engn, engm = 0;
+       u64 mask, todo;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       mask = priv->mask;
+       priv->mask = 0ULL;
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+
+       for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
+               engm |= 1 << nve0_fifo_engidx(priv, engn);
+       nv_mask(priv, 0x002630, engm, engm);
+
+       for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
+               if ((engine = (void *)nouveau_engine(priv, engn))) {
+                       nv_ofuncs(engine)->fini(engine, false);
+                       WARN_ON(nv_ofuncs(engine)->init(engine));
+               }
+               nve0_fifo_runlist_update(priv, nve0_fifo_engidx(priv, engn));
+       }
+
+       nv_wr32(priv, 0x00262c, engm);
+       nv_mask(priv, 0x002630, engm, 0x00000000);
+}
+
+static void
+nve0_fifo_recover(struct nve0_fifo_priv *priv, struct nouveau_engine *engine,
+                 struct nve0_fifo_chan *chan)
+{
+       struct nouveau_object *engobj = nv_object(engine);
+       u32 chid = chan->base.chid;
+       unsigned long flags;
+
+       nv_error(priv, "%s engine fault on channel %d, recovering...\n",
+                      nv_subdev(engine)->name, chid);
+
+       nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800);
+       chan->state = KILLED;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       priv->mask |= 1ULL << nv_engidx(engobj);
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+       schedule_work(&priv->fault);
+}
+
+static int
+nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
+{
+       struct nve0_fifo_chan *chan = NULL;
+       struct nouveau_handle *bind;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&priv->base.lock, flags);
+       if (likely(chid >= priv->base.min && chid <= priv->base.max))
+               chan = (void *)priv->base.channel[chid];
+       if (unlikely(!chan))
+               goto out;
+
+       bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
+       if (likely(bind)) {
+               if (!mthd || !nv_call(bind->object, mthd, data))
+                       ret = 0;
+               nouveau_namedb_put(bind);
+       }
+
+out:
+       spin_unlock_irqrestore(&priv->base.lock, flags);
+       return ret;
+}
+
+static const struct nouveau_enum
+nve0_fifo_bind_reason[] = {
+       { 0x01, "BIND_NOT_UNBOUND" },
+       { 0x02, "SNOOP_WITHOUT_BAR1" },
+       { 0x03, "UNBIND_WHILE_RUNNING" },
+       { 0x05, "INVALID_RUNLIST" },
+       { 0x06, "INVALID_CTX_TGT" },
+       { 0x0b, "UNBIND_WHILE_PARKED" },
+       {}
+};
+
+static void
+nve0_fifo_intr_bind(struct nve0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x00252c);
+       u32 code = intr & 0x000000ff;
+       const struct nouveau_enum *en;
+       char enunk[6] = "";
+
+       en = nouveau_enum_find(nve0_fifo_bind_reason, code);
+       if (!en)
+               snprintf(enunk, sizeof(enunk), "UNK%02x", code);
+
+       nv_error(priv, "BIND_ERROR [ %s ]\n", en ? en->name : enunk);
+}
+
+static const struct nouveau_enum
+nve0_fifo_sched_reason[] = {
        { 0x0a, "CTXSW_TIMEOUT" },
        {}
 };
 
-static const struct nouveau_enum nve0_fifo_fault_engine[] = {
+static void
+nve0_fifo_intr_sched_ctxsw(struct nve0_fifo_priv *priv)
+{
+       struct nouveau_engine *engine;
+       struct nve0_fifo_chan *chan;
+       u32 engn;
+
+       for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) {
+               u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04));
+               u32 busy = (stat & 0x80000000);
+               u32 next = (stat & 0x07ff0000) >> 16;
+               u32 chsw = (stat & 0x00008000);
+               u32 save = (stat & 0x00004000);
+               u32 load = (stat & 0x00002000);
+               u32 prev = (stat & 0x000007ff);
+               u32 chid = load ? next : prev;
+               (void)save;
+
+               if (busy && chsw) {
+                       if (!(chan = (void *)priv->base.channel[chid]))
+                               continue;
+                       if (!(engine = nve0_fifo_engine(priv, engn)))
+                               continue;
+                       nve0_fifo_recover(priv, engine, chan);
+               }
+       }
+}
+
+static void
+nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x00254c);
+       u32 code = intr & 0x000000ff;
+       const struct nouveau_enum *en;
+       char enunk[6] = "";
+
+       en = nouveau_enum_find(nve0_fifo_sched_reason, code);
+       if (!en)
+               snprintf(enunk, sizeof(enunk), "UNK%02x", code);
+
+       nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk);
+
+       switch (code) {
+       case 0x0a:
+               nve0_fifo_intr_sched_ctxsw(priv);
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00256c);
+       nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
+       nv_wr32(priv, 0x00256c, stat);
+}
+
+static void
+nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00259c);
+       nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
+}
+
+static const struct nouveau_enum
+nve0_fifo_fault_engine[] = {
        { 0x00, "GR", NULL, NVDEV_ENGINE_GR },
-       { 0x03, "IFB" },
+       { 0x03, "IFB", NULL, NVDEV_ENGINE_IFB },
        { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
        { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
        { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
@@ -402,7 +619,8 @@ static const struct nouveau_enum nve0_fifo_fault_engine[] = {
        {}
 };
 
-static const struct nouveau_enum nve0_fifo_fault_reason[] = {
+static const struct nouveau_enum
+nve0_fifo_fault_reason[] = {
        { 0x00, "PDE" },
        { 0x01, "PDE_SIZE" },
        { 0x02, "PTE" },
@@ -422,7 +640,8 @@ static const struct nouveau_enum nve0_fifo_fault_reason[] = {
        {}
 };
 
-static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
+static const struct nouveau_enum
+nve0_fifo_fault_hubclient[] = {
        { 0x00, "VIP" },
        { 0x01, "CE0" },
        { 0x02, "CE1" },
@@ -458,7 +677,8 @@ static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
        {}
 };
 
-static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
+static const struct nouveau_enum
+nve0_fifo_fault_gpcclient[] = {
        { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
        { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
        { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
@@ -483,6 +703,82 @@ static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
        {}
 };
 
+static void
+nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
+{
+       u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10));
+       u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10));
+       u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));
+       u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10));
+       u32 gpc    = (stat & 0x1f000000) >> 24;
+       u32 client = (stat & 0x00001f00) >> 8;
+       u32 write  = (stat & 0x00000080);
+       u32 hub    = (stat & 0x00000040);
+       u32 reason = (stat & 0x0000000f);
+       struct nouveau_object *engctx = NULL, *object;
+       struct nouveau_engine *engine = NULL;
+       const struct nouveau_enum *er, *eu, *ec;
+       char erunk[6] = "";
+       char euunk[6] = "";
+       char ecunk[6] = "";
+       char gpcid[3] = "";
+
+       er = nouveau_enum_find(nve0_fifo_fault_reason, reason);
+       if (!er)
+               snprintf(erunk, sizeof(erunk), "UNK%02X", reason);
+
+       eu = nouveau_enum_find(nve0_fifo_fault_engine, unit);
+       if (eu) {
+               switch (eu->data2) {
+               case NVDEV_SUBDEV_BAR:
+                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+                       break;
+               case NVDEV_SUBDEV_INSTMEM:
+                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+                       break;
+               case NVDEV_ENGINE_IFB:
+                       nv_mask(priv, 0x001718, 0x00000000, 0x00000000);
+                       break;
+               default:
+                       engine = nouveau_engine(priv, eu->data2);
+                       if (engine)
+                               engctx = nouveau_engctx_get(engine, inst);
+                       break;
+               }
+       } else {
+               snprintf(euunk, sizeof(euunk), "UNK%02x", unit);
+       }
+
+       if (hub) {
+               ec = nouveau_enum_find(nve0_fifo_fault_hubclient, client);
+       } else {
+               ec = nouveau_enum_find(nve0_fifo_fault_gpcclient, client);
+               snprintf(gpcid, sizeof(gpcid), "%d", gpc);
+       }
+
+       if (!ec)
+               snprintf(ecunk, sizeof(ecunk), "UNK%02x", client);
+
+       nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on "
+                      "channel 0x%010llx [%s]\n", write ? "write" : "read",
+                (u64)vahi << 32 | valo, er ? er->name : erunk,
+                eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/",
+                ec ? ec->name : ecunk, (u64)inst << 12,
+                nouveau_client_name(engctx));
+
+       object = engctx;
+       while (object) {
+               switch (nv_mclass(object)) {
+               case NVE0_CHANNEL_IND_CLASS:
+                       nve0_fifo_recover(priv, engine, (void *)object);
+                       break;
+               }
+               object = object->parent;
+       }
+
+       nouveau_engctx_put(engctx);
+}
+
 static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
        { 0x00000001, "MEMREQ" },
        { 0x00000002, "MEMACK_TIMEOUT" },
@@ -517,104 +813,6 @@ static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
        {}
 };
 
-static void
-nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
-{
-       u32 intr = nv_rd32(priv, 0x00254c);
-       u32 code = intr & 0x000000ff;
-       nv_error(priv, "SCHED_ERROR [");
-       nouveau_enum_print(nve0_fifo_sched_reason, code);
-       pr_cont("]\n");
-}
-
-static void
-nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
-{
-       u32 stat = nv_rd32(priv, 0x00256c);
-       nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
-       nv_wr32(priv, 0x00256c, stat);
-}
-
-static void
-nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
-{
-       u32 stat = nv_rd32(priv, 0x00259c);
-       nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
-}
-
-static void
-nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
-{
-       u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10));
-       u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10));
-       u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
-       u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
-       u32 client = (stat & 0x00001f00) >> 8;
-       struct nouveau_engine *engine = NULL;
-       struct nouveau_object *engctx = NULL;
-       const struct nouveau_enum *en;
-       const char *name = "unknown";
-
-       nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
-                      "write" : "read", (u64)vahi << 32 | valo);
-       nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
-       pr_cont("] from ");
-       en = nouveau_enum_print(nve0_fifo_fault_engine, unit);
-       if (stat & 0x00000040) {
-               pr_cont("/");
-               nouveau_enum_print(nve0_fifo_fault_hubclient, client);
-       } else {
-               pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24);
-               nouveau_enum_print(nve0_fifo_fault_gpcclient, client);
-       }
-
-       if (en && en->data2) {
-               if (en->data2 == NVDEV_SUBDEV_BAR) {
-                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
-                       name = "BAR1";
-               } else
-               if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
-                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
-                       name = "BAR3";
-               } else {
-                       engine = nouveau_engine(priv, en->data2);
-                       if (engine) {
-                               engctx = nouveau_engctx_get(engine, inst);
-                               name   = nouveau_client_name(engctx);
-                       }
-               }
-       }
-       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
-
-       nouveau_engctx_put(engctx);
-}
-
-static int
-nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
-{
-       struct nve0_fifo_chan *chan = NULL;
-       struct nouveau_handle *bind;
-       unsigned long flags;
-       int ret = -EINVAL;
-
-       spin_lock_irqsave(&priv->base.lock, flags);
-       if (likely(chid >= priv->base.min && chid <= priv->base.max))
-               chan = (void *)priv->base.channel[chid];
-       if (unlikely(!chan))
-               goto out;
-
-       bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
-       if (likely(bind)) {
-               if (!mthd || !nv_call(bind->object, mthd, data))
-                       ret = 0;
-               nouveau_namedb_put(bind);
-       }
-
-out:
-       spin_unlock_irqrestore(&priv->base.lock, flags);
-       return ret;
-}
-
 static void
 nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
 {
@@ -646,6 +844,24 @@ nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
        nv_wr32(priv, 0x040108 + (unit * 0x2000), stat);
 }
 
+static void
+nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv)
+{
+       u32 mask = nv_rd32(priv, 0x002a00);
+       while (mask) {
+               u32 engn = __ffs(mask);
+               wake_up(&priv->engine[engn].wait);
+               nv_wr32(priv, 0x002a00, 1 << engn);
+               mask &= ~(1 << engn);
+       }
+}
+
+static void
+nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
+{
+       nouveau_event_trigger(priv->base.uevent, 0);
+}
+
 static void
 nve0_fifo_intr(struct nouveau_subdev *subdev)
 {
@@ -654,8 +870,7 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        u32 stat = nv_rd32(priv, 0x002100) & mask;
 
        if (stat & 0x00000001) {
-               u32 stat = nv_rd32(priv, 0x00252c);
-               nv_error(priv, "BIND_ERROR 0x%08x\n", stat);
+               nve0_fifo_intr_bind(priv);
                nv_wr32(priv, 0x002100, 0x00000001);
                stat &= ~0x00000001;
        }
@@ -697,55 +912,42 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x10000000) {
-               u32 units = nv_rd32(priv, 0x00259c);
-               u32 u = units;
-
-               while (u) {
-                       int i = ffs(u) - 1;
-                       nve0_fifo_intr_fault(priv, i);
-                       u &= ~(1 << i);
+               u32 mask = nv_rd32(priv, 0x00259c);
+               while (mask) {
+                       u32 unit = __ffs(mask);
+                       nve0_fifo_intr_fault(priv, unit);
+                       nv_wr32(priv, 0x00259c, (1 << unit));
+                       mask &= ~(1 << unit);
                }
-
-               nv_wr32(priv, 0x00259c, units);
                stat &= ~0x10000000;
        }
 
        if (stat & 0x20000000) {
                u32 mask = nv_rd32(priv, 0x0025a0);
-               u32 temp = mask;
-
-               while (temp) {
-                       u32 unit = ffs(temp) - 1;
+               while (mask) {
+                       u32 unit = __ffs(mask);
                        nve0_fifo_intr_pbdma(priv, unit);
-                       temp &= ~(1 << unit);
+                       nv_wr32(priv, 0x0025a0, (1 << unit));
+                       mask &= ~(1 << unit);
                }
-
-               nv_wr32(priv, 0x0025a0, mask);
                stat &= ~0x20000000;
        }
 
        if (stat & 0x40000000) {
-               u32 mask = nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
-
-               while (mask) {
-                       u32 engn = ffs(mask) - 1;
-                       /* runlist event, not currently used */
-                       mask &= ~(1 << engn);
-               }
-
+               nve0_fifo_intr_runlist(priv);
                stat &= ~0x40000000;
        }
 
        if (stat & 0x80000000) {
-               nouveau_event_trigger(priv->base.uevent, 0);
+               nve0_fifo_intr_engine(priv);
                nv_wr32(priv, 0x002100, 0x80000000);
                stat &= ~0x80000000;
        }
 
        if (stat) {
-               nv_fatal(priv, "unhandled status 0x%08x\n", stat);
+               nv_error(priv, "INTR 0x%08x\n", stat);
+               nv_mask(priv, 0x002140, stat, 0x00000000);
                nv_wr32(priv, 0x002100, stat);
-               nv_wr32(priv, 0x002140, 0);
        }
 }
 
@@ -802,9 +1004,8 @@ nve0_fifo_init(struct nouveau_object *object)
 
        nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
 
-       nv_wr32(priv, 0x002a00, 0xffffffff);
        nv_wr32(priv, 0x002100, 0xffffffff);
-       nv_wr32(priv, 0x002140, 0x3fffffff);
+       nv_wr32(priv, 0x002140, 0x7fffffff);
        return 0;
 }
 
@@ -840,6 +1041,8 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       INIT_WORK(&priv->fault, nve0_fifo_recover_work);
+
        for (i = 0; i < FIFO_ENGINE_NR; i++) {
                ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
                                         0, &priv->engine[i].runlist[0]);
@@ -850,10 +1053,12 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                                         0, &priv->engine[i].runlist[1]);
                if (ret)
                        return ret;
+
+               init_waitqueue_head(&priv->engine[i].wait);
        }
 
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
-                                NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+       ret = nouveau_gpuobj_new(nv_object(priv), NULL, impl->channels * 0x200,
+                               0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
        if (ret)
                return ret;
 
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 (file)
index 0000000..1dc37b1
--- /dev/null
@@ -0,0 +1,989 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gm107_grctx_init_icmd_0[] = {
+       { 0x001000,   1, 0x01, 0x00000004 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x0000a9,   1, 0x01, 0x0000ffff },
+       { 0x000038,   1, 0x01, 0x0fac6881 },
+       { 0x00003d,   1, 0x01, 0x00000001 },
+       { 0x0000e8,   8, 0x01, 0x00000400 },
+       { 0x000078,   8, 0x01, 0x00000300 },
+       { 0x000050,   1, 0x01, 0x00000011 },
+       { 0x000058,   8, 0x01, 0x00000008 },
+       { 0x000208,   8, 0x01, 0x00000001 },
+       { 0x000081,   1, 0x01, 0x00000001 },
+       { 0x000085,   1, 0x01, 0x00000004 },
+       { 0x000088,   1, 0x01, 0x00000400 },
+       { 0x000090,   1, 0x01, 0x00000300 },
+       { 0x000098,   1, 0x01, 0x00001001 },
+       { 0x0000e3,   1, 0x01, 0x00000001 },
+       { 0x0000da,   1, 0x01, 0x00000001 },
+       { 0x0000f8,   1, 0x01, 0x00000003 },
+       { 0x0000fa,   1, 0x01, 0x00000001 },
+       { 0x0000b1,   2, 0x01, 0x00000001 },
+       { 0x00009f,   4, 0x01, 0x0000ffff },
+       { 0x0000a8,   1, 0x01, 0x0000ffff },
+       { 0x0000ad,   1, 0x01, 0x0000013e },
+       { 0x0000e1,   1, 0x01, 0x00000010 },
+       { 0x000290,  16, 0x01, 0x00000000 },
+       { 0x0003b0,  16, 0x01, 0x00000000 },
+       { 0x0002a0,  16, 0x01, 0x00000000 },
+       { 0x000420,  16, 0x01, 0x00000000 },
+       { 0x0002b0,  16, 0x01, 0x00000000 },
+       { 0x000430,  16, 0x01, 0x00000000 },
+       { 0x0002c0,  16, 0x01, 0x00000000 },
+       { 0x0004d0,  16, 0x01, 0x00000000 },
+       { 0x000720,  16, 0x01, 0x00000000 },
+       { 0x0008c0,  16, 0x01, 0x00000000 },
+       { 0x000890,  16, 0x01, 0x00000000 },
+       { 0x0008e0,  16, 0x01, 0x00000000 },
+       { 0x0008a0,  16, 0x01, 0x00000000 },
+       { 0x0008f0,  16, 0x01, 0x00000000 },
+       { 0x00094c,   1, 0x01, 0x000000ff },
+       { 0x00094d,   1, 0x01, 0xffffffff },
+       { 0x00094e,   1, 0x01, 0x00000002 },
+       { 0x0002f2,   2, 0x01, 0x00000001 },
+       { 0x0002f5,   1, 0x01, 0x00000001 },
+       { 0x0002f7,   1, 0x01, 0x00000001 },
+       { 0x000303,   1, 0x01, 0x00000001 },
+       { 0x0002e6,   1, 0x01, 0x00000001 },
+       { 0x000466,   1, 0x01, 0x00000052 },
+       { 0x000301,   1, 0x01, 0x3f800000 },
+       { 0x000304,   1, 0x01, 0x30201000 },
+       { 0x000305,   1, 0x01, 0x70605040 },
+       { 0x000306,   1, 0x01, 0xb8a89888 },
+       { 0x000307,   1, 0x01, 0xf8e8d8c8 },
+       { 0x00030a,   1, 0x01, 0x00ffff00 },
+       { 0x0000de,   1, 0x01, 0x00000001 },
+       { 0x00030b,   1, 0x01, 0x0000001a },
+       { 0x00030c,   1, 0x01, 0x00000001 },
+       { 0x000318,   1, 0x01, 0x00000001 },
+       { 0x000340,   1, 0x01, 0x00000000 },
+       { 0x00037d,   1, 0x01, 0x00000006 },
+       { 0x0003a0,   1, 0x01, 0x00000002 },
+       { 0x0003aa,   1, 0x01, 0x00000001 },
+       { 0x0003a9,   1, 0x01, 0x00000001 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000383,   1, 0x01, 0x00000011 },
+       { 0x000360,   1, 0x01, 0x00000040 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x00037a,   1, 0x01, 0x00000012 },
+       { 0x000619,   1, 0x01, 0x00000003 },
+       { 0x000811,   1, 0x01, 0x00000003 },
+       { 0x000812,   1, 0x01, 0x00000004 },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000815,   1, 0x01, 0x0000000b },
+       { 0x000800,   6, 0x01, 0x00000001 },
+       { 0x000632,   1, 0x01, 0x00000001 },
+       { 0x000633,   1, 0x01, 0x00000002 },
+       { 0x000634,   1, 0x01, 0x00000003 },
+       { 0x000635,   1, 0x01, 0x00000004 },
+       { 0x000654,   1, 0x01, 0x3f800000 },
+       { 0x000657,   1, 0x01, 0x3f800000 },
+       { 0x000655,   2, 0x01, 0x3f800000 },
+       { 0x0006cd,   1, 0x01, 0x3f800000 },
+       { 0x0007f5,   1, 0x01, 0x3f800000 },
+       { 0x0007dc,   1, 0x01, 0x39291909 },
+       { 0x0007dd,   1, 0x01, 0x79695949 },
+       { 0x0007de,   1, 0x01, 0xb9a99989 },
+       { 0x0007df,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007e8,   1, 0x01, 0x00003210 },
+       { 0x0007e9,   1, 0x01, 0x00007654 },
+       { 0x0007ea,   1, 0x01, 0x00000098 },
+       { 0x0007ec,   1, 0x01, 0x39291909 },
+       { 0x0007ed,   1, 0x01, 0x79695949 },
+       { 0x0007ee,   1, 0x01, 0xb9a99989 },
+       { 0x0007ef,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007f0,   1, 0x01, 0x00003210 },
+       { 0x0007f1,   1, 0x01, 0x00007654 },
+       { 0x0007f2,   1, 0x01, 0x00000098 },
+       { 0x0005a5,   1, 0x01, 0x00000001 },
+       { 0x0005d0,   1, 0x01, 0x20181008 },
+       { 0x0005d1,   1, 0x01, 0x40383028 },
+       { 0x0005d2,   1, 0x01, 0x60585048 },
+       { 0x0005d3,   1, 0x01, 0x80787068 },
+       { 0x000980, 128, 0x01, 0x00000000 },
+       { 0x000468,   1, 0x01, 0x00000004 },
+       { 0x00046c,   1, 0x01, 0x00000001 },
+       { 0x000470,  96, 0x01, 0x00000000 },
+       { 0x000510,  16, 0x01, 0x3f800000 },
+       { 0x000520,   1, 0x01, 0x000002b6 },
+       { 0x000529,   1, 0x01, 0x00000001 },
+       { 0x000530,  16, 0x01, 0xffff0000 },
+       { 0x000550,  32, 0x01, 0xffff0000 },
+       { 0x000585,   1, 0x01, 0x0000003f },
+       { 0x000576,   1, 0x01, 0x00000003 },
+       { 0x00057b,   1, 0x01, 0x00000059 },
+       { 0x000586,   1, 0x01, 0x00000040 },
+       { 0x000582,   2, 0x01, 0x00000080 },
+       { 0x000595,   1, 0x01, 0x00400040 },
+       { 0x000596,   1, 0x01, 0x00000492 },
+       { 0x000597,   1, 0x01, 0x08080203 },
+       { 0x0005ad,   1, 0x01, 0x00000008 },
+       { 0x000598,   1, 0x01, 0x00020001 },
+       { 0x0005c2,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
+       { 0x00063a,   1, 0x01, 0x00000002 },
+       { 0x00063b,   2, 0x01, 0x00000001 },
+       { 0x00063d,   1, 0x01, 0x00000002 },
+       { 0x00063e,   1, 0x01, 0x00000001 },
+       { 0x0008b8,   8, 0x01, 0x00000001 },
+       { 0x000900,   8, 0x01, 0x00000001 },
+       { 0x000908,   8, 0x01, 0x00000002 },
+       { 0x000910,  16, 0x01, 0x00000001 },
+       { 0x000920,   8, 0x01, 0x00000002 },
+       { 0x000928,   8, 0x01, 0x00000001 },
+       { 0x000662,   1, 0x01, 0x00000001 },
+       { 0x000648,   9, 0x01, 0x00000001 },
+       { 0x000658,   1, 0x01, 0x0000000f },
+       { 0x0007ff,   1, 0x01, 0x0000000a },
+       { 0x00066a,   1, 0x01, 0x40000000 },
+       { 0x00066b,   1, 0x01, 0x10000000 },
+       { 0x00066c,   2, 0x01, 0xffff0000 },
+       { 0x0007af,   2, 0x01, 0x00000008 },
+       { 0x0007f6,   1, 0x01, 0x00000001 },
+       { 0x0006b2,   1, 0x01, 0x00000055 },
+       { 0x0007ad,   1, 0x01, 0x00000003 },
+       { 0x000971,   1, 0x01, 0x00000008 },
+       { 0x000972,   1, 0x01, 0x00000040 },
+       { 0x000973,   1, 0x01, 0x0000012c },
+       { 0x00097c,   1, 0x01, 0x00000040 },
+       { 0x000975,   1, 0x01, 0x00000020 },
+       { 0x000976,   1, 0x01, 0x00000001 },
+       { 0x000977,   1, 0x01, 0x00000020 },
+       { 0x000978,   1, 0x01, 0x00000001 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x00095e,   1, 0x01, 0x20164010 },
+       { 0x00095f,   1, 0x01, 0x00000020 },
+       { 0x000a0d,   1, 0x01, 0x00000006 },
+       { 0x00097d,   1, 0x01, 0x0000000c },
+       { 0x000683,   1, 0x01, 0x00000006 },
+       { 0x000687,   1, 0x01, 0x003fffff },
+       { 0x0006a0,   1, 0x01, 0x00000005 },
+       { 0x000840,   1, 0x01, 0x00400008 },
+       { 0x000841,   1, 0x01, 0x08000080 },
+       { 0x000842,   1, 0x01, 0x00400008 },
+       { 0x000843,   1, 0x01, 0x08000080 },
+       { 0x000818,   8, 0x01, 0x00000000 },
+       { 0x000848,  16, 0x01, 0x00000000 },
+       { 0x000738,   1, 0x01, 0x00000000 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ab,   1, 0x01, 0x00000002 },
+       { 0x0006ac,   1, 0x01, 0x00000080 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x0006bb,   1, 0x01, 0x000000cf },
+       { 0x0006ce,   1, 0x01, 0x2a712488 },
+       { 0x000739,   1, 0x01, 0x4085c000 },
+       { 0x00073a,   1, 0x01, 0x00000080 },
+       { 0x000786,   1, 0x01, 0x80000100 },
+       { 0x00073c,   1, 0x01, 0x00010100 },
+       { 0x00073d,   1, 0x01, 0x02800000 },
+       { 0x000787,   1, 0x01, 0x000000cf },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x000836,   1, 0x01, 0x00000001 },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x000833,   1, 0x01, 0x04444480 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c1b0,   8, 0x01, 0x0000000f },
+       { 0x00c1b8,   1, 0x01, 0x0fac6881 },
+       { 0x00c1b9,   1, 0x01, 0x00fac688 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000002 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000008 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000818,   8, 0x01, 0x00000000 },
+       { 0x000848,  16, 0x01, 0x00000000 },
+       { 0x000738,   1, 0x01, 0x00000000 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000001 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_icmd[] = {
+       { gm107_grctx_init_icmd_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_b097_0[] = {
+       { 0x000800,   8, 0x40, 0x00000000 },
+       { 0x000804,   8, 0x40, 0x00000000 },
+       { 0x000808,   8, 0x40, 0x00000400 },
+       { 0x00080c,   8, 0x40, 0x00000300 },
+       { 0x000810,   1, 0x04, 0x000000cf },
+       { 0x000850,   7, 0x40, 0x00000000 },
+       { 0x000814,   8, 0x40, 0x00000040 },
+       { 0x000818,   8, 0x40, 0x00000001 },
+       { 0x00081c,   8, 0x40, 0x00000000 },
+       { 0x000820,   8, 0x40, 0x00000000 },
+       { 0x001c00,  16, 0x10, 0x00000000 },
+       { 0x001c04,  16, 0x10, 0x00000000 },
+       { 0x001c08,  16, 0x10, 0x00000000 },
+       { 0x001c0c,  16, 0x10, 0x00000000 },
+       { 0x001d00,  16, 0x10, 0x00000000 },
+       { 0x001d04,  16, 0x10, 0x00000000 },
+       { 0x001d08,  16, 0x10, 0x00000000 },
+       { 0x001d0c,  16, 0x10, 0x00000000 },
+       { 0x001f00,  16, 0x08, 0x00000000 },
+       { 0x001f04,  16, 0x08, 0x00000000 },
+       { 0x001f80,  16, 0x08, 0x00000000 },
+       { 0x001f84,  16, 0x08, 0x00000000 },
+       { 0x002000,   1, 0x04, 0x00000000 },
+       { 0x002040,   1, 0x04, 0x00000011 },
+       { 0x002080,   1, 0x04, 0x00000020 },
+       { 0x0020c0,   1, 0x04, 0x00000030 },
+       { 0x002100,   1, 0x04, 0x00000040 },
+       { 0x002140,   1, 0x04, 0x00000051 },
+       { 0x00200c,   6, 0x40, 0x00000001 },
+       { 0x002010,   1, 0x04, 0x00000000 },
+       { 0x002050,   1, 0x04, 0x00000000 },
+       { 0x002090,   1, 0x04, 0x00000001 },
+       { 0x0020d0,   1, 0x04, 0x00000002 },
+       { 0x002110,   1, 0x04, 0x00000003 },
+       { 0x002150,   1, 0x04, 0x00000004 },
+       { 0x000380,   4, 0x20, 0x00000000 },
+       { 0x000384,   4, 0x20, 0x00000000 },
+       { 0x000388,   4, 0x20, 0x00000000 },
+       { 0x00038c,   4, 0x20, 0x00000000 },
+       { 0x000700,   4, 0x10, 0x00000000 },
+       { 0x000704,   4, 0x10, 0x00000000 },
+       { 0x000708,   4, 0x10, 0x00000000 },
+       { 0x002800, 128, 0x04, 0x00000000 },
+       { 0x000a00,  16, 0x20, 0x00000000 },
+       { 0x000a04,  16, 0x20, 0x00000000 },
+       { 0x000a08,  16, 0x20, 0x00000000 },
+       { 0x000a0c,  16, 0x20, 0x00000000 },
+       { 0x000a10,  16, 0x20, 0x00000000 },
+       { 0x000a14,  16, 0x20, 0x00000000 },
+       { 0x000c00,  16, 0x10, 0x00000000 },
+       { 0x000c04,  16, 0x10, 0x00000000 },
+       { 0x000c08,  16, 0x10, 0x00000000 },
+       { 0x000c0c,  16, 0x10, 0x3f800000 },
+       { 0x000d00,   8, 0x08, 0xffff0000 },
+       { 0x000d04,   8, 0x08, 0xffff0000 },
+       { 0x000e00,  16, 0x10, 0x00000000 },
+       { 0x000e04,  16, 0x10, 0xffff0000 },
+       { 0x000e08,  16, 0x10, 0xffff0000 },
+       { 0x000d40,   4, 0x08, 0x00000000 },
+       { 0x000d44,   4, 0x08, 0x00000000 },
+       { 0x001e00,   8, 0x20, 0x00000001 },
+       { 0x001e04,   8, 0x20, 0x00000001 },
+       { 0x001e08,   8, 0x20, 0x00000002 },
+       { 0x001e0c,   8, 0x20, 0x00000001 },
+       { 0x001e10,   8, 0x20, 0x00000001 },
+       { 0x001e14,   8, 0x20, 0x00000002 },
+       { 0x001e18,   8, 0x20, 0x00000001 },
+       { 0x001480,   8, 0x10, 0x00000000 },
+       { 0x001484,   8, 0x10, 0x00000000 },
+       { 0x001488,   8, 0x10, 0x00000000 },
+       { 0x003400, 128, 0x04, 0x00000000 },
+       { 0x00030c,   1, 0x04, 0x00000001 },
+       { 0x001944,   1, 0x04, 0x00000000 },
+       { 0x001514,   1, 0x04, 0x00000000 },
+       { 0x000d68,   1, 0x04, 0x0000ffff },
+       { 0x00121c,   1, 0x04, 0x0fac6881 },
+       { 0x000fac,   1, 0x04, 0x00000001 },
+       { 0x001538,   1, 0x04, 0x00000001 },
+       { 0x000fe0,   2, 0x04, 0x00000000 },
+       { 0x000fe8,   1, 0x04, 0x00000014 },
+       { 0x000fec,   1, 0x04, 0x00000040 },
+       { 0x000ff0,   1, 0x04, 0x00000000 },
+       { 0x00179c,   1, 0x04, 0x00000000 },
+       { 0x001228,   1, 0x04, 0x00000400 },
+       { 0x00122c,   1, 0x04, 0x00000300 },
+       { 0x001230,   1, 0x04, 0x00010001 },
+       { 0x0007f8,   1, 0x04, 0x00000000 },
+       { 0x0015b4,   1, 0x04, 0x00000001 },
+       { 0x0015cc,   1, 0x04, 0x00000000 },
+       { 0x001534,   1, 0x04, 0x00000000 },
+       { 0x000754,   1, 0x04, 0x00000001 },
+       { 0x000fb0,   1, 0x04, 0x00000000 },
+       { 0x0015d0,   1, 0x04, 0x00000000 },
+       { 0x00153c,   1, 0x04, 0x00000000 },
+       { 0x0016b4,   1, 0x04, 0x00000003 },
+       { 0x000fbc,   4, 0x04, 0x0000ffff },
+       { 0x000df8,   2, 0x04, 0x00000000 },
+       { 0x001948,   1, 0x04, 0x00000000 },
+       { 0x001970,   1, 0x04, 0x00000001 },
+       { 0x00161c,   1, 0x04, 0x000009f0 },
+       { 0x000dcc,   1, 0x04, 0x00000010 },
+       { 0x0015e4,   1, 0x04, 0x00000000 },
+       { 0x001160,  32, 0x04, 0x25e00040 },
+       { 0x001880,  32, 0x04, 0x00000000 },
+       { 0x000f84,   2, 0x04, 0x00000000 },
+       { 0x0017c8,   2, 0x04, 0x00000000 },
+       { 0x0017d0,   1, 0x04, 0x000000ff },
+       { 0x0017d4,   1, 0x04, 0xffffffff },
+       { 0x0017d8,   1, 0x04, 0x00000002 },
+       { 0x0017dc,   1, 0x04, 0x00000000 },
+       { 0x0015f4,   2, 0x04, 0x00000000 },
+       { 0x001434,   2, 0x04, 0x00000000 },
+       { 0x000d74,   1, 0x04, 0x00000000 },
+       { 0x0013a4,   1, 0x04, 0x00000000 },
+       { 0x001318,   1, 0x04, 0x00000001 },
+       { 0x001080,   2, 0x04, 0x00000000 },
+       { 0x001088,   2, 0x04, 0x00000001 },
+       { 0x001090,   1, 0x04, 0x00000000 },
+       { 0x001094,   1, 0x04, 0x00000001 },
+       { 0x001098,   1, 0x04, 0x00000000 },
+       { 0x00109c,   1, 0x04, 0x00000001 },
+       { 0x0010a0,   2, 0x04, 0x00000000 },
+       { 0x001644,   1, 0x04, 0x00000000 },
+       { 0x000748,   1, 0x04, 0x00000000 },
+       { 0x000de8,   1, 0x04, 0x00000000 },
+       { 0x001648,   1, 0x04, 0x00000000 },
+       { 0x0012a4,   1, 0x04, 0x00000000 },
+       { 0x001120,   4, 0x04, 0x00000000 },
+       { 0x001118,   1, 0x04, 0x00000000 },
+       { 0x00164c,   1, 0x04, 0x00000000 },
+       { 0x001658,   1, 0x04, 0x00000000 },
+       { 0x001910,   1, 0x04, 0x00000290 },
+       { 0x001518,   1, 0x04, 0x00000000 },
+       { 0x00165c,   1, 0x04, 0x00000001 },
+       { 0x001520,   1, 0x04, 0x00000000 },
+       { 0x001604,   1, 0x04, 0x00000000 },
+       { 0x001570,   1, 0x04, 0x00000000 },
+       { 0x0013b0,   2, 0x04, 0x3f800000 },
+       { 0x00020c,   1, 0x04, 0x00000000 },
+       { 0x001670,   1, 0x04, 0x30201000 },
+       { 0x001674,   1, 0x04, 0x70605040 },
+       { 0x001678,   1, 0x04, 0xb8a89888 },
+       { 0x00167c,   1, 0x04, 0xf8e8d8c8 },
+       { 0x00166c,   1, 0x04, 0x00000000 },
+       { 0x001680,   1, 0x04, 0x00ffff00 },
+       { 0x0012d0,   1, 0x04, 0x00000003 },
+       { 0x0012d4,   1, 0x04, 0x00000002 },
+       { 0x001684,   2, 0x04, 0x00000000 },
+       { 0x000dac,   2, 0x04, 0x00001b02 },
+       { 0x000db4,   1, 0x04, 0x00000000 },
+       { 0x00168c,   1, 0x04, 0x00000000 },
+       { 0x0015bc,   1, 0x04, 0x00000000 },
+       { 0x00156c,   1, 0x04, 0x00000000 },
+       { 0x00187c,   1, 0x04, 0x00000000 },
+       { 0x001110,   1, 0x04, 0x00000001 },
+       { 0x000dc0,   3, 0x04, 0x00000000 },
+       { 0x000f40,   5, 0x04, 0x00000000 },
+       { 0x001234,   1, 0x04, 0x00000000 },
+       { 0x001690,   1, 0x04, 0x00000000 },
+       { 0x000790,   5, 0x04, 0x00000000 },
+       { 0x00077c,   1, 0x04, 0x00000000 },
+       { 0x001000,   1, 0x04, 0x00000010 },
+       { 0x0010fc,   1, 0x04, 0x00000000 },
+       { 0x001290,   1, 0x04, 0x00000000 },
+       { 0x000218,   1, 0x04, 0x00000010 },
+       { 0x0012d8,   1, 0x04, 0x00000000 },
+       { 0x0012dc,   1, 0x04, 0x00000010 },
+       { 0x000d94,   1, 0x04, 0x00000001 },
+       { 0x00155c,   2, 0x04, 0x00000000 },
+       { 0x001564,   1, 0x04, 0x00000fff },
+       { 0x001574,   2, 0x04, 0x00000000 },
+       { 0x00157c,   1, 0x04, 0x000fffff },
+       { 0x001354,   1, 0x04, 0x00000000 },
+       { 0x001610,   1, 0x04, 0x00000012 },
+       { 0x001608,   2, 0x04, 0x00000000 },
+       { 0x00260c,   1, 0x04, 0x00000000 },
+       { 0x0007ac,   1, 0x04, 0x00000000 },
+       { 0x00162c,   1, 0x04, 0x00000003 },
+       { 0x000210,   1, 0x04, 0x00000000 },
+       { 0x000320,   1, 0x04, 0x00000000 },
+       { 0x000324,   6, 0x04, 0x3f800000 },
+       { 0x000750,   1, 0x04, 0x00000000 },
+       { 0x000760,   1, 0x04, 0x39291909 },
+       { 0x000764,   1, 0x04, 0x79695949 },
+       { 0x000768,   1, 0x04, 0xb9a99989 },
+       { 0x00076c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x000770,   1, 0x04, 0x30201000 },
+       { 0x000774,   1, 0x04, 0x70605040 },
+       { 0x000778,   1, 0x04, 0x00009080 },
+       { 0x000780,   1, 0x04, 0x39291909 },
+       { 0x000784,   1, 0x04, 0x79695949 },
+       { 0x000788,   1, 0x04, 0xb9a99989 },
+       { 0x00078c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x0007d0,   1, 0x04, 0x30201000 },
+       { 0x0007d4,   1, 0x04, 0x70605040 },
+       { 0x0007d8,   1, 0x04, 0x00009080 },
+       { 0x00037c,   1, 0x04, 0x00000001 },
+       { 0x000740,   2, 0x04, 0x00000000 },
+       { 0x002600,   1, 0x04, 0x00000000 },
+       { 0x001918,   1, 0x04, 0x00000000 },
+       { 0x00191c,   1, 0x04, 0x00000900 },
+       { 0x001920,   1, 0x04, 0x00000405 },
+       { 0x001308,   1, 0x04, 0x00000001 },
+       { 0x001924,   1, 0x04, 0x00000000 },
+       { 0x0013ac,   1, 0x04, 0x00000000 },
+       { 0x00192c,   1, 0x04, 0x00000001 },
+       { 0x00193c,   1, 0x04, 0x00002c1c },
+       { 0x000d7c,   1, 0x04, 0x00000000 },
+       { 0x000f8c,   1, 0x04, 0x00000000 },
+       { 0x0002c0,   1, 0x04, 0x00000001 },
+       { 0x001510,   1, 0x04, 0x00000000 },
+       { 0x001940,   1, 0x04, 0x00000000 },
+       { 0x000ff4,   2, 0x04, 0x00000000 },
+       { 0x00194c,   2, 0x04, 0x00000000 },
+       { 0x001968,   1, 0x04, 0x00000000 },
+       { 0x001590,   1, 0x04, 0x0000003f },
+       { 0x0007e8,   4, 0x04, 0x00000000 },
+       { 0x00196c,   1, 0x04, 0x00000011 },
+       { 0x0002e4,   1, 0x04, 0x0000b001 },
+       { 0x00036c,   2, 0x04, 0x00000000 },
+       { 0x00197c,   1, 0x04, 0x00000000 },
+       { 0x000fcc,   2, 0x04, 0x00000000 },
+       { 0x0002d8,   1, 0x04, 0x00000040 },
+       { 0x001980,   1, 0x04, 0x00000080 },
+       { 0x001504,   1, 0x04, 0x00000080 },
+       { 0x001984,   1, 0x04, 0x00000000 },
+       { 0x000f60,   1, 0x04, 0x00000000 },
+       { 0x000f64,   1, 0x04, 0x00400040 },
+       { 0x000f68,   1, 0x04, 0x00002212 },
+       { 0x000f6c,   1, 0x04, 0x08080203 },
+       { 0x001108,   1, 0x04, 0x00000008 },
+       { 0x000f70,   1, 0x04, 0x00080001 },
+       { 0x000ffc,   1, 0x04, 0x00000000 },
+       { 0x000300,   1, 0x04, 0x00000001 },
+       { 0x0013a8,   1, 0x04, 0x00000000 },
+       { 0x0012ec,   1, 0x04, 0x00000000 },
+       { 0x001310,   1, 0x04, 0x00000000 },
+       { 0x001314,   1, 0x04, 0x00000001 },
+       { 0x001380,   1, 0x04, 0x00000000 },
+       { 0x001384,   4, 0x04, 0x00000001 },
+       { 0x001394,   1, 0x04, 0x00000000 },
+       { 0x00139c,   1, 0x04, 0x00000000 },
+       { 0x001398,   1, 0x04, 0x00000000 },
+       { 0x001594,   1, 0x04, 0x00000000 },
+       { 0x001598,   4, 0x04, 0x00000001 },
+       { 0x000f54,   3, 0x04, 0x00000000 },
+       { 0x0019bc,   1, 0x04, 0x00000000 },
+       { 0x000f9c,   2, 0x04, 0x00000000 },
+       { 0x0012cc,   1, 0x04, 0x00000000 },
+       { 0x0012e8,   1, 0x04, 0x00000000 },
+       { 0x00130c,   1, 0x04, 0x00000001 },
+       { 0x001360,   8, 0x04, 0x00000000 },
+       { 0x00133c,   2, 0x04, 0x00000001 },
+       { 0x001344,   1, 0x04, 0x00000002 },
+       { 0x001348,   2, 0x04, 0x00000001 },
+       { 0x001350,   1, 0x04, 0x00000002 },
+       { 0x001358,   1, 0x04, 0x00000001 },
+       { 0x0012e4,   1, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
+       { 0x0019c0,   1, 0x04, 0x00000000 },
+       { 0x001140,   1, 0x04, 0x00000000 },
+       { 0x000dd0,   1, 0x04, 0x00000000 },
+       { 0x000dd4,   1, 0x04, 0x00000001 },
+       { 0x0002f4,   1, 0x04, 0x00000000 },
+       { 0x0019c4,   1, 0x04, 0x00000000 },
+       { 0x0019c8,   1, 0x04, 0x00001500 },
+       { 0x00135c,   1, 0x04, 0x00000000 },
+       { 0x000f90,   1, 0x04, 0x00000000 },
+       { 0x0019e0,   8, 0x04, 0x00000001 },
+       { 0x0019cc,   1, 0x04, 0x00000001 },
+       { 0x0015b8,   1, 0x04, 0x00000000 },
+       { 0x001a00,   1, 0x04, 0x00001111 },
+       { 0x001a04,   7, 0x04, 0x00000000 },
+       { 0x000d6c,   2, 0x04, 0xffff0000 },
+       { 0x0010f8,   1, 0x04, 0x00001010 },
+       { 0x000d80,   5, 0x04, 0x00000000 },
+       { 0x000da0,   1, 0x04, 0x00000000 },
+       { 0x0007a4,   2, 0x04, 0x00000000 },
+       { 0x001508,   1, 0x04, 0x80000000 },
+       { 0x00150c,   1, 0x04, 0x40000000 },
+       { 0x001668,   1, 0x04, 0x00000000 },
+       { 0x000318,   2, 0x04, 0x00000008 },
+       { 0x000d9c,   1, 0x04, 0x00000001 },
+       { 0x000f14,   1, 0x04, 0x00000000 },
+       { 0x000374,   1, 0x04, 0x00000000 },
+       { 0x000378,   1, 0x04, 0x0000000c },
+       { 0x0007dc,   1, 0x04, 0x00000000 },
+       { 0x00074c,   1, 0x04, 0x00000055 },
+       { 0x001420,   1, 0x04, 0x00000003 },
+       { 0x001008,   1, 0x04, 0x00000008 },
+       { 0x00100c,   1, 0x04, 0x00000040 },
+       { 0x001010,   1, 0x04, 0x0000012c },
+       { 0x000d60,   1, 0x04, 0x00000040 },
+       { 0x001018,   1, 0x04, 0x00000020 },
+       { 0x00101c,   1, 0x04, 0x00000001 },
+       { 0x001020,   1, 0x04, 0x00000020 },
+       { 0x001024,   1, 0x04, 0x00000001 },
+       { 0x001444,   3, 0x04, 0x00000000 },
+       { 0x000360,   1, 0x04, 0x20164010 },
+       { 0x000364,   1, 0x04, 0x00000020 },
+       { 0x000368,   1, 0x04, 0x00000000 },
+       { 0x000da8,   1, 0x04, 0x00000030 },
+       { 0x000de4,   1, 0x04, 0x00000000 },
+       { 0x000204,   1, 0x04, 0x00000006 },
+       { 0x0002d0,   1, 0x04, 0x003fffff },
+       { 0x001220,   1, 0x04, 0x00000005 },
+       { 0x000fdc,   1, 0x04, 0x00000000 },
+       { 0x000f98,   1, 0x04, 0x00400008 },
+       { 0x001284,   1, 0x04, 0x08000080 },
+       { 0x001450,   1, 0x04, 0x00400008 },
+       { 0x001454,   1, 0x04, 0x08000080 },
+       { 0x000214,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_mthd[] = {
+       { gm107_grctx_init_b097_0, 0xb097 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_fe_0[] = {
+       { 0x404004,   8, 0x04, 0x00000000 },
+       { 0x404024,   1, 0x04, 0x0000e000 },
+       { 0x404028,   8, 0x04, 0x00000000 },
+       { 0x4040a8,   8, 0x04, 0x00000000 },
+       { 0x4040c8,   1, 0x04, 0xf800008f },
+       { 0x4040d0,   6, 0x04, 0x00000000 },
+       { 0x4040f8,   1, 0x04, 0x00000000 },
+       { 0x404100,  10, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
+       { 0x404150,   1, 0x04, 0x0000002e },
+       { 0x404154,   1, 0x04, 0x00000400 },
+       { 0x404158,   1, 0x04, 0x00000200 },
+       { 0x404164,   1, 0x04, 0x00000045 },
+       { 0x40417c,   2, 0x04, 0x00000000 },
+       { 0x404194,   1, 0x04, 0x01000700 },
+       { 0x4041a0,   4, 0x04, 0x00000000 },
+       { 0x404200,   4, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_ds_0[] = {
+       { 0x405800,   1, 0x04, 0x0f8001bf },
+       { 0x405830,   1, 0x04, 0x0aa01000 },
+       { 0x405834,   1, 0x04, 0x08000000 },
+       { 0x405838,   1, 0x04, 0x00000000 },
+       { 0x405854,   1, 0x04, 0x00000000 },
+       { 0x405870,   4, 0x04, 0x00000001 },
+       { 0x405a00,   2, 0x04, 0x00000000 },
+       { 0x405a18,   1, 0x04, 0x00000000 },
+       { 0x405a1c,   1, 0x04, 0x000000ff },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_pd_0[] = {
+       { 0x406020,   1, 0x04, 0x07410001 },
+       { 0x406028,   4, 0x04, 0x00000001 },
+       { 0x4064a8,   1, 0x04, 0x00000000 },
+       { 0x4064ac,   1, 0x04, 0x00003fff },
+       { 0x4064b0,   3, 0x04, 0x00000000 },
+       { 0x4064c0,   1, 0x04, 0x80400280 },
+       { 0x4064c4,   1, 0x04, 0x0400ffff },
+       { 0x4064c8,   1, 0x04, 0x018001ff },
+       { 0x4064cc,   9, 0x04, 0x00000000 },
+       { 0x4064fc,   1, 0x04, 0x0000022a },
+       { 0x406500,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_be_0[] = {
+       { 0x408800,   1, 0x04, 0x32802a3c },
+       { 0x408804,   1, 0x04, 0x00000040 },
+       { 0x408808,   1, 0x04, 0x1003e005 },
+       { 0x408840,   1, 0x04, 0x0000000b },
+       { 0x408900,   1, 0x04, 0xb080b801 },
+       { 0x408904,   1, 0x04, 0x63038001 },
+       { 0x408908,   1, 0x04, 0x02c8102f },
+       { 0x408980,   1, 0x04, 0x0000011d },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { gm107_grctx_init_fe_0 },
+       { nvf0_grctx_init_pri_0 },
+       { nve4_grctx_init_memfmt_0 },
+       { gm107_grctx_init_ds_0 },
+       { nvf0_grctx_init_cwd_0 },
+       { gm107_grctx_init_pd_0 },
+       { nv108_grctx_init_rstr2d_0 },
+       { nve4_grctx_init_scc_0 },
+       { gm107_grctx_init_be_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_gpc_unk_0[] = {
+       { 0x418380,   1, 0x04, 0x00000056 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_gpc_unk_1[] = {
+       { 0x418600,   1, 0x04, 0x0000007f },
+       { 0x418684,   1, 0x04, 0x0000001f },
+       { 0x418700,   1, 0x04, 0x00000002 },
+       { 0x418704,   1, 0x04, 0x00000080 },
+       { 0x418708,   1, 0x04, 0x40000000 },
+       { 0x41870c,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_setup_0[] = {
+       { 0x418800,   1, 0x04, 0x7006863a },
+       { 0x418810,   1, 0x04, 0x00000000 },
+       { 0x418828,   1, 0x04, 0x00000044 },
+       { 0x418830,   1, 0x04, 0x10000001 },
+       { 0x4188d8,   1, 0x04, 0x00000008 },
+       { 0x4188e0,   1, 0x04, 0x01000000 },
+       { 0x4188e8,   5, 0x04, 0x00000000 },
+       { 0x4188fc,   1, 0x04, 0x20100058 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_gpc_unk_2[] = {
+       { 0x418d24,   1, 0x04, 0x00000000 },
+       { 0x418e00,   1, 0x04, 0x90000000 },
+       { 0x418e24,   1, 0x04, 0x00000000 },
+       { 0x418e28,   1, 0x04, 0x00000030 },
+       { 0x418e30,   1, 0x04, 0x00000000 },
+       { 0x418e34,   1, 0x04, 0x00010000 },
+       { 0x418e38,   1, 0x04, 0x00000000 },
+       { 0x418e40,  22, 0x04, 0x00000000 },
+       { 0x418ea0,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_gpc[] = {
+       { gm107_grctx_init_gpc_unk_0 },
+       { nv108_grctx_init_prop_0 },
+       { gm107_grctx_init_gpc_unk_1 },
+       { gm107_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nv108_grctx_init_crstr_0 },
+       { nve4_grctx_init_gpm_0 },
+       { gm107_grctx_init_gpc_unk_2 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_tex_0[] = {
+       { 0x419a00,   1, 0x04, 0x000300f0 },
+       { 0x419a04,   1, 0x04, 0x00000005 },
+       { 0x419a08,   1, 0x04, 0x00000421 },
+       { 0x419a0c,   1, 0x04, 0x00120000 },
+       { 0x419a10,   1, 0x04, 0x00000000 },
+       { 0x419a14,   1, 0x04, 0x00002200 },
+       { 0x419a1c,   1, 0x04, 0x0000c000 },
+       { 0x419a20,   1, 0x04, 0x20008a00 },
+       { 0x419a30,   1, 0x04, 0x00000001 },
+       { 0x419a3c,   1, 0x04, 0x00000002 },
+       { 0x419ac4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_mpc_0[] = {
+       { 0x419c00,   1, 0x04, 0x0000001a },
+       { 0x419c04,   1, 0x04, 0x80000006 },
+       { 0x419c08,   1, 0x04, 0x00000002 },
+       { 0x419c20,   1, 0x04, 0x00000000 },
+       { 0x419c24,   1, 0x04, 0x00084210 },
+       { 0x419c28,   1, 0x04, 0x3efbefbe },
+       { 0x419c2c,   1, 0x04, 0x00000000 },
+       { 0x419c34,   1, 0x04, 0x01ff1ff3 },
+       { 0x419c3c,   1, 0x04, 0x00001919 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_l1c_0[] = {
+       { 0x419c84,   1, 0x04, 0x00000020 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_sm_0[] = {
+       { 0x419e04,   3, 0x04, 0x00000000 },
+       { 0x419e10,   1, 0x04, 0x00001c02 },
+       { 0x419e44,   1, 0x04, 0x00d3eff2 },
+       { 0x419e48,   1, 0x04, 0x00000000 },
+       { 0x419e4c,   1, 0x04, 0x0000007f },
+       { 0x419e50,   1, 0x04, 0x00000000 },
+       { 0x419e60,   4, 0x04, 0x00000000 },
+       { 0x419e74,  10, 0x04, 0x00000000 },
+       { 0x419eac,   1, 0x04, 0x0001cf8b },
+       { 0x419eb0,   1, 0x04, 0x00030300 },
+       { 0x419eb8,   1, 0x04, 0x00000000 },
+       { 0x419ef0,  24, 0x04, 0x00000000 },
+       { 0x419f68,   2, 0x04, 0x00000000 },
+       { 0x419f70,   1, 0x04, 0x00000020 },
+       { 0x419f78,   1, 0x04, 0x000003eb },
+       { 0x419f7c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_tpc[] = {
+       { nvd7_grctx_init_pe_0 },
+       { gm107_grctx_init_tex_0 },
+       { gm107_grctx_init_mpc_0 },
+       { gm107_grctx_init_l1c_0 },
+       { gm107_grctx_init_sm_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_cbm_0[] = {
+       { 0x41bec0,   1, 0x04, 0x00000000 },
+       { 0x41bec4,   1, 0x04, 0x01050000 },
+       { 0x41bee4,   1, 0x04, 0x00000000 },
+       { 0x41bef0,   1, 0x04, 0x000003ff },
+       { 0x41bef4,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_grctx_init_wwdx_0[] = {
+       { 0x41bf00,   1, 0x04, 0x0a418820 },
+       { 0x41bf04,   1, 0x04, 0x062080e6 },
+       { 0x41bf08,   1, 0x04, 0x020398a4 },
+       { 0x41bf0c,   1, 0x04, 0x0e629062 },
+       { 0x41bf10,   1, 0x04, 0x0a418820 },
+       { 0x41bf14,   1, 0x04, 0x000000e6 },
+       { 0x41bfd0,   1, 0x04, 0x00900103 },
+       { 0x41bfe0,   1, 0x04, 0x80000000 },
+       { 0x41bfe4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_grctx_pack_ppc[] = {
+       { nve4_grctx_init_pes_0 },
+       { gm107_grctx_init_cbm_0 },
+       { gm107_grctx_init_wwdx_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
+static void
+gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+       mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+
+       mmio_list(0x40800c, 0x00000000,  8, 1);
+       mmio_list(0x408010, 0x80000000,  0, 0);
+       mmio_list(0x419004, 0x00000000,  8, 1);
+       mmio_list(0x419008, 0x00000000,  0, 0);
+       mmio_list(0x4064cc, 0x80000000,  0, 0);
+       mmio_list(0x418e30, 0x80000000,  0, 0);
+
+       mmio_list(0x408004, 0x00000000,  8, 0);
+       mmio_list(0x408008, 0x80000030,  0, 0);
+       mmio_list(0x418e24, 0x00000000,  8, 0);
+       mmio_list(0x418e28, 0x80000030,  0, 0);
+
+       mmio_list(0x418810, 0x80000000, 12, 2);
+       mmio_list(0x419848, 0x10000000, 12, 2);
+       mmio_list(0x419c2c, 0x10000000, 12, 2);
+
+       mmio_list(0x405830, 0x0aa01000,  0, 0);
+       mmio_list(0x4064c4, 0x0400ffff,  0, 0);
+
+       /*XXX*/
+       mmio_list(0x5030c0, 0x00001540,  0, 0);
+       mmio_list(0x5030f4, 0x00000000,  0, 0);
+       mmio_list(0x5030e4, 0x00002000,  0, 0);
+       mmio_list(0x5030f8, 0x00003fc0,  0, 0);
+       mmio_list(0x418ea0, 0x07151540,  0, 0);
+
+       mmio_list(0x5032c0, 0x00001540,  0, 0);
+       mmio_list(0x5032f4, 0x00001fe0,  0, 0);
+       mmio_list(0x5032e4, 0x00002000,  0, 0);
+       mmio_list(0x5032f8, 0x00006fc0,  0, 0);
+       mmio_list(0x418ea4, 0x07151540,  0, 0);
+}
+
+static void
+gm107_grctx_generate_tpcid(struct nvc0_graph_priv *priv)
+{
+       int gpc, tpc, id;
+
+       for (tpc = 0, id = 0; tpc < 4; tpc++) {
+               for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+                       if (tpc < priv->tpc_nr[gpc]) {
+                               nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id);
+                               nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id);
+                               nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id);
+                               id++;
+                       }
+
+                       nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]);
+                       nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]);
+               }
+       }
+}
+
+static void
+gm107_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+       struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
+       int i;
+
+       nvc0_graph_mmio(priv, oclass->hub);
+       nvc0_graph_mmio(priv, oclass->gpc);
+       nvc0_graph_mmio(priv, oclass->zcull);
+       nvc0_graph_mmio(priv, oclass->tpc);
+       nvc0_graph_mmio(priv, oclass->ppc);
+
+       nv_wr32(priv, 0x404154, 0x00000000);
+
+       oclass->mods(priv, info);
+       oclass->unkn(priv);
+
+       gm107_grctx_generate_tpcid(priv);
+       nvc0_grctx_generate_r406028(priv);
+       nve4_grctx_generate_r418bb8(priv);
+       nvc0_grctx_generate_r406800(priv);
+
+       nv_wr32(priv, 0x4064d0, 0x00000001);
+       for (i = 1; i < 8; i++)
+               nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000);
+       nv_wr32(priv, 0x406500, 0x00000001);
+
+       nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
+
+       if (priv->gpc_nr == 1) {
+               nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]);
+               nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]);
+       } else {
+               nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr);
+               nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr);
+       }
+
+       nvc0_graph_icmd(priv, oclass->icmd);
+       nv_wr32(priv, 0x404154, 0x00000400);
+       nvc0_graph_mthd(priv, oclass->mthd);
+
+       nv_mask(priv, 0x419e00, 0x00808080, 0x00808080);
+       nv_mask(priv, 0x419ccc, 0x80000000, 0x80000000);
+       nv_mask(priv, 0x419f80, 0x80000000, 0x80000000);
+       nv_mask(priv, 0x419f88, 0x80000000, 0x80000000);
+}
+
+struct nouveau_oclass *
+gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
+       .base.handle = NV_ENGCTX(GR, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_context_ctor,
+               .dtor = nvc0_graph_context_dtor,
+               .init = _nouveau_graph_context_init,
+               .fini = _nouveau_graph_context_fini,
+               .rd32 = _nouveau_graph_context_rd32,
+               .wr32 = _nouveau_graph_context_wr32,
+       },
+       .main  = gm107_grctx_generate_main,
+       .mods  = gm107_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = gm107_grctx_pack_hub,
+       .gpc   = gm107_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = gm107_grctx_pack_tpc,
+       .ppc   = gm107_grctx_pack_ppc,
+       .icmd  = gm107_grctx_pack_icmd,
+       .mthd  = gm107_grctx_pack_mthd,
+}.base;
index a86bd3352bf823aa4919c301c7c6560e6682f7d7..48351b4d6d6bd8460ee83b2110f9e1adce7235bf 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-static struct nvc0_graph_init
-nv108_grctx_init_icmd[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nv108_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x000039,   3, 0x01, 0x00000000 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
@@ -274,839 +278,14 @@ nv108_grctx_init_icmd[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_a197[] = {
-       { 0x000800,   1, 0x04, 0x00000000 },
-       { 0x000840,   1, 0x04, 0x00000000 },
-       { 0x000880,   1, 0x04, 0x00000000 },
-       { 0x0008c0,   1, 0x04, 0x00000000 },
-       { 0x000900,   1, 0x04, 0x00000000 },
-       { 0x000940,   1, 0x04, 0x00000000 },
-       { 0x000980,   1, 0x04, 0x00000000 },
-       { 0x0009c0,   1, 0x04, 0x00000000 },
-       { 0x000804,   1, 0x04, 0x00000000 },
-       { 0x000844,   1, 0x04, 0x00000000 },
-       { 0x000884,   1, 0x04, 0x00000000 },
-       { 0x0008c4,   1, 0x04, 0x00000000 },
-       { 0x000904,   1, 0x04, 0x00000000 },
-       { 0x000944,   1, 0x04, 0x00000000 },
-       { 0x000984,   1, 0x04, 0x00000000 },
-       { 0x0009c4,   1, 0x04, 0x00000000 },
-       { 0x000808,   1, 0x04, 0x00000400 },
-       { 0x000848,   1, 0x04, 0x00000400 },
-       { 0x000888,   1, 0x04, 0x00000400 },
-       { 0x0008c8,   1, 0x04, 0x00000400 },
-       { 0x000908,   1, 0x04, 0x00000400 },
-       { 0x000948,   1, 0x04, 0x00000400 },
-       { 0x000988,   1, 0x04, 0x00000400 },
-       { 0x0009c8,   1, 0x04, 0x00000400 },
-       { 0x00080c,   1, 0x04, 0x00000300 },
-       { 0x00084c,   1, 0x04, 0x00000300 },
-       { 0x00088c,   1, 0x04, 0x00000300 },
-       { 0x0008cc,   1, 0x04, 0x00000300 },
-       { 0x00090c,   1, 0x04, 0x00000300 },
-       { 0x00094c,   1, 0x04, 0x00000300 },
-       { 0x00098c,   1, 0x04, 0x00000300 },
-       { 0x0009cc,   1, 0x04, 0x00000300 },
-       { 0x000810,   1, 0x04, 0x000000cf },
-       { 0x000850,   1, 0x04, 0x00000000 },
-       { 0x000890,   1, 0x04, 0x00000000 },
-       { 0x0008d0,   1, 0x04, 0x00000000 },
-       { 0x000910,   1, 0x04, 0x00000000 },
-       { 0x000950,   1, 0x04, 0x00000000 },
-       { 0x000990,   1, 0x04, 0x00000000 },
-       { 0x0009d0,   1, 0x04, 0x00000000 },
-       { 0x000814,   1, 0x04, 0x00000040 },
-       { 0x000854,   1, 0x04, 0x00000040 },
-       { 0x000894,   1, 0x04, 0x00000040 },
-       { 0x0008d4,   1, 0x04, 0x00000040 },
-       { 0x000914,   1, 0x04, 0x00000040 },
-       { 0x000954,   1, 0x04, 0x00000040 },
-       { 0x000994,   1, 0x04, 0x00000040 },
-       { 0x0009d4,   1, 0x04, 0x00000040 },
-       { 0x000818,   1, 0x04, 0x00000001 },
-       { 0x000858,   1, 0x04, 0x00000001 },
-       { 0x000898,   1, 0x04, 0x00000001 },
-       { 0x0008d8,   1, 0x04, 0x00000001 },
-       { 0x000918,   1, 0x04, 0x00000001 },
-       { 0x000958,   1, 0x04, 0x00000001 },
-       { 0x000998,   1, 0x04, 0x00000001 },
-       { 0x0009d8,   1, 0x04, 0x00000001 },
-       { 0x00081c,   1, 0x04, 0x00000000 },
-       { 0x00085c,   1, 0x04, 0x00000000 },
-       { 0x00089c,   1, 0x04, 0x00000000 },
-       { 0x0008dc,   1, 0x04, 0x00000000 },
-       { 0x00091c,   1, 0x04, 0x00000000 },
-       { 0x00095c,   1, 0x04, 0x00000000 },
-       { 0x00099c,   1, 0x04, 0x00000000 },
-       { 0x0009dc,   1, 0x04, 0x00000000 },
-       { 0x000820,   1, 0x04, 0x00000000 },
-       { 0x000860,   1, 0x04, 0x00000000 },
-       { 0x0008a0,   1, 0x04, 0x00000000 },
-       { 0x0008e0,   1, 0x04, 0x00000000 },
-       { 0x000920,   1, 0x04, 0x00000000 },
-       { 0x000960,   1, 0x04, 0x00000000 },
-       { 0x0009a0,   1, 0x04, 0x00000000 },
-       { 0x0009e0,   1, 0x04, 0x00000000 },
-       { 0x001c00,   1, 0x04, 0x00000000 },
-       { 0x001c10,   1, 0x04, 0x00000000 },
-       { 0x001c20,   1, 0x04, 0x00000000 },
-       { 0x001c30,   1, 0x04, 0x00000000 },
-       { 0x001c40,   1, 0x04, 0x00000000 },
-       { 0x001c50,   1, 0x04, 0x00000000 },
-       { 0x001c60,   1, 0x04, 0x00000000 },
-       { 0x001c70,   1, 0x04, 0x00000000 },
-       { 0x001c80,   1, 0x04, 0x00000000 },
-       { 0x001c90,   1, 0x04, 0x00000000 },
-       { 0x001ca0,   1, 0x04, 0x00000000 },
-       { 0x001cb0,   1, 0x04, 0x00000000 },
-       { 0x001cc0,   1, 0x04, 0x00000000 },
-       { 0x001cd0,   1, 0x04, 0x00000000 },
-       { 0x001ce0,   1, 0x04, 0x00000000 },
-       { 0x001cf0,   1, 0x04, 0x00000000 },
-       { 0x001c04,   1, 0x04, 0x00000000 },
-       { 0x001c14,   1, 0x04, 0x00000000 },
-       { 0x001c24,   1, 0x04, 0x00000000 },
-       { 0x001c34,   1, 0x04, 0x00000000 },
-       { 0x001c44,   1, 0x04, 0x00000000 },
-       { 0x001c54,   1, 0x04, 0x00000000 },
-       { 0x001c64,   1, 0x04, 0x00000000 },
-       { 0x001c74,   1, 0x04, 0x00000000 },
-       { 0x001c84,   1, 0x04, 0x00000000 },
-       { 0x001c94,   1, 0x04, 0x00000000 },
-       { 0x001ca4,   1, 0x04, 0x00000000 },
-       { 0x001cb4,   1, 0x04, 0x00000000 },
-       { 0x001cc4,   1, 0x04, 0x00000000 },
-       { 0x001cd4,   1, 0x04, 0x00000000 },
-       { 0x001ce4,   1, 0x04, 0x00000000 },
-       { 0x001cf4,   1, 0x04, 0x00000000 },
-       { 0x001c08,   1, 0x04, 0x00000000 },
-       { 0x001c18,   1, 0x04, 0x00000000 },
-       { 0x001c28,   1, 0x04, 0x00000000 },
-       { 0x001c38,   1, 0x04, 0x00000000 },
-       { 0x001c48,   1, 0x04, 0x00000000 },
-       { 0x001c58,   1, 0x04, 0x00000000 },
-       { 0x001c68,   1, 0x04, 0x00000000 },
-       { 0x001c78,   1, 0x04, 0x00000000 },
-       { 0x001c88,   1, 0x04, 0x00000000 },
-       { 0x001c98,   1, 0x04, 0x00000000 },
-       { 0x001ca8,   1, 0x04, 0x00000000 },
-       { 0x001cb8,   1, 0x04, 0x00000000 },
-       { 0x001cc8,   1, 0x04, 0x00000000 },
-       { 0x001cd8,   1, 0x04, 0x00000000 },
-       { 0x001ce8,   1, 0x04, 0x00000000 },
-       { 0x001cf8,   1, 0x04, 0x00000000 },
-       { 0x001c0c,   1, 0x04, 0x00000000 },
-       { 0x001c1c,   1, 0x04, 0x00000000 },
-       { 0x001c2c,   1, 0x04, 0x00000000 },
-       { 0x001c3c,   1, 0x04, 0x00000000 },
-       { 0x001c4c,   1, 0x04, 0x00000000 },
-       { 0x001c5c,   1, 0x04, 0x00000000 },
-       { 0x001c6c,   1, 0x04, 0x00000000 },
-       { 0x001c7c,   1, 0x04, 0x00000000 },
-       { 0x001c8c,   1, 0x04, 0x00000000 },
-       { 0x001c9c,   1, 0x04, 0x00000000 },
-       { 0x001cac,   1, 0x04, 0x00000000 },
-       { 0x001cbc,   1, 0x04, 0x00000000 },
-       { 0x001ccc,   1, 0x04, 0x00000000 },
-       { 0x001cdc,   1, 0x04, 0x00000000 },
-       { 0x001cec,   1, 0x04, 0x00000000 },
-       { 0x001cfc,   2, 0x04, 0x00000000 },
-       { 0x001d10,   1, 0x04, 0x00000000 },
-       { 0x001d20,   1, 0x04, 0x00000000 },
-       { 0x001d30,   1, 0x04, 0x00000000 },
-       { 0x001d40,   1, 0x04, 0x00000000 },
-       { 0x001d50,   1, 0x04, 0x00000000 },
-       { 0x001d60,   1, 0x04, 0x00000000 },
-       { 0x001d70,   1, 0x04, 0x00000000 },
-       { 0x001d80,   1, 0x04, 0x00000000 },
-       { 0x001d90,   1, 0x04, 0x00000000 },
-       { 0x001da0,   1, 0x04, 0x00000000 },
-       { 0x001db0,   1, 0x04, 0x00000000 },
-       { 0x001dc0,   1, 0x04, 0x00000000 },
-       { 0x001dd0,   1, 0x04, 0x00000000 },
-       { 0x001de0,   1, 0x04, 0x00000000 },
-       { 0x001df0,   1, 0x04, 0x00000000 },
-       { 0x001d04,   1, 0x04, 0x00000000 },
-       { 0x001d14,   1, 0x04, 0x00000000 },
-       { 0x001d24,   1, 0x04, 0x00000000 },
-       { 0x001d34,   1, 0x04, 0x00000000 },
-       { 0x001d44,   1, 0x04, 0x00000000 },
-       { 0x001d54,   1, 0x04, 0x00000000 },
-       { 0x001d64,   1, 0x04, 0x00000000 },
-       { 0x001d74,   1, 0x04, 0x00000000 },
-       { 0x001d84,   1, 0x04, 0x00000000 },
-       { 0x001d94,   1, 0x04, 0x00000000 },
-       { 0x001da4,   1, 0x04, 0x00000000 },
-       { 0x001db4,   1, 0x04, 0x00000000 },
-       { 0x001dc4,   1, 0x04, 0x00000000 },
-       { 0x001dd4,   1, 0x04, 0x00000000 },
-       { 0x001de4,   1, 0x04, 0x00000000 },
-       { 0x001df4,   1, 0x04, 0x00000000 },
-       { 0x001d08,   1, 0x04, 0x00000000 },
-       { 0x001d18,   1, 0x04, 0x00000000 },
-       { 0x001d28,   1, 0x04, 0x00000000 },
-       { 0x001d38,   1, 0x04, 0x00000000 },
-       { 0x001d48,   1, 0x04, 0x00000000 },
-       { 0x001d58,   1, 0x04, 0x00000000 },
-       { 0x001d68,   1, 0x04, 0x00000000 },
-       { 0x001d78,   1, 0x04, 0x00000000 },
-       { 0x001d88,   1, 0x04, 0x00000000 },
-       { 0x001d98,   1, 0x04, 0x00000000 },
-       { 0x001da8,   1, 0x04, 0x00000000 },
-       { 0x001db8,   1, 0x04, 0x00000000 },
-       { 0x001dc8,   1, 0x04, 0x00000000 },
-       { 0x001dd8,   1, 0x04, 0x00000000 },
-       { 0x001de8,   1, 0x04, 0x00000000 },
-       { 0x001df8,   1, 0x04, 0x00000000 },
-       { 0x001d0c,   1, 0x04, 0x00000000 },
-       { 0x001d1c,   1, 0x04, 0x00000000 },
-       { 0x001d2c,   1, 0x04, 0x00000000 },
-       { 0x001d3c,   1, 0x04, 0x00000000 },
-       { 0x001d4c,   1, 0x04, 0x00000000 },
-       { 0x001d5c,   1, 0x04, 0x00000000 },
-       { 0x001d6c,   1, 0x04, 0x00000000 },
-       { 0x001d7c,   1, 0x04, 0x00000000 },
-       { 0x001d8c,   1, 0x04, 0x00000000 },
-       { 0x001d9c,   1, 0x04, 0x00000000 },
-       { 0x001dac,   1, 0x04, 0x00000000 },
-       { 0x001dbc,   1, 0x04, 0x00000000 },
-       { 0x001dcc,   1, 0x04, 0x00000000 },
-       { 0x001ddc,   1, 0x04, 0x00000000 },
-       { 0x001dec,   1, 0x04, 0x00000000 },
-       { 0x001dfc,   1, 0x04, 0x00000000 },
-       { 0x001f00,   1, 0x04, 0x00000000 },
-       { 0x001f08,   1, 0x04, 0x00000000 },
-       { 0x001f10,   1, 0x04, 0x00000000 },
-       { 0x001f18,   1, 0x04, 0x00000000 },
-       { 0x001f20,   1, 0x04, 0x00000000 },
-       { 0x001f28,   1, 0x04, 0x00000000 },
-       { 0x001f30,   1, 0x04, 0x00000000 },
-       { 0x001f38,   1, 0x04, 0x00000000 },
-       { 0x001f40,   1, 0x04, 0x00000000 },
-       { 0x001f48,   1, 0x04, 0x00000000 },
-       { 0x001f50,   1, 0x04, 0x00000000 },
-       { 0x001f58,   1, 0x04, 0x00000000 },
-       { 0x001f60,   1, 0x04, 0x00000000 },
-       { 0x001f68,   1, 0x04, 0x00000000 },
-       { 0x001f70,   1, 0x04, 0x00000000 },
-       { 0x001f78,   1, 0x04, 0x00000000 },
-       { 0x001f04,   1, 0x04, 0x00000000 },
-       { 0x001f0c,   1, 0x04, 0x00000000 },
-       { 0x001f14,   1, 0x04, 0x00000000 },
-       { 0x001f1c,   1, 0x04, 0x00000000 },
-       { 0x001f24,   1, 0x04, 0x00000000 },
-       { 0x001f2c,   1, 0x04, 0x00000000 },
-       { 0x001f34,   1, 0x04, 0x00000000 },
-       { 0x001f3c,   1, 0x04, 0x00000000 },
-       { 0x001f44,   1, 0x04, 0x00000000 },
-       { 0x001f4c,   1, 0x04, 0x00000000 },
-       { 0x001f54,   1, 0x04, 0x00000000 },
-       { 0x001f5c,   1, 0x04, 0x00000000 },
-       { 0x001f64,   1, 0x04, 0x00000000 },
-       { 0x001f6c,   1, 0x04, 0x00000000 },
-       { 0x001f74,   1, 0x04, 0x00000000 },
-       { 0x001f7c,   2, 0x04, 0x00000000 },
-       { 0x001f88,   1, 0x04, 0x00000000 },
-       { 0x001f90,   1, 0x04, 0x00000000 },
-       { 0x001f98,   1, 0x04, 0x00000000 },
-       { 0x001fa0,   1, 0x04, 0x00000000 },
-       { 0x001fa8,   1, 0x04, 0x00000000 },
-       { 0x001fb0,   1, 0x04, 0x00000000 },
-       { 0x001fb8,   1, 0x04, 0x00000000 },
-       { 0x001fc0,   1, 0x04, 0x00000000 },
-       { 0x001fc8,   1, 0x04, 0x00000000 },
-       { 0x001fd0,   1, 0x04, 0x00000000 },
-       { 0x001fd8,   1, 0x04, 0x00000000 },
-       { 0x001fe0,   1, 0x04, 0x00000000 },
-       { 0x001fe8,   1, 0x04, 0x00000000 },
-       { 0x001ff0,   1, 0x04, 0x00000000 },
-       { 0x001ff8,   1, 0x04, 0x00000000 },
-       { 0x001f84,   1, 0x04, 0x00000000 },
-       { 0x001f8c,   1, 0x04, 0x00000000 },
-       { 0x001f94,   1, 0x04, 0x00000000 },
-       { 0x001f9c,   1, 0x04, 0x00000000 },
-       { 0x001fa4,   1, 0x04, 0x00000000 },
-       { 0x001fac,   1, 0x04, 0x00000000 },
-       { 0x001fb4,   1, 0x04, 0x00000000 },
-       { 0x001fbc,   1, 0x04, 0x00000000 },
-       { 0x001fc4,   1, 0x04, 0x00000000 },
-       { 0x001fcc,   1, 0x04, 0x00000000 },
-       { 0x001fd4,   1, 0x04, 0x00000000 },
-       { 0x001fdc,   1, 0x04, 0x00000000 },
-       { 0x001fe4,   1, 0x04, 0x00000000 },
-       { 0x001fec,   1, 0x04, 0x00000000 },
-       { 0x001ff4,   1, 0x04, 0x00000000 },
-       { 0x001ffc,   2, 0x04, 0x00000000 },
-       { 0x002040,   1, 0x04, 0x00000011 },
-       { 0x002080,   1, 0x04, 0x00000020 },
-       { 0x0020c0,   1, 0x04, 0x00000030 },
-       { 0x002100,   1, 0x04, 0x00000040 },
-       { 0x002140,   1, 0x04, 0x00000051 },
-       { 0x00200c,   1, 0x04, 0x00000001 },
-       { 0x00204c,   1, 0x04, 0x00000001 },
-       { 0x00208c,   1, 0x04, 0x00000001 },
-       { 0x0020cc,   1, 0x04, 0x00000001 },
-       { 0x00210c,   1, 0x04, 0x00000001 },
-       { 0x00214c,   1, 0x04, 0x00000001 },
-       { 0x002010,   1, 0x04, 0x00000000 },
-       { 0x002050,   1, 0x04, 0x00000000 },
-       { 0x002090,   1, 0x04, 0x00000001 },
-       { 0x0020d0,   1, 0x04, 0x00000002 },
-       { 0x002110,   1, 0x04, 0x00000003 },
-       { 0x002150,   1, 0x04, 0x00000004 },
-       { 0x000380,   1, 0x04, 0x00000000 },
-       { 0x0003a0,   1, 0x04, 0x00000000 },
-       { 0x0003c0,   1, 0x04, 0x00000000 },
-       { 0x0003e0,   1, 0x04, 0x00000000 },
-       { 0x000384,   1, 0x04, 0x00000000 },
-       { 0x0003a4,   1, 0x04, 0x00000000 },
-       { 0x0003c4,   1, 0x04, 0x00000000 },
-       { 0x0003e4,   1, 0x04, 0x00000000 },
-       { 0x000388,   1, 0x04, 0x00000000 },
-       { 0x0003a8,   1, 0x04, 0x00000000 },
-       { 0x0003c8,   1, 0x04, 0x00000000 },
-       { 0x0003e8,   1, 0x04, 0x00000000 },
-       { 0x00038c,   1, 0x04, 0x00000000 },
-       { 0x0003ac,   1, 0x04, 0x00000000 },
-       { 0x0003cc,   1, 0x04, 0x00000000 },
-       { 0x0003ec,   1, 0x04, 0x00000000 },
-       { 0x000700,   1, 0x04, 0x00000000 },
-       { 0x000710,   1, 0x04, 0x00000000 },
-       { 0x000720,   1, 0x04, 0x00000000 },
-       { 0x000730,   1, 0x04, 0x00000000 },
-       { 0x000704,   1, 0x04, 0x00000000 },
-       { 0x000714,   1, 0x04, 0x00000000 },
-       { 0x000724,   1, 0x04, 0x00000000 },
-       { 0x000734,   1, 0x04, 0x00000000 },
-       { 0x000708,   1, 0x04, 0x00000000 },
-       { 0x000718,   1, 0x04, 0x00000000 },
-       { 0x000728,   1, 0x04, 0x00000000 },
-       { 0x000738,   1, 0x04, 0x00000000 },
-       { 0x002800, 128, 0x04, 0x00000000 },
-       { 0x000a00,   1, 0x04, 0x00000000 },
-       { 0x000a20,   1, 0x04, 0x00000000 },
-       { 0x000a40,   1, 0x04, 0x00000000 },
-       { 0x000a60,   1, 0x04, 0x00000000 },
-       { 0x000a80,   1, 0x04, 0x00000000 },
-       { 0x000aa0,   1, 0x04, 0x00000000 },
-       { 0x000ac0,   1, 0x04, 0x00000000 },
-       { 0x000ae0,   1, 0x04, 0x00000000 },
-       { 0x000b00,   1, 0x04, 0x00000000 },
-       { 0x000b20,   1, 0x04, 0x00000000 },
-       { 0x000b40,   1, 0x04, 0x00000000 },
-       { 0x000b60,   1, 0x04, 0x00000000 },
-       { 0x000b80,   1, 0x04, 0x00000000 },
-       { 0x000ba0,   1, 0x04, 0x00000000 },
-       { 0x000bc0,   1, 0x04, 0x00000000 },
-       { 0x000be0,   1, 0x04, 0x00000000 },
-       { 0x000a04,   1, 0x04, 0x00000000 },
-       { 0x000a24,   1, 0x04, 0x00000000 },
-       { 0x000a44,   1, 0x04, 0x00000000 },
-       { 0x000a64,   1, 0x04, 0x00000000 },
-       { 0x000a84,   1, 0x04, 0x00000000 },
-       { 0x000aa4,   1, 0x04, 0x00000000 },
-       { 0x000ac4,   1, 0x04, 0x00000000 },
-       { 0x000ae4,   1, 0x04, 0x00000000 },
-       { 0x000b04,   1, 0x04, 0x00000000 },
-       { 0x000b24,   1, 0x04, 0x00000000 },
-       { 0x000b44,   1, 0x04, 0x00000000 },
-       { 0x000b64,   1, 0x04, 0x00000000 },
-       { 0x000b84,   1, 0x04, 0x00000000 },
-       { 0x000ba4,   1, 0x04, 0x00000000 },
-       { 0x000bc4,   1, 0x04, 0x00000000 },
-       { 0x000be4,   1, 0x04, 0x00000000 },
-       { 0x000a08,   1, 0x04, 0x00000000 },
-       { 0x000a28,   1, 0x04, 0x00000000 },
-       { 0x000a48,   1, 0x04, 0x00000000 },
-       { 0x000a68,   1, 0x04, 0x00000000 },
-       { 0x000a88,   1, 0x04, 0x00000000 },
-       { 0x000aa8,   1, 0x04, 0x00000000 },
-       { 0x000ac8,   1, 0x04, 0x00000000 },
-       { 0x000ae8,   1, 0x04, 0x00000000 },
-       { 0x000b08,   1, 0x04, 0x00000000 },
-       { 0x000b28,   1, 0x04, 0x00000000 },
-       { 0x000b48,   1, 0x04, 0x00000000 },
-       { 0x000b68,   1, 0x04, 0x00000000 },
-       { 0x000b88,   1, 0x04, 0x00000000 },
-       { 0x000ba8,   1, 0x04, 0x00000000 },
-       { 0x000bc8,   1, 0x04, 0x00000000 },
-       { 0x000be8,   1, 0x04, 0x00000000 },
-       { 0x000a0c,   1, 0x04, 0x00000000 },
-       { 0x000a2c,   1, 0x04, 0x00000000 },
-       { 0x000a4c,   1, 0x04, 0x00000000 },
-       { 0x000a6c,   1, 0x04, 0x00000000 },
-       { 0x000a8c,   1, 0x04, 0x00000000 },
-       { 0x000aac,   1, 0x04, 0x00000000 },
-       { 0x000acc,   1, 0x04, 0x00000000 },
-       { 0x000aec,   1, 0x04, 0x00000000 },
-       { 0x000b0c,   1, 0x04, 0x00000000 },
-       { 0x000b2c,   1, 0x04, 0x00000000 },
-       { 0x000b4c,   1, 0x04, 0x00000000 },
-       { 0x000b6c,   1, 0x04, 0x00000000 },
-       { 0x000b8c,   1, 0x04, 0x00000000 },
-       { 0x000bac,   1, 0x04, 0x00000000 },
-       { 0x000bcc,   1, 0x04, 0x00000000 },
-       { 0x000bec,   1, 0x04, 0x00000000 },
-       { 0x000a10,   1, 0x04, 0x00000000 },
-       { 0x000a30,   1, 0x04, 0x00000000 },
-       { 0x000a50,   1, 0x04, 0x00000000 },
-       { 0x000a70,   1, 0x04, 0x00000000 },
-       { 0x000a90,   1, 0x04, 0x00000000 },
-       { 0x000ab0,   1, 0x04, 0x00000000 },
-       { 0x000ad0,   1, 0x04, 0x00000000 },
-       { 0x000af0,   1, 0x04, 0x00000000 },
-       { 0x000b10,   1, 0x04, 0x00000000 },
-       { 0x000b30,   1, 0x04, 0x00000000 },
-       { 0x000b50,   1, 0x04, 0x00000000 },
-       { 0x000b70,   1, 0x04, 0x00000000 },
-       { 0x000b90,   1, 0x04, 0x00000000 },
-       { 0x000bb0,   1, 0x04, 0x00000000 },
-       { 0x000bd0,   1, 0x04, 0x00000000 },
-       { 0x000bf0,   1, 0x04, 0x00000000 },
-       { 0x000a14,   1, 0x04, 0x00000000 },
-       { 0x000a34,   1, 0x04, 0x00000000 },
-       { 0x000a54,   1, 0x04, 0x00000000 },
-       { 0x000a74,   1, 0x04, 0x00000000 },
-       { 0x000a94,   1, 0x04, 0x00000000 },
-       { 0x000ab4,   1, 0x04, 0x00000000 },
-       { 0x000ad4,   1, 0x04, 0x00000000 },
-       { 0x000af4,   1, 0x04, 0x00000000 },
-       { 0x000b14,   1, 0x04, 0x00000000 },
-       { 0x000b34,   1, 0x04, 0x00000000 },
-       { 0x000b54,   1, 0x04, 0x00000000 },
-       { 0x000b74,   1, 0x04, 0x00000000 },
-       { 0x000b94,   1, 0x04, 0x00000000 },
-       { 0x000bb4,   1, 0x04, 0x00000000 },
-       { 0x000bd4,   1, 0x04, 0x00000000 },
-       { 0x000bf4,   1, 0x04, 0x00000000 },
-       { 0x000c00,   1, 0x04, 0x00000000 },
-       { 0x000c10,   1, 0x04, 0x00000000 },
-       { 0x000c20,   1, 0x04, 0x00000000 },
-       { 0x000c30,   1, 0x04, 0x00000000 },
-       { 0x000c40,   1, 0x04, 0x00000000 },
-       { 0x000c50,   1, 0x04, 0x00000000 },
-       { 0x000c60,   1, 0x04, 0x00000000 },
-       { 0x000c70,   1, 0x04, 0x00000000 },
-       { 0x000c80,   1, 0x04, 0x00000000 },
-       { 0x000c90,   1, 0x04, 0x00000000 },
-       { 0x000ca0,   1, 0x04, 0x00000000 },
-       { 0x000cb0,   1, 0x04, 0x00000000 },
-       { 0x000cc0,   1, 0x04, 0x00000000 },
-       { 0x000cd0,   1, 0x04, 0x00000000 },
-       { 0x000ce0,   1, 0x04, 0x00000000 },
-       { 0x000cf0,   1, 0x04, 0x00000000 },
-       { 0x000c04,   1, 0x04, 0x00000000 },
-       { 0x000c14,   1, 0x04, 0x00000000 },
-       { 0x000c24,   1, 0x04, 0x00000000 },
-       { 0x000c34,   1, 0x04, 0x00000000 },
-       { 0x000c44,   1, 0x04, 0x00000000 },
-       { 0x000c54,   1, 0x04, 0x00000000 },
-       { 0x000c64,   1, 0x04, 0x00000000 },
-       { 0x000c74,   1, 0x04, 0x00000000 },
-       { 0x000c84,   1, 0x04, 0x00000000 },
-       { 0x000c94,   1, 0x04, 0x00000000 },
-       { 0x000ca4,   1, 0x04, 0x00000000 },
-       { 0x000cb4,   1, 0x04, 0x00000000 },
-       { 0x000cc4,   1, 0x04, 0x00000000 },
-       { 0x000cd4,   1, 0x04, 0x00000000 },
-       { 0x000ce4,   1, 0x04, 0x00000000 },
-       { 0x000cf4,   1, 0x04, 0x00000000 },
-       { 0x000c08,   1, 0x04, 0x00000000 },
-       { 0x000c18,   1, 0x04, 0x00000000 },
-       { 0x000c28,   1, 0x04, 0x00000000 },
-       { 0x000c38,   1, 0x04, 0x00000000 },
-       { 0x000c48,   1, 0x04, 0x00000000 },
-       { 0x000c58,   1, 0x04, 0x00000000 },
-       { 0x000c68,   1, 0x04, 0x00000000 },
-       { 0x000c78,   1, 0x04, 0x00000000 },
-       { 0x000c88,   1, 0x04, 0x00000000 },
-       { 0x000c98,   1, 0x04, 0x00000000 },
-       { 0x000ca8,   1, 0x04, 0x00000000 },
-       { 0x000cb8,   1, 0x04, 0x00000000 },
-       { 0x000cc8,   1, 0x04, 0x00000000 },
-       { 0x000cd8,   1, 0x04, 0x00000000 },
-       { 0x000ce8,   1, 0x04, 0x00000000 },
-       { 0x000cf8,   1, 0x04, 0x00000000 },
-       { 0x000c0c,   1, 0x04, 0x3f800000 },
-       { 0x000c1c,   1, 0x04, 0x3f800000 },
-       { 0x000c2c,   1, 0x04, 0x3f800000 },
-       { 0x000c3c,   1, 0x04, 0x3f800000 },
-       { 0x000c4c,   1, 0x04, 0x3f800000 },
-       { 0x000c5c,   1, 0x04, 0x3f800000 },
-       { 0x000c6c,   1, 0x04, 0x3f800000 },
-       { 0x000c7c,   1, 0x04, 0x3f800000 },
-       { 0x000c8c,   1, 0x04, 0x3f800000 },
-       { 0x000c9c,   1, 0x04, 0x3f800000 },
-       { 0x000cac,   1, 0x04, 0x3f800000 },
-       { 0x000cbc,   1, 0x04, 0x3f800000 },
-       { 0x000ccc,   1, 0x04, 0x3f800000 },
-       { 0x000cdc,   1, 0x04, 0x3f800000 },
-       { 0x000cec,   1, 0x04, 0x3f800000 },
-       { 0x000cfc,   1, 0x04, 0x3f800000 },
-       { 0x000d00,   1, 0x04, 0xffff0000 },
-       { 0x000d08,   1, 0x04, 0xffff0000 },
-       { 0x000d10,   1, 0x04, 0xffff0000 },
-       { 0x000d18,   1, 0x04, 0xffff0000 },
-       { 0x000d20,   1, 0x04, 0xffff0000 },
-       { 0x000d28,   1, 0x04, 0xffff0000 },
-       { 0x000d30,   1, 0x04, 0xffff0000 },
-       { 0x000d38,   1, 0x04, 0xffff0000 },
-       { 0x000d04,   1, 0x04, 0xffff0000 },
-       { 0x000d0c,   1, 0x04, 0xffff0000 },
-       { 0x000d14,   1, 0x04, 0xffff0000 },
-       { 0x000d1c,   1, 0x04, 0xffff0000 },
-       { 0x000d24,   1, 0x04, 0xffff0000 },
-       { 0x000d2c,   1, 0x04, 0xffff0000 },
-       { 0x000d34,   1, 0x04, 0xffff0000 },
-       { 0x000d3c,   1, 0x04, 0xffff0000 },
-       { 0x000e00,   1, 0x04, 0x00000000 },
-       { 0x000e10,   1, 0x04, 0x00000000 },
-       { 0x000e20,   1, 0x04, 0x00000000 },
-       { 0x000e30,   1, 0x04, 0x00000000 },
-       { 0x000e40,   1, 0x04, 0x00000000 },
-       { 0x000e50,   1, 0x04, 0x00000000 },
-       { 0x000e60,   1, 0x04, 0x00000000 },
-       { 0x000e70,   1, 0x04, 0x00000000 },
-       { 0x000e80,   1, 0x04, 0x00000000 },
-       { 0x000e90,   1, 0x04, 0x00000000 },
-       { 0x000ea0,   1, 0x04, 0x00000000 },
-       { 0x000eb0,   1, 0x04, 0x00000000 },
-       { 0x000ec0,   1, 0x04, 0x00000000 },
-       { 0x000ed0,   1, 0x04, 0x00000000 },
-       { 0x000ee0,   1, 0x04, 0x00000000 },
-       { 0x000ef0,   1, 0x04, 0x00000000 },
-       { 0x000e04,   1, 0x04, 0xffff0000 },
-       { 0x000e14,   1, 0x04, 0xffff0000 },
-       { 0x000e24,   1, 0x04, 0xffff0000 },
-       { 0x000e34,   1, 0x04, 0xffff0000 },
-       { 0x000e44,   1, 0x04, 0xffff0000 },
-       { 0x000e54,   1, 0x04, 0xffff0000 },
-       { 0x000e64,   1, 0x04, 0xffff0000 },
-       { 0x000e74,   1, 0x04, 0xffff0000 },
-       { 0x000e84,   1, 0x04, 0xffff0000 },
-       { 0x000e94,   1, 0x04, 0xffff0000 },
-       { 0x000ea4,   1, 0x04, 0xffff0000 },
-       { 0x000eb4,   1, 0x04, 0xffff0000 },
-       { 0x000ec4,   1, 0x04, 0xffff0000 },
-       { 0x000ed4,   1, 0x04, 0xffff0000 },
-       { 0x000ee4,   1, 0x04, 0xffff0000 },
-       { 0x000ef4,   1, 0x04, 0xffff0000 },
-       { 0x000e08,   1, 0x04, 0xffff0000 },
-       { 0x000e18,   1, 0x04, 0xffff0000 },
-       { 0x000e28,   1, 0x04, 0xffff0000 },
-       { 0x000e38,   1, 0x04, 0xffff0000 },
-       { 0x000e48,   1, 0x04, 0xffff0000 },
-       { 0x000e58,   1, 0x04, 0xffff0000 },
-       { 0x000e68,   1, 0x04, 0xffff0000 },
-       { 0x000e78,   1, 0x04, 0xffff0000 },
-       { 0x000e88,   1, 0x04, 0xffff0000 },
-       { 0x000e98,   1, 0x04, 0xffff0000 },
-       { 0x000ea8,   1, 0x04, 0xffff0000 },
-       { 0x000eb8,   1, 0x04, 0xffff0000 },
-       { 0x000ec8,   1, 0x04, 0xffff0000 },
-       { 0x000ed8,   1, 0x04, 0xffff0000 },
-       { 0x000ee8,   1, 0x04, 0xffff0000 },
-       { 0x000ef8,   1, 0x04, 0xffff0000 },
-       { 0x000d40,   1, 0x04, 0x00000000 },
-       { 0x000d48,   1, 0x04, 0x00000000 },
-       { 0x000d50,   1, 0x04, 0x00000000 },
-       { 0x000d58,   1, 0x04, 0x00000000 },
-       { 0x000d44,   1, 0x04, 0x00000000 },
-       { 0x000d4c,   1, 0x04, 0x00000000 },
-       { 0x000d54,   1, 0x04, 0x00000000 },
-       { 0x000d5c,   1, 0x04, 0x00000000 },
-       { 0x001e00,   1, 0x04, 0x00000001 },
-       { 0x001e20,   1, 0x04, 0x00000001 },
-       { 0x001e40,   1, 0x04, 0x00000001 },
-       { 0x001e60,   1, 0x04, 0x00000001 },
-       { 0x001e80,   1, 0x04, 0x00000001 },
-       { 0x001ea0,   1, 0x04, 0x00000001 },
-       { 0x001ec0,   1, 0x04, 0x00000001 },
-       { 0x001ee0,   1, 0x04, 0x00000001 },
-       { 0x001e04,   1, 0x04, 0x00000001 },
-       { 0x001e24,   1, 0x04, 0x00000001 },
-       { 0x001e44,   1, 0x04, 0x00000001 },
-       { 0x001e64,   1, 0x04, 0x00000001 },
-       { 0x001e84,   1, 0x04, 0x00000001 },
-       { 0x001ea4,   1, 0x04, 0x00000001 },
-       { 0x001ec4,   1, 0x04, 0x00000001 },
-       { 0x001ee4,   1, 0x04, 0x00000001 },
-       { 0x001e08,   1, 0x04, 0x00000002 },
-       { 0x001e28,   1, 0x04, 0x00000002 },
-       { 0x001e48,   1, 0x04, 0x00000002 },
-       { 0x001e68,   1, 0x04, 0x00000002 },
-       { 0x001e88,   1, 0x04, 0x00000002 },
-       { 0x001ea8,   1, 0x04, 0x00000002 },
-       { 0x001ec8,   1, 0x04, 0x00000002 },
-       { 0x001ee8,   1, 0x04, 0x00000002 },
-       { 0x001e0c,   1, 0x04, 0x00000001 },
-       { 0x001e2c,   1, 0x04, 0x00000001 },
-       { 0x001e4c,   1, 0x04, 0x00000001 },
-       { 0x001e6c,   1, 0x04, 0x00000001 },
-       { 0x001e8c,   1, 0x04, 0x00000001 },
-       { 0x001eac,   1, 0x04, 0x00000001 },
-       { 0x001ecc,   1, 0x04, 0x00000001 },
-       { 0x001eec,   1, 0x04, 0x00000001 },
-       { 0x001e10,   1, 0x04, 0x00000001 },
-       { 0x001e30,   1, 0x04, 0x00000001 },
-       { 0x001e50,   1, 0x04, 0x00000001 },
-       { 0x001e70,   1, 0x04, 0x00000001 },
-       { 0x001e90,   1, 0x04, 0x00000001 },
-       { 0x001eb0,   1, 0x04, 0x00000001 },
-       { 0x001ed0,   1, 0x04, 0x00000001 },
-       { 0x001ef0,   1, 0x04, 0x00000001 },
-       { 0x001e14,   1, 0x04, 0x00000002 },
-       { 0x001e34,   1, 0x04, 0x00000002 },
-       { 0x001e54,   1, 0x04, 0x00000002 },
-       { 0x001e74,   1, 0x04, 0x00000002 },
-       { 0x001e94,   1, 0x04, 0x00000002 },
-       { 0x001eb4,   1, 0x04, 0x00000002 },
-       { 0x001ed4,   1, 0x04, 0x00000002 },
-       { 0x001ef4,   1, 0x04, 0x00000002 },
-       { 0x001e18,   1, 0x04, 0x00000001 },
-       { 0x001e38,   1, 0x04, 0x00000001 },
-       { 0x001e58,   1, 0x04, 0x00000001 },
-       { 0x001e78,   1, 0x04, 0x00000001 },
-       { 0x001e98,   1, 0x04, 0x00000001 },
-       { 0x001eb8,   1, 0x04, 0x00000001 },
-       { 0x001ed8,   1, 0x04, 0x00000001 },
-       { 0x001ef8,   1, 0x04, 0x00000001 },
-       { 0x003400, 128, 0x04, 0x00000000 },
-       { 0x00030c,   1, 0x04, 0x00000001 },
-       { 0x001944,   1, 0x04, 0x00000000 },
-       { 0x001514,   1, 0x04, 0x00000000 },
-       { 0x000d68,   1, 0x04, 0x0000ffff },
-       { 0x00121c,   1, 0x04, 0x0fac6881 },
-       { 0x000fac,   1, 0x04, 0x00000001 },
-       { 0x001538,   1, 0x04, 0x00000001 },
-       { 0x000fe0,   2, 0x04, 0x00000000 },
-       { 0x000fe8,   1, 0x04, 0x00000014 },
-       { 0x000fec,   1, 0x04, 0x00000040 },
-       { 0x000ff0,   1, 0x04, 0x00000000 },
-       { 0x00179c,   1, 0x04, 0x00000000 },
-       { 0x001228,   1, 0x04, 0x00000400 },
-       { 0x00122c,   1, 0x04, 0x00000300 },
-       { 0x001230,   1, 0x04, 0x00010001 },
-       { 0x0007f8,   1, 0x04, 0x00000000 },
-       { 0x0015b4,   1, 0x04, 0x00000001 },
-       { 0x0015cc,   1, 0x04, 0x00000000 },
-       { 0x001534,   1, 0x04, 0x00000000 },
-       { 0x000fb0,   1, 0x04, 0x00000000 },
-       { 0x0015d0,   1, 0x04, 0x00000000 },
-       { 0x00153c,   1, 0x04, 0x00000000 },
-       { 0x0016b4,   1, 0x04, 0x00000003 },
-       { 0x000fbc,   4, 0x04, 0x0000ffff },
-       { 0x000df8,   2, 0x04, 0x00000000 },
-       { 0x001948,   1, 0x04, 0x00000000 },
-       { 0x001970,   1, 0x04, 0x00000001 },
-       { 0x00161c,   1, 0x04, 0x000009f0 },
-       { 0x000dcc,   1, 0x04, 0x00000010 },
-       { 0x00163c,   1, 0x04, 0x00000000 },
-       { 0x0015e4,   1, 0x04, 0x00000000 },
-       { 0x001160,  32, 0x04, 0x25e00040 },
-       { 0x001880,  32, 0x04, 0x00000000 },
-       { 0x000f84,   2, 0x04, 0x00000000 },
-       { 0x0017c8,   2, 0x04, 0x00000000 },
-       { 0x0017d0,   1, 0x04, 0x000000ff },
-       { 0x0017d4,   1, 0x04, 0xffffffff },
-       { 0x0017d8,   1, 0x04, 0x00000002 },
-       { 0x0017dc,   1, 0x04, 0x00000000 },
-       { 0x0015f4,   2, 0x04, 0x00000000 },
-       { 0x001434,   2, 0x04, 0x00000000 },
-       { 0x000d74,   1, 0x04, 0x00000000 },
-       { 0x000dec,   1, 0x04, 0x00000001 },
-       { 0x0013a4,   1, 0x04, 0x00000000 },
-       { 0x001318,   1, 0x04, 0x00000001 },
-       { 0x001644,   1, 0x04, 0x00000000 },
-       { 0x000748,   1, 0x04, 0x00000000 },
-       { 0x000de8,   1, 0x04, 0x00000000 },
-       { 0x001648,   1, 0x04, 0x00000000 },
-       { 0x0012a4,   1, 0x04, 0x00000000 },
-       { 0x001120,   4, 0x04, 0x00000000 },
-       { 0x001118,   1, 0x04, 0x00000000 },
-       { 0x00164c,   1, 0x04, 0x00000000 },
-       { 0x001658,   1, 0x04, 0x00000000 },
-       { 0x001910,   1, 0x04, 0x00000290 },
-       { 0x001518,   1, 0x04, 0x00000000 },
-       { 0x00165c,   1, 0x04, 0x00000001 },
-       { 0x001520,   1, 0x04, 0x00000000 },
-       { 0x001604,   1, 0x04, 0x00000000 },
-       { 0x001570,   1, 0x04, 0x00000000 },
-       { 0x0013b0,   2, 0x04, 0x3f800000 },
-       { 0x00020c,   1, 0x04, 0x00000000 },
-       { 0x001670,   1, 0x04, 0x30201000 },
-       { 0x001674,   1, 0x04, 0x70605040 },
-       { 0x001678,   1, 0x04, 0xb8a89888 },
-       { 0x00167c,   1, 0x04, 0xf8e8d8c8 },
-       { 0x00166c,   1, 0x04, 0x00000000 },
-       { 0x001680,   1, 0x04, 0x00ffff00 },
-       { 0x0012d0,   1, 0x04, 0x00000003 },
-       { 0x0012d4,   1, 0x04, 0x00000002 },
-       { 0x001684,   2, 0x04, 0x00000000 },
-       { 0x000dac,   2, 0x04, 0x00001b02 },
-       { 0x000db4,   1, 0x04, 0x00000000 },
-       { 0x00168c,   1, 0x04, 0x00000000 },
-       { 0x0015bc,   1, 0x04, 0x00000000 },
-       { 0x00156c,   1, 0x04, 0x00000000 },
-       { 0x00187c,   1, 0x04, 0x00000000 },
-       { 0x001110,   1, 0x04, 0x00000001 },
-       { 0x000dc0,   3, 0x04, 0x00000000 },
-       { 0x001234,   1, 0x04, 0x00000000 },
-       { 0x001690,   1, 0x04, 0x00000000 },
-       { 0x0012ac,   1, 0x04, 0x00000001 },
-       { 0x0002c4,   1, 0x04, 0x00000000 },
-       { 0x000790,   5, 0x04, 0x00000000 },
-       { 0x00077c,   1, 0x04, 0x00000000 },
-       { 0x001000,   1, 0x04, 0x00000010 },
-       { 0x0010fc,   1, 0x04, 0x00000000 },
-       { 0x001290,   1, 0x04, 0x00000000 },
-       { 0x000218,   1, 0x04, 0x00000010 },
-       { 0x0012d8,   1, 0x04, 0x00000000 },
-       { 0x0012dc,   1, 0x04, 0x00000010 },
-       { 0x000d94,   1, 0x04, 0x00000001 },
-       { 0x00155c,   2, 0x04, 0x00000000 },
-       { 0x001564,   1, 0x04, 0x00000fff },
-       { 0x001574,   2, 0x04, 0x00000000 },
-       { 0x00157c,   1, 0x04, 0x000fffff },
-       { 0x001354,   1, 0x04, 0x00000000 },
-       { 0x001610,   1, 0x04, 0x00000012 },
-       { 0x001608,   2, 0x04, 0x00000000 },
-       { 0x00260c,   1, 0x04, 0x00000000 },
-       { 0x0007ac,   1, 0x04, 0x00000000 },
-       { 0x00162c,   1, 0x04, 0x00000003 },
-       { 0x000210,   1, 0x04, 0x00000000 },
-       { 0x000320,   1, 0x04, 0x00000000 },
-       { 0x000324,   6, 0x04, 0x3f800000 },
-       { 0x000750,   1, 0x04, 0x00000000 },
-       { 0x000760,   1, 0x04, 0x39291909 },
-       { 0x000764,   1, 0x04, 0x79695949 },
-       { 0x000768,   1, 0x04, 0xb9a99989 },
-       { 0x00076c,   1, 0x04, 0xf9e9d9c9 },
-       { 0x000770,   1, 0x04, 0x30201000 },
-       { 0x000774,   1, 0x04, 0x70605040 },
-       { 0x000778,   1, 0x04, 0x00009080 },
-       { 0x000780,   1, 0x04, 0x39291909 },
-       { 0x000784,   1, 0x04, 0x79695949 },
-       { 0x000788,   1, 0x04, 0xb9a99989 },
-       { 0x00078c,   1, 0x04, 0xf9e9d9c9 },
-       { 0x0007d0,   1, 0x04, 0x30201000 },
-       { 0x0007d4,   1, 0x04, 0x70605040 },
-       { 0x0007d8,   1, 0x04, 0x00009080 },
-       { 0x00037c,   1, 0x04, 0x00000001 },
-       { 0x000740,   2, 0x04, 0x00000000 },
-       { 0x002600,   1, 0x04, 0x00000000 },
-       { 0x001918,   1, 0x04, 0x00000000 },
-       { 0x00191c,   1, 0x04, 0x00000900 },
-       { 0x001920,   1, 0x04, 0x00000405 },
-       { 0x001308,   1, 0x04, 0x00000001 },
-       { 0x001924,   1, 0x04, 0x00000000 },
-       { 0x0013ac,   1, 0x04, 0x00000000 },
-       { 0x00192c,   1, 0x04, 0x00000001 },
-       { 0x00193c,   1, 0x04, 0x00002c1c },
-       { 0x000d7c,   1, 0x04, 0x00000000 },
-       { 0x000f8c,   1, 0x04, 0x00000000 },
-       { 0x0002c0,   1, 0x04, 0x00000001 },
-       { 0x001510,   1, 0x04, 0x00000000 },
-       { 0x001940,   1, 0x04, 0x00000000 },
-       { 0x000ff4,   2, 0x04, 0x00000000 },
-       { 0x00194c,   2, 0x04, 0x00000000 },
-       { 0x001968,   1, 0x04, 0x00000000 },
-       { 0x001590,   1, 0x04, 0x0000003f },
-       { 0x0007e8,   4, 0x04, 0x00000000 },
-       { 0x00196c,   1, 0x04, 0x00000011 },
-       { 0x0002e4,   1, 0x04, 0x0000b001 },
-       { 0x00036c,   2, 0x04, 0x00000000 },
-       { 0x00197c,   1, 0x04, 0x00000000 },
-       { 0x000fcc,   2, 0x04, 0x00000000 },
-       { 0x0002d8,   1, 0x04, 0x00000040 },
-       { 0x001980,   1, 0x04, 0x00000080 },
-       { 0x001504,   1, 0x04, 0x00000080 },
-       { 0x001984,   1, 0x04, 0x00000000 },
-       { 0x000300,   1, 0x04, 0x00000001 },
-       { 0x0013a8,   1, 0x04, 0x00000000 },
-       { 0x0012ec,   1, 0x04, 0x00000000 },
-       { 0x001310,   1, 0x04, 0x00000000 },
-       { 0x001314,   1, 0x04, 0x00000001 },
-       { 0x001380,   1, 0x04, 0x00000000 },
-       { 0x001384,   4, 0x04, 0x00000001 },
-       { 0x001394,   1, 0x04, 0x00000000 },
-       { 0x00139c,   1, 0x04, 0x00000000 },
-       { 0x001398,   1, 0x04, 0x00000000 },
-       { 0x001594,   1, 0x04, 0x00000000 },
-       { 0x001598,   4, 0x04, 0x00000001 },
-       { 0x000f54,   3, 0x04, 0x00000000 },
-       { 0x0019bc,   1, 0x04, 0x00000000 },
-       { 0x000f9c,   2, 0x04, 0x00000000 },
-       { 0x0012cc,   1, 0x04, 0x00000000 },
-       { 0x0012e8,   1, 0x04, 0x00000000 },
-       { 0x00130c,   1, 0x04, 0x00000001 },
-       { 0x001360,   8, 0x04, 0x00000000 },
-       { 0x00133c,   2, 0x04, 0x00000001 },
-       { 0x001344,   1, 0x04, 0x00000002 },
-       { 0x001348,   2, 0x04, 0x00000001 },
-       { 0x001350,   1, 0x04, 0x00000002 },
-       { 0x001358,   1, 0x04, 0x00000001 },
-       { 0x0012e4,   1, 0x04, 0x00000000 },
-       { 0x00131c,   4, 0x04, 0x00000000 },
-       { 0x0019c0,   1, 0x04, 0x00000000 },
-       { 0x001140,   1, 0x04, 0x00000000 },
-       { 0x0019c4,   1, 0x04, 0x00000000 },
-       { 0x0019c8,   1, 0x04, 0x00001500 },
-       { 0x00135c,   1, 0x04, 0x00000000 },
-       { 0x000f90,   1, 0x04, 0x00000000 },
-       { 0x0019e0,   8, 0x04, 0x00000001 },
-       { 0x0019cc,   1, 0x04, 0x00000001 },
-       { 0x0015b8,   1, 0x04, 0x00000000 },
-       { 0x001a00,   1, 0x04, 0x00001111 },
-       { 0x001a04,   7, 0x04, 0x00000000 },
-       { 0x000d6c,   2, 0x04, 0xffff0000 },
-       { 0x0010f8,   1, 0x04, 0x00001010 },
-       { 0x000d80,   5, 0x04, 0x00000000 },
-       { 0x000da0,   1, 0x04, 0x00000000 },
-       { 0x0007a4,   2, 0x04, 0x00000000 },
-       { 0x001508,   1, 0x04, 0x80000000 },
-       { 0x00150c,   1, 0x04, 0x40000000 },
-       { 0x001668,   1, 0x04, 0x00000000 },
-       { 0x000318,   2, 0x04, 0x00000008 },
-       { 0x000d9c,   1, 0x04, 0x00000001 },
-       { 0x000ddc,   1, 0x04, 0x00000002 },
-       { 0x000374,   1, 0x04, 0x00000000 },
-       { 0x000378,   1, 0x04, 0x00000020 },
-       { 0x0007dc,   1, 0x04, 0x00000000 },
-       { 0x00074c,   1, 0x04, 0x00000055 },
-       { 0x001420,   1, 0x04, 0x00000003 },
-       { 0x0017bc,   2, 0x04, 0x00000000 },
-       { 0x0017c4,   1, 0x04, 0x00000001 },
-       { 0x001008,   1, 0x04, 0x00000008 },
-       { 0x00100c,   1, 0x04, 0x00000040 },
-       { 0x001010,   1, 0x04, 0x0000012c },
-       { 0x000d60,   1, 0x04, 0x00000040 },
-       { 0x00075c,   1, 0x04, 0x00000003 },
-       { 0x001018,   1, 0x04, 0x00000020 },
-       { 0x00101c,   1, 0x04, 0x00000001 },
-       { 0x001020,   1, 0x04, 0x00000020 },
-       { 0x001024,   1, 0x04, 0x00000001 },
-       { 0x001444,   3, 0x04, 0x00000000 },
-       { 0x000360,   1, 0x04, 0x20164010 },
-       { 0x000364,   1, 0x04, 0x00000020 },
-       { 0x000368,   1, 0x04, 0x00000000 },
-       { 0x000de4,   1, 0x04, 0x00000000 },
-       { 0x000204,   1, 0x04, 0x00000006 },
-       { 0x000208,   1, 0x04, 0x00000000 },
-       { 0x0002cc,   2, 0x04, 0x003fffff },
-       { 0x001220,   1, 0x04, 0x00000005 },
-       { 0x000fdc,   1, 0x04, 0x00000000 },
-       { 0x000f98,   1, 0x04, 0x00400008 },
-       { 0x001284,   1, 0x04, 0x08000080 },
-       { 0x001450,   1, 0x04, 0x00400008 },
-       { 0x001454,   1, 0x04, 0x08000080 },
-       { 0x000214,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nv108_grctx_pack_icmd[] = {
+       { nv108_grctx_init_icmd_0 },
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk40xx[] = {
+static const struct nvc0_graph_init
+nv108_grctx_init_fe_0[] = {
        { 0x404004,   8, 0x04, 0x00000000 },
        { 0x404024,   1, 0x04, 0x0000e000 },
        { 0x404028,   8, 0x04, 0x00000000 },
@@ -1132,8 +311,8 @@ nv108_grctx_init_unk40xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nv108_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x0f8000bf },
        { 0x405830,   1, 0x04, 0x02180648 },
        { 0x405834,   1, 0x04, 0x08000000 },
@@ -1146,8 +325,10 @@ nv108_grctx_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk64xx[] = {
+static const struct nvc0_graph_init
+nv108_grctx_init_pd_0[] = {
+       { 0x406020,   1, 0x04, 0x034103c1 },
+       { 0x406028,   4, 0x04, 0x00000001 },
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b0,   3, 0x04, 0x00000000 },
@@ -1159,8 +340,8 @@ nv108_grctx_init_unk64xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk78xx[] = {
+const struct nvc0_graph_init
+nv108_grctx_init_rstr2d_0[] = {
        { 0x407804,   1, 0x04, 0x00000063 },
        { 0x40780c,   1, 0x04, 0x0a418820 },
        { 0x407810,   1, 0x04, 0x062080e6 },
@@ -1172,8 +353,8 @@ nv108_grctx_init_unk78xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk88xx[] = {
+static const struct nvc0_graph_init
+nv108_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x32802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x1003e005 },
@@ -1185,9 +366,23 @@ nv108_grctx_init_unk88xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
+static const struct nvc0_graph_pack
+nv108_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nv108_grctx_init_fe_0 },
+       { nvf0_grctx_init_pri_0 },
+       { nve4_grctx_init_memfmt_0 },
+       { nv108_grctx_init_ds_0 },
+       { nvf0_grctx_init_cwd_0 },
+       { nv108_grctx_init_pd_0 },
+       { nv108_grctx_init_rstr2d_0 },
+       { nve4_grctx_init_scc_0 },
+       { nv108_grctx_init_be_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nv108_grctx_init_prop_0[] = {
        { 0x418400,   1, 0x04, 0x38005e00 },
        { 0x418404,   1, 0x04, 0x71e0ffff },
        { 0x41840c,   1, 0x04, 0x00001008 },
@@ -1196,11 +391,21 @@ nv108_grctx_init_gpc_0[] = {
        { 0x418450,   6, 0x04, 0x00000000 },
        { 0x418468,   1, 0x04, 0x00000001 },
        { 0x41846c,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_gpc_unk_1[] = {
        { 0x418600,   1, 0x04, 0x0000007f },
        { 0x418684,   1, 0x04, 0x0000001f },
        { 0x418700,   1, 0x04, 0x00000002 },
        { 0x418704,   2, 0x04, 0x00000080 },
        { 0x41870c,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x7006863a },
        { 0x418808,   1, 0x04, 0x00000000 },
        { 0x41880c,   1, 0x04, 0x00000030 },
@@ -1211,10 +416,11 @@ nv108_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x20100058 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
+       {}
+};
+
+const struct nvc0_graph_init
+nv108_grctx_init_crstr_0[] = {
        { 0x418b00,   1, 0x04, 0x0000001e },
        { 0x418b08,   1, 0x04, 0x0a418820 },
        { 0x418b0c,   1, 0x04, 0x062080e6 },
@@ -1223,24 +429,36 @@ nv108_grctx_init_gpc_0[] = {
        { 0x418b18,   1, 0x04, 0x0a418820 },
        { 0x418b1c,   1, 0x04, 0x000000e6 },
        { 0x418bb8,   1, 0x04, 0x00000103 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_gpm_0[] = {
        { 0x418c08,   1, 0x04, 0x00000001 },
        { 0x418c10,   8, 0x04, 0x00000000 },
        { 0x418c40,   1, 0x04, 0xffffffff },
        { 0x418c6c,   1, 0x04, 0x00000001 },
        { 0x418c80,   1, 0x04, 0x2020000c },
        { 0x418c8c,   1, 0x04, 0x00000001 },
-       { 0x418d24,   1, 0x04, 0x00000000 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_tpc[] = {
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x00000129 },
-       { 0x419888,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nv108_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nv108_grctx_init_prop_0 },
+       { nv108_grctx_init_gpc_unk_1 },
+       { nv108_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nv108_grctx_init_crstr_0 },
+       { nv108_grctx_init_gpm_0 },
+       { nvf0_grctx_init_gpc_unk_2 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000100f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000421 },
@@ -1251,14 +469,11 @@ nv108_grctx_init_tpc[] = {
        { 0x419a20,   1, 0x04, 0x00000800 },
        { 0x419a30,   1, 0x04, 0x00000001 },
        { 0x419ac4,   1, 0x04, 0x0037f440 },
-       { 0x419c00,   1, 0x04, 0x0000001a },
-       { 0x419c04,   1, 0x04, 0x80000006 },
-       { 0x419c08,   1, 0x04, 0x00000002 },
-       { 0x419c20,   1, 0x04, 0x00000000 },
-       { 0x419c24,   1, 0x04, 0x00084210 },
-       { 0x419c28,   1, 0x04, 0x3efbefbe },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000203 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_sm_0[] = {
        { 0x419e04,   1, 0x04, 0x00000000 },
        { 0x419e08,   1, 0x04, 0x0000001d },
        { 0x419e0c,   1, 0x04, 0x00000000 },
@@ -1272,7 +487,7 @@ nv108_grctx_init_tpc[] = {
        { 0x419e68,   1, 0x04, 0x00000002 },
        { 0x419e6c,  12, 0x04, 0x00000000 },
        { 0x419eac,   1, 0x04, 0x00001f8f },
-       { 0x419eb0,   1, 0x04, 0x0db00da0 },
+       { 0x419eb0,   1, 0x04, 0x0db00d2f },
        { 0x419eb8,   1, 0x04, 0x00000000 },
        { 0x419ec8,   1, 0x04, 0x0001304f },
        { 0x419f30,   4, 0x04, 0x00000000 },
@@ -1285,25 +500,37 @@ nv108_grctx_init_tpc[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nv108_grctx_init_unk[] = {
-       { 0x41be24,   1, 0x04, 0x00000006 },
+static const struct nvc0_graph_pack
+nv108_grctx_pack_tpc[] = {
+       { nvd7_grctx_init_pe_0 },
+       { nv108_grctx_init_tex_0 },
+       { nvf0_grctx_init_mpc_0 },
+       { nvf0_grctx_init_l1c_0 },
+       { nv108_grctx_init_sm_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_grctx_init_cbm_0[] = {
        { 0x41bec0,   1, 0x04, 0x10000000 },
        { 0x41bec4,   1, 0x04, 0x00037f7f },
        { 0x41bee4,   1, 0x04, 0x00000000 },
        { 0x41bef0,   1, 0x04, 0x000003ff },
-       { 0x41bf00,   1, 0x04, 0x0a418820 },
-       { 0x41bf04,   1, 0x04, 0x062080e6 },
-       { 0x41bf08,   1, 0x04, 0x020398a4 },
-       { 0x41bf0c,   1, 0x04, 0x0e629062 },
-       { 0x41bf10,   1, 0x04, 0x0a418820 },
-       { 0x41bf14,   1, 0x04, 0x000000e6 },
-       { 0x41bfd0,   1, 0x04, 0x00900103 },
-       { 0x41bfe0,   1, 0x04, 0x00400001 },
-       { 0x41bfe4,   1, 0x04, 0x00000000 },
        {}
 };
 
+static const struct nvc0_graph_pack
+nv108_grctx_pack_ppc[] = {
+       { nve4_grctx_init_pes_0 },
+       { nv108_grctx_init_cbm_0 },
+       { nvd7_grctx_init_wwdx_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 static void
 nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -1346,47 +573,6 @@ nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        mmio_list(0x17e920, 0x00090d08, 0, 0);
 }
 
-static struct nvc0_graph_init *
-nv108_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nv108_grctx_init_unk40xx,
-       nvf0_grctx_init_unk44xx,
-       nve4_grctx_init_unk46xx,
-       nve4_grctx_init_unk47xx,
-       nv108_grctx_init_unk58xx,
-       nvf0_grctx_init_unk5bxx,
-       nvf0_grctx_init_unk60xx,
-       nv108_grctx_init_unk64xx,
-       nv108_grctx_init_unk78xx,
-       nve4_grctx_init_unk80xx,
-       nv108_grctx_init_unk88xx,
-       NULL
-};
-
-struct nvc0_graph_init *
-nv108_grctx_init_gpc[] = {
-       nv108_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nv108_grctx_init_tpc,
-       nv108_grctx_init_unk,
-       NULL
-};
-
-struct nvc0_graph_init
-nv108_grctx_init_mthd_magic[] = {
-       { 0x3410, 1, 0x04, 0x8e0e2006 },
-       { 0x3414, 1, 0x04, 0x00000038 },
-       {}
-};
-
-static struct nvc0_graph_mthd
-nv108_grctx_init_mthd[] = {
-       { 0xa197, nv108_grctx_init_a197, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x902d, nv108_grctx_init_mthd_magic, },
-       {}
-};
-
 struct nouveau_oclass *
 nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0x08),
@@ -1398,11 +584,14 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nve4_grctx_generate_main,
-       .mods = nv108_grctx_generate_mods,
-       .unkn = nve4_grctx_generate_unkn,
-       .hub  = nv108_grctx_init_hub,
-       .gpc  = nv108_grctx_init_gpc,
-       .icmd = nv108_grctx_init_icmd,
-       .mthd = nv108_grctx_init_mthd,
+       .main  = nve4_grctx_generate_main,
+       .mods  = nv108_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = nv108_grctx_pack_hub,
+       .gpc   = nv108_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nv108_grctx_pack_tpc,
+       .ppc   = nv108_grctx_pack_ppc,
+       .icmd  = nv108_grctx_pack_icmd,
+       .mthd  = nvf0_grctx_pack_mthd,
 }.base;
index fe67415c3e175ce17de2be2e8ba7e03570d97cf7..833a96508c4e8fa96c6c3d2b3da0f16a8c1dd26c 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-struct nvc0_graph_init
-nvc0_grctx_init_icmd[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
        { 0x000038,   1, 0x01, 0x0fac6881 },
@@ -140,8 +144,7 @@ nvc0_grctx_init_icmd[] = {
        { 0x000586,   1, 0x01, 0x00000040 },
        { 0x000582,   2, 0x01, 0x00000080 },
        { 0x0005c2,   1, 0x01, 0x00000001 },
-       { 0x000638,   1, 0x01, 0x00000001 },
-       { 0x000639,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
        { 0x00063a,   1, 0x01, 0x00000002 },
        { 0x00063b,   2, 0x01, 0x00000001 },
        { 0x00063d,   1, 0x01, 0x00000002 },
@@ -201,15 +204,13 @@ nvc0_grctx_init_icmd[] = {
        { 0x000787,   1, 0x01, 0x000000cf },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x000836,   1, 0x01, 0x00000001 },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x00080c,   1, 0x01, 0x00000002 },
        { 0x00080d,   2, 0x01, 0x00000100 },
@@ -235,14 +236,12 @@ nvc0_grctx_init_icmd[] = {
        { 0x0006b1,   1, 0x01, 0x00000011 },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x01e100,   1, 0x01, 0x00000001 },
        { 0x001000,   1, 0x01, 0x00000014 },
@@ -267,8 +266,14 @@ nvc0_grctx_init_icmd[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_9097[] = {
+const struct nvc0_graph_pack
+nvc0_grctx_pack_icmd[] = {
+       { nvc0_grctx_init_icmd_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_9097_0[] = {
        { 0x000800,   8, 0x40, 0x00000000 },
        { 0x000804,   8, 0x40, 0x00000000 },
        { 0x000808,   8, 0x40, 0x00000400 },
@@ -516,8 +521,7 @@ nvc0_grctx_init_9097[] = {
        { 0x001350,   1, 0x04, 0x00000002 },
        { 0x001358,   1, 0x04, 0x00000001 },
        { 0x0012e4,   1, 0x04, 0x00000000 },
-       { 0x00131c,   1, 0x04, 0x00000000 },
-       { 0x001320,   3, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
        { 0x0019c0,   1, 0x04, 0x00000000 },
        { 0x001140,   1, 0x04, 0x00000000 },
        { 0x0019c4,   1, 0x04, 0x00000000 },
@@ -571,8 +575,8 @@ nvc0_grctx_init_9097[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_902d[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_902d_0[] = {
        { 0x000200,   1, 0x04, 0x000000cf },
        { 0x000204,   1, 0x04, 0x00000001 },
        { 0x000208,   1, 0x04, 0x00000020 },
@@ -590,8 +594,8 @@ nvc0_grctx_init_902d[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_9039[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_9039_0[] = {
        { 0x00030c,   3, 0x04, 0x00000000 },
        { 0x000320,   1, 0x04, 0x00000000 },
        { 0x000238,   2, 0x04, 0x00000000 },
@@ -599,8 +603,8 @@ nvc0_grctx_init_9039[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_90c0[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_90c0_0[] = {
        { 0x00270c,   8, 0x20, 0x00000000 },
        { 0x00030c,   1, 0x04, 0x00000001 },
        { 0x001944,   1, 0x04, 0x00000000 },
@@ -617,38 +621,44 @@ nvc0_grctx_init_90c0[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_base[] = {
+const struct nvc0_graph_pack
+nvc0_grctx_pack_mthd[] = {
+       { nvc0_grctx_init_9097_0, 0x9097 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       { nvc0_grctx_init_9039_0, 0x9039 },
+       { nvc0_grctx_init_90c0_0, 0x90c0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_main_0[] = {
        { 0x400204,   2, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk40xx[] = {
-       { 0x404004,  10, 0x04, 0x00000000 },
+const struct nvc0_graph_init
+nvc0_grctx_init_fe_0[] = {
+       { 0x404004,  11, 0x04, 0x00000000 },
        { 0x404044,   1, 0x04, 0x00000000 },
-       { 0x404094,   1, 0x04, 0x00000000 },
-       { 0x404098,  12, 0x04, 0x00000000 },
+       { 0x404094,  13, 0x04, 0x00000000 },
        { 0x4040c8,   1, 0x04, 0xf0000087 },
        { 0x4040d0,   6, 0x04, 0x00000000 },
        { 0x4040e8,   1, 0x04, 0x00001000 },
        { 0x4040f8,   1, 0x04, 0x00000000 },
-       { 0x404130,   1, 0x04, 0x00000000 },
-       { 0x404134,   1, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
        { 0x404138,   1, 0x04, 0x20000040 },
        { 0x404150,   1, 0x04, 0x0000002e },
        { 0x404154,   1, 0x04, 0x00000400 },
        { 0x404158,   1, 0x04, 0x00000200 },
        { 0x404164,   1, 0x04, 0x00000055 },
        { 0x404168,   1, 0x04, 0x00000000 },
-       { 0x404174,   1, 0x04, 0x00000000 },
-       { 0x404178,   2, 0x04, 0x00000000 },
+       { 0x404174,   3, 0x04, 0x00000000 },
        { 0x404200,   8, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk44xx[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_pri_0[] = {
        { 0x404404,  14, 0x04, 0x00000000 },
        { 0x404460,   2, 0x04, 0x00000000 },
        { 0x404468,   1, 0x04, 0x00ffffff },
@@ -658,8 +668,8 @@ nvc0_grctx_init_unk44xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk46xx[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_memfmt_0[] = {
        { 0x404604,   1, 0x04, 0x00000015 },
        { 0x404608,   1, 0x04, 0x00000000 },
        { 0x40460c,   1, 0x04, 0x00002e00 },
@@ -674,19 +684,14 @@ nvc0_grctx_init_unk46xx[] = {
        { 0x4046a0,   1, 0x04, 0x007f0080 },
        { 0x4046a4,  18, 0x04, 0x00000000 },
        { 0x4046f0,   2, 0x04, 0x00000000 },
-       {}
-};
-
-struct nvc0_graph_init
-nvc0_grctx_init_unk47xx[] = {
        { 0x404700,  13, 0x04, 0x00000000 },
        { 0x404734,   1, 0x04, 0x00000100 },
        { 0x404738,   8, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nvc0_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x078000bf },
        { 0x405830,   1, 0x04, 0x02180000 },
        { 0x405834,   2, 0x04, 0x00000000 },
@@ -697,23 +702,18 @@ nvc0_grctx_init_unk58xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk60xx[] = {
+static const struct nvc0_graph_init
+nvc0_grctx_init_pd_0[] = {
        { 0x406020,   1, 0x04, 0x000103c1 },
        { 0x406028,   4, 0x04, 0x00000001 },
-       {}
-};
-
-struct nvc0_graph_init
-nvc0_grctx_init_unk64xx[] = {
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b4,   2, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk78xx[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_rstr2d_0[] = {
        { 0x407804,   1, 0x04, 0x00000023 },
        { 0x40780c,   1, 0x04, 0x0a418820 },
        { 0x407810,   1, 0x04, 0x062080e6 },
@@ -725,8 +725,8 @@ nvc0_grctx_init_unk78xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_unk80xx[] = {
+const struct nvc0_graph_init
+nvc0_grctx_init_scc_0[] = {
        { 0x408000,   2, 0x04, 0x00000000 },
        { 0x408008,   1, 0x04, 0x00000018 },
        { 0x40800c,   2, 0x04, 0x00000000 },
@@ -736,8 +736,8 @@ nvc0_grctx_init_unk80xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_rop[] = {
+static const struct nvc0_graph_init
+nvc0_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x02802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x0003e00d },
@@ -748,9 +748,28 @@ nvc0_grctx_init_rop[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_gpc_0[] = {
+const struct nvc0_graph_pack
+nvc0_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nvc0_grctx_init_fe_0 },
+       { nvc0_grctx_init_pri_0 },
+       { nvc0_grctx_init_memfmt_0 },
+       { nvc0_grctx_init_ds_0 },
+       { nvc0_grctx_init_pd_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nvc0_grctx_init_scc_0 },
+       { nvc0_grctx_init_be_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_gpc_unk_0[] = {
        { 0x418380,   1, 0x04, 0x00000016 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_prop_0[] = {
        { 0x418400,   1, 0x04, 0x38004e00 },
        { 0x418404,   1, 0x04, 0x71e0ffff },
        { 0x418408,   1, 0x04, 0x00000000 },
@@ -760,6 +779,11 @@ nvc0_grctx_init_gpc_0[] = {
        { 0x418450,   6, 0x04, 0x00000000 },
        { 0x418468,   1, 0x04, 0x00000001 },
        { 0x41846c,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_gpc_unk_1[] = {
        { 0x418600,   1, 0x04, 0x0000001f },
        { 0x418684,   1, 0x04, 0x0000000f },
        { 0x418700,   1, 0x04, 0x00000002 },
@@ -767,6 +791,11 @@ nvc0_grctx_init_gpc_0[] = {
        { 0x418708,   1, 0x04, 0x00000000 },
        { 0x41870c,   1, 0x04, 0x07c80000 },
        { 0x418710,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x0006860a },
        { 0x418808,   3, 0x04, 0x00000000 },
        { 0x418828,   1, 0x04, 0x00008442 },
@@ -775,10 +804,20 @@ nvc0_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x00100000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_zcull_0[] = {
        { 0x41891c,   1, 0x04, 0x00ff00ff },
        { 0x418924,   1, 0x04, 0x00000000 },
        { 0x418928,   1, 0x04, 0x00ffff00 },
        { 0x41892c,   1, 0x04, 0x0000ff00 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_crstr_0[] = {
        { 0x418b00,   1, 0x04, 0x00000000 },
        { 0x418b08,   1, 0x04, 0x0a418820 },
        { 0x418b0c,   1, 0x04, 0x062080e6 },
@@ -787,18 +826,41 @@ nvc0_grctx_init_gpc_0[] = {
        { 0x418b18,   1, 0x04, 0x0a418820 },
        { 0x418b1c,   1, 0x04, 0x000000e6 },
        { 0x418bb8,   1, 0x04, 0x00000103 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_gpm_0[] = {
        { 0x418c08,   1, 0x04, 0x00000001 },
        { 0x418c10,   8, 0x04, 0x00000000 },
        { 0x418c80,   1, 0x04, 0x20200004 },
        { 0x418c8c,   1, 0x04, 0x00000001 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_gcc_0[] = {
        { 0x419000,   1, 0x04, 0x00000780 },
        { 0x419004,   2, 0x04, 0x00000000 },
        { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_gpc_1[] = {
+const struct nvc0_graph_pack
+nvc0_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvc0_grctx_init_prop_0 },
+       { nvc0_grctx_init_gpc_unk_1 },
+       { nvc0_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvc0_grctx_init_crstr_0 },
+       { nvc0_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_zcullr_0[] = {
        { 0x418a00,   3, 0x04, 0x00000000 },
        { 0x418a0c,   1, 0x04, 0x00010000 },
        { 0x418a10,   3, 0x04, 0x00000000 },
@@ -826,19 +888,35 @@ nvc0_grctx_init_gpc_1[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_grctx_init_tpc[] = {
+const struct nvc0_graph_pack
+nvc0_grctx_pack_zcull[] = {
+       { nvc0_grctx_init_zcullr_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_pe_0[] = {
        { 0x419818,   1, 0x04, 0x00000000 },
        { 0x41983c,   1, 0x04, 0x00038bc7 },
        { 0x419848,   1, 0x04, 0x00000000 },
        { 0x419864,   1, 0x04, 0x0000012a },
        { 0x419888,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000001f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000023 },
        { 0x419a0c,   1, 0x04, 0x00020000 },
        { 0x419a10,   1, 0x04, 0x00000000 },
        { 0x419a14,   1, 0x04, 0x00000200 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_wwdx_0[] = {
        { 0x419b00,   1, 0x04, 0x0a418820 },
        { 0x419b04,   1, 0x04, 0x062080e6 },
        { 0x419b08,   1, 0x04, 0x020398a4 },
@@ -848,15 +926,35 @@ nvc0_grctx_init_tpc[] = {
        { 0x419bd0,   1, 0x04, 0x00900103 },
        { 0x419be0,   1, 0x04, 0x00000001 },
        { 0x419be4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_mpc_0[] = {
        { 0x419c00,   1, 0x04, 0x00000002 },
        { 0x419c04,   1, 0x04, 0x00000006 },
        { 0x419c08,   1, 0x04, 0x00000002 },
        { 0x419c20,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_l1c_0[] = {
        { 0x419cb0,   1, 0x04, 0x00060048 },
        { 0x419ce8,   1, 0x04, 0x00000000 },
        { 0x419cf4,   1, 0x04, 0x00000183 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_grctx_init_tpccs_0[] = {
        { 0x419d20,   1, 0x04, 0x02180000 },
        { 0x419d24,   1, 0x04, 0x00001fff },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_grctx_init_sm_0[] = {
        { 0x419e04,   3, 0x04, 0x00000000 },
        { 0x419e10,   1, 0x04, 0x00000002 },
        { 0x419e44,   1, 0x04, 0x001beff2 },
@@ -868,6 +966,22 @@ nvc0_grctx_init_tpc[] = {
        {}
 };
 
+const struct nvc0_graph_pack
+nvc0_grctx_pack_tpc[] = {
+       { nvc0_grctx_init_pe_0 },
+       { nvc0_grctx_init_tex_0 },
+       { nvc0_grctx_init_wwdx_0 },
+       { nvc0_grctx_init_mpc_0 },
+       { nvc0_grctx_init_l1c_0 },
+       { nvc0_grctx_init_tpccs_0 },
+       { nvc0_grctx_init_sm_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 void
 nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -1055,14 +1169,14 @@ void
 nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
        struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
-       int i;
 
        nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
 
-       for (i = 0; oclass->hub[i]; i++)
-               nvc0_graph_mmio(priv, oclass->hub[i]);
-       for (i = 0; oclass->gpc[i]; i++)
-               nvc0_graph_mmio(priv, oclass->gpc[i]);
+       nvc0_graph_mmio(priv, oclass->hub);
+       nvc0_graph_mmio(priv, oclass->gpc);
+       nvc0_graph_mmio(priv, oclass->zcull);
+       nvc0_graph_mmio(priv, oclass->tpc);
+       nvc0_graph_mmio(priv, oclass->ppc);
 
        nv_wr32(priv, 0x404154, 0x00000000);
 
@@ -1182,46 +1296,6 @@ done:
        return ret;
 }
 
-struct nvc0_graph_init *
-nvc0_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nvc0_grctx_init_unk40xx,
-       nvc0_grctx_init_unk44xx,
-       nvc0_grctx_init_unk46xx,
-       nvc0_grctx_init_unk47xx,
-       nvc0_grctx_init_unk58xx,
-       nvc0_grctx_init_unk60xx,
-       nvc0_grctx_init_unk64xx,
-       nvc0_grctx_init_unk78xx,
-       nvc0_grctx_init_unk80xx,
-       nvc0_grctx_init_rop,
-       NULL
-};
-
-static struct nvc0_graph_init *
-nvc0_grctx_init_gpc[] = {
-       nvc0_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvc0_grctx_init_tpc,
-       NULL
-};
-
-struct nvc0_graph_init
-nvc0_grctx_init_mthd_magic[] = {
-       { 0x3410, 1, 0x04, 0x00000000 },
-       {}
-};
-
-struct nvc0_graph_mthd
-nvc0_grctx_init_mthd[] = {
-       { 0x9097, nvc0_grctx_init_9097, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x9039, nvc0_grctx_init_9039, },
-       { 0x90c0, nvc0_grctx_init_90c0, },
-       { 0x902d, nvc0_grctx_init_mthd_magic, },
-       {}
-};
-
 struct nouveau_oclass *
 nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xc0),
@@ -1233,11 +1307,13 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nvc0_grctx_generate_main,
-       .mods = nvc0_grctx_generate_mods,
-       .unkn = nvc0_grctx_generate_unkn,
-       .hub  = nvc0_grctx_init_hub,
-       .gpc  = nvc0_grctx_init_gpc,
-       .icmd = nvc0_grctx_init_icmd,
-       .mthd = nvc0_grctx_init_mthd,
+       .main  = nvc0_grctx_generate_main,
+       .mods  = nvc0_grctx_generate_mods,
+       .unkn  = nvc0_grctx_generate_unkn,
+       .hub   = nvc0_grctx_pack_hub,
+       .gpc   = nvc0_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvc0_grctx_pack_tpc,
+       .icmd  = nvc0_grctx_pack_icmd,
+       .mthd  = nvc0_grctx_pack_mthd,
 }.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 (file)
index 0000000..9c815d1
--- /dev/null
@@ -0,0 +1,170 @@
+#ifndef __NVKM_GRCTX_NVC0_H__
+#define __NVKM_GRCTX_NVC0_H__
+
+#include "nvc0.h"
+
+struct nvc0_grctx {
+       struct nvc0_graph_priv *priv;
+       struct nvc0_graph_data *data;
+       struct nvc0_graph_mmio *mmio;
+       int buffer_nr;
+       u64 buffer[4];
+       u64 addr;
+};
+
+struct nvc0_grctx_oclass {
+       struct nouveau_oclass base;
+       /* main context generation function */
+       void  (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
+       /* context-specific modify-on-first-load list generation function */
+       void  (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
+       void  (*unkn)(struct nvc0_graph_priv *);
+       /* mmio context data */
+       const struct nvc0_graph_pack *hub;
+       const struct nvc0_graph_pack *gpc;
+       const struct nvc0_graph_pack *zcull;
+       const struct nvc0_graph_pack *tpc;
+       const struct nvc0_graph_pack *ppc;
+       /* indirect context data, generated with icmds/mthds */
+       const struct nvc0_graph_pack *icmd;
+       const struct nvc0_graph_pack *mthd;
+};
+
+#define mmio_data(s,a,p) do {                                                  \
+       info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
+       info->addr = info->buffer[info->buffer_nr++] + (s);                    \
+       info->data->size = (s);                                                \
+       info->data->align = (a);                                               \
+       info->data->access = (p);                                              \
+       info->data++;                                                          \
+} while(0)
+
+#define mmio_list(r,d,s,b) do {                                                \
+       info->mmio->addr = (r);                                                \
+       info->mmio->data = (d);                                                \
+       info->mmio->shift = (s);                                               \
+       info->mmio->buffer = (b);                                              \
+       info->mmio++;                                                          \
+       nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0));      \
+} while(0)
+
+extern struct nouveau_oclass *nvc0_grctx_oclass;
+int  nvc0_grctx_generate(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *);
+void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
+
+extern struct nouveau_oclass *nvc1_grctx_oclass;
+void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
+
+extern struct nouveau_oclass *nvc4_grctx_oclass;
+extern struct nouveau_oclass *nvc8_grctx_oclass;
+extern struct nouveau_oclass *nvd7_grctx_oclass;
+extern struct nouveau_oclass *nvd9_grctx_oclass;
+
+extern struct nouveau_oclass *nve4_grctx_oclass;
+void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
+void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
+
+extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nouveau_oclass *nv108_grctx_oclass;
+extern struct nouveau_oclass *gm107_grctx_oclass;
+
+/* context init value lists */
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_icmd[];
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_mthd[];
+extern const struct nvc0_graph_init nvc0_grctx_init_902d_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_9039_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_90c0_0[];
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_hub[];
+extern const struct nvc0_graph_init nvc0_grctx_init_main_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_fe_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_pri_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_memfmt_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_rstr2d_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_scc_0[];
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_gpc[];
+extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_prop_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvc0_grctx_init_zcull_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_crstr_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_gpm_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_gcc_0[];
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_zcull[];
+
+extern const struct nvc0_graph_pack nvc0_grctx_pack_tpc[];
+extern const struct nvc0_graph_init nvc0_grctx_init_pe_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_wwdx_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_mpc_0[];
+extern const struct nvc0_graph_init nvc0_grctx_init_tpccs_0[];
+
+extern const struct nvc0_graph_init nvc4_grctx_init_tex_0[];
+extern const struct nvc0_graph_init nvc4_grctx_init_l1c_0[];
+extern const struct nvc0_graph_init nvc4_grctx_init_sm_0[];
+
+extern const struct nvc0_graph_init nvc1_grctx_init_9097_0[];
+
+extern const struct nvc0_graph_init nvc1_grctx_init_gpm_0[];
+
+extern const struct nvc0_graph_init nvc1_grctx_init_pe_0[];
+extern const struct nvc0_graph_init nvc1_grctx_init_wwdx_0[];
+extern const struct nvc0_graph_init nvc1_grctx_init_tpccs_0[];
+
+extern const struct nvc0_graph_init nvc8_grctx_init_9197_0[];
+extern const struct nvc0_graph_init nvc8_grctx_init_9297_0[];
+
+extern const struct nvc0_graph_pack nvd9_grctx_pack_icmd[];
+
+extern const struct nvc0_graph_pack nvd9_grctx_pack_mthd[];
+
+extern const struct nvc0_graph_init nvd9_grctx_init_fe_0[];
+extern const struct nvc0_graph_init nvd9_grctx_init_be_0[];
+
+extern const struct nvc0_graph_init nvd9_grctx_init_prop_0[];
+extern const struct nvc0_graph_init nvd9_grctx_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvd9_grctx_init_crstr_0[];
+
+extern const struct nvc0_graph_init nvd9_grctx_init_sm_0[];
+
+extern const struct nvc0_graph_init nvd7_grctx_init_pe_0[];
+
+extern const struct nvc0_graph_init nvd7_grctx_init_wwdx_0[];
+
+extern const struct nvc0_graph_init nve4_grctx_init_memfmt_0[];
+extern const struct nvc0_graph_init nve4_grctx_init_ds_0[];
+extern const struct nvc0_graph_init nve4_grctx_init_scc_0[];
+
+extern const struct nvc0_graph_init nve4_grctx_init_gpm_0[];
+
+extern const struct nvc0_graph_init nve4_grctx_init_pes_0[];
+
+extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
+
+extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
+extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[];
+
+extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[];
+
+extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[];
+extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[];
+
+extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[];
+
+extern const struct nvc0_graph_init nv108_grctx_init_prop_0[];
+extern const struct nvc0_graph_init nv108_grctx_init_crstr_0[];
+
+
+#endif
index 71b4283f7fad532fa7a799fd9182f4733e4bb7ce..24a92c569c0a2b971870da21f9ff97e992e8bffc 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-static struct nvc0_graph_init
-nvc1_grctx_init_icmd[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nvc1_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
        { 0x000038,   1, 0x01, 0x0fac6881 },
@@ -141,8 +145,7 @@ nvc1_grctx_init_icmd[] = {
        { 0x000586,   1, 0x01, 0x00000040 },
        { 0x000582,   2, 0x01, 0x00000080 },
        { 0x0005c2,   1, 0x01, 0x00000001 },
-       { 0x000638,   1, 0x01, 0x00000001 },
-       { 0x000639,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
        { 0x00063a,   1, 0x01, 0x00000002 },
        { 0x00063b,   2, 0x01, 0x00000001 },
        { 0x00063d,   1, 0x01, 0x00000002 },
@@ -202,15 +205,13 @@ nvc1_grctx_init_icmd[] = {
        { 0x000787,   1, 0x01, 0x000000cf },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x000836,   1, 0x01, 0x00000001 },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x00080c,   1, 0x01, 0x00000002 },
        { 0x00080d,   2, 0x01, 0x00000100 },
@@ -236,14 +237,12 @@ nvc1_grctx_init_icmd[] = {
        { 0x0006b1,   1, 0x01, 0x00000011 },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x01e100,   1, 0x01, 0x00000001 },
        { 0x001000,   1, 0x01, 0x00000014 },
@@ -268,8 +267,14 @@ nvc1_grctx_init_icmd[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc1_grctx_init_9097[] = {
+static const struct nvc0_graph_pack
+nvc1_grctx_pack_icmd[] = {
+       { nvc1_grctx_init_icmd_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_grctx_init_9097_0[] = {
        { 0x000800,   8, 0x40, 0x00000000 },
        { 0x000804,   8, 0x40, 0x00000000 },
        { 0x000808,   8, 0x40, 0x00000400 },
@@ -516,8 +521,7 @@ nvc1_grctx_init_9097[] = {
        { 0x001350,   1, 0x04, 0x00000002 },
        { 0x001358,   1, 0x04, 0x00000001 },
        { 0x0012e4,   1, 0x04, 0x00000000 },
-       { 0x00131c,   1, 0x04, 0x00000000 },
-       { 0x001320,   3, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
        { 0x0019c0,   1, 0x04, 0x00000000 },
        { 0x001140,   1, 0x04, 0x00000000 },
        { 0x0019c4,   1, 0x04, 0x00000000 },
@@ -571,15 +575,25 @@ nvc1_grctx_init_9097[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_grctx_init_9197[] = {
+static const struct nvc0_graph_init
+nvc1_grctx_init_9197_0[] = {
        { 0x003400, 128, 0x04, 0x00000000 },
        { 0x0002e4,   1, 0x04, 0x0000b001 },
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_grctx_init_unk58xx[] = {
+static const struct nvc0_graph_pack
+nvc1_grctx_pack_mthd[] = {
+       { nvc1_grctx_init_9097_0, 0x9097 },
+       { nvc1_grctx_init_9197_0, 0x9197 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       { nvc0_grctx_init_9039_0, 0x9039 },
+       { nvc0_grctx_init_90c0_0, 0x90c0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc1_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x0f8000bf },
        { 0x405830,   1, 0x04, 0x02180218 },
        { 0x405834,   2, 0x04, 0x00000000 },
@@ -590,8 +604,20 @@ nvc1_grctx_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_grctx_init_rop[] = {
+static const struct nvc0_graph_init
+nvc1_grctx_init_pd_0[] = {
+       { 0x406020,   1, 0x04, 0x000103c1 },
+       { 0x406028,   4, 0x04, 0x00000001 },
+       { 0x4064a8,   1, 0x04, 0x00000000 },
+       { 0x4064ac,   1, 0x04, 0x00003fff },
+       { 0x4064b4,   2, 0x04, 0x00000000 },
+       { 0x4064c0,   1, 0x04, 0x80140078 },
+       { 0x4064c4,   1, 0x04, 0x0086ffff },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc1_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x02802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x1003e005 },
@@ -602,25 +628,22 @@ nvc1_grctx_init_rop[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
-       { 0x418400,   1, 0x04, 0x38004e00 },
-       { 0x418404,   1, 0x04, 0x71e0ffff },
-       { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x41840c,   1, 0x04, 0x00001008 },
-       { 0x418410,   1, 0x04, 0x0fff0fff },
-       { 0x418414,   1, 0x04, 0x00200fff },
-       { 0x418450,   6, 0x04, 0x00000000 },
-       { 0x418468,   1, 0x04, 0x00000001 },
-       { 0x41846c,   2, 0x04, 0x00000000 },
-       { 0x418600,   1, 0x04, 0x0000001f },
-       { 0x418684,   1, 0x04, 0x0000000f },
-       { 0x418700,   1, 0x04, 0x00000002 },
-       { 0x418704,   1, 0x04, 0x00000080 },
-       { 0x418708,   1, 0x04, 0x00000000 },
-       { 0x41870c,   1, 0x04, 0x07c80000 },
-       { 0x418710,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvc1_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nvc0_grctx_init_fe_0 },
+       { nvc0_grctx_init_pri_0 },
+       { nvc0_grctx_init_memfmt_0 },
+       { nvc1_grctx_init_ds_0 },
+       { nvc1_grctx_init_pd_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nvc0_grctx_init_scc_0 },
+       { nvc1_grctx_init_be_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc1_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x0006860a },
        { 0x418808,   3, 0x04, 0x00000000 },
        { 0x418828,   1, 0x04, 0x00008442 },
@@ -629,69 +652,44 @@ nvc1_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x00100018 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
-       { 0x418a00,   3, 0x04, 0x00000000 },
-       { 0x418a0c,   1, 0x04, 0x00010000 },
-       { 0x418a10,   3, 0x04, 0x00000000 },
-       { 0x418a20,   3, 0x04, 0x00000000 },
-       { 0x418a2c,   1, 0x04, 0x00010000 },
-       { 0x418a30,   3, 0x04, 0x00000000 },
-       { 0x418a40,   3, 0x04, 0x00000000 },
-       { 0x418a4c,   1, 0x04, 0x00010000 },
-       { 0x418a50,   3, 0x04, 0x00000000 },
-       { 0x418a60,   3, 0x04, 0x00000000 },
-       { 0x418a6c,   1, 0x04, 0x00010000 },
-       { 0x418a70,   3, 0x04, 0x00000000 },
-       { 0x418a80,   3, 0x04, 0x00000000 },
-       { 0x418a8c,   1, 0x04, 0x00010000 },
-       { 0x418a90,   3, 0x04, 0x00000000 },
-       { 0x418aa0,   3, 0x04, 0x00000000 },
-       { 0x418aac,   1, 0x04, 0x00010000 },
-       { 0x418ab0,   3, 0x04, 0x00000000 },
-       { 0x418ac0,   3, 0x04, 0x00000000 },
-       { 0x418acc,   1, 0x04, 0x00010000 },
-       { 0x418ad0,   3, 0x04, 0x00000000 },
-       { 0x418ae0,   3, 0x04, 0x00000000 },
-       { 0x418aec,   1, 0x04, 0x00010000 },
-       { 0x418af0,   3, 0x04, 0x00000000 },
-       { 0x418b00,   1, 0x04, 0x00000000 },
-       { 0x418b08,   1, 0x04, 0x0a418820 },
-       { 0x418b0c,   1, 0x04, 0x062080e6 },
-       { 0x418b10,   1, 0x04, 0x020398a4 },
-       { 0x418b14,   1, 0x04, 0x0e629062 },
-       { 0x418b18,   1, 0x04, 0x0a418820 },
-       { 0x418b1c,   1, 0x04, 0x000000e6 },
-       { 0x418bb8,   1, 0x04, 0x00000103 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_grctx_init_gpm_0[] = {
        { 0x418c08,   1, 0x04, 0x00000001 },
        { 0x418c10,   8, 0x04, 0x00000000 },
        { 0x418c6c,   1, 0x04, 0x00000001 },
        { 0x418c80,   1, 0x04, 0x20200004 },
        { 0x418c8c,   1, 0x04, 0x00000001 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_grctx_init_tpc[] = {
+static const struct nvc0_graph_pack
+nvc1_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvc0_grctx_init_prop_0 },
+       { nvc0_grctx_init_gpc_unk_1 },
+       { nvc1_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvc0_grctx_init_crstr_0 },
+       { nvc1_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_grctx_init_pe_0[] = {
        { 0x419818,   1, 0x04, 0x00000000 },
        { 0x41983c,   1, 0x04, 0x00038bc7 },
        { 0x419848,   1, 0x04, 0x00000000 },
        { 0x419864,   1, 0x04, 0x00000129 },
        { 0x419888,   1, 0x04, 0x00000000 },
-       { 0x419a00,   1, 0x04, 0x000001f0 },
-       { 0x419a04,   1, 0x04, 0x00000001 },
-       { 0x419a08,   1, 0x04, 0x00000023 },
-       { 0x419a0c,   1, 0x04, 0x00020000 },
-       { 0x419a10,   1, 0x04, 0x00000000 },
-       { 0x419a14,   1, 0x04, 0x00000200 },
-       { 0x419a1c,   1, 0x04, 0x00000000 },
-       { 0x419a20,   1, 0x04, 0x00000800 },
-       { 0x419ac4,   1, 0x04, 0x0007f440 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_grctx_init_wwdx_0[] = {
        { 0x419b00,   1, 0x04, 0x0a418820 },
        { 0x419b04,   1, 0x04, 0x062080e6 },
        { 0x419b08,   1, 0x04, 0x020398a4 },
@@ -701,28 +699,33 @@ nvc1_grctx_init_tpc[] = {
        { 0x419bd0,   1, 0x04, 0x00900103 },
        { 0x419be0,   1, 0x04, 0x00400001 },
        { 0x419be4,   1, 0x04, 0x00000000 },
-       { 0x419c00,   1, 0x04, 0x00000002 },
-       { 0x419c04,   1, 0x04, 0x00000006 },
-       { 0x419c08,   1, 0x04, 0x00000002 },
-       { 0x419c20,   1, 0x04, 0x00000000 },
-       { 0x419cb0,   1, 0x04, 0x00020048 },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000183 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_grctx_init_tpccs_0[] = {
        { 0x419d20,   1, 0x04, 0x12180000 },
        { 0x419d24,   1, 0x04, 0x00001fff },
        { 0x419d44,   1, 0x04, 0x02180218 },
-       { 0x419e04,   3, 0x04, 0x00000000 },
-       { 0x419e10,   1, 0x04, 0x00000002 },
-       { 0x419e44,   1, 0x04, 0x001beff2 },
-       { 0x419e48,   1, 0x04, 0x00000000 },
-       { 0x419e4c,   1, 0x04, 0x0000000f },
-       { 0x419e50,  17, 0x04, 0x00000000 },
-       { 0x419e98,   1, 0x04, 0x00000000 },
-       { 0x419ee0,   1, 0x04, 0x00011110 },
-       { 0x419f30,  11, 0x04, 0x00000000 },
        {}
 };
 
+static const struct nvc0_graph_pack
+nvc1_grctx_pack_tpc[] = {
+       { nvc1_grctx_init_pe_0 },
+       { nvc4_grctx_init_tex_0 },
+       { nvc1_grctx_init_wwdx_0 },
+       { nvc0_grctx_init_mpc_0 },
+       { nvc4_grctx_init_l1c_0 },
+       { nvc1_grctx_init_tpccs_0 },
+       { nvc4_grctx_init_sm_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 void
 nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -771,41 +774,6 @@ nvc1_grctx_generate_unkn(struct nvc0_graph_priv *priv)
        nv_mask(priv, 0x419c00, 0x00000008, 0x00000008);
 }
 
-static struct nvc0_graph_init *
-nvc1_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nvc0_grctx_init_unk40xx,
-       nvc0_grctx_init_unk44xx,
-       nvc0_grctx_init_unk46xx,
-       nvc0_grctx_init_unk47xx,
-       nvc1_grctx_init_unk58xx,
-       nvc0_grctx_init_unk60xx,
-       nvc0_grctx_init_unk64xx,
-       nvc0_grctx_init_unk78xx,
-       nvc0_grctx_init_unk80xx,
-       nvc1_grctx_init_rop,
-       NULL
-};
-
-struct nvc0_graph_init *
-nvc1_grctx_init_gpc[] = {
-       nvc1_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvc1_grctx_init_tpc,
-       NULL
-};
-
-static struct nvc0_graph_mthd
-nvc1_grctx_init_mthd[] = {
-       { 0x9097, nvc1_grctx_init_9097, },
-       { 0x9197, nvc1_grctx_init_9197, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x9039, nvc0_grctx_init_9039, },
-       { 0x90c0, nvc0_grctx_init_90c0, },
-       { 0x902d, nvc0_grctx_init_mthd_magic, },
-       {}
-};
-
 struct nouveau_oclass *
 nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xc1),
@@ -817,11 +785,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nvc0_grctx_generate_main,
-       .mods = nvc1_grctx_generate_mods,
-       .unkn = nvc1_grctx_generate_unkn,
-       .hub  = nvc1_grctx_init_hub,
-       .gpc  = nvc1_grctx_init_gpc,
-       .icmd = nvc1_grctx_init_icmd,
-       .mthd = nvc1_grctx_init_mthd,
+       .main  = nvc0_grctx_generate_main,
+       .mods  = nvc1_grctx_generate_mods,
+       .unkn  = nvc1_grctx_generate_unkn,
+       .hub   = nvc1_grctx_pack_hub,
+       .gpc   = nvc1_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvc1_grctx_pack_tpc,
+       .icmd  = nvc1_grctx_pack_icmd,
+       .mthd  = nvc1_grctx_pack_mthd,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c
deleted file mode 100644 (file)
index 8f237b3..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2013 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs <bskeggs@redhat.com>
- */
-
-#include "nvc0.h"
-
-static struct nvc0_graph_init
-nvc3_grctx_init_tpc[] = {
-       { 0x419818,   1, 0x04, 0x00000000 },
-       { 0x41983c,   1, 0x04, 0x00038bc7 },
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x0000012a },
-       { 0x419888,   1, 0x04, 0x00000000 },
-       { 0x419a00,   1, 0x04, 0x000001f0 },
-       { 0x419a04,   1, 0x04, 0x00000001 },
-       { 0x419a08,   1, 0x04, 0x00000023 },
-       { 0x419a0c,   1, 0x04, 0x00020000 },
-       { 0x419a10,   1, 0x04, 0x00000000 },
-       { 0x419a14,   1, 0x04, 0x00000200 },
-       { 0x419a1c,   1, 0x04, 0x00000000 },
-       { 0x419a20,   1, 0x04, 0x00000800 },
-       { 0x419ac4,   1, 0x04, 0x0007f440 },
-       { 0x419b00,   1, 0x04, 0x0a418820 },
-       { 0x419b04,   1, 0x04, 0x062080e6 },
-       { 0x419b08,   1, 0x04, 0x020398a4 },
-       { 0x419b0c,   1, 0x04, 0x0e629062 },
-       { 0x419b10,   1, 0x04, 0x0a418820 },
-       { 0x419b14,   1, 0x04, 0x000000e6 },
-       { 0x419bd0,   1, 0x04, 0x00900103 },
-       { 0x419be0,   1, 0x04, 0x00000001 },
-       { 0x419be4,   1, 0x04, 0x00000000 },
-       { 0x419c00,   1, 0x04, 0x00000002 },
-       { 0x419c04,   1, 0x04, 0x00000006 },
-       { 0x419c08,   1, 0x04, 0x00000002 },
-       { 0x419c20,   1, 0x04, 0x00000000 },
-       { 0x419cb0,   1, 0x04, 0x00020048 },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000183 },
-       { 0x419d20,   1, 0x04, 0x02180000 },
-       { 0x419d24,   1, 0x04, 0x00001fff },
-       { 0x419e04,   3, 0x04, 0x00000000 },
-       { 0x419e10,   1, 0x04, 0x00000002 },
-       { 0x419e44,   1, 0x04, 0x001beff2 },
-       { 0x419e48,   1, 0x04, 0x00000000 },
-       { 0x419e4c,   1, 0x04, 0x0000000f },
-       { 0x419e50,  17, 0x04, 0x00000000 },
-       { 0x419e98,   1, 0x04, 0x00000000 },
-       { 0x419ee0,   1, 0x04, 0x00011110 },
-       { 0x419f30,  11, 0x04, 0x00000000 },
-       {}
-};
-
-struct nvc0_graph_init *
-nvc3_grctx_init_gpc[] = {
-       nvc0_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvc3_grctx_init_tpc,
-       NULL
-};
-
-struct nouveau_oclass *
-nvc3_grctx_oclass = &(struct nvc0_grctx_oclass) {
-       .base.handle = NV_ENGCTX(GR, 0xc3),
-       .base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nvc0_graph_context_ctor,
-               .dtor = nvc0_graph_context_dtor,
-               .init = _nouveau_graph_context_init,
-               .fini = _nouveau_graph_context_fini,
-               .rd32 = _nouveau_graph_context_rd32,
-               .wr32 = _nouveau_graph_context_wr32,
-       },
-       .main = nvc0_grctx_generate_main,
-       .mods = nvc0_grctx_generate_mods,
-       .unkn = nvc0_grctx_generate_unkn,
-       .hub  = nvc0_grctx_init_hub,
-       .gpc  = nvc3_grctx_init_gpc,
-       .icmd = nvc0_grctx_init_icmd,
-       .mthd = nvc0_grctx_init_mthd,
-}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
new file mode 100644 (file)
index 0000000..e11ed55
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+const struct nvc0_graph_init
+nvc4_grctx_init_tex_0[] = {
+       { 0x419a00,   1, 0x04, 0x000001f0 },
+       { 0x419a04,   1, 0x04, 0x00000001 },
+       { 0x419a08,   1, 0x04, 0x00000023 },
+       { 0x419a0c,   1, 0x04, 0x00020000 },
+       { 0x419a10,   1, 0x04, 0x00000000 },
+       { 0x419a14,   1, 0x04, 0x00000200 },
+       { 0x419a1c,   1, 0x04, 0x00000000 },
+       { 0x419a20,   1, 0x04, 0x00000800 },
+       { 0x419ac4,   1, 0x04, 0x0007f440 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc4_grctx_init_l1c_0[] = {
+       { 0x419cb0,   1, 0x04, 0x00020048 },
+       { 0x419ce8,   1, 0x04, 0x00000000 },
+       { 0x419cf4,   1, 0x04, 0x00000183 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc4_grctx_init_sm_0[] = {
+       { 0x419e04,   3, 0x04, 0x00000000 },
+       { 0x419e10,   1, 0x04, 0x00000002 },
+       { 0x419e44,   1, 0x04, 0x001beff2 },
+       { 0x419e48,   1, 0x04, 0x00000000 },
+       { 0x419e4c,   1, 0x04, 0x0000000f },
+       { 0x419e50,  17, 0x04, 0x00000000 },
+       { 0x419e98,   1, 0x04, 0x00000000 },
+       { 0x419ee0,   1, 0x04, 0x00011110 },
+       { 0x419f30,  11, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nvc4_grctx_pack_tpc[] = {
+       { nvc0_grctx_init_pe_0 },
+       { nvc4_grctx_init_tex_0 },
+       { nvc0_grctx_init_wwdx_0 },
+       { nvc0_grctx_init_mpc_0 },
+       { nvc4_grctx_init_l1c_0 },
+       { nvc0_grctx_init_tpccs_0 },
+       { nvc4_grctx_init_sm_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
+struct nouveau_oclass *
+nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
+       .base.handle = NV_ENGCTX(GR, 0xc3),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_context_ctor,
+               .dtor = nvc0_graph_context_dtor,
+               .init = _nouveau_graph_context_init,
+               .fini = _nouveau_graph_context_fini,
+               .rd32 = _nouveau_graph_context_rd32,
+               .wr32 = _nouveau_graph_context_wr32,
+       },
+       .main  = nvc0_grctx_generate_main,
+       .mods  = nvc0_grctx_generate_mods,
+       .unkn  = nvc0_grctx_generate_unkn,
+       .hub   = nvc0_grctx_pack_hub,
+       .gpc   = nvc0_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvc4_grctx_pack_tpc,
+       .icmd  = nvc0_grctx_pack_icmd,
+       .mthd  = nvc0_grctx_pack_mthd,
+}.base;
index d0d4ce3c489244f6cb2a0923295cecaf7b60d242..feebd58dfe8d005679860f5d57ee8df80a8fb442 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-static struct nvc0_graph_init
-nvc8_grctx_init_icmd[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nvc8_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
        { 0x000038,   1, 0x01, 0x0fac6881 },
@@ -141,8 +145,7 @@ nvc8_grctx_init_icmd[] = {
        { 0x000586,   1, 0x01, 0x00000040 },
        { 0x000582,   2, 0x01, 0x00000080 },
        { 0x0005c2,   1, 0x01, 0x00000001 },
-       { 0x000638,   1, 0x01, 0x00000001 },
-       { 0x000639,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
        { 0x00063a,   1, 0x01, 0x00000002 },
        { 0x00063b,   2, 0x01, 0x00000001 },
        { 0x00063d,   1, 0x01, 0x00000002 },
@@ -203,15 +206,13 @@ nvc8_grctx_init_icmd[] = {
        { 0x000787,   1, 0x01, 0x000000cf },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x000836,   1, 0x01, 0x00000001 },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x00080c,   1, 0x01, 0x00000002 },
        { 0x00080d,   2, 0x01, 0x00000100 },
@@ -237,14 +238,12 @@ nvc8_grctx_init_icmd[] = {
        { 0x0006b1,   1, 0x01, 0x00000011 },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x01e100,   1, 0x01, 0x00000001 },
        { 0x001000,   1, 0x01, 0x00000014 },
@@ -269,58 +268,20 @@ nvc8_grctx_init_icmd[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvc8_grctx_init_tpc[] = {
-       { 0x419818,   1, 0x04, 0x00000000 },
-       { 0x41983c,   1, 0x04, 0x00038bc7 },
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x0000012a },
-       { 0x419888,   1, 0x04, 0x00000000 },
-       { 0x419a00,   1, 0x04, 0x000001f0 },
-       { 0x419a04,   1, 0x04, 0x00000001 },
-       { 0x419a08,   1, 0x04, 0x00000023 },
-       { 0x419a0c,   1, 0x04, 0x00020000 },
-       { 0x419a10,   1, 0x04, 0x00000000 },
-       { 0x419a14,   1, 0x04, 0x00000200 },
-       { 0x419a1c,   1, 0x04, 0x00000000 },
-       { 0x419a20,   1, 0x04, 0x00000800 },
-       { 0x419b00,   1, 0x04, 0x0a418820 },
-       { 0x419b04,   1, 0x04, 0x062080e6 },
-       { 0x419b08,   1, 0x04, 0x020398a4 },
-       { 0x419b0c,   1, 0x04, 0x0e629062 },
-       { 0x419b10,   1, 0x04, 0x0a418820 },
-       { 0x419b14,   1, 0x04, 0x000000e6 },
-       { 0x419bd0,   1, 0x04, 0x00900103 },
-       { 0x419be0,   1, 0x04, 0x00000001 },
-       { 0x419be4,   1, 0x04, 0x00000000 },
-       { 0x419c00,   1, 0x04, 0x00000002 },
-       { 0x419c04,   1, 0x04, 0x00000006 },
-       { 0x419c08,   1, 0x04, 0x00000002 },
-       { 0x419c20,   1, 0x04, 0x00000000 },
-       { 0x419cb0,   1, 0x04, 0x00060048 },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000183 },
-       { 0x419d20,   1, 0x04, 0x02180000 },
-       { 0x419d24,   1, 0x04, 0x00001fff },
-       { 0x419e04,   3, 0x04, 0x00000000 },
-       { 0x419e10,   1, 0x04, 0x00000002 },
-       { 0x419e44,   1, 0x04, 0x001beff2 },
-       { 0x419e48,   1, 0x04, 0x00000000 },
-       { 0x419e4c,   1, 0x04, 0x0000000f },
-       { 0x419e50,  17, 0x04, 0x00000000 },
-       { 0x419e98,   1, 0x04, 0x00000000 },
-       { 0x419f50,   2, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvc8_grctx_pack_icmd[] = {
+       { nvc8_grctx_init_icmd_0 },
        {}
 };
 
-struct nvc0_graph_init
-nvc8_grctx_init_9197[] = {
+const struct nvc0_graph_init
+nvc8_grctx_init_9197_0[] = {
        { 0x0002e4,   1, 0x04, 0x0000b001 },
        {}
 };
 
-struct nvc0_graph_init
-nvc8_grctx_init_9297[] = {
+const struct nvc0_graph_init
+nvc8_grctx_init_9297_0[] = {
        { 0x003400, 128, 0x04, 0x00000000 },
        { 0x00036c,   2, 0x04, 0x00000000 },
        { 0x0007a4,   2, 0x04, 0x00000000 },
@@ -329,26 +290,47 @@ nvc8_grctx_init_9297[] = {
        {}
 };
 
-static struct nvc0_graph_mthd
-nvc8_grctx_init_mthd[] = {
-       { 0x9097, nvc1_grctx_init_9097, },
-       { 0x9197, nvc8_grctx_init_9197, },
-       { 0x9297, nvc8_grctx_init_9297, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x9039, nvc0_grctx_init_9039, },
-       { 0x90c0, nvc0_grctx_init_90c0, },
-       { 0x902d, nvc0_grctx_init_mthd_magic, },
+static const struct nvc0_graph_pack
+nvc8_grctx_pack_mthd[] = {
+       { nvc1_grctx_init_9097_0, 0x9097 },
+       { nvc8_grctx_init_9197_0, 0x9197 },
+       { nvc8_grctx_init_9297_0, 0x9297 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       { nvc0_grctx_init_9039_0, 0x9039 },
+       { nvc0_grctx_init_90c0_0, 0x90c0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc8_grctx_init_setup_0[] = {
+       { 0x418800,   1, 0x04, 0x0006860a },
+       { 0x418808,   3, 0x04, 0x00000000 },
+       { 0x418828,   1, 0x04, 0x00008442 },
+       { 0x418830,   1, 0x04, 0x00000001 },
+       { 0x4188d8,   1, 0x04, 0x00000008 },
+       { 0x4188e0,   1, 0x04, 0x01000000 },
+       { 0x4188e8,   5, 0x04, 0x00000000 },
+       { 0x4188fc,   1, 0x04, 0x20100000 },
        {}
 };
 
-static struct nvc0_graph_init *
-nvc8_grctx_init_gpc[] = {
-       nvc0_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvc8_grctx_init_tpc,
-       NULL
+static const struct nvc0_graph_pack
+nvc8_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvc0_grctx_init_prop_0 },
+       { nvc0_grctx_init_gpc_unk_1 },
+       { nvc8_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvc0_grctx_init_crstr_0 },
+       { nvc0_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
 };
 
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 struct nouveau_oclass *
 nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xc8),
@@ -360,11 +342,13 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nvc0_grctx_generate_main,
-       .mods = nvc0_grctx_generate_mods,
-       .unkn = nvc0_grctx_generate_unkn,
-       .hub  = nvc0_grctx_init_hub,
-       .gpc  = nvc8_grctx_init_gpc,
-       .icmd = nvc8_grctx_init_icmd,
-       .mthd = nvc8_grctx_init_mthd,
+       .main  = nvc0_grctx_generate_main,
+       .mods  = nvc0_grctx_generate_mods,
+       .unkn  = nvc0_grctx_generate_unkn,
+       .hub   = nvc0_grctx_pack_hub,
+       .gpc   = nvc8_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvc0_grctx_pack_tpc,
+       .icmd  = nvc8_grctx_pack_icmd,
+       .mthd  = nvc8_grctx_pack_mthd,
 }.base;
index c4740d52853286eb5dc75b43710c3c4eb0c07d3e..1dbc8d7f2e86553b2450e3f901430a116d7024da 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-struct nvc0_graph_init
-nvd7_grctx_init_unk40xx[] = {
-       { 0x404004,  10, 0x04, 0x00000000 },
-       { 0x404044,   1, 0x04, 0x00000000 },
-       { 0x404094,   1, 0x04, 0x00000000 },
-       { 0x404098,  12, 0x04, 0x00000000 },
-       { 0x4040c8,   1, 0x04, 0xf0000087 },
-       { 0x4040d0,   6, 0x04, 0x00000000 },
-       { 0x4040e8,   1, 0x04, 0x00001000 },
-       { 0x4040f8,   1, 0x04, 0x00000000 },
-       { 0x404130,   1, 0x04, 0x00000000 },
-       { 0x404134,   1, 0x04, 0x00000000 },
-       { 0x404138,   1, 0x04, 0x20000040 },
-       { 0x404150,   1, 0x04, 0x0000002e },
-       { 0x404154,   1, 0x04, 0x00000400 },
-       { 0x404158,   1, 0x04, 0x00000200 },
-       { 0x404164,   1, 0x04, 0x00000055 },
-       { 0x404168,   1, 0x04, 0x00000000 },
-       { 0x404178,   2, 0x04, 0x00000000 },
-       { 0x404200,   8, 0x04, 0x00000000 },
-       {}
-};
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
 
-static struct nvc0_graph_init
-nvd7_grctx_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nvd7_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x0f8000bf },
        { 0x405830,   1, 0x04, 0x02180324 },
        { 0x405834,   1, 0x04, 0x08000000 },
@@ -60,8 +41,10 @@ nvd7_grctx_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvd7_grctx_init_unk64xx[] = {
+static const struct nvc0_graph_init
+nvd7_grctx_init_pd_0[] = {
+       { 0x406020,   1, 0x04, 0x000103c1 },
+       { 0x406028,   4, 0x04, 0x00000001 },
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b4,   3, 0x04, 0x00000000 },
@@ -71,22 +54,22 @@ nvd7_grctx_init_unk64xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvd7_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
-       { 0x418400,   1, 0x04, 0x38004e00 },
-       { 0x418404,   1, 0x04, 0x71e0ffff },
-       { 0x41840c,   1, 0x04, 0x00001008 },
-       { 0x418410,   1, 0x04, 0x0fff0fff },
-       { 0x418414,   1, 0x04, 0x02200fff },
-       { 0x418450,   6, 0x04, 0x00000000 },
-       { 0x418468,   1, 0x04, 0x00000001 },
-       { 0x41846c,   2, 0x04, 0x00000000 },
-       { 0x418600,   1, 0x04, 0x0000001f },
-       { 0x418684,   1, 0x04, 0x0000000f },
-       { 0x418700,   1, 0x04, 0x00000002 },
-       { 0x418704,   1, 0x04, 0x00000080 },
-       { 0x418708,   3, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvd7_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nvd9_grctx_init_fe_0 },
+       { nvc0_grctx_init_pri_0 },
+       { nvc0_grctx_init_memfmt_0 },
+       { nvd7_grctx_init_ds_0 },
+       { nvd7_grctx_init_pd_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nvc0_grctx_init_scc_0 },
+       { nvd9_grctx_init_be_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd7_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x7006860a },
        { 0x418808,   3, 0x04, 0x00000000 },
        { 0x418828,   1, 0x04, 0x00008442 },
@@ -95,34 +78,32 @@ nvd7_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x20100018 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
-       { 0x418b00,   1, 0x04, 0x00000006 },
-       { 0x418b08,   1, 0x04, 0x0a418820 },
-       { 0x418b0c,   1, 0x04, 0x062080e6 },
-       { 0x418b10,   1, 0x04, 0x020398a4 },
-       { 0x418b14,   1, 0x04, 0x0e629062 },
-       { 0x418b18,   1, 0x04, 0x0a418820 },
-       { 0x418b1c,   1, 0x04, 0x000000e6 },
-       { 0x418bb8,   1, 0x04, 0x00000103 },
-       { 0x418c08,   1, 0x04, 0x00000001 },
-       { 0x418c10,   8, 0x04, 0x00000000 },
-       { 0x418c6c,   1, 0x04, 0x00000001 },
-       { 0x418c80,   1, 0x04, 0x20200004 },
-       { 0x418c8c,   1, 0x04, 0x00000001 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nvd7_grctx_init_tpc[] = {
+static const struct nvc0_graph_pack
+nvd7_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvd9_grctx_init_prop_0 },
+       { nvd9_grctx_init_gpc_unk_1 },
+       { nvd7_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvd9_grctx_init_crstr_0 },
+       { nvc1_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd7_grctx_init_pe_0[] = {
        { 0x419848,   1, 0x04, 0x00000000 },
        { 0x419864,   1, 0x04, 0x00000129 },
        { 0x419888,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd7_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000001f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000023 },
@@ -132,33 +113,46 @@ nvd7_grctx_init_tpc[] = {
        { 0x419a1c,   1, 0x04, 0x00008000 },
        { 0x419a20,   1, 0x04, 0x00000800 },
        { 0x419ac4,   1, 0x04, 0x0017f440 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd7_grctx_init_mpc_0[] = {
        { 0x419c00,   1, 0x04, 0x0000000a },
        { 0x419c04,   1, 0x04, 0x00000006 },
        { 0x419c08,   1, 0x04, 0x00000002 },
        { 0x419c20,   1, 0x04, 0x00000000 },
        { 0x419c24,   1, 0x04, 0x00084210 },
        { 0x419c28,   1, 0x04, 0x3efbefbe },
-       { 0x419cb0,   1, 0x04, 0x00020048 },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000183 },
-       { 0x419e04,   3, 0x04, 0x00000000 },
-       { 0x419e10,   1, 0x04, 0x00000002 },
-       { 0x419e44,   1, 0x04, 0x001beff2 },
-       { 0x419e48,   1, 0x04, 0x00000000 },
-       { 0x419e4c,   1, 0x04, 0x0000000f },
-       { 0x419e50,  17, 0x04, 0x00000000 },
-       { 0x419e98,   1, 0x04, 0x00000000 },
-       { 0x419ee0,   1, 0x04, 0x00010110 },
-       { 0x419f30,  11, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvd7_grctx_init_unk[] = {
+static const struct nvc0_graph_pack
+nvd7_grctx_pack_tpc[] = {
+       { nvd7_grctx_init_pe_0 },
+       { nvd7_grctx_init_tex_0 },
+       { nvd7_grctx_init_mpc_0 },
+       { nvc4_grctx_init_l1c_0 },
+       { nvd9_grctx_init_sm_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd7_grctx_init_pes_0[] = {
        { 0x41be24,   1, 0x04, 0x00000002 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd7_grctx_init_cbm_0[] = {
        { 0x41bec0,   1, 0x04, 0x12180000 },
        { 0x41bec4,   1, 0x04, 0x00003fff },
        { 0x41bee4,   1, 0x04, 0x03240218 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd7_grctx_init_wwdx_0[] = {
        { 0x41bf00,   1, 0x04, 0x0a418820 },
        { 0x41bf04,   1, 0x04, 0x062080e6 },
        { 0x41bf08,   1, 0x04, 0x020398a4 },
@@ -171,6 +165,18 @@ nvd7_grctx_init_unk[] = {
        {}
 };
 
+static const struct nvc0_graph_pack
+nvd7_grctx_pack_ppc[] = {
+       { nvd7_grctx_init_pes_0 },
+       { nvd7_grctx_init_cbm_0 },
+       { nvd7_grctx_init_wwdx_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 static void
 nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -219,10 +225,11 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 
        nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
 
-       for (i = 0; oclass->hub[i]; i++)
-               nvc0_graph_mmio(priv, oclass->hub[i]);
-       for (i = 0; oclass->gpc[i]; i++)
-               nvc0_graph_mmio(priv, oclass->gpc[i]);
+       nvc0_graph_mmio(priv, oclass->hub);
+       nvc0_graph_mmio(priv, oclass->gpc);
+       nvc0_graph_mmio(priv, oclass->zcull);
+       nvc0_graph_mmio(priv, oclass->tpc);
+       nvc0_graph_mmio(priv, oclass->ppc);
 
        nv_wr32(priv, 0x404154, 0x00000000);
 
@@ -244,32 +251,6 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
 }
 
-
-static struct nvc0_graph_init *
-nvd7_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nvd7_grctx_init_unk40xx,
-       nvc0_grctx_init_unk44xx,
-       nvc0_grctx_init_unk46xx,
-       nvc0_grctx_init_unk47xx,
-       nvd7_grctx_init_unk58xx,
-       nvc0_grctx_init_unk60xx,
-       nvd7_grctx_init_unk64xx,
-       nvc0_grctx_init_unk78xx,
-       nvc0_grctx_init_unk80xx,
-       nvd9_grctx_init_rop,
-       NULL
-};
-
-struct nvc0_graph_init *
-nvd7_grctx_init_gpc[] = {
-       nvd7_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvd7_grctx_init_tpc,
-       nvd7_grctx_init_unk,
-       NULL
-};
-
 struct nouveau_oclass *
 nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xd7),
@@ -281,11 +262,14 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nvd7_grctx_generate_main,
-       .mods = nvd7_grctx_generate_mods,
-       .unkn = nve4_grctx_generate_unkn,
-       .hub  = nvd7_grctx_init_hub,
-       .gpc  = nvd7_grctx_init_gpc,
-       .icmd = nvd9_grctx_init_icmd,
-       .mthd = nvd9_grctx_init_mthd,
+       .main  = nvd7_grctx_generate_main,
+       .mods  = nvd7_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = nvd7_grctx_pack_hub,
+       .gpc   = nvd7_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvd7_grctx_pack_tpc,
+       .ppc   = nvd7_grctx_pack_ppc,
+       .icmd  = nvd9_grctx_pack_icmd,
+       .mthd  = nvd9_grctx_pack_mthd,
 }.base;
index a1102cbf2fdca0f95e30c2d0ae77d9c3ddbfd72d..c665fb7e4660a0560889258ab756c8a04f68277e 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-struct nvc0_graph_init
-nvd9_grctx_init_90c0[] = {
-       { 0x002700,   4, 0x40, 0x00000000 },
-       { 0x002720,   4, 0x40, 0x00000000 },
-       { 0x002704,   4, 0x40, 0x00000000 },
-       { 0x002724,   4, 0x40, 0x00000000 },
-       { 0x002708,   4, 0x40, 0x00000000 },
-       { 0x002728,   4, 0x40, 0x00000000 },
-       { 0x00270c,   8, 0x20, 0x00000000 },
-       { 0x002710,   4, 0x40, 0x00014000 },
-       { 0x002730,   4, 0x40, 0x00014000 },
-       { 0x002714,   4, 0x40, 0x00000040 },
-       { 0x002734,   4, 0x40, 0x00000040 },
-       { 0x00030c,   1, 0x04, 0x00000001 },
-       { 0x001944,   1, 0x04, 0x00000000 },
-       { 0x000758,   1, 0x04, 0x00000100 },
-       { 0x0002c4,   1, 0x04, 0x00000000 },
-       { 0x000790,   5, 0x04, 0x00000000 },
-       { 0x00077c,   1, 0x04, 0x00000000 },
-       { 0x000204,   3, 0x04, 0x00000000 },
-       { 0x000214,   1, 0x04, 0x00000000 },
-       { 0x00024c,   1, 0x04, 0x00000000 },
-       { 0x000d94,   1, 0x04, 0x00000001 },
-       { 0x001608,   2, 0x04, 0x00000000 },
-       { 0x001664,   1, 0x04, 0x00000000 },
-       {}
-};
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
 
-struct nvc0_graph_init
-nvd9_grctx_init_icmd[] = {
+static const struct nvc0_graph_init
+nvd9_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
        { 0x000038,   1, 0x01, 0x0fac6881 },
@@ -171,8 +147,7 @@ nvd9_grctx_init_icmd[] = {
        { 0x000586,   1, 0x01, 0x00000040 },
        { 0x000582,   2, 0x01, 0x00000080 },
        { 0x0005c2,   1, 0x01, 0x00000001 },
-       { 0x000638,   1, 0x01, 0x00000001 },
-       { 0x000639,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
        { 0x00063a,   1, 0x01, 0x00000002 },
        { 0x00063b,   2, 0x01, 0x00000001 },
        { 0x00063d,   1, 0x01, 0x00000002 },
@@ -233,15 +208,13 @@ nvd9_grctx_init_icmd[] = {
        { 0x000787,   1, 0x01, 0x000000cf },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x000836,   1, 0x01, 0x00000001 },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x00080c,   1, 0x01, 0x00000002 },
        { 0x00080d,   2, 0x01, 0x00000100 },
@@ -267,14 +240,12 @@ nvd9_grctx_init_icmd[] = {
        { 0x0006b1,   1, 0x01, 0x00000011 },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x01e100,   1, 0x01, 0x00000001 },
        { 0x001000,   1, 0x01, 0x00000014 },
@@ -299,18 +270,56 @@ nvd9_grctx_init_icmd[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvd9_grctx_init_unk40xx[] = {
-       { 0x404004,  11, 0x04, 0x00000000 },
+const struct nvc0_graph_pack
+nvd9_grctx_pack_icmd[] = {
+       { nvd9_grctx_init_icmd_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_grctx_init_90c0_0[] = {
+       { 0x002700,   8, 0x20, 0x00000000 },
+       { 0x002704,   8, 0x20, 0x00000000 },
+       { 0x002708,   8, 0x20, 0x00000000 },
+       { 0x00270c,   8, 0x20, 0x00000000 },
+       { 0x002710,   8, 0x20, 0x00014000 },
+       { 0x002714,   8, 0x20, 0x00000040 },
+       { 0x00030c,   1, 0x04, 0x00000001 },
+       { 0x001944,   1, 0x04, 0x00000000 },
+       { 0x000758,   1, 0x04, 0x00000100 },
+       { 0x0002c4,   1, 0x04, 0x00000000 },
+       { 0x000790,   5, 0x04, 0x00000000 },
+       { 0x00077c,   1, 0x04, 0x00000000 },
+       { 0x000204,   3, 0x04, 0x00000000 },
+       { 0x000214,   1, 0x04, 0x00000000 },
+       { 0x00024c,   1, 0x04, 0x00000000 },
+       { 0x000d94,   1, 0x04, 0x00000001 },
+       { 0x001608,   2, 0x04, 0x00000000 },
+       { 0x001664,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_pack
+nvd9_grctx_pack_mthd[] = {
+       { nvc1_grctx_init_9097_0, 0x9097 },
+       { nvc8_grctx_init_9197_0, 0x9197 },
+       { nvc8_grctx_init_9297_0, 0x9297 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       { nvc0_grctx_init_9039_0, 0x9039 },
+       { nvd9_grctx_init_90c0_0, 0x90c0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_grctx_init_fe_0[] = {
+       { 0x404004,  10, 0x04, 0x00000000 },
        { 0x404044,   1, 0x04, 0x00000000 },
-       { 0x404094,   1, 0x04, 0x00000000 },
-       { 0x404098,  12, 0x04, 0x00000000 },
+       { 0x404094,  13, 0x04, 0x00000000 },
        { 0x4040c8,   1, 0x04, 0xf0000087 },
        { 0x4040d0,   6, 0x04, 0x00000000 },
        { 0x4040e8,   1, 0x04, 0x00001000 },
        { 0x4040f8,   1, 0x04, 0x00000000 },
-       { 0x404130,   1, 0x04, 0x00000000 },
-       { 0x404134,   1, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
        { 0x404138,   1, 0x04, 0x20000040 },
        { 0x404150,   1, 0x04, 0x0000002e },
        { 0x404154,   1, 0x04, 0x00000400 },
@@ -322,8 +331,8 @@ nvd9_grctx_init_unk40xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_grctx_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nvd9_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x0f8000bf },
        { 0x405830,   1, 0x04, 0x02180218 },
        { 0x405834,   1, 0x04, 0x08000000 },
@@ -335,8 +344,10 @@ nvd9_grctx_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_grctx_init_unk64xx[] = {
+static const struct nvc0_graph_init
+nvd9_grctx_init_pd_0[] = {
+       { 0x406020,   1, 0x04, 0x000103c1 },
+       { 0x406028,   4, 0x04, 0x00000001 },
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b4,   3, 0x04, 0x00000000 },
@@ -345,21 +356,34 @@ nvd9_grctx_init_unk64xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvd9_grctx_init_rop[] = {
+const struct nvc0_graph_init
+nvd9_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x02802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x1043e005 },
        { 0x408900,   1, 0x04, 0x3080b801 },
-       { 0x408904,   1, 0x04, 0x1043e005 },
+       { 0x408904,   1, 0x04, 0x62000001 },
        { 0x408908,   1, 0x04, 0x00c8102f },
        { 0x408980,   1, 0x04, 0x0000011d },
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
+static const struct nvc0_graph_pack
+nvd9_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nvd9_grctx_init_fe_0 },
+       { nvc0_grctx_init_pri_0 },
+       { nvc0_grctx_init_memfmt_0 },
+       { nvd9_grctx_init_ds_0 },
+       { nvd9_grctx_init_pd_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nvc0_grctx_init_scc_0 },
+       { nvd9_grctx_init_be_0 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_grctx_init_prop_0[] = {
        { 0x418400,   1, 0x04, 0x38004e00 },
        { 0x418404,   1, 0x04, 0x71e0ffff },
        { 0x41840c,   1, 0x04, 0x00001008 },
@@ -368,11 +392,21 @@ nvd9_grctx_init_gpc_0[] = {
        { 0x418450,   6, 0x04, 0x00000000 },
        { 0x418468,   1, 0x04, 0x00000001 },
        { 0x41846c,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_grctx_init_gpc_unk_1[] = {
        { 0x418600,   1, 0x04, 0x0000001f },
        { 0x418684,   1, 0x04, 0x0000000f },
        { 0x418700,   1, 0x04, 0x00000002 },
        { 0x418704,   1, 0x04, 0x00000080 },
        { 0x418708,   3, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x7006860a },
        { 0x418808,   3, 0x04, 0x00000000 },
        { 0x418828,   1, 0x04, 0x00008442 },
@@ -381,10 +415,11 @@ nvd9_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x20100008 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_grctx_init_crstr_0[] = {
        { 0x418b00,   1, 0x04, 0x00000006 },
        { 0x418b08,   1, 0x04, 0x0a418820 },
        { 0x418b0c,   1, 0x04, 0x062080e6 },
@@ -393,24 +428,24 @@ nvd9_grctx_init_gpc_0[] = {
        { 0x418b18,   1, 0x04, 0x0a418820 },
        { 0x418b1c,   1, 0x04, 0x000000e6 },
        { 0x418bb8,   1, 0x04, 0x00000103 },
-       { 0x418c08,   1, 0x04, 0x00000001 },
-       { 0x418c10,   8, 0x04, 0x00000000 },
-       { 0x418c6c,   1, 0x04, 0x00000001 },
-       { 0x418c80,   1, 0x04, 0x20200004 },
-       { 0x418c8c,   1, 0x04, 0x00000001 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_grctx_init_tpc[] = {
-       { 0x419818,   1, 0x04, 0x00000000 },
-       { 0x41983c,   1, 0x04, 0x00038bc7 },
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x00000129 },
-       { 0x419888,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvd9_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvd9_grctx_init_prop_0 },
+       { nvd9_grctx_init_gpc_unk_1 },
+       { nvd9_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvd9_grctx_init_crstr_0 },
+       { nvc1_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000001f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000023 },
@@ -420,27 +455,22 @@ nvd9_grctx_init_tpc[] = {
        { 0x419a1c,   1, 0x04, 0x00000000 },
        { 0x419a20,   1, 0x04, 0x00000800 },
        { 0x419ac4,   1, 0x04, 0x0017f440 },
-       { 0x419b00,   1, 0x04, 0x0a418820 },
-       { 0x419b04,   1, 0x04, 0x062080e6 },
-       { 0x419b08,   1, 0x04, 0x020398a4 },
-       { 0x419b0c,   1, 0x04, 0x0e629062 },
-       { 0x419b10,   1, 0x04, 0x0a418820 },
-       { 0x419b14,   1, 0x04, 0x000000e6 },
-       { 0x419bd0,   1, 0x04, 0x00900103 },
-       { 0x419be0,   1, 0x04, 0x00400001 },
-       { 0x419be4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_grctx_init_mpc_0[] = {
        { 0x419c00,   1, 0x04, 0x0000000a },
        { 0x419c04,   1, 0x04, 0x00000006 },
        { 0x419c08,   1, 0x04, 0x00000002 },
        { 0x419c20,   1, 0x04, 0x00000000 },
        { 0x419c24,   1, 0x04, 0x00084210 },
        { 0x419c28,   1, 0x04, 0x3cf3cf3c },
-       { 0x419cb0,   1, 0x04, 0x00020048 },
-       { 0x419ce8,   1, 0x04, 0x00000000 },
-       { 0x419cf4,   1, 0x04, 0x00000183 },
-       { 0x419d20,   1, 0x04, 0x12180000 },
-       { 0x419d24,   1, 0x04, 0x00001fff },
-       { 0x419d44,   1, 0x04, 0x02180218 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_grctx_init_sm_0[] = {
        { 0x419e04,   3, 0x04, 0x00000000 },
        { 0x419e10,   1, 0x04, 0x00000002 },
        { 0x419e44,   1, 0x04, 0x001beff2 },
@@ -453,47 +483,21 @@ nvd9_grctx_init_tpc[] = {
        {}
 };
 
-static struct nvc0_graph_init *
-nvd9_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nvd9_grctx_init_unk40xx,
-       nvc0_grctx_init_unk44xx,
-       nvc0_grctx_init_unk46xx,
-       nvc0_grctx_init_unk47xx,
-       nvd9_grctx_init_unk58xx,
-       nvc0_grctx_init_unk60xx,
-       nvd9_grctx_init_unk64xx,
-       nvc0_grctx_init_unk78xx,
-       nvc0_grctx_init_unk80xx,
-       nvd9_grctx_init_rop,
-       NULL
-};
-
-struct nvc0_graph_init *
-nvd9_grctx_init_gpc[] = {
-       nvd9_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvd9_grctx_init_tpc,
-       NULL
-};
-
-struct nvc0_graph_init
-nvd9_grctx_init_mthd_magic[] = {
-       { 0x3410, 1, 0x04, 0x80002006 },
+static const struct nvc0_graph_pack
+nvd9_grctx_pack_tpc[] = {
+       { nvc1_grctx_init_pe_0 },
+       { nvd9_grctx_init_tex_0 },
+       { nvc1_grctx_init_wwdx_0 },
+       { nvd9_grctx_init_mpc_0 },
+       { nvc4_grctx_init_l1c_0 },
+       { nvc1_grctx_init_tpccs_0 },
+       { nvd9_grctx_init_sm_0 },
        {}
 };
 
-struct nvc0_graph_mthd
-nvd9_grctx_init_mthd[] = {
-       { 0x9097, nvc1_grctx_init_9097, },
-       { 0x9197, nvc8_grctx_init_9197, },
-       { 0x9297, nvc8_grctx_init_9297, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x9039, nvc0_grctx_init_9039, },
-       { 0x90c0, nvd9_grctx_init_90c0, },
-       { 0x902d, nvd9_grctx_init_mthd_magic, },
-       {}
-};
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
 
 struct nouveau_oclass *
 nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
@@ -506,11 +510,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nvc0_grctx_generate_main,
-       .mods = nvc1_grctx_generate_mods,
-       .unkn = nvc1_grctx_generate_unkn,
-       .hub  = nvd9_grctx_init_hub,
-       .gpc  = nvd9_grctx_init_gpc,
-       .icmd = nvd9_grctx_init_icmd,
-       .mthd = nvd9_grctx_init_mthd,
+       .main  = nvc0_grctx_generate_main,
+       .mods  = nvc1_grctx_generate_mods,
+       .unkn  = nvc1_grctx_generate_unkn,
+       .hub   = nvd9_grctx_pack_hub,
+       .gpc   = nvd9_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvd9_grctx_pack_tpc,
+       .icmd  = nvd9_grctx_pack_icmd,
+       .mthd  = nvd9_grctx_pack_mthd,
 }.base;
index e2de73ee5eee529696b13914b92434cf5887cc6b..49a14b116a5f81fd771da20c756478b7e7dfd839 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-struct nvc0_graph_init
-nve4_grctx_init_icmd[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nve4_grctx_init_icmd_0[] = {
        { 0x001000,   1, 0x01, 0x00000004 },
        { 0x000039,   3, 0x01, 0x00000000 },
        { 0x0000a9,   1, 0x01, 0x0000ffff },
@@ -138,8 +142,7 @@ nve4_grctx_init_icmd[] = {
        { 0x000586,   1, 0x01, 0x00000040 },
        { 0x000582,   2, 0x01, 0x00000080 },
        { 0x0005c2,   1, 0x01, 0x00000001 },
-       { 0x000638,   1, 0x01, 0x00000001 },
-       { 0x000639,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
        { 0x00063a,   1, 0x01, 0x00000002 },
        { 0x00063b,   2, 0x01, 0x00000001 },
        { 0x00063d,   1, 0x01, 0x00000002 },
@@ -197,15 +200,13 @@ nve4_grctx_init_icmd[] = {
        { 0x000787,   1, 0x01, 0x000000cf },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x000836,   1, 0x01, 0x00000001 },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x000b07,   1, 0x01, 0x00000002 },
        { 0x000b08,   2, 0x01, 0x00000100 },
@@ -231,14 +232,12 @@ nve4_grctx_init_icmd[] = {
        { 0x0006b1,   1, 0x01, 0x00000011 },
        { 0x00078c,   1, 0x01, 0x00000008 },
        { 0x000792,   1, 0x01, 0x00000001 },
-       { 0x000794,   1, 0x01, 0x00000001 },
-       { 0x000795,   2, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
        { 0x000797,   1, 0x01, 0x000000cf },
        { 0x00079a,   1, 0x01, 0x00000002 },
        { 0x000833,   1, 0x01, 0x04444480 },
        { 0x0007a1,   1, 0x01, 0x00000001 },
-       { 0x0007a3,   1, 0x01, 0x00000001 },
-       { 0x0007a4,   2, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
        { 0x000831,   1, 0x01, 0x00000004 },
        { 0x01e100,   1, 0x01, 0x00000001 },
        { 0x001000,   1, 0x01, 0x00000008 },
@@ -273,8 +272,14 @@ nve4_grctx_init_icmd[] = {
        {}
 };
 
-struct nvc0_graph_init
-nve4_grctx_init_a097[] = {
+static const struct nvc0_graph_pack
+nve4_grctx_pack_icmd[] = {
+       { nve4_grctx_init_icmd_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_a097_0[] = {
        { 0x000800,   8, 0x40, 0x00000000 },
        { 0x000804,   8, 0x40, 0x00000000 },
        { 0x000808,   8, 0x40, 0x00000400 },
@@ -517,8 +522,7 @@ nve4_grctx_init_a097[] = {
        { 0x001350,   1, 0x04, 0x00000002 },
        { 0x001358,   1, 0x04, 0x00000001 },
        { 0x0012e4,   1, 0x04, 0x00000000 },
-       { 0x00131c,   1, 0x04, 0x00000000 },
-       { 0x001320,   3, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
        { 0x0019c0,   1, 0x04, 0x00000000 },
        { 0x001140,   1, 0x04, 0x00000000 },
        { 0x0019c4,   1, 0x04, 0x00000000 },
@@ -574,19 +578,24 @@ nve4_grctx_init_a097[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_unk40xx[] = {
+static const struct nvc0_graph_pack
+nve4_grctx_pack_mthd[] = {
+       { nve4_grctx_init_a097_0, 0xa097 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_fe_0[] = {
        { 0x404010,   5, 0x04, 0x00000000 },
        { 0x404024,   1, 0x04, 0x0000e000 },
        { 0x404028,   1, 0x04, 0x00000000 },
-       { 0x4040a8,   1, 0x04, 0x00000000 },
-       { 0x4040ac,   7, 0x04, 0x00000000 },
+       { 0x4040a8,   8, 0x04, 0x00000000 },
        { 0x4040c8,   1, 0x04, 0xf800008f },
        { 0x4040d0,   6, 0x04, 0x00000000 },
        { 0x4040e8,   1, 0x04, 0x00001000 },
        { 0x4040f8,   1, 0x04, 0x00000000 },
-       { 0x404130,   1, 0x04, 0x00000000 },
-       { 0x404134,   1, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
        { 0x404138,   1, 0x04, 0x20000040 },
        { 0x404150,   1, 0x04, 0x0000002e },
        { 0x404154,   1, 0x04, 0x00000400 },
@@ -597,8 +606,8 @@ nve4_grctx_init_unk40xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nve4_grctx_init_unk46xx[] = {
+const struct nvc0_graph_init
+nve4_grctx_init_memfmt_0[] = {
        { 0x404604,   1, 0x04, 0x00000014 },
        { 0x404608,   1, 0x04, 0x00000000 },
        { 0x40460c,   1, 0x04, 0x00003fff },
@@ -614,11 +623,6 @@ nve4_grctx_init_unk46xx[] = {
        { 0x4046a0,   1, 0x04, 0x007f0080 },
        { 0x4046a4,   8, 0x04, 0x00000000 },
        { 0x4046c8,   3, 0x04, 0x00000000 },
-       {}
-};
-
-struct nvc0_graph_init
-nve4_grctx_init_unk47xx[] = {
        { 0x404700,   3, 0x04, 0x00000000 },
        { 0x404718,   7, 0x04, 0x00000000 },
        { 0x404734,   1, 0x04, 0x00000100 },
@@ -628,8 +632,8 @@ nve4_grctx_init_unk47xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nve4_grctx_init_unk58xx[] = {
+const struct nvc0_graph_init
+nve4_grctx_init_ds_0[] = {
        { 0x405800,   1, 0x04, 0x0f8000bf },
        { 0x405830,   1, 0x04, 0x02180648 },
        { 0x405834,   1, 0x04, 0x08000000 },
@@ -641,22 +645,17 @@ nve4_grctx_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_unk5bxx[] = {
+static const struct nvc0_graph_init
+nve4_grctx_init_cwd_0[] = {
        { 0x405b00,   1, 0x04, 0x00000000 },
        { 0x405b10,   1, 0x04, 0x00001000 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_unk60xx[] = {
+static const struct nvc0_graph_init
+nve4_grctx_init_pd_0[] = {
        { 0x406020,   1, 0x04, 0x004103c1 },
        { 0x406028,   4, 0x04, 0x00000001 },
-       {}
-};
-
-static struct nvc0_graph_init
-nve4_grctx_init_unk64xx[] = {
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b4,   2, 0x04, 0x00000000 },
@@ -668,14 +667,14 @@ nve4_grctx_init_unk64xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_unk70xx[] = {
+static const struct nvc0_graph_init
+nve4_grctx_init_sked_0[] = {
        { 0x407040,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nve4_grctx_init_unk80xx[] = {
+const struct nvc0_graph_init
+nve4_grctx_init_scc_0[] = {
        { 0x408000,   2, 0x04, 0x00000000 },
        { 0x408008,   1, 0x04, 0x00000030 },
        { 0x40800c,   2, 0x04, 0x00000000 },
@@ -685,8 +684,8 @@ nve4_grctx_init_unk80xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_rop[] = {
+static const struct nvc0_graph_init
+nve4_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x02802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x1043e005 },
@@ -698,22 +697,24 @@ nve4_grctx_init_rop[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
-       { 0x418400,   1, 0x04, 0x38004e00 },
-       { 0x418404,   1, 0x04, 0x71e0ffff },
-       { 0x41840c,   1, 0x04, 0x00001008 },
-       { 0x418410,   1, 0x04, 0x0fff0fff },
-       { 0x418414,   1, 0x04, 0x02200fff },
-       { 0x418450,   6, 0x04, 0x00000000 },
-       { 0x418468,   1, 0x04, 0x00000001 },
-       { 0x41846c,   2, 0x04, 0x00000000 },
-       { 0x418600,   1, 0x04, 0x0000001f },
-       { 0x418684,   1, 0x04, 0x0000000f },
-       { 0x418700,   1, 0x04, 0x00000002 },
-       { 0x418704,   1, 0x04, 0x00000080 },
-       { 0x418708,   3, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nve4_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nve4_grctx_init_fe_0 },
+       { nvc0_grctx_init_pri_0 },
+       { nve4_grctx_init_memfmt_0 },
+       { nve4_grctx_init_ds_0 },
+       { nve4_grctx_init_cwd_0 },
+       { nve4_grctx_init_pd_0 },
+       { nve4_grctx_init_sked_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nve4_grctx_init_scc_0 },
+       { nve4_grctx_init_be_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x7006860a },
        { 0x418808,   3, 0x04, 0x00000000 },
        { 0x418828,   1, 0x04, 0x00000044 },
@@ -722,35 +723,35 @@ nve4_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x20100018 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
-       { 0x418b00,   1, 0x04, 0x00000006 },
-       { 0x418b08,   1, 0x04, 0x0a418820 },
-       { 0x418b0c,   1, 0x04, 0x062080e6 },
-       { 0x418b10,   1, 0x04, 0x020398a4 },
-       { 0x418b14,   1, 0x04, 0x0e629062 },
-       { 0x418b18,   1, 0x04, 0x0a418820 },
-       { 0x418b1c,   1, 0x04, 0x000000e6 },
-       { 0x418bb8,   1, 0x04, 0x00000103 },
+       {}
+};
+
+const struct nvc0_graph_init
+nve4_grctx_init_gpm_0[] = {
        { 0x418c08,   1, 0x04, 0x00000001 },
        { 0x418c10,   8, 0x04, 0x00000000 },
        { 0x418c40,   1, 0x04, 0xffffffff },
        { 0x418c6c,   1, 0x04, 0x00000001 },
        { 0x418c80,   1, 0x04, 0x20200004 },
        { 0x418c8c,   1, 0x04, 0x00000001 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_tpc[] = {
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x00000129 },
-       { 0x419888,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nve4_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvd9_grctx_init_prop_0 },
+       { nvd9_grctx_init_gpc_unk_1 },
+       { nve4_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvd9_grctx_init_crstr_0 },
+       { nve4_grctx_init_gpm_0 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000000f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000021 },
@@ -761,14 +762,29 @@ nve4_grctx_init_tpc[] = {
        { 0x419a20,   1, 0x04, 0x00000800 },
        { 0x419a30,   1, 0x04, 0x00000001 },
        { 0x419ac4,   1, 0x04, 0x0037f440 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_mpc_0[] = {
        { 0x419c00,   1, 0x04, 0x0000000a },
        { 0x419c04,   1, 0x04, 0x80000006 },
        { 0x419c08,   1, 0x04, 0x00000002 },
        { 0x419c20,   1, 0x04, 0x00000000 },
        { 0x419c24,   1, 0x04, 0x00084210 },
        { 0x419c28,   1, 0x04, 0x3efbefbe },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_l1c_0[] = {
        { 0x419ce8,   1, 0x04, 0x00000000 },
        { 0x419cf4,   1, 0x04, 0x00003203 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_sm_0[] = {
        { 0x419e04,   3, 0x04, 0x00000000 },
        { 0x419e10,   1, 0x04, 0x00000402 },
        { 0x419e44,   1, 0x04, 0x0013eff2 },
@@ -782,28 +798,46 @@ nve4_grctx_init_tpc[] = {
        { 0x419f58,   1, 0x04, 0x00000000 },
        { 0x419f70,   1, 0x04, 0x00000000 },
        { 0x419f78,   1, 0x04, 0x0000000b },
-       { 0x419f7c,   1, 0x04, 0x0000027a },
+       { 0x419f7c,   1, 0x04, 0x0000027c },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nve4_grctx_pack_tpc[] = {
+       { nvd7_grctx_init_pe_0 },
+       { nve4_grctx_init_tex_0 },
+       { nve4_grctx_init_mpc_0 },
+       { nve4_grctx_init_l1c_0 },
+       { nve4_grctx_init_sm_0 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_grctx_init_unk[] = {
+const struct nvc0_graph_init
+nve4_grctx_init_pes_0[] = {
        { 0x41be24,   1, 0x04, 0x00000006 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_grctx_init_cbm_0[] = {
        { 0x41bec0,   1, 0x04, 0x12180000 },
        { 0x41bec4,   1, 0x04, 0x00037f7f },
        { 0x41bee4,   1, 0x04, 0x06480430 },
-       { 0x41bf00,   1, 0x04, 0x0a418820 },
-       { 0x41bf04,   1, 0x04, 0x062080e6 },
-       { 0x41bf08,   1, 0x04, 0x020398a4 },
-       { 0x41bf0c,   1, 0x04, 0x0e629062 },
-       { 0x41bf10,   1, 0x04, 0x0a418820 },
-       { 0x41bf14,   1, 0x04, 0x000000e6 },
-       { 0x41bfd0,   1, 0x04, 0x00900103 },
-       { 0x41bfe0,   1, 0x04, 0x00400001 },
-       { 0x41bfe4,   1, 0x04, 0x00000000 },
        {}
 };
 
+static const struct nvc0_graph_pack
+nve4_grctx_pack_ppc[] = {
+       { nve4_grctx_init_pes_0 },
+       { nve4_grctx_init_cbm_0 },
+       { nvd7_grctx_init_wwdx_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 static void
 nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -925,10 +959,11 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 
        nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
 
-       for (i = 0; oclass->hub[i]; i++)
-               nvc0_graph_mmio(priv, oclass->hub[i]);
-       for (i = 0; oclass->gpc[i]; i++)
-               nvc0_graph_mmio(priv, oclass->gpc[i]);
+       nvc0_graph_mmio(priv, oclass->hub);
+       nvc0_graph_mmio(priv, oclass->gpc);
+       nvc0_graph_mmio(priv, oclass->zcull);
+       nvc0_graph_mmio(priv, oclass->tpc);
+       nvc0_graph_mmio(priv, oclass->ppc);
 
        nv_wr32(priv, 0x404154, 0x00000000);
 
@@ -962,41 +997,6 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);
 }
 
-static struct nvc0_graph_init *
-nve4_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nve4_grctx_init_unk40xx,
-       nvc0_grctx_init_unk44xx,
-       nve4_grctx_init_unk46xx,
-       nve4_grctx_init_unk47xx,
-       nve4_grctx_init_unk58xx,
-       nve4_grctx_init_unk5bxx,
-       nve4_grctx_init_unk60xx,
-       nve4_grctx_init_unk64xx,
-       nve4_grctx_init_unk70xx,
-       nvc0_grctx_init_unk78xx,
-       nve4_grctx_init_unk80xx,
-       nve4_grctx_init_rop,
-       NULL
-};
-
-struct nvc0_graph_init *
-nve4_grctx_init_gpc[] = {
-       nve4_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nve4_grctx_init_tpc,
-       nve4_grctx_init_unk,
-       NULL
-};
-
-static struct nvc0_graph_mthd
-nve4_grctx_init_mthd[] = {
-       { 0xa097, nve4_grctx_init_a097, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x902d, nvc0_grctx_init_mthd_magic, },
-       {}
-};
-
 struct nouveau_oclass *
 nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xe4),
@@ -1008,11 +1008,14 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nve4_grctx_generate_main,
-       .mods = nve4_grctx_generate_mods,
-       .unkn = nve4_grctx_generate_unkn,
-       .hub  = nve4_grctx_init_hub,
-       .gpc  = nve4_grctx_init_gpc,
-       .icmd = nve4_grctx_init_icmd,
-       .mthd = nve4_grctx_init_mthd,
+       .main  = nve4_grctx_generate_main,
+       .mods  = nve4_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = nve4_grctx_pack_hub,
+       .gpc   = nve4_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nve4_grctx_pack_tpc,
+       .ppc   = nve4_grctx_pack_ppc,
+       .icmd  = nve4_grctx_pack_icmd,
+       .mthd  = nve4_grctx_pack_mthd,
 }.base;
index 44012c3da53832c325e2286bafcc191208d9e946..0fab95e49f53b4f8c452b8afd3c114a5b4ad55f2 100644 (file)
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nvc0.h"
+#include "ctxnvc0.h"
 
-static struct nvc0_graph_init
-nvf0_grctx_init_unk40xx[] = {
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_icmd_0[] = {
+       { 0x001000,   1, 0x01, 0x00000004 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x0000a9,   1, 0x01, 0x0000ffff },
+       { 0x000038,   1, 0x01, 0x0fac6881 },
+       { 0x00003d,   1, 0x01, 0x00000001 },
+       { 0x0000e8,   8, 0x01, 0x00000400 },
+       { 0x000078,   8, 0x01, 0x00000300 },
+       { 0x000050,   1, 0x01, 0x00000011 },
+       { 0x000058,   8, 0x01, 0x00000008 },
+       { 0x000208,   8, 0x01, 0x00000001 },
+       { 0x000081,   1, 0x01, 0x00000001 },
+       { 0x000085,   1, 0x01, 0x00000004 },
+       { 0x000088,   1, 0x01, 0x00000400 },
+       { 0x000090,   1, 0x01, 0x00000300 },
+       { 0x000098,   1, 0x01, 0x00001001 },
+       { 0x0000e3,   1, 0x01, 0x00000001 },
+       { 0x0000da,   1, 0x01, 0x00000001 },
+       { 0x0000f8,   1, 0x01, 0x00000003 },
+       { 0x0000fa,   1, 0x01, 0x00000001 },
+       { 0x00009f,   4, 0x01, 0x0000ffff },
+       { 0x0000b1,   1, 0x01, 0x00000001 },
+       { 0x0000ad,   1, 0x01, 0x0000013e },
+       { 0x0000e1,   1, 0x01, 0x00000010 },
+       { 0x000290,  16, 0x01, 0x00000000 },
+       { 0x0003b0,  16, 0x01, 0x00000000 },
+       { 0x0002a0,  16, 0x01, 0x00000000 },
+       { 0x000420,  16, 0x01, 0x00000000 },
+       { 0x0002b0,  16, 0x01, 0x00000000 },
+       { 0x000430,  16, 0x01, 0x00000000 },
+       { 0x0002c0,  16, 0x01, 0x00000000 },
+       { 0x0004d0,  16, 0x01, 0x00000000 },
+       { 0x000720,  16, 0x01, 0x00000000 },
+       { 0x0008c0,  16, 0x01, 0x00000000 },
+       { 0x000890,  16, 0x01, 0x00000000 },
+       { 0x0008e0,  16, 0x01, 0x00000000 },
+       { 0x0008a0,  16, 0x01, 0x00000000 },
+       { 0x0008f0,  16, 0x01, 0x00000000 },
+       { 0x00094c,   1, 0x01, 0x000000ff },
+       { 0x00094d,   1, 0x01, 0xffffffff },
+       { 0x00094e,   1, 0x01, 0x00000002 },
+       { 0x0002ec,   1, 0x01, 0x00000001 },
+       { 0x0002f2,   2, 0x01, 0x00000001 },
+       { 0x0002f5,   1, 0x01, 0x00000001 },
+       { 0x0002f7,   1, 0x01, 0x00000001 },
+       { 0x000303,   1, 0x01, 0x00000001 },
+       { 0x0002e6,   1, 0x01, 0x00000001 },
+       { 0x000466,   1, 0x01, 0x00000052 },
+       { 0x000301,   1, 0x01, 0x3f800000 },
+       { 0x000304,   1, 0x01, 0x30201000 },
+       { 0x000305,   1, 0x01, 0x70605040 },
+       { 0x000306,   1, 0x01, 0xb8a89888 },
+       { 0x000307,   1, 0x01, 0xf8e8d8c8 },
+       { 0x00030a,   1, 0x01, 0x00ffff00 },
+       { 0x00030b,   1, 0x01, 0x0000001a },
+       { 0x00030c,   1, 0x01, 0x00000001 },
+       { 0x000318,   1, 0x01, 0x00000001 },
+       { 0x000340,   1, 0x01, 0x00000000 },
+       { 0x000375,   1, 0x01, 0x00000001 },
+       { 0x00037d,   1, 0x01, 0x00000006 },
+       { 0x0003a0,   1, 0x01, 0x00000002 },
+       { 0x0003aa,   1, 0x01, 0x00000001 },
+       { 0x0003a9,   1, 0x01, 0x00000001 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000383,   1, 0x01, 0x00000011 },
+       { 0x000360,   1, 0x01, 0x00000040 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x00037a,   1, 0x01, 0x00000012 },
+       { 0x000619,   1, 0x01, 0x00000003 },
+       { 0x000811,   1, 0x01, 0x00000003 },
+       { 0x000812,   1, 0x01, 0x00000004 },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000815,   1, 0x01, 0x0000000b },
+       { 0x000800,   6, 0x01, 0x00000001 },
+       { 0x000632,   1, 0x01, 0x00000001 },
+       { 0x000633,   1, 0x01, 0x00000002 },
+       { 0x000634,   1, 0x01, 0x00000003 },
+       { 0x000635,   1, 0x01, 0x00000004 },
+       { 0x000654,   1, 0x01, 0x3f800000 },
+       { 0x000657,   1, 0x01, 0x3f800000 },
+       { 0x000655,   2, 0x01, 0x3f800000 },
+       { 0x0006cd,   1, 0x01, 0x3f800000 },
+       { 0x0007f5,   1, 0x01, 0x3f800000 },
+       { 0x0007dc,   1, 0x01, 0x39291909 },
+       { 0x0007dd,   1, 0x01, 0x79695949 },
+       { 0x0007de,   1, 0x01, 0xb9a99989 },
+       { 0x0007df,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007e8,   1, 0x01, 0x00003210 },
+       { 0x0007e9,   1, 0x01, 0x00007654 },
+       { 0x0007ea,   1, 0x01, 0x00000098 },
+       { 0x0007ec,   1, 0x01, 0x39291909 },
+       { 0x0007ed,   1, 0x01, 0x79695949 },
+       { 0x0007ee,   1, 0x01, 0xb9a99989 },
+       { 0x0007ef,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007f0,   1, 0x01, 0x00003210 },
+       { 0x0007f1,   1, 0x01, 0x00007654 },
+       { 0x0007f2,   1, 0x01, 0x00000098 },
+       { 0x0005a5,   1, 0x01, 0x00000001 },
+       { 0x000980, 128, 0x01, 0x00000000 },
+       { 0x000468,   1, 0x01, 0x00000004 },
+       { 0x00046c,   1, 0x01, 0x00000001 },
+       { 0x000470,  96, 0x01, 0x00000000 },
+       { 0x000510,  16, 0x01, 0x3f800000 },
+       { 0x000520,   1, 0x01, 0x000002b6 },
+       { 0x000529,   1, 0x01, 0x00000001 },
+       { 0x000530,  16, 0x01, 0xffff0000 },
+       { 0x000585,   1, 0x01, 0x0000003f },
+       { 0x000576,   1, 0x01, 0x00000003 },
+       { 0x00057b,   1, 0x01, 0x00000059 },
+       { 0x000586,   1, 0x01, 0x00000040 },
+       { 0x000582,   2, 0x01, 0x00000080 },
+       { 0x0005c2,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
+       { 0x00063a,   1, 0x01, 0x00000002 },
+       { 0x00063b,   2, 0x01, 0x00000001 },
+       { 0x00063d,   1, 0x01, 0x00000002 },
+       { 0x00063e,   1, 0x01, 0x00000001 },
+       { 0x0008b8,   8, 0x01, 0x00000001 },
+       { 0x000900,   8, 0x01, 0x00000001 },
+       { 0x000908,   8, 0x01, 0x00000002 },
+       { 0x000910,  16, 0x01, 0x00000001 },
+       { 0x000920,   8, 0x01, 0x00000002 },
+       { 0x000928,   8, 0x01, 0x00000001 },
+       { 0x000662,   1, 0x01, 0x00000001 },
+       { 0x000648,   9, 0x01, 0x00000001 },
+       { 0x000658,   1, 0x01, 0x0000000f },
+       { 0x0007ff,   1, 0x01, 0x0000000a },
+       { 0x00066a,   1, 0x01, 0x40000000 },
+       { 0x00066b,   1, 0x01, 0x10000000 },
+       { 0x00066c,   2, 0x01, 0xffff0000 },
+       { 0x0007af,   2, 0x01, 0x00000008 },
+       { 0x0007f6,   1, 0x01, 0x00000001 },
+       { 0x00080b,   1, 0x01, 0x00000002 },
+       { 0x0006b2,   1, 0x01, 0x00000055 },
+       { 0x0007ad,   1, 0x01, 0x00000003 },
+       { 0x000937,   1, 0x01, 0x00000001 },
+       { 0x000971,   1, 0x01, 0x00000008 },
+       { 0x000972,   1, 0x01, 0x00000040 },
+       { 0x000973,   1, 0x01, 0x0000012c },
+       { 0x00097c,   1, 0x01, 0x00000040 },
+       { 0x000979,   1, 0x01, 0x00000003 },
+       { 0x000975,   1, 0x01, 0x00000020 },
+       { 0x000976,   1, 0x01, 0x00000001 },
+       { 0x000977,   1, 0x01, 0x00000020 },
+       { 0x000978,   1, 0x01, 0x00000001 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x00095e,   1, 0x01, 0x20164010 },
+       { 0x00095f,   1, 0x01, 0x00000020 },
+       { 0x000a0d,   1, 0x01, 0x00000006 },
+       { 0x00097d,   1, 0x01, 0x00000020 },
+       { 0x000683,   1, 0x01, 0x00000006 },
+       { 0x000685,   1, 0x01, 0x003fffff },
+       { 0x000687,   1, 0x01, 0x003fffff },
+       { 0x0006a0,   1, 0x01, 0x00000005 },
+       { 0x000840,   1, 0x01, 0x00400008 },
+       { 0x000841,   1, 0x01, 0x08000080 },
+       { 0x000842,   1, 0x01, 0x00400008 },
+       { 0x000843,   1, 0x01, 0x08000080 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ab,   1, 0x01, 0x00000002 },
+       { 0x0006ac,   1, 0x01, 0x00000080 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x0006bb,   1, 0x01, 0x000000cf },
+       { 0x0006ce,   1, 0x01, 0x2a712488 },
+       { 0x000739,   1, 0x01, 0x4085c000 },
+       { 0x00073a,   1, 0x01, 0x00000080 },
+       { 0x000786,   1, 0x01, 0x80000100 },
+       { 0x00073c,   1, 0x01, 0x00010100 },
+       { 0x00073d,   1, 0x01, 0x02800000 },
+       { 0x000787,   1, 0x01, 0x000000cf },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x000836,   1, 0x01, 0x00000001 },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x000833,   1, 0x01, 0x04444480 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c1b0,   8, 0x01, 0x0000000f },
+       { 0x00c1b8,   1, 0x01, 0x0fac6881 },
+       { 0x00c1b9,   1, 0x01, 0x00fac688 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000002 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x000833,   1, 0x01, 0x04444480 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000008 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000001 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nvf0_grctx_pack_icmd[] = {
+       { nvf0_grctx_init_icmd_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_a197_0[] = {
+       { 0x000800,   8, 0x40, 0x00000000 },
+       { 0x000804,   8, 0x40, 0x00000000 },
+       { 0x000808,   8, 0x40, 0x00000400 },
+       { 0x00080c,   8, 0x40, 0x00000300 },
+       { 0x000810,   1, 0x04, 0x000000cf },
+       { 0x000850,   7, 0x40, 0x00000000 },
+       { 0x000814,   8, 0x40, 0x00000040 },
+       { 0x000818,   8, 0x40, 0x00000001 },
+       { 0x00081c,   8, 0x40, 0x00000000 },
+       { 0x000820,   8, 0x40, 0x00000000 },
+       { 0x001c00,  16, 0x10, 0x00000000 },
+       { 0x001c04,  16, 0x10, 0x00000000 },
+       { 0x001c08,  16, 0x10, 0x00000000 },
+       { 0x001c0c,  16, 0x10, 0x00000000 },
+       { 0x001d00,  16, 0x10, 0x00000000 },
+       { 0x001d04,  16, 0x10, 0x00000000 },
+       { 0x001d08,  16, 0x10, 0x00000000 },
+       { 0x001d0c,  16, 0x10, 0x00000000 },
+       { 0x001f00,  16, 0x08, 0x00000000 },
+       { 0x001f04,  16, 0x08, 0x00000000 },
+       { 0x001f80,  16, 0x08, 0x00000000 },
+       { 0x001f84,  16, 0x08, 0x00000000 },
+       { 0x002000,   1, 0x04, 0x00000000 },
+       { 0x002040,   1, 0x04, 0x00000011 },
+       { 0x002080,   1, 0x04, 0x00000020 },
+       { 0x0020c0,   1, 0x04, 0x00000030 },
+       { 0x002100,   1, 0x04, 0x00000040 },
+       { 0x002140,   1, 0x04, 0x00000051 },
+       { 0x00200c,   6, 0x40, 0x00000001 },
+       { 0x002010,   1, 0x04, 0x00000000 },
+       { 0x002050,   1, 0x04, 0x00000000 },
+       { 0x002090,   1, 0x04, 0x00000001 },
+       { 0x0020d0,   1, 0x04, 0x00000002 },
+       { 0x002110,   1, 0x04, 0x00000003 },
+       { 0x002150,   1, 0x04, 0x00000004 },
+       { 0x000380,   4, 0x20, 0x00000000 },
+       { 0x000384,   4, 0x20, 0x00000000 },
+       { 0x000388,   4, 0x20, 0x00000000 },
+       { 0x00038c,   4, 0x20, 0x00000000 },
+       { 0x000700,   4, 0x10, 0x00000000 },
+       { 0x000704,   4, 0x10, 0x00000000 },
+       { 0x000708,   4, 0x10, 0x00000000 },
+       { 0x002800, 128, 0x04, 0x00000000 },
+       { 0x000a00,  16, 0x20, 0x00000000 },
+       { 0x000a04,  16, 0x20, 0x00000000 },
+       { 0x000a08,  16, 0x20, 0x00000000 },
+       { 0x000a0c,  16, 0x20, 0x00000000 },
+       { 0x000a10,  16, 0x20, 0x00000000 },
+       { 0x000a14,  16, 0x20, 0x00000000 },
+       { 0x000c00,  16, 0x10, 0x00000000 },
+       { 0x000c04,  16, 0x10, 0x00000000 },
+       { 0x000c08,  16, 0x10, 0x00000000 },
+       { 0x000c0c,  16, 0x10, 0x3f800000 },
+       { 0x000d00,   8, 0x08, 0xffff0000 },
+       { 0x000d04,   8, 0x08, 0xffff0000 },
+       { 0x000e00,  16, 0x10, 0x00000000 },
+       { 0x000e04,  16, 0x10, 0xffff0000 },
+       { 0x000e08,  16, 0x10, 0xffff0000 },
+       { 0x000d40,   4, 0x08, 0x00000000 },
+       { 0x000d44,   4, 0x08, 0x00000000 },
+       { 0x001e00,   8, 0x20, 0x00000001 },
+       { 0x001e04,   8, 0x20, 0x00000001 },
+       { 0x001e08,   8, 0x20, 0x00000002 },
+       { 0x001e0c,   8, 0x20, 0x00000001 },
+       { 0x001e10,   8, 0x20, 0x00000001 },
+       { 0x001e14,   8, 0x20, 0x00000002 },
+       { 0x001e18,   8, 0x20, 0x00000001 },
+       { 0x003400, 128, 0x04, 0x00000000 },
+       { 0x00030c,   1, 0x04, 0x00000001 },
+       { 0x001944,   1, 0x04, 0x00000000 },
+       { 0x001514,   1, 0x04, 0x00000000 },
+       { 0x000d68,   1, 0x04, 0x0000ffff },
+       { 0x00121c,   1, 0x04, 0x0fac6881 },
+       { 0x000fac,   1, 0x04, 0x00000001 },
+       { 0x001538,   1, 0x04, 0x00000001 },
+       { 0x000fe0,   2, 0x04, 0x00000000 },
+       { 0x000fe8,   1, 0x04, 0x00000014 },
+       { 0x000fec,   1, 0x04, 0x00000040 },
+       { 0x000ff0,   1, 0x04, 0x00000000 },
+       { 0x00179c,   1, 0x04, 0x00000000 },
+       { 0x001228,   1, 0x04, 0x00000400 },
+       { 0x00122c,   1, 0x04, 0x00000300 },
+       { 0x001230,   1, 0x04, 0x00010001 },
+       { 0x0007f8,   1, 0x04, 0x00000000 },
+       { 0x0015b4,   1, 0x04, 0x00000001 },
+       { 0x0015cc,   1, 0x04, 0x00000000 },
+       { 0x001534,   1, 0x04, 0x00000000 },
+       { 0x000fb0,   1, 0x04, 0x00000000 },
+       { 0x0015d0,   1, 0x04, 0x00000000 },
+       { 0x00153c,   1, 0x04, 0x00000000 },
+       { 0x0016b4,   1, 0x04, 0x00000003 },
+       { 0x000fbc,   4, 0x04, 0x0000ffff },
+       { 0x000df8,   2, 0x04, 0x00000000 },
+       { 0x001948,   1, 0x04, 0x00000000 },
+       { 0x001970,   1, 0x04, 0x00000001 },
+       { 0x00161c,   1, 0x04, 0x000009f0 },
+       { 0x000dcc,   1, 0x04, 0x00000010 },
+       { 0x00163c,   1, 0x04, 0x00000000 },
+       { 0x0015e4,   1, 0x04, 0x00000000 },
+       { 0x001160,  32, 0x04, 0x25e00040 },
+       { 0x001880,  32, 0x04, 0x00000000 },
+       { 0x000f84,   2, 0x04, 0x00000000 },
+       { 0x0017c8,   2, 0x04, 0x00000000 },
+       { 0x0017d0,   1, 0x04, 0x000000ff },
+       { 0x0017d4,   1, 0x04, 0xffffffff },
+       { 0x0017d8,   1, 0x04, 0x00000002 },
+       { 0x0017dc,   1, 0x04, 0x00000000 },
+       { 0x0015f4,   2, 0x04, 0x00000000 },
+       { 0x001434,   2, 0x04, 0x00000000 },
+       { 0x000d74,   1, 0x04, 0x00000000 },
+       { 0x000dec,   1, 0x04, 0x00000001 },
+       { 0x0013a4,   1, 0x04, 0x00000000 },
+       { 0x001318,   1, 0x04, 0x00000001 },
+       { 0x001644,   1, 0x04, 0x00000000 },
+       { 0x000748,   1, 0x04, 0x00000000 },
+       { 0x000de8,   1, 0x04, 0x00000000 },
+       { 0x001648,   1, 0x04, 0x00000000 },
+       { 0x0012a4,   1, 0x04, 0x00000000 },
+       { 0x001120,   4, 0x04, 0x00000000 },
+       { 0x001118,   1, 0x04, 0x00000000 },
+       { 0x00164c,   1, 0x04, 0x00000000 },
+       { 0x001658,   1, 0x04, 0x00000000 },
+       { 0x001910,   1, 0x04, 0x00000290 },
+       { 0x001518,   1, 0x04, 0x00000000 },
+       { 0x00165c,   1, 0x04, 0x00000001 },
+       { 0x001520,   1, 0x04, 0x00000000 },
+       { 0x001604,   1, 0x04, 0x00000000 },
+       { 0x001570,   1, 0x04, 0x00000000 },
+       { 0x0013b0,   2, 0x04, 0x3f800000 },
+       { 0x00020c,   1, 0x04, 0x00000000 },
+       { 0x001670,   1, 0x04, 0x30201000 },
+       { 0x001674,   1, 0x04, 0x70605040 },
+       { 0x001678,   1, 0x04, 0xb8a89888 },
+       { 0x00167c,   1, 0x04, 0xf8e8d8c8 },
+       { 0x00166c,   1, 0x04, 0x00000000 },
+       { 0x001680,   1, 0x04, 0x00ffff00 },
+       { 0x0012d0,   1, 0x04, 0x00000003 },
+       { 0x0012d4,   1, 0x04, 0x00000002 },
+       { 0x001684,   2, 0x04, 0x00000000 },
+       { 0x000dac,   2, 0x04, 0x00001b02 },
+       { 0x000db4,   1, 0x04, 0x00000000 },
+       { 0x00168c,   1, 0x04, 0x00000000 },
+       { 0x0015bc,   1, 0x04, 0x00000000 },
+       { 0x00156c,   1, 0x04, 0x00000000 },
+       { 0x00187c,   1, 0x04, 0x00000000 },
+       { 0x001110,   1, 0x04, 0x00000001 },
+       { 0x000dc0,   3, 0x04, 0x00000000 },
+       { 0x001234,   1, 0x04, 0x00000000 },
+       { 0x001690,   1, 0x04, 0x00000000 },
+       { 0x0012ac,   1, 0x04, 0x00000001 },
+       { 0x0002c4,   1, 0x04, 0x00000000 },
+       { 0x000790,   5, 0x04, 0x00000000 },
+       { 0x00077c,   1, 0x04, 0x00000000 },
+       { 0x001000,   1, 0x04, 0x00000010 },
+       { 0x0010fc,   1, 0x04, 0x00000000 },
+       { 0x001290,   1, 0x04, 0x00000000 },
+       { 0x000218,   1, 0x04, 0x00000010 },
+       { 0x0012d8,   1, 0x04, 0x00000000 },
+       { 0x0012dc,   1, 0x04, 0x00000010 },
+       { 0x000d94,   1, 0x04, 0x00000001 },
+       { 0x00155c,   2, 0x04, 0x00000000 },
+       { 0x001564,   1, 0x04, 0x00000fff },
+       { 0x001574,   2, 0x04, 0x00000000 },
+       { 0x00157c,   1, 0x04, 0x000fffff },
+       { 0x001354,   1, 0x04, 0x00000000 },
+       { 0x001610,   1, 0x04, 0x00000012 },
+       { 0x001608,   2, 0x04, 0x00000000 },
+       { 0x00260c,   1, 0x04, 0x00000000 },
+       { 0x0007ac,   1, 0x04, 0x00000000 },
+       { 0x00162c,   1, 0x04, 0x00000003 },
+       { 0x000210,   1, 0x04, 0x00000000 },
+       { 0x000320,   1, 0x04, 0x00000000 },
+       { 0x000324,   6, 0x04, 0x3f800000 },
+       { 0x000750,   1, 0x04, 0x00000000 },
+       { 0x000760,   1, 0x04, 0x39291909 },
+       { 0x000764,   1, 0x04, 0x79695949 },
+       { 0x000768,   1, 0x04, 0xb9a99989 },
+       { 0x00076c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x000770,   1, 0x04, 0x30201000 },
+       { 0x000774,   1, 0x04, 0x70605040 },
+       { 0x000778,   1, 0x04, 0x00009080 },
+       { 0x000780,   1, 0x04, 0x39291909 },
+       { 0x000784,   1, 0x04, 0x79695949 },
+       { 0x000788,   1, 0x04, 0xb9a99989 },
+       { 0x00078c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x0007d0,   1, 0x04, 0x30201000 },
+       { 0x0007d4,   1, 0x04, 0x70605040 },
+       { 0x0007d8,   1, 0x04, 0x00009080 },
+       { 0x00037c,   1, 0x04, 0x00000001 },
+       { 0x000740,   2, 0x04, 0x00000000 },
+       { 0x002600,   1, 0x04, 0x00000000 },
+       { 0x001918,   1, 0x04, 0x00000000 },
+       { 0x00191c,   1, 0x04, 0x00000900 },
+       { 0x001920,   1, 0x04, 0x00000405 },
+       { 0x001308,   1, 0x04, 0x00000001 },
+       { 0x001924,   1, 0x04, 0x00000000 },
+       { 0x0013ac,   1, 0x04, 0x00000000 },
+       { 0x00192c,   1, 0x04, 0x00000001 },
+       { 0x00193c,   1, 0x04, 0x00002c1c },
+       { 0x000d7c,   1, 0x04, 0x00000000 },
+       { 0x000f8c,   1, 0x04, 0x00000000 },
+       { 0x0002c0,   1, 0x04, 0x00000001 },
+       { 0x001510,   1, 0x04, 0x00000000 },
+       { 0x001940,   1, 0x04, 0x00000000 },
+       { 0x000ff4,   2, 0x04, 0x00000000 },
+       { 0x00194c,   2, 0x04, 0x00000000 },
+       { 0x001968,   1, 0x04, 0x00000000 },
+       { 0x001590,   1, 0x04, 0x0000003f },
+       { 0x0007e8,   4, 0x04, 0x00000000 },
+       { 0x00196c,   1, 0x04, 0x00000011 },
+       { 0x0002e4,   1, 0x04, 0x0000b001 },
+       { 0x00036c,   2, 0x04, 0x00000000 },
+       { 0x00197c,   1, 0x04, 0x00000000 },
+       { 0x000fcc,   2, 0x04, 0x00000000 },
+       { 0x0002d8,   1, 0x04, 0x00000040 },
+       { 0x001980,   1, 0x04, 0x00000080 },
+       { 0x001504,   1, 0x04, 0x00000080 },
+       { 0x001984,   1, 0x04, 0x00000000 },
+       { 0x000300,   1, 0x04, 0x00000001 },
+       { 0x0013a8,   1, 0x04, 0x00000000 },
+       { 0x0012ec,   1, 0x04, 0x00000000 },
+       { 0x001310,   1, 0x04, 0x00000000 },
+       { 0x001314,   1, 0x04, 0x00000001 },
+       { 0x001380,   1, 0x04, 0x00000000 },
+       { 0x001384,   4, 0x04, 0x00000001 },
+       { 0x001394,   1, 0x04, 0x00000000 },
+       { 0x00139c,   1, 0x04, 0x00000000 },
+       { 0x001398,   1, 0x04, 0x00000000 },
+       { 0x001594,   1, 0x04, 0x00000000 },
+       { 0x001598,   4, 0x04, 0x00000001 },
+       { 0x000f54,   3, 0x04, 0x00000000 },
+       { 0x0019bc,   1, 0x04, 0x00000000 },
+       { 0x000f9c,   2, 0x04, 0x00000000 },
+       { 0x0012cc,   1, 0x04, 0x00000000 },
+       { 0x0012e8,   1, 0x04, 0x00000000 },
+       { 0x00130c,   1, 0x04, 0x00000001 },
+       { 0x001360,   8, 0x04, 0x00000000 },
+       { 0x00133c,   2, 0x04, 0x00000001 },
+       { 0x001344,   1, 0x04, 0x00000002 },
+       { 0x001348,   2, 0x04, 0x00000001 },
+       { 0x001350,   1, 0x04, 0x00000002 },
+       { 0x001358,   1, 0x04, 0x00000001 },
+       { 0x0012e4,   1, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
+       { 0x0019c0,   1, 0x04, 0x00000000 },
+       { 0x001140,   1, 0x04, 0x00000000 },
+       { 0x0019c4,   1, 0x04, 0x00000000 },
+       { 0x0019c8,   1, 0x04, 0x00001500 },
+       { 0x00135c,   1, 0x04, 0x00000000 },
+       { 0x000f90,   1, 0x04, 0x00000000 },
+       { 0x0019e0,   8, 0x04, 0x00000001 },
+       { 0x0019cc,   1, 0x04, 0x00000001 },
+       { 0x0015b8,   1, 0x04, 0x00000000 },
+       { 0x001a00,   1, 0x04, 0x00001111 },
+       { 0x001a04,   7, 0x04, 0x00000000 },
+       { 0x000d6c,   2, 0x04, 0xffff0000 },
+       { 0x0010f8,   1, 0x04, 0x00001010 },
+       { 0x000d80,   5, 0x04, 0x00000000 },
+       { 0x000da0,   1, 0x04, 0x00000000 },
+       { 0x0007a4,   2, 0x04, 0x00000000 },
+       { 0x001508,   1, 0x04, 0x80000000 },
+       { 0x00150c,   1, 0x04, 0x40000000 },
+       { 0x001668,   1, 0x04, 0x00000000 },
+       { 0x000318,   2, 0x04, 0x00000008 },
+       { 0x000d9c,   1, 0x04, 0x00000001 },
+       { 0x000ddc,   1, 0x04, 0x00000002 },
+       { 0x000374,   1, 0x04, 0x00000000 },
+       { 0x000378,   1, 0x04, 0x00000020 },
+       { 0x0007dc,   1, 0x04, 0x00000000 },
+       { 0x00074c,   1, 0x04, 0x00000055 },
+       { 0x001420,   1, 0x04, 0x00000003 },
+       { 0x0017bc,   2, 0x04, 0x00000000 },
+       { 0x0017c4,   1, 0x04, 0x00000001 },
+       { 0x001008,   1, 0x04, 0x00000008 },
+       { 0x00100c,   1, 0x04, 0x00000040 },
+       { 0x001010,   1, 0x04, 0x0000012c },
+       { 0x000d60,   1, 0x04, 0x00000040 },
+       { 0x00075c,   1, 0x04, 0x00000003 },
+       { 0x001018,   1, 0x04, 0x00000020 },
+       { 0x00101c,   1, 0x04, 0x00000001 },
+       { 0x001020,   1, 0x04, 0x00000020 },
+       { 0x001024,   1, 0x04, 0x00000001 },
+       { 0x001444,   3, 0x04, 0x00000000 },
+       { 0x000360,   1, 0x04, 0x20164010 },
+       { 0x000364,   1, 0x04, 0x00000020 },
+       { 0x000368,   1, 0x04, 0x00000000 },
+       { 0x000de4,   1, 0x04, 0x00000000 },
+       { 0x000204,   1, 0x04, 0x00000006 },
+       { 0x000208,   1, 0x04, 0x00000000 },
+       { 0x0002cc,   2, 0x04, 0x003fffff },
+       { 0x001220,   1, 0x04, 0x00000005 },
+       { 0x000fdc,   1, 0x04, 0x00000000 },
+       { 0x000f98,   1, 0x04, 0x00400008 },
+       { 0x001284,   1, 0x04, 0x08000080 },
+       { 0x001450,   1, 0x04, 0x00400008 },
+       { 0x001454,   1, 0x04, 0x08000080 },
+       { 0x000214,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_pack
+nvf0_grctx_pack_mthd[] = {
+       { nvf0_grctx_init_a197_0, 0xa197 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_fe_0[] = {
        { 0x404004,   8, 0x04, 0x00000000 },
        { 0x404024,   1, 0x04, 0x0000e000 },
        { 0x404028,   8, 0x04, 0x00000000 },
@@ -50,8 +620,8 @@ nvf0_grctx_init_unk40xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvf0_grctx_init_unk44xx[] = {
+const struct nvc0_graph_init
+nvf0_grctx_init_pri_0[] = {
        { 0x404404,  12, 0x04, 0x00000000 },
        { 0x404438,   1, 0x04, 0x00000000 },
        { 0x404460,   2, 0x04, 0x00000000 },
@@ -62,23 +632,18 @@ nvf0_grctx_init_unk44xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvf0_grctx_init_unk5bxx[] = {
+const struct nvc0_graph_init
+nvf0_grctx_init_cwd_0[] = {
        { 0x405b00,   1, 0x04, 0x00000000 },
        { 0x405b10,   1, 0x04, 0x00001000 },
        { 0x405b20,   1, 0x04, 0x04000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvf0_grctx_init_unk60xx[] = {
+static const struct nvc0_graph_init
+nvf0_grctx_init_pd_0[] = {
        { 0x406020,   1, 0x04, 0x034103c1 },
        { 0x406028,   4, 0x04, 0x00000001 },
-       {}
-};
-
-static struct nvc0_graph_init
-nvf0_grctx_init_unk64xx[] = {
        { 0x4064a8,   1, 0x04, 0x00000000 },
        { 0x4064ac,   1, 0x04, 0x00003fff },
        { 0x4064b0,   3, 0x04, 0x00000000 },
@@ -90,8 +655,8 @@ nvf0_grctx_init_unk64xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_grctx_init_unk88xx[] = {
+static const struct nvc0_graph_init
+nvf0_grctx_init_be_0[] = {
        { 0x408800,   1, 0x04, 0x12802a3c },
        { 0x408804,   1, 0x04, 0x00000040 },
        { 0x408808,   1, 0x04, 0x1003e005 },
@@ -103,22 +668,23 @@ nvf0_grctx_init_unk88xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_grctx_init_gpc_0[] = {
-       { 0x418380,   1, 0x04, 0x00000016 },
-       { 0x418400,   1, 0x04, 0x38004e00 },
-       { 0x418404,   1, 0x04, 0x71e0ffff },
-       { 0x41840c,   1, 0x04, 0x00001008 },
-       { 0x418410,   1, 0x04, 0x0fff0fff },
-       { 0x418414,   1, 0x04, 0x02200fff },
-       { 0x418450,   6, 0x04, 0x00000000 },
-       { 0x418468,   1, 0x04, 0x00000001 },
-       { 0x41846c,   2, 0x04, 0x00000000 },
-       { 0x418600,   1, 0x04, 0x0000001f },
-       { 0x418684,   1, 0x04, 0x0000000f },
-       { 0x418700,   1, 0x04, 0x00000002 },
-       { 0x418704,   1, 0x04, 0x00000080 },
-       { 0x418708,   3, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvf0_grctx_pack_hub[] = {
+       { nvc0_grctx_init_main_0 },
+       { nvf0_grctx_init_fe_0 },
+       { nvf0_grctx_init_pri_0 },
+       { nve4_grctx_init_memfmt_0 },
+       { nve4_grctx_init_ds_0 },
+       { nvf0_grctx_init_cwd_0 },
+       { nvf0_grctx_init_pd_0 },
+       { nvc0_grctx_init_rstr2d_0 },
+       { nve4_grctx_init_scc_0 },
+       { nvf0_grctx_init_be_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_setup_0[] = {
        { 0x418800,   1, 0x04, 0x7006860a },
        { 0x418808,   1, 0x04, 0x00000000 },
        { 0x41880c,   1, 0x04, 0x00000030 },
@@ -129,36 +695,31 @@ nvf0_grctx_init_gpc_0[] = {
        { 0x4188e0,   1, 0x04, 0x01000000 },
        { 0x4188e8,   5, 0x04, 0x00000000 },
        { 0x4188fc,   1, 0x04, 0x20100018 },
-       { 0x41891c,   1, 0x04, 0x00ff00ff },
-       { 0x418924,   1, 0x04, 0x00000000 },
-       { 0x418928,   1, 0x04, 0x00ffff00 },
-       { 0x41892c,   1, 0x04, 0x0000ff00 },
-       { 0x418b00,   1, 0x04, 0x00000006 },
-       { 0x418b08,   1, 0x04, 0x0a418820 },
-       { 0x418b0c,   1, 0x04, 0x062080e6 },
-       { 0x418b10,   1, 0x04, 0x020398a4 },
-       { 0x418b14,   1, 0x04, 0x0e629062 },
-       { 0x418b18,   1, 0x04, 0x0a418820 },
-       { 0x418b1c,   1, 0x04, 0x000000e6 },
-       { 0x418bb8,   1, 0x04, 0x00000103 },
-       { 0x418c08,   1, 0x04, 0x00000001 },
-       { 0x418c10,   8, 0x04, 0x00000000 },
-       { 0x418c40,   1, 0x04, 0xffffffff },
-       { 0x418c6c,   1, 0x04, 0x00000001 },
-       { 0x418c80,   1, 0x04, 0x20200004 },
-       { 0x418c8c,   1, 0x04, 0x00000001 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvf0_grctx_init_gpc_unk_2[] = {
        { 0x418d24,   1, 0x04, 0x00000000 },
-       { 0x419000,   1, 0x04, 0x00000780 },
-       { 0x419004,   2, 0x04, 0x00000000 },
-       { 0x419014,   1, 0x04, 0x00000004 },
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_grctx_init_tpc[] = {
-       { 0x419848,   1, 0x04, 0x00000000 },
-       { 0x419864,   1, 0x04, 0x00000129 },
-       { 0x419888,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_pack
+nvf0_grctx_pack_gpc[] = {
+       { nvc0_grctx_init_gpc_unk_0 },
+       { nvd9_grctx_init_prop_0 },
+       { nvd9_grctx_init_gpc_unk_1 },
+       { nvf0_grctx_init_setup_0 },
+       { nvc0_grctx_init_zcull_0 },
+       { nvd9_grctx_init_crstr_0 },
+       { nve4_grctx_init_gpm_0 },
+       { nvf0_grctx_init_gpc_unk_2 },
+       { nvc0_grctx_init_gcc_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_tex_0[] = {
        { 0x419a00,   1, 0x04, 0x000000f0 },
        { 0x419a04,   1, 0x04, 0x00000001 },
        { 0x419a08,   1, 0x04, 0x00000021 },
@@ -169,14 +730,29 @@ nvf0_grctx_init_tpc[] = {
        { 0x419a20,   1, 0x04, 0x00020800 },
        { 0x419a30,   1, 0x04, 0x00000001 },
        { 0x419ac4,   1, 0x04, 0x0037f440 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvf0_grctx_init_mpc_0[] = {
        { 0x419c00,   1, 0x04, 0x0000001a },
        { 0x419c04,   1, 0x04, 0x80000006 },
        { 0x419c08,   1, 0x04, 0x00000002 },
        { 0x419c20,   1, 0x04, 0x00000000 },
        { 0x419c24,   1, 0x04, 0x00084210 },
        { 0x419c28,   1, 0x04, 0x3efbefbe },
+       {}
+};
+
+const struct nvc0_graph_init
+nvf0_grctx_init_l1c_0[] = {
        { 0x419ce8,   1, 0x04, 0x00000000 },
        { 0x419cf4,   1, 0x04, 0x00000203 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_sm_0[] = {
        { 0x419e04,   1, 0x04, 0x00000000 },
        { 0x419e08,   1, 0x04, 0x0000001d },
        { 0x419e0c,   1, 0x04, 0x00000000 },
@@ -189,8 +765,8 @@ nvf0_grctx_init_tpc[] = {
        { 0x419e5c,   3, 0x04, 0x00000000 },
        { 0x419e68,   1, 0x04, 0x00000002 },
        { 0x419e6c,  12, 0x04, 0x00000000 },
-       { 0x419eac,   1, 0x04, 0x00001fcf },
-       { 0x419eb0,   1, 0x04, 0x0db00da0 },
+       { 0x419eac,   1, 0x04, 0x00001f8f },
+       { 0x419eb0,   1, 0x04, 0x0db00d2f },
        { 0x419eb8,   1, 0x04, 0x00000000 },
        { 0x419ec8,   1, 0x04, 0x0001304f },
        { 0x419f30,   4, 0x04, 0x00000000 },
@@ -203,24 +779,36 @@ nvf0_grctx_init_tpc[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_grctx_init_unk[] = {
-       { 0x41be24,   1, 0x04, 0x00000006 },
+static const struct nvc0_graph_pack
+nvf0_grctx_pack_tpc[] = {
+       { nvd7_grctx_init_pe_0 },
+       { nvf0_grctx_init_tex_0 },
+       { nvf0_grctx_init_mpc_0 },
+       { nvf0_grctx_init_l1c_0 },
+       { nvf0_grctx_init_sm_0 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_grctx_init_cbm_0[] = {
        { 0x41bec0,   1, 0x04, 0x10000000 },
        { 0x41bec4,   1, 0x04, 0x00037f7f },
        { 0x41bee4,   1, 0x04, 0x00000000 },
-       { 0x41bf00,   1, 0x04, 0x0a418820 },
-       { 0x41bf04,   1, 0x04, 0x062080e6 },
-       { 0x41bf08,   1, 0x04, 0x020398a4 },
-       { 0x41bf0c,   1, 0x04, 0x0e629062 },
-       { 0x41bf10,   1, 0x04, 0x0a418820 },
-       { 0x41bf14,   1, 0x04, 0x000000e6 },
-       { 0x41bfd0,   1, 0x04, 0x00900103 },
-       { 0x41bfe0,   1, 0x04, 0x00400001 },
-       { 0x41bfe4,   1, 0x04, 0x00000000 },
        {}
 };
 
+static const struct nvc0_graph_pack
+nvf0_grctx_pack_ppc[] = {
+       { nve4_grctx_init_pes_0 },
+       { nvf0_grctx_init_cbm_0 },
+       { nvd7_grctx_init_wwdx_0 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
 static void
 nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
@@ -273,39 +861,6 @@ nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        mmio_list(0x17e920, 0x00090a05, 0, 0);
 }
 
-static struct nvc0_graph_init *
-nvf0_grctx_init_hub[] = {
-       nvc0_grctx_init_base,
-       nvf0_grctx_init_unk40xx,
-       nvf0_grctx_init_unk44xx,
-       nve4_grctx_init_unk46xx,
-       nve4_grctx_init_unk47xx,
-       nve4_grctx_init_unk58xx,
-       nvf0_grctx_init_unk5bxx,
-       nvf0_grctx_init_unk60xx,
-       nvf0_grctx_init_unk64xx,
-       nve4_grctx_init_unk80xx,
-       nvf0_grctx_init_unk88xx,
-       NULL
-};
-
-struct nvc0_graph_init *
-nvf0_grctx_init_gpc[] = {
-       nvf0_grctx_init_gpc_0,
-       nvc0_grctx_init_gpc_1,
-       nvf0_grctx_init_tpc,
-       nvf0_grctx_init_unk,
-       NULL
-};
-
-static struct nvc0_graph_mthd
-nvf0_grctx_init_mthd[] = {
-       { 0xa197, nvc1_grctx_init_9097, },
-       { 0x902d, nvc0_grctx_init_902d, },
-       { 0x902d, nvc0_grctx_init_mthd_magic, },
-       {}
-};
-
 struct nouveau_oclass *
 nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
        .base.handle = NV_ENGCTX(GR, 0xf0),
@@ -317,11 +872,14 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
                .rd32 = _nouveau_graph_context_rd32,
                .wr32 = _nouveau_graph_context_wr32,
        },
-       .main = nve4_grctx_generate_main,
-       .mods = nvf0_grctx_generate_mods,
-       .unkn = nve4_grctx_generate_unkn,
-       .hub  = nvf0_grctx_init_hub,
-       .gpc  = nvf0_grctx_init_gpc,
-       .icmd = nvc0_grctx_init_icmd,
-       .mthd = nvf0_grctx_init_mthd,
+       .main  = nve4_grctx_generate_main,
+       .mods  = nvf0_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = nvf0_grctx_pack_hub,
+       .gpc   = nvf0_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nvf0_grctx_pack_tpc,
+       .ppc   = nvf0_grctx_pack_ppc,
+       .icmd  = nvf0_grctx_pack_icmd,
+       .mthd  = nvf0_grctx_pack_mthd,
 }.base;
index e148961b8075e96be5ab2f1b86ebc7170676db4e..e37d8106ae1a892679de32c16135044aedde2c1c 100644 (file)
@@ -228,7 +228,7 @@ mmctx_xfer:
                        and $r11 0x1f
                        cmpu b32 $r11 0x10
                        bra ne #mmctx_fini_wait
-               mov $r10 2                              // DONE_MMCTX
+               mov $r10 5                      // DONE_MMCTX
                call(wait_donez)
                bra #mmctx_done
        mmctx_stop:
index 96cbcea3b2c96aa71f2c7ef3d59b3d3184a67e17..2f7345f7fe074a3854309a9909d4741d9cd30a8c 100644 (file)
@@ -78,7 +78,12 @@ error:
 //
 init:
        clear b32 $r0
-       mov $sp $r0
+
+       // setup stack
+       nv_iord($r1, NV_PGRAPH_GPCX_GPCCS_CAPS, 0)
+       extr $r1 $r1 9:17
+       shl b32 $r1 8
+       mov $sp $r1
 
        // enable fifo access
        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 (file)
index 0000000..e730603
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000002
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #gm107_grgpc_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "gpc.fuc"
+#undef INCLUDE_DATA
+
+.section #gm107_grgpc_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "gpc.fuc"
+.align 256
+#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 (file)
index 0000000..6d53b67
--- /dev/null
@@ -0,0 +1,473 @@
+uint32_t gm107_grgpc_data[] = {
+/* 0x0000: gpc_mmio_list_head */
+       0x0000006c,
+/* 0x0004: gpc_mmio_list_tail */
+/* 0x0004: tpc_mmio_list_head */
+       0x0000006c,
+/* 0x0008: tpc_mmio_list_tail */
+/* 0x0008: unk_mmio_list_head */
+       0x0000006c,
+/* 0x000c: unk_mmio_list_tail */
+       0x0000006c,
+/* 0x0010: gpc_id */
+       0x00000000,
+/* 0x0014: tpc_count */
+       0x00000000,
+/* 0x0018: tpc_mask */
+       0x00000000,
+/* 0x001c: unk_count */
+       0x00000000,
+/* 0x0020: unk_mask */
+       0x00000000,
+/* 0x0024: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+uint32_t gm107_grgpc_code[] = {
+       0x03140ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e05,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0xffb2e0f9,
+       0x4098148e,
+       0x00008f7e,
+       0xffb2010f,
+       0x409c1c8e,
+       0x00008f7e,
+       0x00f8e0fc,
+/* 0x0314: init */
+       0x004104bd,
+       0x0011cf42,
+       0x010911e7,
+       0xfe0814b6,
+       0x02020014,
+       0xf6120040,
+       0x04bd0002,
+       0xfe047241,
+       0x00400010,
+       0x0000f607,
+       0x040204bd,
+       0xf6040040,
+       0x04bd0002,
+       0x821031f4,
+       0xcf018200,
+       0x01030022,
+       0xbb1f24f0,
+       0x32b60432,
+       0x0502b501,
+       0x820603b5,
+       0xcf018600,
+       0x02b50022,
+       0x0c308e04,
+       0xbd24bd50,
+/* 0x0377: init_unk_loop */
+       0x7e44bd34,
+       0xb0000065,
+       0x0bf400f6,
+       0xbb010f0e,
+       0x4ffd04f2,
+       0x0130b605,
+/* 0x038c: init_unk_next */
+       0xb60120b6,
+       0x26b004e0,
+       0xe21bf402,
+/* 0x0398: init_unk_done */
+       0xb50703b5,
+       0x00820804,
+       0x22cf0201,
+       0x9534bd00,
+       0x00800825,
+       0x05f601c0,
+       0x8004bd00,
+       0xf601c100,
+       0x04bd0005,
+       0x98000e98,
+       0x207e010f,
+       0x2fbb0001,
+       0x003fbb00,
+       0x98010e98,
+       0x207e020f,
+       0x0e980001,
+       0x00effd05,
+       0xbb002ebb,
+       0x0e98003e,
+       0x030f9802,
+       0x0001207e,
+       0xfd070e98,
+       0x2ebb00ef,
+       0x003ebb00,
+       0x800235b6,
+       0xf601d300,
+       0x04bd0003,
+       0xb60825b6,
+       0x20b60635,
+       0x0130b601,
+       0xb60824b6,
+       0x2fb20834,
+       0x0002687e,
+       0x80003fbb,
+       0xf6020100,
+       0x04bd0003,
+       0x29f024bd,
+       0x3000801f,
+       0x0002f602,
+/* 0x0436: main */
+       0x31f404bd,
+       0x0028f400,
+       0x377e240d,
+       0x01f40000,
+       0x04e4b0f4,
+       0xfe1d18f4,
+       0x06020181,
+       0x12fd20bd,
+       0x01e4b604,
+       0xfe051efd,
+       0x097e0018,
+       0x0ef40005,
+/* 0x0465: main_not_ctx_xfer */
+       0x10ef94d4,
+       0x7e01f5f0,
+       0xf40002f8,
+/* 0x0472: ih */
+       0x80f9c70e,
+       0xf90188fe,
+       0xf990f980,
+       0xf9b0f9a0,
+       0xf9e0f9d0,
+       0x4a04bdf0,
+       0xaacf0200,
+       0x04abc400,
+       0x0d1f0bf4,
+       0x1a004e24,
+       0x4f00eecf,
+       0xffcf1900,
+       0x00047e00,
+       0x40010e00,
+       0x0ef61d00,
+/* 0x04af: ih_no_fifo */
+       0x4004bd00,
+       0x0af60100,
+       0xfc04bd00,
+       0xfce0fcf0,
+       0xfcb0fcd0,
+       0xfc90fca0,
+       0x0088fe80,
+       0x32f480fc,
+/* 0x04cf: hub_barrier_done */
+       0x0f01f800,
+       0x040e9801,
+       0xb204febb,
+       0x94188eff,
+       0x008f7e40,
+/* 0x04e3: ctx_redswitch */
+       0x0f00f800,
+       0x85008020,
+       0x000ff601,
+       0x080e04bd,
+/* 0x04f0: ctx_redswitch_delay */
+       0xf401e2b6,
+       0xf5f1fd1b,
+       0xf5f10800,
+       0x00800200,
+       0x0ff60185,
+       0xf804bd00,
+/* 0x0509: ctx_xfer */
+       0x81008000,
+       0x000ff602,
+       0x11f404bd,
+       0x04e37e07,
+/* 0x0519: ctx_xfer_not_load */
+       0x02167e00,
+       0x8024bd00,
+       0xf60247fc,
+       0x04bd0002,
+       0xb6012cf0,
+       0xfc800320,
+       0x02f6024a,
+       0xf004bd00,
+       0xa5f001ac,
+       0x00008b02,
+       0x040c9850,
+       0xbb0fc4b6,
+       0x0c9800bc,
+       0x010d9800,
+       0x3d7e000e,
+       0xacf00001,
+       0x40008b01,
+       0x040c9850,
+       0xbb0fc4b6,
+       0x0c9800bc,
+       0x020d9801,
+       0x4e060f98,
+       0x3d7e0800,
+       0xacf00001,
+       0x04a5f001,
+       0x5030008b,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x020c9800,
+       0x98030d98,
+       0x004e080f,
+       0x013d7e02,
+       0x020a7e00,
+       0x0601f400,
+/* 0x05a3: ctx_xfer_post */
+       0x7e0712f4,
+/* 0x05a7: ctx_xfer_done */
+       0x7e000227,
+       0xf80004cf,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index 27dc1280dc10136fd3bcaed8ee4834b825112742..31922707794f79069ea775d53d294d9f02540fe4 100644 (file)
@@ -177,7 +177,7 @@ uint32_t nv108_grgpc_code[] = {
        0xb4f000bb,
        0x10b4b01f,
        0x0af31bf4,
-       0x00b87e02,
+       0x00b87e05,
        0x250ef400,
 /* 0x01d8: mmctx_stop */
        0xb600abc8,
@@ -269,186 +269,186 @@ uint32_t nv108_grgpc_code[] = {
        0x00008f7e,
        0x00f8e0fc,
 /* 0x0314: init */
-       0x04fe04bd,
-       0x40020200,
-       0x02f61200,
-       0x4104bd00,
-       0x10fe0465,
-       0x07004000,
-       0xbd0000f6,
-       0x40040204,
-       0x02f60400,
-       0xf404bd00,
-       0x00821031,
-       0x22cf0182,
-       0xf0010300,
-       0x32bb1f24,
-       0x0132b604,
-       0xb50502b5,
-       0x00820603,
-       0x22cf0186,
-       0x0402b500,
-       0x500c308e,
-       0x34bd24bd,
-/* 0x036a: init_unk_loop */
-       0x657e44bd,
-       0xf6b00000,
-       0x0e0bf400,
-       0xf2bb010f,
-       0x054ffd04,
-/* 0x037f: init_unk_next */
-       0xb60130b6,
-       0xe0b60120,
-       0x0126b004,
-/* 0x038b: init_unk_done */
-       0xb5e21bf4,
-       0x04b50703,
-       0x01008208,
-       0x0022cf02,
-       0x259534bd,
-       0xc0008008,
-       0x0005f601,
-       0x008004bd,
-       0x05f601c1,
-       0x9804bd00,
-       0x0f98000e,
-       0x01207e01,
-       0x002fbb00,
-       0x98003fbb,
-       0x0f98010e,
-       0x01207e02,
-       0x050e9800,
-       0xbb00effd,
-       0x3ebb002e,
-       0x020e9800,
-       0x7e030f98,
-       0x98000120,
-       0xeffd070e,
-       0x002ebb00,
-       0xb6003ebb,
-       0x00800235,
-       0x03f601d3,
-       0xb604bd00,
-       0x35b60825,
-       0x0120b606,
-       0xb60130b6,
-       0x34b60824,
-       0x7e2fb208,
-       0xbb000268,
-       0x0080003f,
-       0x03f60201,
-       0xbd04bd00,
-       0x1f29f024,
-       0x02300080,
-       0xbd0002f6,
-/* 0x0429: main */
-       0x0031f404,
-       0x0d0028f4,
-       0x00377e24,
-       0xf401f400,
-       0xf404e4b0,
-       0x81fe1d18,
-       0xbd060201,
-       0x0412fd20,
-       0xfd01e4b6,
-       0x18fe051e,
-       0x04fc7e00,
-       0xd40ef400,
-/* 0x0458: main_not_ctx_xfer */
-       0xf010ef94,
-       0xf87e01f5,
-       0x0ef40002,
-/* 0x0465: ih */
-       0xfe80f9c7,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x004a04bd,
-       0x00aacf02,
-       0xf404abc4,
-       0x240d1f0b,
-       0xcf1a004e,
-       0x004f00ee,
-       0x00ffcf19,
-       0x0000047e,
-       0x0040010e,
-       0x000ef61d,
-/* 0x04a2: ih_no_fifo */
-       0x004004bd,
-       0x000af601,
-       0xf0fc04bd,
-       0xd0fce0fc,
-       0xa0fcb0fc,
-       0x80fc90fc,
-       0xfc0088fe,
-       0x0032f480,
-/* 0x04c2: hub_barrier_done */
-       0x010f01f8,
-       0xbb040e98,
-       0xffb204fe,
-       0x4094188e,
-       0x00008f7e,
-/* 0x04d6: ctx_redswitch */
-       0x200f00f8,
-       0x01850080,
-       0xbd000ff6,
-/* 0x04e3: ctx_redswitch_delay */
-       0xb6080e04,
-       0x1bf401e2,
-       0x00f5f1fd,
-       0x00f5f108,
-       0x85008002,
+       0x004104bd,
+       0x0011cf42,
+       0x010911e7,
+       0xfe0814b6,
+       0x02020014,
+       0xf6120040,
+       0x04bd0002,
+       0xfe047241,
+       0x00400010,
+       0x0000f607,
+       0x040204bd,
+       0xf6040040,
+       0x04bd0002,
+       0x821031f4,
+       0xcf018200,
+       0x01030022,
+       0xbb1f24f0,
+       0x32b60432,
+       0x0502b501,
+       0x820603b5,
+       0xcf018600,
+       0x02b50022,
+       0x0c308e04,
+       0xbd24bd50,
+/* 0x0377: init_unk_loop */
+       0x7e44bd34,
+       0xb0000065,
+       0x0bf400f6,
+       0xbb010f0e,
+       0x4ffd04f2,
+       0x0130b605,
+/* 0x038c: init_unk_next */
+       0xb60120b6,
+       0x26b004e0,
+       0xe21bf401,
+/* 0x0398: init_unk_done */
+       0xb50703b5,
+       0x00820804,
+       0x22cf0201,
+       0x9534bd00,
+       0x00800825,
+       0x05f601c0,
+       0x8004bd00,
+       0xf601c100,
+       0x04bd0005,
+       0x98000e98,
+       0x207e010f,
+       0x2fbb0001,
+       0x003fbb00,
+       0x98010e98,
+       0x207e020f,
+       0x0e980001,
+       0x00effd05,
+       0xbb002ebb,
+       0x0e98003e,
+       0x030f9802,
+       0x0001207e,
+       0xfd070e98,
+       0x2ebb00ef,
+       0x003ebb00,
+       0x800235b6,
+       0xf601d300,
+       0x04bd0003,
+       0xb60825b6,
+       0x20b60635,
+       0x0130b601,
+       0xb60824b6,
+       0x2fb20834,
+       0x0002687e,
+       0x80003fbb,
+       0xf6020100,
+       0x04bd0003,
+       0x29f024bd,
+       0x3000801f,
+       0x0002f602,
+/* 0x0436: main */
+       0x31f404bd,
+       0x0028f400,
+       0x377e240d,
+       0x01f40000,
+       0x04e4b0f4,
+       0xfe1d18f4,
+       0x06020181,
+       0x12fd20bd,
+       0x01e4b604,
+       0xfe051efd,
+       0x097e0018,
+       0x0ef40005,
+/* 0x0465: main_not_ctx_xfer */
+       0x10ef94d4,
+       0x7e01f5f0,
+       0xf40002f8,
+/* 0x0472: ih */
+       0x80f9c70e,
+       0xf90188fe,
+       0xf990f980,
+       0xf9b0f9a0,
+       0xf9e0f9d0,
+       0x4a04bdf0,
+       0xaacf0200,
+       0x04abc400,
+       0x0d1f0bf4,
+       0x1a004e24,
+       0x4f00eecf,
+       0xffcf1900,
+       0x00047e00,
+       0x40010e00,
+       0x0ef61d00,
+/* 0x04af: ih_no_fifo */
+       0x4004bd00,
+       0x0af60100,
+       0xfc04bd00,
+       0xfce0fcf0,
+       0xfcb0fcd0,
+       0xfc90fca0,
+       0x0088fe80,
+       0x32f480fc,
+/* 0x04cf: hub_barrier_done */
+       0x0f01f800,
+       0x040e9801,
+       0xb204febb,
+       0x94188eff,
+       0x008f7e40,
+/* 0x04e3: ctx_redswitch */
+       0x0f00f800,
+       0x85008020,
        0x000ff601,
-       0x00f804bd,
-/* 0x04fc: ctx_xfer */
-       0x02810080,
-       0xbd000ff6,
-       0x0711f404,
-       0x0004d67e,
-/* 0x050c: ctx_xfer_not_load */
-       0x0002167e,
-       0xfc8024bd,
-       0x02f60247,
+       0x080e04bd,
+/* 0x04f0: ctx_redswitch_delay */
+       0xf401e2b6,
+       0xf5f1fd1b,
+       0xf5f10800,
+       0x00800200,
+       0x0ff60185,
+       0xf804bd00,
+/* 0x0509: ctx_xfer */
+       0x81008000,
+       0x000ff602,
+       0x11f404bd,
+       0x04e37e07,
+/* 0x0519: ctx_xfer_not_load */
+       0x02167e00,
+       0x8024bd00,
+       0xf60247fc,
+       0x04bd0002,
+       0xb6012cf0,
+       0xfc800320,
+       0x02f6024a,
        0xf004bd00,
-       0x20b6012c,
-       0x4afc8003,
-       0x0002f602,
-       0xacf004bd,
-       0x02a5f001,
-       0x5000008b,
+       0xa5f001ac,
+       0x00008b02,
+       0x040c9850,
+       0xbb0fc4b6,
+       0x0c9800bc,
+       0x010d9800,
+       0x3d7e000e,
+       0xacf00001,
+       0x40008b01,
+       0x040c9850,
+       0xbb0fc4b6,
+       0x0c9800bc,
+       0x020d9801,
+       0x4e060f98,
+       0x3d7e0800,
+       0xacf00001,
+       0x04a5f001,
+       0x5030008b,
        0xb6040c98,
        0xbcbb0fc4,
-       0x000c9800,
-       0x0e010d98,
-       0x013d7e00,
-       0x01acf000,
-       0x5040008b,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0x004e060f,
-       0x013d7e08,
-       0x01acf000,
-       0x8b04a5f0,
-       0x98503000,
-       0xc4b6040c,
-       0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x02004e08,
-       0x00013d7e,
-       0x00020a7e,
-       0xf40601f4,
-/* 0x0596: ctx_xfer_post */
-       0x277e0712,
-/* 0x059a: ctx_xfer_done */
-       0xc27e0002,
-       0x00f80004,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x020c9800,
+       0x98030d98,
+       0x004e080f,
+       0x013d7e02,
+       0x020a7e00,
+       0x0601f400,
+/* 0x05a3: ctx_xfer_post */
+       0x7e0712f4,
+/* 0x05a7: ctx_xfer_done */
+       0x7e000227,
+       0xf80004cf,
        0x00000000,
        0x00000000,
        0x00000000,
index 0e7b01efae8d2979cdffac5bbf4e4a4030580d2d..325cc7b7b2fbeb21445f1e9160a47d16d5d87044 100644 (file)
@@ -192,7 +192,7 @@ uint32_t nvc0_grgpc_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
@@ -300,182 +300,182 @@ uint32_t nvc0_grgpc_code[] = {
        0x21f440e3,
        0xf8e0fc9d,
 /* 0x03a1: init */
-       0xfe04bd00,
-       0x27f00004,
-       0x0007f102,
-       0x0003f012,
-       0xbd0002d0,
-       0xd517f104,
-       0x0010fe04,
-       0x070007f1,
+       0xf104bd00,
+       0xf0420017,
+       0x11cf0013,
+       0x0911e700,
+       0x0814b601,
+       0xf00014fe,
+       0x07f10227,
+       0x03f01200,
+       0x0002d000,
+       0x17f104bd,
+       0x10fe04e6,
+       0x0007f100,
+       0x0003f007,
+       0xbd0000d0,
+       0x0427f004,
+       0x040007f1,
        0xd00003f0,
-       0x04bd0000,
-       0xf10427f0,
-       0xf0040007,
-       0x02d00003,
-       0xf404bd00,
-       0x27f11031,
-       0x23f08200,
-       0x0022cf01,
-       0xf00137f0,
-       0x32bb1f24,
-       0x0132b604,
-       0x80050280,
-       0x27f10603,
-       0x23f08600,
-       0x0022cf01,
-       0xf1040280,
-       0xf0010027,
-       0x22cf0223,
-       0x9534bd00,
-       0x07f10825,
-       0x03f0c000,
-       0x0005d001,
-       0x07f104bd,
-       0x03f0c100,
-       0x0005d001,
-       0x0e9804bd,
-       0x010f9800,
-       0x015021f5,
-       0xbb002fbb,
-       0x0e98003f,
-       0x020f9801,
-       0x015021f5,
-       0xfd050e98,
-       0x2ebb00ef,
-       0x003ebb00,
-       0xf10235b6,
-       0xf0d30007,
-       0x03d00103,
-       0xb604bd00,
-       0x35b60825,
-       0x0120b606,
-       0xb60130b6,
-       0x34b60824,
-       0x022fb908,
-       0x02d321f5,
-       0xf1003fbb,
-       0xf0010007,
-       0x03d00203,
-       0xbd04bd00,
-       0x1f29f024,
-       0x080007f1,
-       0xd00203f0,
        0x04bd0002,
-/* 0x0498: main */
-       0xf40031f4,
-       0xd7f00028,
-       0x3921f41c,
-       0xb0f401f4,
-       0x18f404e4,
-       0x0181fe1e,
-       0xbd0627f0,
-       0x0412fd20,
-       0xfd01e4b6,
-       0x18fe051e,
-       0x8d21f500,
-       0xd30ef405,
-/* 0x04c8: main_not_ctx_xfer */
-       0xf010ef94,
-       0x21f501f5,
-       0x0ef4037e,
-/* 0x04d5: ih */
-       0xfe80f9c6,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0xa7f104bd,
-       0xa3f00200,
-       0x00aacf00,
-       0xf404abc4,
-       0xd7f02c0b,
-       0x00e7f11c,
-       0x00e3f01a,
-       0xf100eecf,
-       0xf01900f7,
-       0xffcf00f3,
-       0x0421f400,
-       0xf101e7f0,
-       0xf01d0007,
-       0x0ed00003,
-/* 0x0523: ih_no_fifo */
+       0xf11031f4,
+       0xf0820027,
+       0x22cf0123,
+       0x0137f000,
+       0xbb1f24f0,
+       0x32b60432,
+       0x05028001,
+       0xf1060380,
+       0xf0860027,
+       0x22cf0123,
+       0x04028000,
+       0x010027f1,
+       0xcf0223f0,
+       0x34bd0022,
+       0xf1082595,
+       0xf0c00007,
+       0x05d00103,
        0xf104bd00,
-       0xf0010007,
-       0x0ad00003,
-       0xfc04bd00,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x0547: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0xf102ffb9,
-       0xf09418e7,
-       0x21f440e3,
-/* 0x055f: ctx_redswitch */
-       0xf000f89d,
-       0x07f120f7,
-       0x03f08500,
-       0x000fd001,
-       0xe7f004bd,
-/* 0x0571: ctx_redswitch_delay */
-       0x01e2b608,
-       0xf1fd1bf4,
-       0xf10800f5,
-       0xf10200f5,
+       0xf0c10007,
+       0x05d00103,
+       0x9804bd00,
+       0x0f98000e,
+       0x5021f501,
+       0x002fbb01,
+       0x98003fbb,
+       0x0f98010e,
+       0x5021f502,
+       0x050e9801,
+       0xbb00effd,
+       0x3ebb002e,
+       0x0235b600,
+       0xd30007f1,
+       0xd00103f0,
+       0x04bd0003,
+       0xb60825b6,
+       0x20b60635,
+       0x0130b601,
+       0xb60824b6,
+       0x2fb90834,
+       0xd321f502,
+       0x003fbb02,
+       0x010007f1,
+       0xd00203f0,
+       0x04bd0003,
+       0x29f024bd,
+       0x0007f11f,
+       0x0203f008,
+       0xbd0002d0,
+/* 0x04a9: main */
+       0x0031f404,
+       0xf00028f4,
+       0x21f41cd7,
+       0xf401f439,
+       0xf404e4b0,
+       0x81fe1e18,
+       0x0627f001,
+       0x12fd20bd,
+       0x01e4b604,
+       0xfe051efd,
+       0x21f50018,
+       0x0ef4059e,
+/* 0x04d9: main_not_ctx_xfer */
+       0x10ef94d3,
+       0xf501f5f0,
+       0xf4037e21,
+/* 0x04e6: ih */
+       0x80f9c60e,
+       0xf90188fe,
+       0xf990f980,
+       0xf9b0f9a0,
+       0xf9e0f9d0,
+       0xf104bdf0,
+       0xf00200a7,
+       0xaacf00a3,
+       0x04abc400,
+       0xf02c0bf4,
+       0xe7f11cd7,
+       0xe3f01a00,
+       0x00eecf00,
+       0x1900f7f1,
+       0xcf00f3f0,
+       0x21f400ff,
+       0x01e7f004,
+       0x1d0007f1,
+       0xd00003f0,
+       0x04bd000e,
+/* 0x0534: ih_no_fifo */
+       0x010007f1,
+       0xd00003f0,
+       0x04bd000a,
+       0xe0fcf0fc,
+       0xb0fcd0fc,
+       0x90fca0fc,
+       0x88fe80fc,
+       0xf480fc00,
+       0x01f80032,
+/* 0x0558: hub_barrier_done */
+       0x9801f7f0,
+       0xfebb040e,
+       0x02ffb904,
+       0x9418e7f1,
+       0xf440e3f0,
+       0x00f89d21,
+/* 0x0570: ctx_redswitch */
+       0xf120f7f0,
        0xf0850007,
        0x0fd00103,
-       0xf804bd00,
-/* 0x058d: ctx_xfer */
-       0x0007f100,
-       0x0203f081,
-       0xbd000fd0,
-       0x0711f404,
-       0x055f21f5,
-/* 0x05a0: ctx_xfer_not_load */
-       0x026a21f5,
-       0x07f124bd,
-       0x03f047fc,
-       0x0002d002,
-       0x2cf004bd,
-       0x0320b601,
-       0x4afc07f1,
-       0xd00203f0,
-       0x04bd0002,
+       0xf004bd00,
+/* 0x0582: ctx_redswitch_delay */
+       0xe2b608e7,
+       0xfd1bf401,
+       0x0800f5f1,
+       0x0200f5f1,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x059e: ctx_xfer */
+       0x07f100f8,
+       0x03f08100,
+       0x000fd002,
+       0x11f404bd,
+       0x7021f507,
+/* 0x05b1: ctx_xfer_not_load */
+       0x6a21f505,
+       0xf124bd02,
+       0xf047fc07,
+       0x02d00203,
+       0xf004bd00,
+       0x20b6012c,
+       0xfc07f103,
+       0x0203f04a,
+       0xbd0002d0,
+       0x01acf004,
+       0xf102a5f0,
+       0xf00000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98000c,
+       0x00e7f001,
+       0x016f21f5,
        0xf001acf0,
-       0xb7f102a5,
-       0xb3f00000,
+       0xb7f104a5,
+       0xb3f04000,
        0x040c9850,
        0xbb0fc4b6,
        0x0c9800bc,
-       0x010d9800,
-       0xf500e7f0,
-       0xf0016f21,
-       0xa5f001ac,
-       0x00b7f104,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0x21f5016f,
-       0x01f4025e,
-       0x0712f406,
-/* 0x0618: ctx_xfer_post */
-       0x027f21f5,
-/* 0x061c: ctx_xfer_done */
-       0x054721f5,
-       0x000000f8,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x020d9801,
+       0xf1060f98,
+       0xf50800e7,
+       0xf5016f21,
+       0xf4025e21,
+       0x12f40601,
+/* 0x0629: ctx_xfer_post */
+       0x7f21f507,
+/* 0x062d: ctx_xfer_done */
+       0x5821f502,
+       0x0000f805,
        0x00000000,
        0x00000000,
        0x00000000,
index 84dd32db28a02cff0118eec2bae837ddf56dcc90..d1504a4059c618e38f7f7215ff28e9de9e2180b7 100644 (file)
@@ -196,7 +196,7 @@ uint32_t nvd7_grgpc_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nvd7_grgpc_code[] = {
        0x21f440e3,
        0xf8e0fc9d,
 /* 0x03a1: init */
-       0xfe04bd00,
-       0x27f00004,
-       0x0007f102,
-       0x0003f012,
-       0xbd0002d0,
-       0x1f17f104,
-       0x0010fe05,
-       0x070007f1,
+       0xf104bd00,
+       0xf0420017,
+       0x11cf0013,
+       0x0911e700,
+       0x0814b601,
+       0xf00014fe,
+       0x07f10227,
+       0x03f01200,
+       0x0002d000,
+       0x17f104bd,
+       0x10fe0530,
+       0x0007f100,
+       0x0003f007,
+       0xbd0000d0,
+       0x0427f004,
+       0x040007f1,
        0xd00003f0,
-       0x04bd0000,
-       0xf10427f0,
-       0xf0040007,
-       0x02d00003,
+       0x04bd0002,
+       0xf11031f4,
+       0xf0820027,
+       0x22cf0123,
+       0x0137f000,
+       0xbb1f24f0,
+       0x32b60432,
+       0x05028001,
+       0xf1060380,
+       0xf0860027,
+       0x22cf0123,
+       0x04028000,
+       0x0c30e7f1,
+       0xbd50e3f0,
+       0xbd34bd24,
+/* 0x0421: init_unk_loop */
+       0x6821f444,
+       0xf400f6b0,
+       0xf7f00f0b,
+       0x04f2bb01,
+       0xb6054ffd,
+/* 0x0436: init_unk_next */
+       0x20b60130,
+       0x04e0b601,
+       0xf40126b0,
+/* 0x0442: init_unk_done */
+       0x0380e21b,
+       0x08048007,
+       0x010027f1,
+       0xcf0223f0,
+       0x34bd0022,
+       0xf1082595,
+       0xf0c00007,
+       0x05d00103,
+       0xf104bd00,
+       0xf0c10007,
+       0x05d00103,
+       0x9804bd00,
+       0x0f98000e,
+       0x5021f501,
+       0x002fbb01,
+       0x98003fbb,
+       0x0f98010e,
+       0x5021f502,
+       0x050e9801,
+       0xbb00effd,
+       0x3ebb002e,
+       0x020e9800,
+       0xf5030f98,
+       0x98015021,
+       0xeffd070e,
+       0x002ebb00,
+       0xb6003ebb,
+       0x07f10235,
+       0x03f0d300,
+       0x0003d001,
+       0x25b604bd,
+       0x0635b608,
+       0xb60120b6,
+       0x24b60130,
+       0x0834b608,
+       0xf5022fb9,
+       0xbb02d321,
+       0x07f1003f,
+       0x03f00100,
+       0x0003d002,
+       0x24bd04bd,
+       0xf11f29f0,
+       0xf0080007,
+       0x02d00203,
+/* 0x04f3: main */
        0xf404bd00,
-       0x27f11031,
-       0x23f08200,
-       0x0022cf01,
-       0xf00137f0,
-       0x32bb1f24,
-       0x0132b604,
-       0x80050280,
-       0x27f10603,
-       0x23f08600,
-       0x0022cf01,
-       0xf1040280,
-       0xf00c30e7,
-       0x24bd50e3,
-       0x44bd34bd,
-/* 0x0410: init_unk_loop */
-       0xb06821f4,
-       0x0bf400f6,
-       0x01f7f00f,
-       0xfd04f2bb,
-       0x30b6054f,
-/* 0x0425: init_unk_next */
-       0x0120b601,
-       0xb004e0b6,
-       0x1bf40126,
-/* 0x0431: init_unk_done */
-       0x070380e2,
-       0xf1080480,
-       0xf0010027,
-       0x22cf0223,
-       0x9534bd00,
-       0x07f10825,
-       0x03f0c000,
-       0x0005d001,
+       0x28f40031,
+       0x24d7f000,
+       0xf43921f4,
+       0xe4b0f401,
+       0x1e18f404,
+       0xf00181fe,
+       0x20bd0627,
+       0xb60412fd,
+       0x1efd01e4,
+       0x0018fe05,
+       0x05e821f5,
+/* 0x0523: main_not_ctx_xfer */
+       0x94d30ef4,
+       0xf5f010ef,
+       0x7e21f501,
+       0xc60ef403,
+/* 0x0530: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x24d7f02c,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
+       0xf00421f4,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x057e: ih_no_fifo */
        0x07f104bd,
-       0x03f0c100,
-       0x0005d001,
-       0x0e9804bd,
-       0x010f9800,
-       0x015021f5,
-       0xbb002fbb,
-       0x0e98003f,
-       0x020f9801,
-       0x015021f5,
-       0xfd050e98,
-       0x2ebb00ef,
-       0x003ebb00,
-       0x98020e98,
-       0x21f5030f,
-       0x0e980150,
-       0x00effd07,
-       0xbb002ebb,
-       0x35b6003e,
-       0x0007f102,
-       0x0103f0d3,
-       0xbd0003d0,
-       0x0825b604,
-       0xb60635b6,
-       0x30b60120,
-       0x0824b601,
-       0xb90834b6,
-       0x21f5022f,
-       0x3fbb02d3,
-       0x0007f100,
-       0x0203f001,
-       0xbd0003d0,
-       0xf024bd04,
-       0x07f11f29,
-       0x03f00800,
-       0x0002d002,
-/* 0x04e2: main */
-       0x31f404bd,
-       0x0028f400,
-       0xf424d7f0,
-       0x01f43921,
-       0x04e4b0f4,
-       0xfe1e18f4,
-       0x27f00181,
-       0xfd20bd06,
-       0xe4b60412,
-       0x051efd01,
-       0xf50018fe,
-       0xf405d721,
-/* 0x0512: main_not_ctx_xfer */
-       0xef94d30e,
-       0x01f5f010,
-       0x037e21f5,
-/* 0x051f: ih */
-       0xf9c60ef4,
-       0x0188fe80,
-       0x90f980f9,
-       0xb0f9a0f9,
-       0xe0f9d0f9,
-       0x04bdf0f9,
-       0x0200a7f1,
-       0xcf00a3f0,
-       0xabc400aa,
-       0x2c0bf404,
-       0xf124d7f0,
-       0xf01a00e7,
-       0xeecf00e3,
-       0x00f7f100,
-       0x00f3f019,
-       0xf400ffcf,
-       0xe7f00421,
-       0x0007f101,
-       0x0003f01d,
-       0xbd000ed0,
-/* 0x056d: ih_no_fifo */
-       0x0007f104,
-       0x0003f001,
-       0xbd000ad0,
-       0xfcf0fc04,
-       0xfcd0fce0,
-       0xfca0fcb0,
-       0xfe80fc90,
-       0x80fc0088,
-       0xf80032f4,
-/* 0x0591: hub_barrier_done */
-       0x01f7f001,
-       0xbb040e98,
-       0xffb904fe,
-       0x18e7f102,
-       0x40e3f094,
-       0xf89d21f4,
-/* 0x05a9: ctx_redswitch */
-       0x20f7f000,
-       0x850007f1,
-       0xd00103f0,
-       0x04bd000f,
-/* 0x05bb: ctx_redswitch_delay */
-       0xb608e7f0,
-       0x1bf401e2,
-       0x00f5f1fd,
-       0x00f5f108,
-       0x0007f102,
+       0x03f00100,
+       0x000ad000,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x05a2: hub_barrier_done */
+       0xf7f001f8,
+       0x040e9801,
+       0xb904febb,
+       0xe7f102ff,
+       0xe3f09418,
+       0x9d21f440,
+/* 0x05ba: ctx_redswitch */
+       0xf7f000f8,
+       0x0007f120,
        0x0103f085,
        0xbd000fd0,
-/* 0x05d7: ctx_xfer */
-       0xf100f804,
-       0xf0810007,
-       0x0fd00203,
-       0xf404bd00,
-       0x21f50711,
-/* 0x05ea: ctx_xfer_not_load */
-       0x21f505a9,
-       0x24bd026a,
-       0x47fc07f1,
+       0x08e7f004,
+/* 0x05cc: ctx_redswitch_delay */
+       0xf401e2b6,
+       0xf5f1fd1b,
+       0xf5f10800,
+       0x07f10200,
+       0x03f08500,
+       0x000fd001,
+       0x00f804bd,
+/* 0x05e8: ctx_xfer */
+       0x810007f1,
        0xd00203f0,
-       0x04bd0002,
-       0xb6012cf0,
-       0x07f10320,
-       0x03f04afc,
-       0x0002d002,
-       0xacf004bd,
-       0x02a5f001,
-       0x0000b7f1,
-       0x9850b3f0,
-       0xc4b6040c,
-       0x00bcbb0f,
-       0x98000c98,
-       0xe7f0010d,
-       0x6f21f500,
-       0x01acf001,
-       0x4000b7f1,
+       0x04bd000f,
+       0xf50711f4,
+/* 0x05fb: ctx_xfer_not_load */
+       0xf505ba21,
+       0xbd026a21,
+       0xfc07f124,
+       0x0203f047,
+       0xbd0002d0,
+       0x012cf004,
+       0xf10320b6,
+       0xf04afc07,
+       0x02d00203,
+       0xf004bd00,
+       0xa5f001ac,
+       0x00b7f102,
+       0x50b3f000,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xacf0016f,
+       0x00b7f101,
+       0x50b3f040,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0xe7f1060f,
+       0x21f50800,
+       0xacf0016f,
+       0x04a5f001,
+       0x3000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98010c98,
-       0x0f98020d,
-       0x00e7f106,
-       0x6f21f508,
-       0x01acf001,
-       0xf104a5f0,
-       0xf03000b7,
-       0x0c9850b3,
-       0x0fc4b604,
-       0x9800bcbb,
-       0x0d98020c,
-       0x080f9803,
-       0x0200e7f1,
-       0x016f21f5,
-       0x025e21f5,
-       0xf40601f4,
-/* 0x0686: ctx_xfer_post */
-       0x21f50712,
-/* 0x068a: ctx_xfer_done */
-       0x21f5027f,
-       0x00f80591,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x98020c98,
+       0x0f98030d,
+       0x00e7f108,
+       0x6f21f502,
+       0x5e21f501,
+       0x0601f402,
+/* 0x0697: ctx_xfer_post */
+       0xf50712f4,
+/* 0x069b: ctx_xfer_done */
+       0xf5027f21,
+       0xf805a221,
        0x00000000,
        0x00000000,
        0x00000000,
index b6da800ee9c2ddbd2baae4cf5812c681c09fccc6..855b220378f9f002730cc0874bc8d01edc112c82 100644 (file)
@@ -196,7 +196,7 @@ uint32_t nve0_grgpc_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nve0_grgpc_code[] = {
        0x21f440e3,
        0xf8e0fc9d,
 /* 0x03a1: init */
-       0xfe04bd00,
-       0x27f00004,
-       0x0007f102,
-       0x0003f012,
-       0xbd0002d0,
-       0x1f17f104,
-       0x0010fe05,
-       0x070007f1,
+       0xf104bd00,
+       0xf0420017,
+       0x11cf0013,
+       0x0911e700,
+       0x0814b601,
+       0xf00014fe,
+       0x07f10227,
+       0x03f01200,
+       0x0002d000,
+       0x17f104bd,
+       0x10fe0530,
+       0x0007f100,
+       0x0003f007,
+       0xbd0000d0,
+       0x0427f004,
+       0x040007f1,
        0xd00003f0,
-       0x04bd0000,
-       0xf10427f0,
-       0xf0040007,
-       0x02d00003,
+       0x04bd0002,
+       0xf11031f4,
+       0xf0820027,
+       0x22cf0123,
+       0x0137f000,
+       0xbb1f24f0,
+       0x32b60432,
+       0x05028001,
+       0xf1060380,
+       0xf0860027,
+       0x22cf0123,
+       0x04028000,
+       0x0c30e7f1,
+       0xbd50e3f0,
+       0xbd34bd24,
+/* 0x0421: init_unk_loop */
+       0x6821f444,
+       0xf400f6b0,
+       0xf7f00f0b,
+       0x04f2bb01,
+       0xb6054ffd,
+/* 0x0436: init_unk_next */
+       0x20b60130,
+       0x04e0b601,
+       0xf40126b0,
+/* 0x0442: init_unk_done */
+       0x0380e21b,
+       0x08048007,
+       0x010027f1,
+       0xcf0223f0,
+       0x34bd0022,
+       0xf1082595,
+       0xf0c00007,
+       0x05d00103,
+       0xf104bd00,
+       0xf0c10007,
+       0x05d00103,
+       0x9804bd00,
+       0x0f98000e,
+       0x5021f501,
+       0x002fbb01,
+       0x98003fbb,
+       0x0f98010e,
+       0x5021f502,
+       0x050e9801,
+       0xbb00effd,
+       0x3ebb002e,
+       0x020e9800,
+       0xf5030f98,
+       0x98015021,
+       0xeffd070e,
+       0x002ebb00,
+       0xb6003ebb,
+       0x07f10235,
+       0x03f0d300,
+       0x0003d001,
+       0x25b604bd,
+       0x0635b608,
+       0xb60120b6,
+       0x24b60130,
+       0x0834b608,
+       0xf5022fb9,
+       0xbb02d321,
+       0x07f1003f,
+       0x03f00100,
+       0x0003d002,
+       0x24bd04bd,
+       0xf11f29f0,
+       0xf0080007,
+       0x02d00203,
+/* 0x04f3: main */
        0xf404bd00,
-       0x27f11031,
-       0x23f08200,
-       0x0022cf01,
-       0xf00137f0,
-       0x32bb1f24,
-       0x0132b604,
-       0x80050280,
-       0x27f10603,
-       0x23f08600,
-       0x0022cf01,
-       0xf1040280,
-       0xf00c30e7,
-       0x24bd50e3,
-       0x44bd34bd,
-/* 0x0410: init_unk_loop */
-       0xb06821f4,
-       0x0bf400f6,
-       0x01f7f00f,
-       0xfd04f2bb,
-       0x30b6054f,
-/* 0x0425: init_unk_next */
-       0x0120b601,
-       0xb004e0b6,
-       0x1bf40126,
-/* 0x0431: init_unk_done */
-       0x070380e2,
-       0xf1080480,
-       0xf0010027,
-       0x22cf0223,
-       0x9534bd00,
-       0x07f10825,
-       0x03f0c000,
-       0x0005d001,
+       0x28f40031,
+       0x24d7f000,
+       0xf43921f4,
+       0xe4b0f401,
+       0x1e18f404,
+       0xf00181fe,
+       0x20bd0627,
+       0xb60412fd,
+       0x1efd01e4,
+       0x0018fe05,
+       0x05e821f5,
+/* 0x0523: main_not_ctx_xfer */
+       0x94d30ef4,
+       0xf5f010ef,
+       0x7e21f501,
+       0xc60ef403,
+/* 0x0530: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x24d7f02c,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
+       0xf00421f4,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x057e: ih_no_fifo */
        0x07f104bd,
-       0x03f0c100,
-       0x0005d001,
-       0x0e9804bd,
-       0x010f9800,
-       0x015021f5,
-       0xbb002fbb,
-       0x0e98003f,
-       0x020f9801,
-       0x015021f5,
-       0xfd050e98,
-       0x2ebb00ef,
-       0x003ebb00,
-       0x98020e98,
-       0x21f5030f,
-       0x0e980150,
-       0x00effd07,
-       0xbb002ebb,
-       0x35b6003e,
-       0x0007f102,
-       0x0103f0d3,
-       0xbd0003d0,
-       0x0825b604,
-       0xb60635b6,
-       0x30b60120,
-       0x0824b601,
-       0xb90834b6,
-       0x21f5022f,
-       0x3fbb02d3,
-       0x0007f100,
-       0x0203f001,
-       0xbd0003d0,
-       0xf024bd04,
-       0x07f11f29,
-       0x03f00800,
-       0x0002d002,
-/* 0x04e2: main */
-       0x31f404bd,
-       0x0028f400,
-       0xf424d7f0,
-       0x01f43921,
-       0x04e4b0f4,
-       0xfe1e18f4,
-       0x27f00181,
-       0xfd20bd06,
-       0xe4b60412,
-       0x051efd01,
-       0xf50018fe,
-       0xf405d721,
-/* 0x0512: main_not_ctx_xfer */
-       0xef94d30e,
-       0x01f5f010,
-       0x037e21f5,
-/* 0x051f: ih */
-       0xf9c60ef4,
-       0x0188fe80,
-       0x90f980f9,
-       0xb0f9a0f9,
-       0xe0f9d0f9,
-       0x04bdf0f9,
-       0x0200a7f1,
-       0xcf00a3f0,
-       0xabc400aa,
-       0x2c0bf404,
-       0xf124d7f0,
-       0xf01a00e7,
-       0xeecf00e3,
-       0x00f7f100,
-       0x00f3f019,
-       0xf400ffcf,
-       0xe7f00421,
-       0x0007f101,
-       0x0003f01d,
-       0xbd000ed0,
-/* 0x056d: ih_no_fifo */
-       0x0007f104,
-       0x0003f001,
-       0xbd000ad0,
-       0xfcf0fc04,
-       0xfcd0fce0,
-       0xfca0fcb0,
-       0xfe80fc90,
-       0x80fc0088,
-       0xf80032f4,
-/* 0x0591: hub_barrier_done */
-       0x01f7f001,
-       0xbb040e98,
-       0xffb904fe,
-       0x18e7f102,
-       0x40e3f094,
-       0xf89d21f4,
-/* 0x05a9: ctx_redswitch */
-       0x20f7f000,
-       0x850007f1,
-       0xd00103f0,
-       0x04bd000f,
-/* 0x05bb: ctx_redswitch_delay */
-       0xb608e7f0,
-       0x1bf401e2,
-       0x00f5f1fd,
-       0x00f5f108,
-       0x0007f102,
+       0x03f00100,
+       0x000ad000,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x05a2: hub_barrier_done */
+       0xf7f001f8,
+       0x040e9801,
+       0xb904febb,
+       0xe7f102ff,
+       0xe3f09418,
+       0x9d21f440,
+/* 0x05ba: ctx_redswitch */
+       0xf7f000f8,
+       0x0007f120,
        0x0103f085,
        0xbd000fd0,
-/* 0x05d7: ctx_xfer */
-       0xf100f804,
-       0xf0810007,
-       0x0fd00203,
-       0xf404bd00,
-       0x21f50711,
-/* 0x05ea: ctx_xfer_not_load */
-       0x21f505a9,
-       0x24bd026a,
-       0x47fc07f1,
+       0x08e7f004,
+/* 0x05cc: ctx_redswitch_delay */
+       0xf401e2b6,
+       0xf5f1fd1b,
+       0xf5f10800,
+       0x07f10200,
+       0x03f08500,
+       0x000fd001,
+       0x00f804bd,
+/* 0x05e8: ctx_xfer */
+       0x810007f1,
        0xd00203f0,
-       0x04bd0002,
-       0xb6012cf0,
-       0x07f10320,
-       0x03f04afc,
-       0x0002d002,
-       0xacf004bd,
-       0x02a5f001,
-       0x0000b7f1,
-       0x9850b3f0,
-       0xc4b6040c,
-       0x00bcbb0f,
-       0x98000c98,
-       0xe7f0010d,
-       0x6f21f500,
-       0x01acf001,
-       0x4000b7f1,
+       0x04bd000f,
+       0xf50711f4,
+/* 0x05fb: ctx_xfer_not_load */
+       0xf505ba21,
+       0xbd026a21,
+       0xfc07f124,
+       0x0203f047,
+       0xbd0002d0,
+       0x012cf004,
+       0xf10320b6,
+       0xf04afc07,
+       0x02d00203,
+       0xf004bd00,
+       0xa5f001ac,
+       0x00b7f102,
+       0x50b3f000,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xacf0016f,
+       0x00b7f101,
+       0x50b3f040,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0xe7f1060f,
+       0x21f50800,
+       0xacf0016f,
+       0x04a5f001,
+       0x3000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98010c98,
-       0x0f98020d,
-       0x00e7f106,
-       0x6f21f508,
-       0x01acf001,
-       0xf104a5f0,
-       0xf03000b7,
-       0x0c9850b3,
-       0x0fc4b604,
-       0x9800bcbb,
-       0x0d98020c,
-       0x080f9803,
-       0x0200e7f1,
-       0x016f21f5,
-       0x025e21f5,
-       0xf40601f4,
-/* 0x0686: ctx_xfer_post */
-       0x21f50712,
-/* 0x068a: ctx_xfer_done */
-       0x21f5027f,
-       0x00f80591,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x98020c98,
+       0x0f98030d,
+       0x00e7f108,
+       0x6f21f502,
+       0x5e21f501,
+       0x0601f402,
+/* 0x0697: ctx_xfer_post */
+       0xf50712f4,
+/* 0x069b: ctx_xfer_done */
+       0xf5027f21,
+       0xf805a221,
        0x00000000,
        0x00000000,
        0x00000000,
index 6316ebaf5d9a581dae8ac9e5a6d0464d0f8ec478..1b803197d28be4e6bd71a34b5cc15c569bec16c4 100644 (file)
@@ -196,7 +196,7 @@ uint32_t nvf0_grgpc_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
@@ -304,212 +304,212 @@ uint32_t nvf0_grgpc_code[] = {
        0x21f440e3,
        0xf8e0fc9d,
 /* 0x03a1: init */
-       0xfe04bd00,
-       0x27f00004,
-       0x0007f102,
-       0x0003f012,
-       0xbd0002d0,
-       0x1f17f104,
-       0x0010fe05,
-       0x070007f1,
+       0xf104bd00,
+       0xf0420017,
+       0x11cf0013,
+       0x0911e700,
+       0x0814b601,
+       0xf00014fe,
+       0x07f10227,
+       0x03f01200,
+       0x0002d000,
+       0x17f104bd,
+       0x10fe0530,
+       0x0007f100,
+       0x0003f007,
+       0xbd0000d0,
+       0x0427f004,
+       0x040007f1,
        0xd00003f0,
-       0x04bd0000,
-       0xf10427f0,
-       0xf0040007,
-       0x02d00003,
+       0x04bd0002,
+       0xf11031f4,
+       0xf0820027,
+       0x22cf0123,
+       0x0137f000,
+       0xbb1f24f0,
+       0x32b60432,
+       0x05028001,
+       0xf1060380,
+       0xf0860027,
+       0x22cf0123,
+       0x04028000,
+       0x0c30e7f1,
+       0xbd50e3f0,
+       0xbd34bd24,
+/* 0x0421: init_unk_loop */
+       0x6821f444,
+       0xf400f6b0,
+       0xf7f00f0b,
+       0x04f2bb01,
+       0xb6054ffd,
+/* 0x0436: init_unk_next */
+       0x20b60130,
+       0x04e0b601,
+       0xf40226b0,
+/* 0x0442: init_unk_done */
+       0x0380e21b,
+       0x08048007,
+       0x010027f1,
+       0xcf0223f0,
+       0x34bd0022,
+       0xf1082595,
+       0xf0c00007,
+       0x05d00103,
+       0xf104bd00,
+       0xf0c10007,
+       0x05d00103,
+       0x9804bd00,
+       0x0f98000e,
+       0x5021f501,
+       0x002fbb01,
+       0x98003fbb,
+       0x0f98010e,
+       0x5021f502,
+       0x050e9801,
+       0xbb00effd,
+       0x3ebb002e,
+       0x020e9800,
+       0xf5030f98,
+       0x98015021,
+       0xeffd070e,
+       0x002ebb00,
+       0xb6003ebb,
+       0x07f10235,
+       0x03f0d300,
+       0x0003d001,
+       0x25b604bd,
+       0x0635b608,
+       0xb60120b6,
+       0x24b60130,
+       0x0834b608,
+       0xf5022fb9,
+       0xbb02d321,
+       0x07f1003f,
+       0x03f00100,
+       0x0003d002,
+       0x24bd04bd,
+       0xf11f29f0,
+       0xf0300007,
+       0x02d00203,
+/* 0x04f3: main */
        0xf404bd00,
-       0x27f11031,
-       0x23f08200,
-       0x0022cf01,
-       0xf00137f0,
-       0x32bb1f24,
-       0x0132b604,
-       0x80050280,
-       0x27f10603,
-       0x23f08600,
-       0x0022cf01,
-       0xf1040280,
-       0xf00c30e7,
-       0x24bd50e3,
-       0x44bd34bd,
-/* 0x0410: init_unk_loop */
-       0xb06821f4,
-       0x0bf400f6,
-       0x01f7f00f,
-       0xfd04f2bb,
-       0x30b6054f,
-/* 0x0425: init_unk_next */
-       0x0120b601,
-       0xb004e0b6,
-       0x1bf40226,
-/* 0x0431: init_unk_done */
-       0x070380e2,
-       0xf1080480,
-       0xf0010027,
-       0x22cf0223,
-       0x9534bd00,
-       0x07f10825,
-       0x03f0c000,
-       0x0005d001,
+       0x28f40031,
+       0x24d7f000,
+       0xf43921f4,
+       0xe4b0f401,
+       0x1e18f404,
+       0xf00181fe,
+       0x20bd0627,
+       0xb60412fd,
+       0x1efd01e4,
+       0x0018fe05,
+       0x05e821f5,
+/* 0x0523: main_not_ctx_xfer */
+       0x94d30ef4,
+       0xf5f010ef,
+       0x7e21f501,
+       0xc60ef403,
+/* 0x0530: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x24d7f02c,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
+       0xf00421f4,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x057e: ih_no_fifo */
        0x07f104bd,
-       0x03f0c100,
-       0x0005d001,
-       0x0e9804bd,
-       0x010f9800,
-       0x015021f5,
-       0xbb002fbb,
-       0x0e98003f,
-       0x020f9801,
-       0x015021f5,
-       0xfd050e98,
-       0x2ebb00ef,
-       0x003ebb00,
-       0x98020e98,
-       0x21f5030f,
-       0x0e980150,
-       0x00effd07,
-       0xbb002ebb,
-       0x35b6003e,
-       0x0007f102,
-       0x0103f0d3,
-       0xbd0003d0,
-       0x0825b604,
-       0xb60635b6,
-       0x30b60120,
-       0x0824b601,
-       0xb90834b6,
-       0x21f5022f,
-       0x3fbb02d3,
-       0x0007f100,
-       0x0203f001,
-       0xbd0003d0,
-       0xf024bd04,
-       0x07f11f29,
-       0x03f03000,
-       0x0002d002,
-/* 0x04e2: main */
-       0x31f404bd,
-       0x0028f400,
-       0xf424d7f0,
-       0x01f43921,
-       0x04e4b0f4,
-       0xfe1e18f4,
-       0x27f00181,
-       0xfd20bd06,
-       0xe4b60412,
-       0x051efd01,
-       0xf50018fe,
-       0xf405d721,
-/* 0x0512: main_not_ctx_xfer */
-       0xef94d30e,
-       0x01f5f010,
-       0x037e21f5,
-/* 0x051f: ih */
-       0xf9c60ef4,
-       0x0188fe80,
-       0x90f980f9,
-       0xb0f9a0f9,
-       0xe0f9d0f9,
-       0x04bdf0f9,
-       0x0200a7f1,
-       0xcf00a3f0,
-       0xabc400aa,
-       0x2c0bf404,
-       0xf124d7f0,
-       0xf01a00e7,
-       0xeecf00e3,
-       0x00f7f100,
-       0x00f3f019,
-       0xf400ffcf,
-       0xe7f00421,
-       0x0007f101,
-       0x0003f01d,
-       0xbd000ed0,
-/* 0x056d: ih_no_fifo */
-       0x0007f104,
-       0x0003f001,
-       0xbd000ad0,
-       0xfcf0fc04,
-       0xfcd0fce0,
-       0xfca0fcb0,
-       0xfe80fc90,
-       0x80fc0088,
-       0xf80032f4,
-/* 0x0591: hub_barrier_done */
-       0x01f7f001,
-       0xbb040e98,
-       0xffb904fe,
-       0x18e7f102,
-       0x40e3f094,
-       0xf89d21f4,
-/* 0x05a9: ctx_redswitch */
-       0x20f7f000,
-       0x850007f1,
-       0xd00103f0,
-       0x04bd000f,
-/* 0x05bb: ctx_redswitch_delay */
-       0xb608e7f0,
-       0x1bf401e2,
-       0x00f5f1fd,
-       0x00f5f108,
-       0x0007f102,
+       0x03f00100,
+       0x000ad000,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x05a2: hub_barrier_done */
+       0xf7f001f8,
+       0x040e9801,
+       0xb904febb,
+       0xe7f102ff,
+       0xe3f09418,
+       0x9d21f440,
+/* 0x05ba: ctx_redswitch */
+       0xf7f000f8,
+       0x0007f120,
        0x0103f085,
        0xbd000fd0,
-/* 0x05d7: ctx_xfer */
-       0xf100f804,
-       0xf0810007,
-       0x0fd00203,
-       0xf404bd00,
-       0x21f50711,
-/* 0x05ea: ctx_xfer_not_load */
-       0x21f505a9,
-       0x24bd026a,
-       0x47fc07f1,
+       0x08e7f004,
+/* 0x05cc: ctx_redswitch_delay */
+       0xf401e2b6,
+       0xf5f1fd1b,
+       0xf5f10800,
+       0x07f10200,
+       0x03f08500,
+       0x000fd001,
+       0x00f804bd,
+/* 0x05e8: ctx_xfer */
+       0x810007f1,
        0xd00203f0,
-       0x04bd0002,
-       0xb6012cf0,
-       0x07f10320,
-       0x03f04afc,
-       0x0002d002,
-       0xacf004bd,
-       0x02a5f001,
-       0x0000b7f1,
-       0x9850b3f0,
-       0xc4b6040c,
-       0x00bcbb0f,
-       0x98000c98,
-       0xe7f0010d,
-       0x6f21f500,
-       0x01acf001,
-       0x4000b7f1,
+       0x04bd000f,
+       0xf50711f4,
+/* 0x05fb: ctx_xfer_not_load */
+       0xf505ba21,
+       0xbd026a21,
+       0xfc07f124,
+       0x0203f047,
+       0xbd0002d0,
+       0x012cf004,
+       0xf10320b6,
+       0xf04afc07,
+       0x02d00203,
+       0xf004bd00,
+       0xa5f001ac,
+       0x00b7f102,
+       0x50b3f000,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xacf0016f,
+       0x00b7f101,
+       0x50b3f040,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0xe7f1060f,
+       0x21f50800,
+       0xacf0016f,
+       0x04a5f001,
+       0x3000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98010c98,
-       0x0f98020d,
-       0x00e7f106,
-       0x6f21f508,
-       0x01acf001,
-       0xf104a5f0,
-       0xf03000b7,
-       0x0c9850b3,
-       0x0fc4b604,
-       0x9800bcbb,
-       0x0d98020c,
-       0x080f9803,
-       0x0200e7f1,
-       0x016f21f5,
-       0x025e21f5,
-       0xf40601f4,
-/* 0x0686: ctx_xfer_post */
-       0x21f50712,
-/* 0x068a: ctx_xfer_done */
-       0x21f5027f,
-       0x00f80591,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x98020c98,
+       0x0f98030d,
+       0x00e7f108,
+       0x6f21f502,
+       0x5e21f501,
+       0x0601f402,
+/* 0x0697: ctx_xfer_post */
+       0xf50712f4,
+/* 0x069b: ctx_xfer_done */
+       0xf5027f21,
+       0xf805a221,
        0x00000000,
        0x00000000,
        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 (file)
index 0000000..27591b3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #gm107_grhub_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "hub.fuc"
+#undef INCLUDE_DATA
+
+.section #gm107_grhub_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "hub.fuc"
+.align 256
+#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 (file)
index 0000000..214dd16
--- /dev/null
@@ -0,0 +1,916 @@
+uint32_t gm107_grhub_data[] = {
+/* 0x0000: hub_mmio_list_head */
+       0x00000300,
+/* 0x0004: hub_mmio_list_tail */
+       0x00000304,
+/* 0x0008: gpc_count */
+       0x00000000,
+/* 0x000c: rop_count */
+       0x00000000,
+/* 0x0010: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0058: ctx_current */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0100: chan_data */
+/* 0x0100: chan_mmio_count */
+       0x00000000,
+/* 0x0104: chan_mmio_address */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0200: xfer_data */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0300: hub_mmio_list_base */
+       0x0417e91c,
+};
+
+uint32_t gm107_grhub_code[] = {
+       0x030e0ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e05,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0x02050080,
+       0xbd000ff6,
+       0x80010f04,
+       0xf6030700,
+       0x04bd000f,
+/* 0x030e: init */
+       0x04bd00f8,
+       0x410007fe,
+       0x11cf4200,
+       0x0911e700,
+       0x0814b601,
+       0x020014fe,
+       0x12004002,
+       0xbd0002f6,
+       0x05c94104,
+       0xbd0010fe,
+       0x07004024,
+       0xbd0002f6,
+       0x20034204,
+       0x01010080,
+       0xbd0002f6,
+       0x20044204,
+       0x01010480,
+       0xbd0002f6,
+       0x200b4204,
+       0x01010880,
+       0xbd0002f6,
+       0x200c4204,
+       0x01011c80,
+       0xbd0002f6,
+       0x01039204,
+       0x03090080,
+       0xbd0003f6,
+       0x87044204,
+       0xf6040040,
+       0x04bd0002,
+       0x00400402,
+       0x0002f603,
+       0x31f404bd,
+       0x96048e10,
+       0x00657e40,
+       0xc7feb200,
+       0x01b590f1,
+       0x1ff4f003,
+       0x01020fb5,
+       0x041fbb01,
+       0x800112b6,
+       0xf6010300,
+       0x04bd0001,
+       0x01040080,
+       0xbd0001f6,
+       0x01004104,
+       0x627e020f,
+       0x717e0006,
+       0x100f0006,
+       0x0006b37e,
+       0x98000e98,
+       0x207e010f,
+       0x14950001,
+       0xc0008008,
+       0x0004f601,
+       0x008004bd,
+       0x04f601c1,
+       0xb704bd00,
+       0xbb130030,
+       0xf5b6001f,
+       0xd3008002,
+       0x000ff601,
+       0x15b604bd,
+       0x0110b608,
+       0xb20814b6,
+       0x02687e1f,
+       0x001fbb00,
+       0x84020398,
+/* 0x041f: init_gpc */
+       0xb8502000,
+       0x0008044e,
+       0x8f7e1fb2,
+       0x4eb80000,
+       0xbd00010c,
+       0x008f7ef4,
+       0x044eb800,
+       0x8f7e0001,
+       0x4eb80000,
+       0x0f000100,
+       0x008f7e02,
+       0x004eb800,
+/* 0x044e: init_gpc_wait */
+       0x657e0008,
+       0xffc80000,
+       0xf90bf41f,
+       0x08044eb8,
+       0x00657e00,
+       0x001fbb00,
+       0x800040b7,
+       0xf40132b6,
+       0x000fb41b,
+       0x0006b37e,
+       0x627e000f,
+       0x00800006,
+       0x01f60201,
+       0xbd04bd00,
+       0x1f19f014,
+       0x02300080,
+       0xbd0001f6,
+/* 0x0491: main */
+       0x0031f404,
+       0x0d0028f4,
+       0x00377e10,
+       0xf401f400,
+       0x4001e4b1,
+       0x00c71bf5,
+       0x99f094bd,
+       0x37008004,
+       0x0009f602,
+       0x008104bd,
+       0x11cf02c0,
+       0xc1008200,
+       0x0022cf02,
+       0xf41f13c8,
+       0x23c8770b,
+       0x550bf41f,
+       0x12b220f9,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0231f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x20fc04bd,
+       0x99f094bd,
+       0x37008006,
+       0x0009f602,
+       0x31f404bd,
+       0x08367e01,
+       0xf094bd00,
+       0x00800699,
+       0x09f60217,
+       0xf404bd00,
+/* 0x0522: chsw_prev_no_next */
+       0x20f92f0e,
+       0x32f412b2,
+       0x0232f401,
+       0x0008367e,
+       0x008020fc,
+       0x02f602c0,
+       0xf404bd00,
+/* 0x053e: chsw_no_prev */
+       0x23c8130e,
+       0x0d0bf41f,
+       0xf40131f4,
+       0x367e0232,
+/* 0x054e: chsw_done */
+       0x01020008,
+       0x02c30080,
+       0xbd0002f6,
+       0xf094bd04,
+       0x00800499,
+       0x09f60217,
+       0xf504bd00,
+/* 0x056b: main_not_ctx_switch */
+       0xb0ff2a0e,
+       0x1bf401e4,
+       0x7ef2b20c,
+       0xf40007d6,
+/* 0x057a: main_not_ctx_chan */
+       0xe4b0400e,
+       0x2c1bf402,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0232f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x0ef404bd,
+/* 0x05a9: main_not_ctx_save */
+       0x10ef9411,
+       0x7e01f5f0,
+       0xf50002f8,
+/* 0x05b7: main_done */
+       0xbdfede0e,
+       0x1f29f024,
+       0x02300080,
+       0xbd0002f6,
+       0xcc0ef504,
+/* 0x05c9: ih */
+       0xfe80f9fe,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0x004a04bd,
+       0x00aacf02,
+       0xf404abc4,
+       0x100d230b,
+       0xcf1a004e,
+       0x004f00ee,
+       0x00ffcf19,
+       0x0000047e,
+       0x0400b0b7,
+       0x0040010e,
+       0x000ef61d,
+/* 0x060a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x4e100d0c,
+       0x047e4001,
+/* 0x061a: ih_no_ctxsw */
+       0xabe40000,
+       0x0bf40400,
+       0x01004b10,
+       0x448ebfb2,
+       0x8f7e4001,
+/* 0x062e: ih_no_fwmthd */
+       0x044b0000,
+       0xffb0bd01,
+       0x0bf4b4ab,
+       0x0700800c,
+       0x000bf603,
+/* 0x0642: ih_no_other */
+       0x004004bd,
+       0x000af601,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x0662: ctx_4170s */
+       0xf5f001f8,
+       0x8effb210,
+       0x7e404170,
+       0xf800008f,
+/* 0x0671: ctx_4170w */
+       0x41708e00,
+       0x00657e40,
+       0xf0ffb200,
+       0x1bf410f4,
+/* 0x0683: ctx_redswitch */
+       0x4e00f8f3,
+       0xe5f00200,
+       0x20e5f040,
+       0x8010e5f0,
+       0xf6018500,
+       0x04bd000e,
+/* 0x069a: ctx_redswitch_delay */
+       0xf2b6080f,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x01850080,
+       0xbd000ef6,
+/* 0x06b3: ctx_86c */
+       0x8000f804,
+       0xf6022300,
+       0x04bd000f,
+       0x148effb2,
+       0x8f7e408a,
+       0xffb20000,
+       0x41a88c8e,
+       0x00008f7e,
+/* 0x06d2: ctx_mem */
+       0x008000f8,
+       0x0ff60284,
+/* 0x06db: ctx_mem_wait */
+       0x8f04bd00,
+       0xcf028400,
+       0xfffd00ff,
+       0xf61bf405,
+/* 0x06ea: ctx_load */
+       0x94bd00f8,
+       0x800599f0,
+       0xf6023700,
+       0x04bd0009,
+       0xb87e0c0a,
+       0xf4bd0000,
+       0x02890080,
+       0xbd000ff6,
+       0xc1008004,
+       0x0002f602,
+       0x008004bd,
+       0x02f60283,
+       0x0f04bd00,
+       0x06d27e07,
+       0xc0008000,
+       0x0002f602,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0x800899f0,
+       0xf6023700,
+       0x04bd0009,
+       0x02810080,
+       0xbd0002f6,
+       0x0000d204,
+       0x25f08000,
+       0x88008002,
+       0x0002f602,
+       0x100104bd,
+       0xf0020042,
+       0x12fa0223,
+       0xbd03f805,
+       0x0899f094,
+       0x02170080,
+       0xbd0009f6,
+       0x81019804,
+       0x981814b6,
+       0x25b68002,
+       0x0512fd08,
+       0xbd1601b5,
+       0x0999f094,
+       0x02370080,
+       0xbd0009f6,
+       0x81008004,
+       0x0001f602,
+       0x010204bd,
+       0x02880080,
+       0xbd0002f6,
+       0x01004104,
+       0xfa0613f0,
+       0x03f80501,
+       0x99f094bd,
+       0x17008009,
+       0x0009f602,
+       0x94bd04bd,
+       0x800599f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x07d6: ctx_chan */
+       0xea7e00f8,
+       0x0c0a0006,
+       0x0000b87e,
+       0xd27e050f,
+       0x00f80006,
+/* 0x07e8: ctx_mmio_exec */
+       0x80410398,
+       0xf6028100,
+       0x04bd0003,
+/* 0x07f6: ctx_mmio_loop */
+       0x34c434bd,
+       0x0e1bf4ff,
+       0xf0020045,
+       0x35fa0653,
+/* 0x0807: ctx_mmio_pull */
+       0x9803f805,
+       0x4f98804e,
+       0x008f7e81,
+       0x0830b600,
+       0xf40112b6,
+/* 0x081a: ctx_mmio_done */
+       0x0398df1b,
+       0x81008016,
+       0x0003f602,
+       0x00b504bd,
+       0x01004140,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x0836: ctx_xfer */
+       0x040e00f8,
+       0x03020080,
+       0xbd000ef6,
+/* 0x0841: ctx_xfer_idle */
+       0x00008e04,
+       0x00eecf03,
+       0x2000e4f1,
+       0xf4f51bf4,
+       0x02f40611,
+/* 0x0855: ctx_xfer_pre */
+       0x7e100f0c,
+       0xf40006b3,
+/* 0x085e: ctx_xfer_pre_load */
+       0x020f1b11,
+       0x0006627e,
+       0x0006717e,
+       0x0006837e,
+       0x627ef4bd,
+       0xea7e0006,
+/* 0x0876: ctx_xfer_exec */
+       0x01980006,
+       0x8024bd16,
+       0xf6010500,
+       0x04bd0002,
+       0x008e1fb2,
+       0x8f7e41a5,
+       0xfcf00000,
+       0x022cf001,
+       0xfd0124b6,
+       0xffb205f2,
+       0x41a5048e,
+       0x00008f7e,
+       0x0002167e,
+       0xfc8024bd,
+       0x02f60247,
+       0xf004bd00,
+       0x20b6012c,
+       0x4afc8003,
+       0x0002f602,
+       0xacf004bd,
+       0x06a5f001,
+       0x0c98000b,
+       0x010d9800,
+       0x3d7e000e,
+       0x080a0001,
+       0x0000ec7e,
+       0x00020a7e,
+       0x0a1201f4,
+       0x00b87e0c,
+       0x7e050f00,
+       0xf40006d2,
+/* 0x08f2: ctx_xfer_post */
+       0x020f2d02,
+       0x0006627e,
+       0xb37ef4bd,
+       0x277e0006,
+       0x717e0002,
+       0xf4bd0006,
+       0x0006627e,
+       0x981011f4,
+       0x11fd4001,
+       0x070bf405,
+       0x0007e87e,
+/* 0x091c: ctx_xfer_no_post_mmio */
+/* 0x091c: ctx_xfer_done */
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index 4750984bf380a0dede5c0416330f448e1041ccd1..64dfd75192bfff1f92a1f9df37c396eaca7c55e6 100644 (file)
@@ -342,7 +342,7 @@ uint32_t nv108_grhub_code[] = {
        0xb4f000bb,
        0x10b4b01f,
        0x0af31bf4,
-       0x00b87e02,
+       0x00b87e05,
        0x250ef400,
 /* 0x01d8: mmctx_stop */
        0xb600abc8,
index 132f684b1946a9357697eace024fa866af43b72f..f8f7b278a13fcd181dd6e275ce40cc8a85fe3724 100644 (file)
@@ -361,7 +361,7 @@ uint32_t nvc0_grhub_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
index 84af8241898764bfef6116d881c0425346684ee2..624215a005b02be92d803d377a58e65ce1e284b4 100644 (file)
@@ -361,7 +361,7 @@ uint32_t nvd7_grhub_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
index 1c179bdd48cc2a0ddd3228a3e8bfc0005f1bf06a..6547b3dfc7ed09bac0b67b7b307f6b270936ff7b 100644 (file)
@@ -361,7 +361,7 @@ uint32_t nve0_grhub_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
index 229c0ae3722844c16d39e33fb669b677bcefa13c..a5aee5a4302f59b1f76b484d25b84cfea2e6ca50 100644 (file)
@@ -361,7 +361,7 @@ uint32_t nvf0_grhub_code[] = {
        0x1fb4f000,
        0xf410b4b0,
        0xa7f0f01b,
-       0xd021f402,
+       0xd021f405,
 /* 0x0223: mmctx_stop */
        0xc82b0ef4,
        0xb4b600ab,
index 6ffe28307dbd6e420a019d0e7dd4ac891f531fd7..a47d49db5232ed8a06f1911bb1d646b709cc8869 100644 (file)
 #define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD                                  0x41a068
 #define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK                                  0x41a074
 #define NV_PGRAPH_GPCX_GPCCS_UNITS                                     0x41a608
+#define NV_PGRAPH_GPCX_GPCCS_CAPS                                      0x41a108
 #define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH                                0x41a614
 #define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11                        0x00000800
 #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 (file)
index 0000000..21c5f31
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/P0260.h>
+
+#include "nvc0.h"
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * Graphics object classes
+ ******************************************************************************/
+
+static struct nouveau_oclass
+gm107_graph_sclass[] = {
+       { 0x902d, &nouveau_object_ofuncs },
+       { 0xa140, &nouveau_object_ofuncs },
+       { 0xb097, &nouveau_object_ofuncs },
+       { 0xb0c0, &nouveau_object_ofuncs },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gm107_graph_init_main_0[] = {
+       { 0x400080,   1, 0x04, 0x003003c2 },
+       { 0x400088,   1, 0x04, 0x0001bfe7 },
+       { 0x40008c,   1, 0x04, 0x00060000 },
+       { 0x400090,   1, 0x04, 0x00000030 },
+       { 0x40013c,   1, 0x04, 0x003901f3 },
+       { 0x400140,   1, 0x04, 0x00000100 },
+       { 0x400144,   1, 0x04, 0x00000000 },
+       { 0x400148,   1, 0x04, 0x00000110 },
+       { 0x400138,   1, 0x04, 0x00000000 },
+       { 0x400130,   2, 0x04, 0x00000000 },
+       { 0x400124,   1, 0x04, 0x00000002 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_ds_0[] = {
+       { 0x405844,   1, 0x04, 0x00ffffff },
+       { 0x405850,   1, 0x04, 0x00000000 },
+       { 0x405900,   1, 0x04, 0x00000000 },
+       { 0x405908,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_scc_0[] = {
+       { 0x40803c,   1, 0x04, 0x00000010 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_sked_0[] = {
+       { 0x407010,   1, 0x04, 0x00000000 },
+       { 0x407040,   1, 0x04, 0x40440424 },
+       { 0x407048,   1, 0x04, 0x0000000a },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_prop_0[] = {
+       { 0x418408,   1, 0x04, 0x00000000 },
+       { 0x4184a0,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_setup_1[] = {
+       { 0x4188c8,   2, 0x04, 0x00000000 },
+       { 0x4188d0,   1, 0x04, 0x00010000 },
+       { 0x4188d4,   1, 0x04, 0x00010201 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_zcull_0[] = {
+       { 0x418910,   1, 0x04, 0x00010001 },
+       { 0x418914,   1, 0x04, 0x00000301 },
+       { 0x418918,   1, 0x04, 0x00800000 },
+       { 0x418930,   2, 0x04, 0x00000000 },
+       { 0x418980,   1, 0x04, 0x77777770 },
+       { 0x418984,   3, 0x04, 0x77777777 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_gpc_unk_1[] = {
+       { 0x418d00,   1, 0x04, 0x00000000 },
+       { 0x418f00,   1, 0x04, 0x00000400 },
+       { 0x418f08,   1, 0x04, 0x00000000 },
+       { 0x418e08,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_tpccs_0[] = {
+       { 0x419dc4,   1, 0x04, 0x00000000 },
+       { 0x419dc8,   1, 0x04, 0x00000501 },
+       { 0x419dd0,   1, 0x04, 0x00000000 },
+       { 0x419dd4,   1, 0x04, 0x00000100 },
+       { 0x419dd8,   1, 0x04, 0x00000001 },
+       { 0x419ddc,   1, 0x04, 0x00000002 },
+       { 0x419de0,   1, 0x04, 0x00000001 },
+       { 0x419d0c,   1, 0x04, 0x00000000 },
+       { 0x419d10,   1, 0x04, 0x00000014 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_tex_0[] = {
+       { 0x419ab0,   1, 0x04, 0x00000000 },
+       { 0x419ab8,   1, 0x04, 0x000000e7 },
+       { 0x419abc,   1, 0x04, 0x00000000 },
+       { 0x419acc,   1, 0x04, 0x000000ff },
+       { 0x419ac0,   1, 0x04, 0x00000000 },
+       { 0x419aa8,   2, 0x04, 0x00000000 },
+       { 0x419ad0,   2, 0x04, 0x00000000 },
+       { 0x419ae0,   2, 0x04, 0x00000000 },
+       { 0x419af0,   4, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_pe_0[] = {
+       { 0x419900,   1, 0x04, 0x000000ff },
+       { 0x41980c,   1, 0x04, 0x00000010 },
+       { 0x419844,   1, 0x04, 0x00000000 },
+       { 0x419838,   1, 0x04, 0x000000ff },
+       { 0x419850,   1, 0x04, 0x00000004 },
+       { 0x419854,   2, 0x04, 0x00000000 },
+       { 0x419894,   3, 0x04, 0x00100401 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_l1c_0[] = {
+       { 0x419c98,   1, 0x04, 0x00000000 },
+       { 0x419cc0,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_sm_0[] = {
+       { 0x419e30,   1, 0x04, 0x000000ff },
+       { 0x419e00,   1, 0x04, 0x00000000 },
+       { 0x419ea0,   1, 0x04, 0x00000000 },
+       { 0x419ee4,   1, 0x04, 0x00000000 },
+       { 0x419ea4,   1, 0x04, 0x00000100 },
+       { 0x419ea8,   1, 0x04, 0x01000000 },
+       { 0x419ee8,   1, 0x04, 0x00000091 },
+       { 0x419eb4,   1, 0x04, 0x00000000 },
+       { 0x419ebc,   2, 0x04, 0x00000000 },
+       { 0x419edc,   1, 0x04, 0x000c1810 },
+       { 0x419ed8,   1, 0x04, 0x00000000 },
+       { 0x419ee0,   1, 0x04, 0x00000000 },
+       { 0x419f74,   1, 0x04, 0x00005155 },
+       { 0x419f80,   4, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_l1c_1[] = {
+       { 0x419ccc,   2, 0x04, 0x00000000 },
+       { 0x419c80,   1, 0x04, 0x3f006022 },
+       { 0x419c88,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_pes_0[] = {
+       { 0x41be50,   1, 0x04, 0x000000ff },
+       { 0x41be04,   1, 0x04, 0x00000000 },
+       { 0x41be08,   1, 0x04, 0x00000004 },
+       { 0x41be0c,   1, 0x04, 0x00000008 },
+       { 0x41be10,   1, 0x04, 0x0e3b8bc7 },
+       { 0x41be14,   2, 0x04, 0x00000000 },
+       { 0x41be3c,   5, 0x04, 0x00100401 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_wwdx_0[] = {
+       { 0x41bfd4,   1, 0x04, 0x00800000 },
+       { 0x41bfdc,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_cbm_0[] = {
+       { 0x41becc,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_be_0[] = {
+       { 0x408890,   1, 0x04, 0x000000ff },
+       { 0x40880c,   1, 0x04, 0x00000000 },
+       { 0x408850,   1, 0x04, 0x00000004 },
+       { 0x408878,   1, 0x04, 0x00c81603 },
+       { 0x40887c,   1, 0x04, 0x80543432 },
+       { 0x408880,   1, 0x04, 0x0010581e },
+       { 0x408884,   1, 0x04, 0x00001205 },
+       { 0x408974,   1, 0x04, 0x000000ff },
+       { 0x408910,   9, 0x04, 0x00000000 },
+       { 0x408950,   1, 0x04, 0x00000000 },
+       { 0x408954,   1, 0x04, 0x0000ffff },
+       { 0x408958,   1, 0x04, 0x00000034 },
+       { 0x40895c,   1, 0x04, 0x8531a003 },
+       { 0x408960,   1, 0x04, 0x0561985a },
+       { 0x408964,   1, 0x04, 0x04e15c4f },
+       { 0x408968,   1, 0x04, 0x02808833 },
+       { 0x40896c,   1, 0x04, 0x01f02438 },
+       { 0x408970,   1, 0x04, 0x00012c00 },
+       { 0x408984,   1, 0x04, 0x00000000 },
+       { 0x408988,   1, 0x04, 0x08040201 },
+       { 0x40898c,   1, 0x04, 0x80402010 },
+       {}
+};
+
+static const struct nvc0_graph_init
+gm107_graph_init_sm_1[] = {
+       { 0x419e5c,   1, 0x04, 0x00000000 },
+       { 0x419e58,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+gm107_graph_pack_mmio[] = {
+       { gm107_graph_init_main_0 },
+       { nvf0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvc0_graph_init_pd_0 },
+       { gm107_graph_init_ds_0 },
+       { gm107_graph_init_scc_0 },
+       { gm107_graph_init_sked_0 },
+       { nvf0_graph_init_cwd_0 },
+       { gm107_graph_init_prop_0 },
+       { nv108_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { gm107_graph_init_setup_1 },
+       { gm107_graph_init_zcull_0 },
+       { nvc0_graph_init_gpm_0 },
+       { gm107_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { gm107_graph_init_tpccs_0 },
+       { gm107_graph_init_tex_0 },
+       { gm107_graph_init_pe_0 },
+       { gm107_graph_init_l1c_0 },
+       { nvc0_graph_init_mpc_0 },
+       { gm107_graph_init_sm_0 },
+       { gm107_graph_init_l1c_1 },
+       { gm107_graph_init_pes_0 },
+       { gm107_graph_init_wwdx_0 },
+       { gm107_graph_init_cbm_0 },
+       { gm107_graph_init_be_0 },
+       { gm107_graph_init_sm_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static void
+gm107_graph_init_bios(struct nvc0_graph_priv *priv)
+{
+       static const struct {
+               u32 ctrl;
+               u32 data;
+       } regs[] = {
+               { 0x419ed8, 0x419ee0 },
+               { 0x419ad0, 0x419ad4 },
+               { 0x419ae0, 0x419ae4 },
+               { 0x419af0, 0x419af4 },
+               { 0x419af8, 0x419afc },
+       };
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_P0260E infoE;
+       struct nvbios_P0260X infoX;
+       int E = -1, X;
+       u8 ver, hdr;
+
+       while (nvbios_P0260Ep(bios, ++E, &ver, &hdr, &infoE)) {
+               if (X = -1, E < ARRAY_SIZE(regs)) {
+                       nv_wr32(priv, regs[E].ctrl, infoE.data);
+                       while (nvbios_P0260Xp(bios, ++X, &ver, &hdr, &infoX))
+                               nv_wr32(priv, regs[E].data, infoX.data);
+               }
+       }
+}
+
+int
+gm107_graph_init(struct nouveau_object *object)
+{
+       struct nvc0_graph_oclass *oclass = (void *)object->oclass;
+       struct nvc0_graph_priv *priv = (void *)object;
+       const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
+       u32 data[TPC_MAX / 8] = {};
+       u8  tpcnr[GPC_MAX];
+       int gpc, tpc, ppc, rop;
+       int ret, i;
+
+       ret = nouveau_graph_init(&priv->base);
+       if (ret)
+               return ret;
+
+       nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
+       nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000);
+       nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000);
+       nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
+       nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
+
+       nvc0_graph_mmio(priv, oclass->mmio);
+
+       gm107_graph_init_bios(priv);
+
+       nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
+
+       memset(data, 0x00, sizeof(data));
+       memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
+       for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
+               do {
+                       gpc = (gpc + 1) % priv->gpc_nr;
+               } while (!tpcnr[gpc]);
+               tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
+
+               data[i / 8] |= tpc << ((i % 8) * 4);
+       }
+
+       nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
+       nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
+       nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
+       nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
+
+       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0914),
+                       priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 |
+                       priv->tpc_total);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
+       }
+
+       nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
+       nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
+
+       nv_wr32(priv, 0x400500, 0x00010001);
+
+       nv_wr32(priv, 0x400100, 0xffffffff);
+       nv_wr32(priv, 0x40013c, 0xffffffff);
+       nv_wr32(priv, 0x400124, 0x00000002);
+       nv_wr32(priv, 0x409c24, 0x000e0000);
+
+       nv_wr32(priv, 0x404000, 0xc0000000);
+       nv_wr32(priv, 0x404600, 0xc0000000);
+       nv_wr32(priv, 0x408030, 0xc0000000);
+       nv_wr32(priv, 0x404490, 0xc0000000);
+       nv_wr32(priv, 0x406018, 0xc0000000);
+       nv_wr32(priv, 0x407020, 0x40000000);
+       nv_wr32(priv, 0x405840, 0xc0000000);
+       nv_wr32(priv, 0x405844, 0x00ffffff);
+       nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
+
+       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+               for (ppc = 0; ppc < 2 /* priv->ppc_nr[gpc] */; ppc++)
+                       nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
+               for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe);
+                       nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005);
+               }
+               nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
+               nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
+       }
+
+       for (rop = 0; rop < priv->rop_nr; rop++) {
+               nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000);
+               nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000);
+               nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
+               nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
+       }
+
+       nv_wr32(priv, 0x400108, 0xffffffff);
+       nv_wr32(priv, 0x400138, 0xffffffff);
+       nv_wr32(priv, 0x400118, 0xffffffff);
+       nv_wr32(priv, 0x400130, 0xffffffff);
+       nv_wr32(priv, 0x40011c, 0xffffffff);
+       nv_wr32(priv, 0x400134, 0xffffffff);
+
+       nv_wr32(priv, 0x400054, 0x2c350f63);
+       return nvc0_graph_init_ctxctl(priv);
+}
+
+#include "fuc/hubgm107.fuc5.h"
+
+static struct nvc0_graph_ucode
+gm107_graph_fecs_ucode = {
+       .code.data = gm107_grhub_code,
+       .code.size = sizeof(gm107_grhub_code),
+       .data.data = gm107_grhub_data,
+       .data.size = sizeof(gm107_grhub_data),
+};
+
+#include "fuc/gpcgm107.fuc5.h"
+
+static struct nvc0_graph_ucode
+gm107_graph_gpccs_ucode = {
+       .code.data = gm107_grgpc_code,
+       .code.size = sizeof(gm107_grgpc_code),
+       .data.data = gm107_grgpc_data,
+       .data.size = sizeof(gm107_grgpc_data),
+};
+
+struct nouveau_oclass *
+gm107_graph_oclass = &(struct nvc0_graph_oclass) {
+       .base.handle = NV_ENGINE(GR, 0x07),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_ctor,
+               .dtor = nvc0_graph_dtor,
+               .init = gm107_graph_init,
+               .fini = _nouveau_graph_fini,
+       },
+       .cclass = &gm107_grctx_oclass,
+       .sclass =  gm107_graph_sclass,
+       .mmio = gm107_graph_pack_mmio,
+       .fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL,
+       .gpccs.ucode = &gm107_graph_gpccs_ucode,
+}.base;
index e1af65ead379844459c52e9d29cf1e405523cd14..00ea1a0898229bf4b5ab0b3ee1f93bc23402db9a 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -38,11 +39,11 @@ nv108_graph_sclass[] = {
 };
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-static struct nvc0_graph_init
-nv108_graph_init_regs[] = {
+static const struct nvc0_graph_init
+nv108_graph_init_main_0[] = {
        { 0x400080,   1, 0x04, 0x003083c2 },
        { 0x400088,   1, 0x04, 0x0001bfe7 },
        { 0x40008c,   1, 0x04, 0x00000000 },
@@ -57,66 +58,46 @@ nv108_graph_init_regs[] = {
        {}
 };
 
-struct nvc0_graph_init
-nv108_graph_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nv108_graph_init_ds_0[] = {
        { 0x405844,   1, 0x04, 0x00ffffff },
        { 0x405850,   1, 0x04, 0x00000000 },
        { 0x405900,   1, 0x04, 0x00000000 },
        { 0x405908,   1, 0x04, 0x00000000 },
-       { 0x405928,   1, 0x04, 0x00000000 },
-       { 0x40592c,   1, 0x04, 0x00000000 },
+       { 0x405928,   2, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nv108_graph_init_gpc[] = {
-       { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x4184a0,   3, 0x04, 0x00000000 },
+const struct nvc0_graph_init
+nv108_graph_init_gpc_unk_0[] = {
        { 0x418604,   1, 0x04, 0x00000000 },
        { 0x418680,   1, 0x04, 0x00000000 },
        { 0x418714,   1, 0x04, 0x00000000 },
        { 0x418384,   2, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_graph_init_setup_1[] = {
        { 0x4188c8,   2, 0x04, 0x00000000 },
        { 0x4188d0,   1, 0x04, 0x00010000 },
        { 0x4188d4,   1, 0x04, 0x00000201 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c64,   2, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
-       { 0x418cb4,   2, 0x04, 0x00000000 },
-       { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418d28,   2, 0x04, 0x00000000 },
-       { 0x418f00,   1, 0x04, 0x00000400 },
-       { 0x418f08,   1, 0x04, 0x00000000 },
-       { 0x418f20,   2, 0x04, 0x00000000 },
-       { 0x418e00,   1, 0x04, 0x00000000 },
-       { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x418e1c,   2, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nv108_graph_init_tpc[] = {
-       { 0x419d0c,   1, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
+static const struct nvc0_graph_init
+nv108_graph_init_tex_0[] = {
        { 0x419ab0,   1, 0x04, 0x00000000 },
        { 0x419ac8,   1, 0x04, 0x00000000 },
        { 0x419ab8,   1, 0x04, 0x000000e7 },
        { 0x419abc,   2, 0x04, 0x00000000 },
        { 0x419ab4,   1, 0x04, 0x00000000 },
        { 0x419aa8,   2, 0x04, 0x00000000 },
-       { 0x41980c,   1, 0x04, 0x00000010 },
-       { 0x419844,   1, 0x04, 0x00000000 },
-       { 0x419850,   1, 0x04, 0x00000004 },
-       { 0x419854,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nv108_graph_init_l1c_0[] = {
        { 0x419c98,   1, 0x04, 0x00000000 },
        { 0x419ca8,   1, 0x04, 0x00000000 },
        { 0x419cb0,   1, 0x04, 0x01000000 },
@@ -127,22 +108,47 @@ nv108_graph_init_tpc[] = {
        { 0x419cc0,   2, 0x04, 0x00000000 },
        { 0x419c80,   1, 0x04, 0x00000230 },
        { 0x419ccc,   2, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
-       { 0x419e00,   1, 0x04, 0x00000080 },
-       { 0x419ea0,   1, 0x04, 0x00000000 },
-       { 0x419ee4,   1, 0x04, 0x00000000 },
-       { 0x419ea4,   1, 0x04, 0x00000100 },
-       { 0x419ea8,   1, 0x04, 0x00000000 },
-       { 0x419eb4,   1, 0x04, 0x00000000 },
-       { 0x419ebc,   2, 0x04, 0x00000000 },
-       { 0x419edc,   1, 0x04, 0x00000000 },
-       { 0x419f00,   1, 0x04, 0x00000000 },
-       { 0x419ed0,   1, 0x04, 0x00003234 },
-       { 0x419f74,   1, 0x04, 0x00015555 },
-       { 0x419f80,   4, 0x04, 0x00000000 },
        {}
 };
 
+static const struct nvc0_graph_pack
+nv108_graph_pack_mmio[] = {
+       { nv108_graph_init_main_0 },
+       { nvf0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvd9_graph_init_pd_0 },
+       { nv108_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvf0_graph_init_sked_0 },
+       { nvf0_graph_init_cwd_0 },
+       { nvd9_graph_init_prop_0 },
+       { nv108_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nv108_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvd9_graph_init_gpm_0 },
+       { nvf0_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nve4_graph_init_tpccs_0 },
+       { nv108_graph_init_tex_0 },
+       { nve4_graph_init_pe_0 },
+       { nv108_graph_init_l1c_0 },
+       { nvc0_graph_init_mpc_0 },
+       { nvf0_graph_init_sm_0 },
+       { nvd7_graph_init_pes_0 },
+       { nvd7_graph_init_wwdx_0 },
+       { nvd7_graph_init_cbm_0 },
+       { nve4_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 static int
 nv108_graph_fini(struct nouveau_object *object, bool suspend)
 {
@@ -180,25 +186,6 @@ nv108_graph_fini(struct nouveau_object *object, bool suspend)
        return nouveau_graph_fini(&priv->base, suspend);
 }
 
-static struct nvc0_graph_init *
-nv108_graph_init_mmio[] = {
-       nv108_graph_init_regs,
-       nvf0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvd9_graph_init_unk64xx,
-       nv108_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvf0_graph_init_unk70xx,
-       nvf0_graph_init_unk5bxx,
-       nv108_graph_init_gpc,
-       nv108_graph_init_tpc,
-       nve4_graph_init_unk,
-       nve4_graph_init_unk88xx,
-       NULL
-};
-
 #include "fuc/hubnv108.fuc5.h"
 
 static struct nvc0_graph_ucode
@@ -230,7 +217,7 @@ nv108_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nv108_grctx_oclass,
        .sclass =  nv108_graph_sclass,
-       .mmio = nv108_graph_init_mmio,
+       .mmio = nv108_graph_pack_mmio,
        .fecs.ucode = &nv108_graph_fecs_ucode,
        .gpccs.ucode = &nv108_graph_gpccs_ucode,
 }.base;
index b24559315903f56b23dad5df1aa3cf95f9572882..d145e080899afd788f27638f580d45b108dd7425 100644 (file)
@@ -349,7 +349,7 @@ nv20_graph_init(struct nouveau_object *object)
        nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp);
 
        /* begin RAM config */
-       vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
+       vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
        nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
        nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204));
        nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
index 193a5de1b48287e05c732c28ddc066b8e4e5048a..6477fbf6a550ce84804d2b5c743b1802ed41548d 100644 (file)
@@ -484,7 +484,7 @@ nv40_graph_init(struct nouveau_object *object)
                engine->tile_prog(engine, i);
 
        /* begin RAM config */
-       vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
+       vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
        switch (nv_device(priv)->chipset) {
        case 0x40:
                nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
index 7a367c4029786f9d3b0941b62d697902b3681e93..2c7809e1a09b6c906c3bd58f7cd9e49287bc9fa5 100644 (file)
@@ -197,34 +197,35 @@ static const struct nouveau_bitfield nv50_pgraph_status[] = {
        { 0x00000080, "UNK7" },
        { 0x00000100, "CTXPROG" },
        { 0x00000200, "VFETCH" },
-       { 0x00000400, "CCACHE_UNK4" },
-       { 0x00000800, "STRMOUT_GSCHED_UNK5" },
-       { 0x00001000, "UNK14XX" },
-       { 0x00002000, "UNK24XX_CSCHED" },
-       { 0x00004000, "UNK1CXX" },
+       { 0x00000400, "CCACHE_PREGEOM" },
+       { 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
+       { 0x00001000, "VCLIP" },
+       { 0x00002000, "RATTR_APLANE" },
+       { 0x00004000, "TRAST" },
        { 0x00008000, "CLIPID" },
        { 0x00010000, "ZCULL" },
        { 0x00020000, "ENG2D" },
-       { 0x00040000, "UNK34XX" },
-       { 0x00080000, "TPRAST" },
-       { 0x00100000, "TPROP" },
-       { 0x00200000, "TEX" },
-       { 0x00400000, "TPVP" },
-       { 0x00800000, "MP" },
+       { 0x00040000, "RMASK" },
+       { 0x00080000, "TPC_RAST" },
+       { 0x00100000, "TPC_PROP" },
+       { 0x00200000, "TPC_TEX" },
+       { 0x00400000, "TPC_GEOM" },
+       { 0x00800000, "TPC_MP" },
        { 0x01000000, "ROP" },
        {}
 };
 
 static const char *const nv50_pgraph_vstatus_0[] = {
-       "VFETCH", "CCACHE", "UNK4", "UNK5", "GSCHED", "STRMOUT", "UNK14XX", NULL
+       "VFETCH", "CCACHE", "PREGEOM", "POSTGEOM", "VATTR", "STRMOUT", "VCLIP",
+       NULL
 };
 
 static const char *const nv50_pgraph_vstatus_1[] = {
-       "TPRAST", "TPROP", "TEXTURE", "TPVP", "MP", NULL
+       "TPC_RAST", "TPC_PROP", "TPC_TEX", "TPC_GEOM", "TPC_MP", NULL
 };
 
 static const char *const nv50_pgraph_vstatus_2[] = {
-       "UNK24XX", "CSCHED", "UNK1CXX", "CLIPID", "ZCULL", "ENG2D", "UNK34XX",
+       "RATTR", "APLANE", "TRAST", "CLIPID", "ZCULL", "ENG2D", "RMASK",
        "ROP", NULL
 };
 
@@ -329,6 +330,15 @@ static const struct nouveau_bitfield nv50_mpc_traps[] = {
        {}
 };
 
+static const struct nouveau_bitfield nv50_tex_traps[] = {
+       { 0x00000001, "" }, /* any bit set? */
+       { 0x00000002, "FAULT" },
+       { 0x00000004, "STORAGE_TYPE_MISMATCH" },
+       { 0x00000008, "LINEAR_MISMATCH" },
+       { 0x00000020, "WRONG_MEMTYPE" },
+       {}
+};
+
 static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
        { 0x00000001, "NOTIFY" },
        { 0x00000002, "IN" },
@@ -531,6 +541,13 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
                                for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
                                        nv_error(priv, "\t0x%08x: 0x%08x\n", r,
                                                nv_rd32(priv, r));
+                               if (ustatus) {
+                                       nv_error(priv, "%s - TP%d:", name, i);
+                                       nouveau_bitfield_print(nv50_tex_traps,
+                                                              ustatus);
+                                       pr_cont("\n");
+                                       ustatus = 0;
+                               }
                        }
                        break;
                case 7: /* MP error */
index a73ab209ea88c85121fe3580e9daa189b29de46e..f3c7329da0a04c8870ccba95a9b525c2ebc3ddca 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -146,11 +147,11 @@ nvc0_graph_context_dtor(struct nouveau_object *object)
 }
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-struct nvc0_graph_init
-nvc0_graph_init_regs[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_main_0[] = {
        { 0x400080,   1, 0x04, 0x003083c2 },
        { 0x400088,   1, 0x04, 0x00006fe7 },
        { 0x40008c,   1, 0x04, 0x00000000 },
@@ -165,95 +166,170 @@ nvc0_graph_init_regs[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk40xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_fe_0[] = {
        { 0x40415c,   1, 0x04, 0x00000000 },
        { 0x404170,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk44xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_pri_0[] = {
        { 0x404488,   2, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk78xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_rstr2d_0[] = {
        { 0x407808,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk60xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_pd_0[] = {
        { 0x406024,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk58xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_ds_0[] = {
        { 0x405844,   1, 0x04, 0x00ffffff },
        { 0x405850,   1, 0x04, 0x00000000 },
        { 0x405908,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk80xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_scc_0[] = {
        { 0x40803c,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_gpc[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_prop_0[] = {
        { 0x4184a0,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_gpc_unk_0[] = {
        { 0x418604,   1, 0x04, 0x00000000 },
        { 0x418680,   1, 0x04, 0x00000000 },
        { 0x418714,   1, 0x04, 0x80000000 },
        { 0x418384,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_setup_0[] = {
        { 0x418814,   3, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_crstr_0[] = {
        { 0x418b04,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_setup_1[] = {
        { 0x4188c8,   1, 0x04, 0x80000000 },
        { 0x4188cc,   1, 0x04, 0x00000000 },
        { 0x4188d0,   1, 0x04, 0x00010000 },
        { 0x4188d4,   1, 0x04, 0x00000001 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_zcull_0[] = {
        { 0x418910,   1, 0x04, 0x00010001 },
        { 0x418914,   1, 0x04, 0x00000301 },
        { 0x418918,   1, 0x04, 0x00800000 },
        { 0x418980,   1, 0x04, 0x77777770 },
        { 0x418984,   3, 0x04, 0x77777777 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_gpm_0[] = {
        { 0x418c04,   1, 0x04, 0x00000000 },
        { 0x418c88,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_gpc_unk_1[] = {
        { 0x418d00,   1, 0x04, 0x00000000 },
        { 0x418f08,   1, 0x04, 0x00000000 },
        { 0x418e00,   1, 0x04, 0x00000050 },
        { 0x418e08,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_gcc_0[] = {
        { 0x41900c,   1, 0x04, 0x00000000 },
        { 0x419018,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvc0_graph_init_tpc[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_tpccs_0[] = {
        { 0x419d08,   2, 0x04, 0x00000000 },
        { 0x419d10,   1, 0x04, 0x00000014 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_tex_0[] = {
        { 0x419ab0,   1, 0x04, 0x00000000 },
        { 0x419ab8,   1, 0x04, 0x000000e7 },
        { 0x419abc,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_pe_0[] = {
        { 0x41980c,   3, 0x04, 0x00000000 },
        { 0x419844,   1, 0x04, 0x00000000 },
        { 0x41984c,   1, 0x04, 0x00005bc5 },
        { 0x419850,   4, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_l1c_0[] = {
        { 0x419c98,   1, 0x04, 0x00000000 },
        { 0x419ca8,   1, 0x04, 0x80000000 },
        { 0x419cb4,   1, 0x04, 0x00000000 },
        { 0x419cb8,   1, 0x04, 0x00008bf4 },
        { 0x419cbc,   1, 0x04, 0x28137606 },
        { 0x419cc0,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_wwdx_0[] = {
        { 0x419bd4,   1, 0x04, 0x00800000 },
        { 0x419bdc,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_tpccs_1[] = {
        { 0x419d2c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc0_graph_init_mpc_0[] = {
        { 0x419c0c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc0_graph_init_sm_0[] = {
        { 0x419e00,   1, 0x04, 0x00000000 },
        { 0x419ea0,   1, 0x04, 0x00000000 },
        { 0x419ea4,   1, 0x04, 0x00000100 },
@@ -270,8 +346,8 @@ nvc0_graph_init_tpc[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_init_unk88xx[] = {
+const struct nvc0_graph_init
+nvc0_graph_init_be_0[] = {
        { 0x40880c,   1, 0x04, 0x00000000 },
        { 0x408910,   9, 0x04, 0x00000000 },
        { 0x408950,   1, 0x04, 0x00000000 },
@@ -282,18 +358,64 @@ nvc0_graph_init_unk88xx[] = {
        {}
 };
 
-struct nvc0_graph_init
-nvc0_graph_tpc_0[] = {
-       { 0x50405c,   1, 0x04, 0x00000001 },
+const struct nvc0_graph_init
+nvc0_graph_init_fe_1[] = {
+       { 0x4040f0,   1, 0x04, 0x00000000 },
        {}
 };
 
+const struct nvc0_graph_init
+nvc0_graph_init_pe_1[] = {
+       { 0x419880,   1, 0x04, 0x00000002 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nvc0_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvc0_graph_init_pd_0 },
+       { nvc0_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvc0_graph_init_prop_0 },
+       { nvc0_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc0_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvc0_graph_init_gpm_0 },
+       { nvc0_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvc0_graph_init_tex_0 },
+       { nvc0_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvc0_graph_init_wwdx_0 },
+       { nvc0_graph_init_tpccs_1 },
+       { nvc0_graph_init_mpc_0 },
+       { nvc0_graph_init_sm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       { nvc0_graph_init_pe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 void
-nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init)
+nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
 {
-       for (; init && init->count; init++) {
-               u32 addr = init->addr, i;
-               for (i = 0; i < init->count; i++) {
+       const struct nvc0_graph_pack *pack;
+       const struct nvc0_graph_init *init;
+
+       pack_for_each_init(init, pack, p) {
+               u32 next = init->addr + init->count * init->pitch;
+               u32 addr = init->addr;
+               while (addr < next) {
                        nv_wr32(priv, addr, init->data);
                        addr += init->pitch;
                }
@@ -301,49 +423,53 @@ nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init)
 }
 
 void
-nvc0_graph_icmd(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init)
+nvc0_graph_icmd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
 {
-       u32 addr, data;
-       int i, j;
+       const struct nvc0_graph_pack *pack;
+       const struct nvc0_graph_init *init;
+       u32 data = 0;
 
        nv_wr32(priv, 0x400208, 0x80000000);
-       for (i = 0; init->count; init++, i++) {
-               if (!i || data != init->data) {
+
+       pack_for_each_init(init, pack, p) {
+               u32 next = init->addr + init->count * init->pitch;
+               u32 addr = init->addr;
+
+               if ((pack == p && init == p->init) || data != init->data) {
                        nv_wr32(priv, 0x400204, init->data);
                        data = init->data;
                }
 
-               addr = init->addr;
-               for (j = 0; j < init->count; j++) {
+               while (addr < next) {
                        nv_wr32(priv, 0x400200, addr);
+                       nv_wait(priv, 0x400700, 0x00000002, 0x00000000);
                        addr += init->pitch;
-                       while (nv_rd32(priv, 0x400700) & 0x00000002) {}
                }
        }
+
        nv_wr32(priv, 0x400208, 0x00000000);
 }
 
 void
-nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds)
+nvc0_graph_mthd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
 {
-       struct nvc0_graph_mthd *mthd;
-       struct nvc0_graph_init *init;
-       int i = 0, j;
-       u32 data;
-
-       while ((mthd = &mthds[i++]) && (init = mthd->init)) {
-               u32  addr = 0x80000000 | mthd->oclass;
-               for (data = 0; init->count; init++) {
-                       if (init == mthd->init || data != init->data) {
-                               nv_wr32(priv, 0x40448c, init->data);
-                               data = init->data;
-                       }
+       const struct nvc0_graph_pack *pack;
+       const struct nvc0_graph_init *init;
+       u32 data = 0;
 
-                       addr = (addr & 0x8000ffff) | (init->addr << 14);
-                       for (j = 0; j < init->count; j++) {
-                               nv_wr32(priv, 0x404488, addr);
-                               addr += init->pitch << 14;
-                       }
+       pack_for_each_init(init, pack, p) {
+               u32 ctrl = 0x80000000 | pack->type;
+               u32 next = init->addr + init->count * init->pitch;
+               u32 addr = init->addr;
+
+               if ((pack == p && init == p->init) || data != init->data) {
+                       nv_wr32(priv, 0x40448c, init->data);
+                       data = init->data;
+               }
+
+               while (addr < next) {
+                       nv_wr32(priv, 0x404488, ctrl | (addr << 14));
+                       addr += init->pitch;
                }
        }
 }
@@ -772,11 +898,12 @@ nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,
 
 static void
 nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,
-                      struct nvc0_graph_init *init,
+                      const struct nvc0_graph_pack *pack,
                       u32 falcon, u32 starstar, u32 base)
 {
-       u32 addr = init->addr;
-       u32 next = addr;
+       const struct nvc0_graph_pack *iter;
+       const struct nvc0_graph_init *init;
+       u32 addr = ~0, prev = ~0, xfer = 0;
        u32 star, temp;
 
        nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar);
@@ -786,22 +913,28 @@ nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,
                star = temp;
        nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star);
 
-       do {
-               if (init->addr != next) {
-                       while (addr < next) {
-                               u32 nr = min((int)(next - addr) / 4, 32);
-                               nv_wr32(priv, falcon + 0x01c4,
-                                       ((nr - 1) << 26) | (addr - base));
-                               addr += nr * 4;
-                               star += 4;
+       pack_for_each_init(init, iter, pack) {
+               u32 head = init->addr - base;
+               u32 tail = head + init->count * init->pitch;
+               while (head < tail) {
+                       if (head != prev + 4 || xfer >= 32) {
+                               if (xfer) {
+                                       u32 data = ((--xfer << 26) | addr);
+                                       nv_wr32(priv, falcon + 0x01c4, data);
+                                       star += 4;
+                               }
+                               addr = head;
+                               xfer = 0;
                        }
-                       addr = next = init->addr;
+                       prev = head;
+                       xfer = xfer + 1;
+                       head = head + init->pitch;
                }
-               next += init->count * 4;
-       } while ((init++)->count);
+       }
 
+       nv_wr32(priv, falcon + 0x01c4, (--xfer << 26) | addr);
        nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar);
-       nv_wr32(priv, falcon + 0x01c4, star);
+       nv_wr32(priv, falcon + 0x01c4, star + 4);
 }
 
 int
@@ -809,7 +942,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
 {
        struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
        struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
-       struct nvc0_graph_init *init;
        u32 r000260;
        int i;
 
@@ -919,10 +1051,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
                nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]);
        }
 
-       for (i = 0; (init = cclass->hub[i]); i++) {
-               nvc0_graph_init_csdata(priv, init, 0x409000, 0x000, 0x000000);
-       }
-
        /* load GPC microcode */
        nv_wr32(priv, 0x41a1c0, 0x01000000);
        for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
@@ -936,12 +1064,11 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
        }
        nv_wr32(priv, 0x000260, r000260);
 
-       if ((init = cclass->gpc[0]))
-               nvc0_graph_init_csdata(priv, init, 0x41a000, 0x000, 0x418000);
-       if ((init = cclass->gpc[2]))
-               nvc0_graph_init_csdata(priv, init, 0x41a000, 0x004, 0x419800);
-       if ((init = cclass->gpc[3]))
-               nvc0_graph_init_csdata(priv, init, 0x41a000, 0x008, 0x41be00);
+       /* load register lists */
+       nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
+       nvc0_graph_init_csdata(priv, cclass->gpc, 0x41a000, 0x000, 0x418000);
+       nvc0_graph_init_csdata(priv, cclass->tpc, 0x41a000, 0x004, 0x419800);
+       nvc0_graph_init_csdata(priv, cclass->ppc, 0x41a000, 0x008, 0x41be00);
 
        /* start HUB ucode running, it'll init the GPCs */
        nv_wr32(priv, 0x40910c, 0x00000000);
@@ -988,8 +1115,7 @@ nvc0_graph_init(struct nouveau_object *object)
        nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
        nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
 
-       for (i = 0; oclass->mmio[i]; i++)
-               nvc0_graph_mmio(priv, oclass->mmio[i]);
+       nvc0_graph_mmio(priv, oclass->mmio);
 
        memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
        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,
        int ret;
 
        snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
-       ret = request_firmware(&fw, f, &device->pdev->dev);
+       ret = request_firmware(&fw, f, nv_device_base(device));
        if (ret) {
                snprintf(f, sizeof(f), "nouveau/%s", fwname);
-               ret = request_firmware(&fw, f, &device->pdev->dev);
+               ret = request_firmware(&fw, f, nv_device_base(device));
                if (ret) {
                        nv_error(priv, "failed to load %s\n", fwname);
                        return ret;
@@ -1220,22 +1346,6 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-struct nvc0_graph_init *
-nvc0_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvc0_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvc0_graph_init_gpc,
-       nvc0_graph_init_tpc,
-       nvc0_graph_init_unk88xx,
-       nvc0_graph_tpc_0,
-       NULL
-};
-
 #include "fuc/hubnvc0.fuc.h"
 
 struct nvc0_graph_ucode
@@ -1267,7 +1377,7 @@ nvc0_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvc0_grctx_oclass,
        .sclass =  nvc0_graph_sclass,
-       .mmio = nvc0_graph_init_mmio,
+       .mmio = nvc0_graph_pack_mmio,
        .fecs.ucode = &nvc0_graph_fecs_ucode,
        .gpccs.ucode = &nvc0_graph_gpccs_ucode,
 }.base;
index b0ab6de270b2ea9d148b483b8249bc11efa27496..90d44616c876e3d62d23dc619f16a6d24dab4b3a 100644 (file)
@@ -45,6 +45,7 @@
 #define ROP_UNIT(u, r)    (0x410000 + (u) * 0x400 + (r))
 #define GPC_BCAST(r)      (0x418000 + (r))
 #define GPC_UNIT(t, r)    (0x500000 + (t) * 0x8000 + (r))
+#define PPC_UNIT(t, m, r) (0x503000 + (t) * 0x8000 + (m) * 0x200 + (r))
 #define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
 
 struct nvc0_graph_data {
@@ -102,8 +103,6 @@ struct nvc0_graph_chan {
        } data[4];
 };
 
-int  nvc0_grctx_generate(struct nvc0_graph_priv *);
-
 int  nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *,
                             struct nouveau_oclass *, void *, u32,
                             struct nouveau_object **);
@@ -130,34 +129,14 @@ struct nvc0_graph_init {
        u32 data;
 };
 
-struct nvc0_graph_mthd {
-       u16 oclass;
-       struct nvc0_graph_init *init;
-};
-
-struct nvc0_grctx {
-       struct nvc0_graph_priv *priv;
-       struct nvc0_graph_data *data;
-       struct nvc0_graph_mmio *mmio;
-       int buffer_nr;
-       u64 buffer[4];
-       u64 addr;
+struct nvc0_graph_pack {
+       const struct nvc0_graph_init *init;
+       u32 type;
 };
 
-struct nvc0_grctx_oclass {
-       struct nouveau_oclass base;
-       /* main context generation function */
-       void  (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
-       /* context-specific modify-on-first-load list generation function */
-       void  (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
-       void  (*unkn)(struct nvc0_graph_priv *);
-       /* mmio context data */
-       struct nvc0_graph_init **hub;
-       struct nvc0_graph_init **gpc;
-       /* indirect context data, generated with icmds/mthds */
-       struct nvc0_graph_init *icmd;
-       struct nvc0_graph_mthd *mthd;
-};
+#define pack_for_each_init(init, pack, head)                                   \
+       for (pack = head; pack && pack->init; pack++)                          \
+                 for (init = pack->init; init && init->count; init++)
 
 struct nvc0_graph_ucode {
        struct nvc0_graph_fuc code;
@@ -171,7 +150,7 @@ struct nvc0_graph_oclass {
        struct nouveau_oclass base;
        struct nouveau_oclass **cclass;
        struct nouveau_oclass *sclass;
-       struct nvc0_graph_init **mmio;
+       const struct nvc0_graph_pack *mmio;
        struct {
                struct nvc0_graph_ucode *ucode;
        } fecs;
@@ -180,119 +159,72 @@ struct nvc0_graph_oclass {
        } gpccs;
 };
 
-void nvc0_graph_mmio(struct nvc0_graph_priv *, struct nvc0_graph_init *);
-void nvc0_graph_icmd(struct nvc0_graph_priv *, struct nvc0_graph_init *);
-void nvc0_graph_mthd(struct nvc0_graph_priv *, struct nvc0_graph_mthd *);
+void nvc0_graph_mmio(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
+void nvc0_graph_icmd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
+void nvc0_graph_mthd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
 int  nvc0_graph_init_ctxctl(struct nvc0_graph_priv *);
 
-extern struct nvc0_graph_init nvc0_graph_init_regs[];
-extern struct nvc0_graph_init nvc0_graph_init_unk40xx[];
-extern struct nvc0_graph_init nvc0_graph_init_unk44xx[];
-extern struct nvc0_graph_init nvc0_graph_init_unk78xx[];
-extern struct nvc0_graph_init nvc0_graph_init_unk60xx[];
-extern struct nvc0_graph_init nvc0_graph_init_unk58xx[];
-extern struct nvc0_graph_init nvc0_graph_init_unk80xx[];
-extern struct nvc0_graph_init nvc0_graph_init_gpc[];
-extern struct nvc0_graph_init nvc0_graph_init_unk88xx[];
-extern struct nvc0_graph_init nvc0_graph_tpc_0[];
-
-extern struct nvc0_graph_init nvc3_graph_init_unk58xx[];
-
-extern struct nvc0_graph_init nvd9_graph_init_unk58xx[];
-extern struct nvc0_graph_init nvd9_graph_init_unk64xx[];
-
-extern struct nvc0_graph_init nve4_graph_init_regs[];
-extern struct nvc0_graph_init nve4_graph_init_unk[];
-extern struct nvc0_graph_init nve4_graph_init_unk88xx[];
-
-extern struct nvc0_graph_init nvf0_graph_init_unk40xx[];
-extern struct nvc0_graph_init nvf0_graph_init_unk70xx[];
-extern struct nvc0_graph_init nvf0_graph_init_unk5bxx[];
-extern struct nvc0_graph_init nvf0_graph_init_tpc[];
-
-int  nvc0_grctx_generate(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *);
-void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
-void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
-
-extern struct nouveau_oclass *nvc0_grctx_oclass;
-extern struct nvc0_graph_init *nvc0_grctx_init_hub[];
-extern struct nvc0_graph_init nvc0_grctx_init_base[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk40xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk44xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk46xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk47xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk60xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk64xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk78xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_unk80xx[];
-extern struct nvc0_graph_init nvc0_grctx_init_gpc_0[];
-extern struct nvc0_graph_init nvc0_grctx_init_gpc_1[];
-extern struct nvc0_graph_init nvc0_grctx_init_tpc[];
-extern struct nvc0_graph_init nvc0_grctx_init_icmd[];
-extern struct nvc0_graph_init nvd9_grctx_init_icmd[]; //
-
-extern struct nvc0_graph_mthd nvc0_grctx_init_mthd[];
-extern struct nvc0_graph_init nvc0_grctx_init_902d[];
-extern struct nvc0_graph_init nvc0_grctx_init_9039[];
-extern struct nvc0_graph_init nvc0_grctx_init_90c0[];
-extern struct nvc0_graph_init nvc0_grctx_init_mthd_magic[];
-
-void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
-extern struct nouveau_oclass *nvc1_grctx_oclass;
-extern struct nvc0_graph_init nvc1_grctx_init_9097[];
-
-extern struct nouveau_oclass *nvc3_grctx_oclass;
-
-extern struct nouveau_oclass *nvc8_grctx_oclass;
-extern struct nvc0_graph_init nvc8_grctx_init_9197[];
-extern struct nvc0_graph_init nvc8_grctx_init_9297[];
-
-extern struct nouveau_oclass *nvd7_grctx_oclass;
-
-extern struct nouveau_oclass *nvd9_grctx_oclass;
-extern struct nvc0_graph_init nvd9_grctx_init_rop[];
-extern struct nvc0_graph_mthd nvd9_grctx_init_mthd[];
-
-void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
-extern struct nouveau_oclass *nve4_grctx_oclass;
-extern struct nvc0_graph_init nve4_grctx_init_unk46xx[];
-extern struct nvc0_graph_init nve4_grctx_init_unk47xx[];
-extern struct nvc0_graph_init nve4_grctx_init_unk58xx[];
-extern struct nvc0_graph_init nve4_grctx_init_unk80xx[];
-extern struct nvc0_graph_init nve4_grctx_init_unk90xx[];
-
-extern struct nouveau_oclass *nvf0_grctx_oclass;
-extern struct nvc0_graph_init nvf0_grctx_init_unk44xx[];
-extern struct nvc0_graph_init nvf0_grctx_init_unk5bxx[];
-extern struct nvc0_graph_init nvf0_grctx_init_unk60xx[];
-
-extern struct nouveau_oclass *nv108_grctx_oclass;
-
-#define mmio_data(s,a,p) do {                                                  \
-       info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
-       info->addr = info->buffer[info->buffer_nr++] + (s);                    \
-       info->data->size = (s);                                                \
-       info->data->align = (a);                                               \
-       info->data->access = (p);                                              \
-       info->data++;                                                          \
-} while(0)
-
-#define mmio_list(r,d,s,b) do {                                                \
-       info->mmio->addr = (r);                                                \
-       info->mmio->data = (d);                                                \
-       info->mmio->shift = (s);                                               \
-       info->mmio->buffer = (b);                                              \
-       info->mmio++;                                                          \
-       nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0));      \
-} while(0)
+/* register init value lists */
+
+extern const struct nvc0_graph_init nvc0_graph_init_main_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_fe_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_pri_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_rstr2d_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_pd_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_ds_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_scc_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_prop_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_setup_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_crstr_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_setup_1[];
+extern const struct nvc0_graph_init nvc0_graph_init_zcull_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_gpm_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvc0_graph_init_gcc_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_tpccs_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_tex_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_pe_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_l1c_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_wwdx_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_tpccs_1[];
+extern const struct nvc0_graph_init nvc0_graph_init_mpc_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_be_0[];
+extern const struct nvc0_graph_init nvc0_graph_init_fe_1[];
+extern const struct nvc0_graph_init nvc0_graph_init_pe_1[];
+
+extern const struct nvc0_graph_init nvc4_graph_init_ds_0[];
+extern const struct nvc0_graph_init nvc4_graph_init_tex_0[];
+extern const struct nvc0_graph_init nvc4_graph_init_sm_0[];
+
+extern const struct nvc0_graph_init nvc1_graph_init_gpc_unk_0[];
+extern const struct nvc0_graph_init nvc1_graph_init_setup_1[];
+
+extern const struct nvc0_graph_init nvd9_graph_init_pd_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_ds_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_prop_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_gpm_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvd9_graph_init_tex_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_sm_0[];
+extern const struct nvc0_graph_init nvd9_graph_init_fe_1[];
+
+extern const struct nvc0_graph_init nvd7_graph_init_pes_0[];
+extern const struct nvc0_graph_init nvd7_graph_init_wwdx_0[];
+extern const struct nvc0_graph_init nvd7_graph_init_cbm_0[];
+
+extern const struct nvc0_graph_init nve4_graph_init_main_0[];
+extern const struct nvc0_graph_init nve4_graph_init_tpccs_0[];
+extern const struct nvc0_graph_init nve4_graph_init_pe_0[];
+extern const struct nvc0_graph_init nve4_graph_init_be_0[];
+
+extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
+extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
+extern const struct nvc0_graph_init nvf0_graph_init_cwd_0[];
+extern const struct nvc0_graph_init nvf0_graph_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvf0_graph_init_sm_0[];
+
+extern const struct nvc0_graph_init nv108_graph_init_gpc_unk_0[];
+
 
 #endif
index bc4a469b86cb98538e8411f9e5d628a781e079d7..30cab0b2eba1efe4a2cfd4ec94f896d7b18869a8 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -39,94 +40,82 @@ nvc1_graph_sclass[] = {
 };
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-static struct nvc0_graph_init
-nvc1_graph_init_gpc[] = {
-       { 0x4184a0,   1, 0x04, 0x00000000 },
+const struct nvc0_graph_init
+nvc1_graph_init_gpc_unk_0[] = {
        { 0x418604,   1, 0x04, 0x00000000 },
        { 0x418680,   1, 0x04, 0x00000000 },
        { 0x418714,   1, 0x04, 0x00000000 },
        { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc1_graph_init_setup_1[] = {
        { 0x4188c8,   2, 0x04, 0x00000000 },
        { 0x4188d0,   1, 0x04, 0x00010000 },
        { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc1_graph_init_gpc_unk_1[] = {
        { 0x418d00,   1, 0x04, 0x00000000 },
        { 0x418f08,   1, 0x04, 0x00000000 },
        { 0x418e00,   1, 0x04, 0x00000003 },
        { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvc1_graph_init_tpc[] = {
-       { 0x419d08,   2, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
-       { 0x419ab0,   1, 0x04, 0x00000000 },
-       { 0x419ac8,   1, 0x04, 0x00000000 },
-       { 0x419ab8,   1, 0x04, 0x000000e7 },
-       { 0x419abc,   2, 0x04, 0x00000000 },
-       { 0x41980c,   2, 0x04, 0x00000000 },
+static const struct nvc0_graph_init
+nvc1_graph_init_pe_0[] = {
+       { 0x41980c,   1, 0x04, 0x00000010 },
+       { 0x419810,   1, 0x04, 0x00000000 },
        { 0x419814,   1, 0x04, 0x00000004 },
        { 0x419844,   1, 0x04, 0x00000000 },
        { 0x41984c,   1, 0x04, 0x00005bc5 },
        { 0x419850,   4, 0x04, 0x00000000 },
        { 0x419880,   1, 0x04, 0x00000002 },
-       { 0x419c98,   1, 0x04, 0x00000000 },
-       { 0x419ca8,   1, 0x04, 0x80000000 },
-       { 0x419cb4,   1, 0x04, 0x00000000 },
-       { 0x419cb8,   1, 0x04, 0x00008bf4 },
-       { 0x419cbc,   1, 0x04, 0x28137606 },
-       { 0x419cc0,   2, 0x04, 0x00000000 },
-       { 0x419bd4,   1, 0x04, 0x00800000 },
-       { 0x419bdc,   1, 0x04, 0x00000000 },
-       { 0x419d2c,   1, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
-       { 0x419e00,   1, 0x04, 0x00000000 },
-       { 0x419ea0,   1, 0x04, 0x00000000 },
-       { 0x419ea4,   1, 0x04, 0x00000100 },
-       { 0x419ea8,   1, 0x04, 0x00001100 },
-       { 0x419eac,   1, 0x04, 0x11100702 },
-       { 0x419eb0,   1, 0x04, 0x00000003 },
-       { 0x419eb4,   4, 0x04, 0x00000000 },
-       { 0x419ec8,   1, 0x04, 0x0e063818 },
-       { 0x419ecc,   1, 0x04, 0x0e060e06 },
-       { 0x419ed0,   1, 0x04, 0x00003818 },
-       { 0x419ed4,   1, 0x04, 0x011104f1 },
-       { 0x419edc,   1, 0x04, 0x00000000 },
-       { 0x419f00,   1, 0x04, 0x00000000 },
-       { 0x419f2c,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init *
-nvc1_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvc3_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvc1_graph_init_gpc,
-       nvc1_graph_init_tpc,
-       nvc0_graph_init_unk88xx,
-       nvc0_graph_tpc_0,
-       NULL
+static const struct nvc0_graph_pack
+nvc1_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvc0_graph_init_pd_0 },
+       { nvc4_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvc0_graph_init_prop_0 },
+       { nvc1_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvc0_graph_init_gpm_0 },
+       { nvc1_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvc4_graph_init_tex_0 },
+       { nvc1_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvc0_graph_init_wwdx_0 },
+       { nvc0_graph_init_tpccs_1 },
+       { nvc0_graph_init_mpc_0 },
+       { nvc4_graph_init_sm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       {}
 };
 
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 struct nouveau_oclass *
 nvc1_graph_oclass = &(struct nvc0_graph_oclass) {
        .base.handle = NV_ENGINE(GR, 0xc1),
@@ -138,7 +127,7 @@ nvc1_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvc1_grctx_oclass,
        .sclass = nvc1_graph_sclass,
-       .mmio = nvc1_graph_init_mmio,
+       .mmio = nvc1_graph_pack_mmio,
        .fecs.ucode = &nvc0_graph_fecs_ucode,
        .gpccs.ucode = &nvc0_graph_gpccs_ucode,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c
deleted file mode 100644 (file)
index d44b3b3..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2013 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs <bskeggs@redhat.com>
- */
-
-#include "nvc0.h"
-
-/*******************************************************************************
- * PGRAPH engine/subdev functions
- ******************************************************************************/
-
-struct nvc0_graph_init
-nvc3_graph_init_unk58xx[] = {
-       { 0x405844,   1, 0x04, 0x00ffffff },
-       { 0x405850,   1, 0x04, 0x00000000 },
-       { 0x405900,   1, 0x04, 0x00002834 },
-       { 0x405908,   1, 0x04, 0x00000000 },
-       {}
-};
-
-static struct nvc0_graph_init
-nvc3_graph_init_tpc[] = {
-       { 0x419d08,   2, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
-       { 0x419ab0,   1, 0x04, 0x00000000 },
-       { 0x419ac8,   1, 0x04, 0x00000000 },
-       { 0x419ab8,   1, 0x04, 0x000000e7 },
-       { 0x419abc,   2, 0x04, 0x00000000 },
-       { 0x41980c,   3, 0x04, 0x00000000 },
-       { 0x419844,   1, 0x04, 0x00000000 },
-       { 0x41984c,   1, 0x04, 0x00005bc5 },
-       { 0x419850,   4, 0x04, 0x00000000 },
-       { 0x419880,   1, 0x04, 0x00000002 },
-       { 0x419c98,   1, 0x04, 0x00000000 },
-       { 0x419ca8,   1, 0x04, 0x80000000 },
-       { 0x419cb4,   1, 0x04, 0x00000000 },
-       { 0x419cb8,   1, 0x04, 0x00008bf4 },
-       { 0x419cbc,   1, 0x04, 0x28137606 },
-       { 0x419cc0,   2, 0x04, 0x00000000 },
-       { 0x419bd4,   1, 0x04, 0x00800000 },
-       { 0x419bdc,   1, 0x04, 0x00000000 },
-       { 0x419d2c,   1, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
-       { 0x419e00,   1, 0x04, 0x00000000 },
-       { 0x419ea0,   1, 0x04, 0x00000000 },
-       { 0x419ea4,   1, 0x04, 0x00000100 },
-       { 0x419ea8,   1, 0x04, 0x00001100 },
-       { 0x419eac,   1, 0x04, 0x11100702 },
-       { 0x419eb0,   1, 0x04, 0x00000003 },
-       { 0x419eb4,   4, 0x04, 0x00000000 },
-       { 0x419ec8,   1, 0x04, 0x0e063818 },
-       { 0x419ecc,   1, 0x04, 0x0e060e06 },
-       { 0x419ed0,   1, 0x04, 0x00003818 },
-       { 0x419ed4,   1, 0x04, 0x011104f1 },
-       { 0x419edc,   1, 0x04, 0x00000000 },
-       { 0x419f00,   1, 0x04, 0x00000000 },
-       { 0x419f2c,   1, 0x04, 0x00000000 },
-       {}
-};
-
-static struct nvc0_graph_init *
-nvc3_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvc3_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvc0_graph_init_gpc,
-       nvc3_graph_init_tpc,
-       nvc0_graph_init_unk88xx,
-       nvc0_graph_tpc_0,
-       NULL
-};
-
-struct nouveau_oclass *
-nvc3_graph_oclass = &(struct nvc0_graph_oclass) {
-       .base.handle = NV_ENGINE(GR, 0xc3),
-       .base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nvc0_graph_ctor,
-               .dtor = nvc0_graph_dtor,
-               .init = nvc0_graph_init,
-               .fini = _nouveau_graph_fini,
-       },
-       .cclass = &nvc3_grctx_oclass,
-       .sclass = nvc0_graph_sclass,
-       .mmio = nvc3_graph_init_mmio,
-       .fecs.ucode = &nvc0_graph_fecs_ucode,
-       .gpccs.ucode = &nvc0_graph_gpccs_ucode,
-}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c
new file mode 100644 (file)
index 0000000..e82e70c
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+const struct nvc0_graph_init
+nvc4_graph_init_ds_0[] = {
+       { 0x405844,   1, 0x04, 0x00ffffff },
+       { 0x405850,   1, 0x04, 0x00000000 },
+       { 0x405900,   1, 0x04, 0x00002834 },
+       { 0x405908,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc4_graph_init_tex_0[] = {
+       { 0x419ab0,   1, 0x04, 0x00000000 },
+       { 0x419ac8,   1, 0x04, 0x00000000 },
+       { 0x419ab8,   1, 0x04, 0x000000e7 },
+       { 0x419abc,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvc4_graph_init_pe_0[] = {
+       { 0x41980c,   3, 0x04, 0x00000000 },
+       { 0x419844,   1, 0x04, 0x00000000 },
+       { 0x41984c,   1, 0x04, 0x00005bc5 },
+       { 0x419850,   4, 0x04, 0x00000000 },
+       { 0x419880,   1, 0x04, 0x00000002 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvc4_graph_init_sm_0[] = {
+       { 0x419e00,   1, 0x04, 0x00000000 },
+       { 0x419ea0,   1, 0x04, 0x00000000 },
+       { 0x419ea4,   1, 0x04, 0x00000100 },
+       { 0x419ea8,   1, 0x04, 0x00001100 },
+       { 0x419eac,   1, 0x04, 0x11100702 },
+       { 0x419eb0,   1, 0x04, 0x00000003 },
+       { 0x419eb4,   4, 0x04, 0x00000000 },
+       { 0x419ec8,   1, 0x04, 0x0e063818 },
+       { 0x419ecc,   1, 0x04, 0x0e060e06 },
+       { 0x419ed0,   1, 0x04, 0x00003818 },
+       { 0x419ed4,   1, 0x04, 0x011104f1 },
+       { 0x419edc,   1, 0x04, 0x00000000 },
+       { 0x419f00,   1, 0x04, 0x00000000 },
+       { 0x419f2c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nvc4_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvc0_graph_init_pd_0 },
+       { nvc4_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvc0_graph_init_prop_0 },
+       { nvc0_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc0_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvc0_graph_init_gpm_0 },
+       { nvc0_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvc4_graph_init_tex_0 },
+       { nvc4_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvc0_graph_init_wwdx_0 },
+       { nvc0_graph_init_tpccs_1 },
+       { nvc0_graph_init_mpc_0 },
+       { nvc4_graph_init_sm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+struct nouveau_oclass *
+nvc4_graph_oclass = &(struct nvc0_graph_oclass) {
+       .base.handle = NV_ENGINE(GR, 0xc3),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_ctor,
+               .dtor = nvc0_graph_dtor,
+               .init = nvc0_graph_init,
+               .fini = _nouveau_graph_fini,
+       },
+       .cclass = &nvc4_grctx_oclass,
+       .sclass = nvc0_graph_sclass,
+       .mmio = nvc4_graph_pack_mmio,
+       .fecs.ucode = &nvc0_graph_fecs_ucode,
+       .gpccs.ucode = &nvc0_graph_gpccs_ucode,
+}.base;
index 02845e5673147285e921ca7a2a639ae09b0cba7e..a6bf783e12563718ee9aec1be5fb8c204e55aa05 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -40,58 +41,11 @@ nvc8_graph_sclass[] = {
 };
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-static struct nvc0_graph_init
-nvc8_graph_init_gpc[] = {
-       { 0x4184a0,   1, 0x04, 0x00000000 },
-       { 0x418604,   1, 0x04, 0x00000000 },
-       { 0x418680,   1, 0x04, 0x00000000 },
-       { 0x418714,   1, 0x04, 0x80000000 },
-       { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
-       { 0x4188c8,   2, 0x04, 0x00000000 },
-       { 0x4188d0,   1, 0x04, 0x00010000 },
-       { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
-       { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418f08,   1, 0x04, 0x00000000 },
-       { 0x418e00,   1, 0x04, 0x00000050 },
-       { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
-       {}
-};
-
-static struct nvc0_graph_init
-nvc8_graph_init_tpc[] = {
-       { 0x419d08,   2, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
-       { 0x419ab0,   1, 0x04, 0x00000000 },
-       { 0x419ab8,   1, 0x04, 0x000000e7 },
-       { 0x419abc,   2, 0x04, 0x00000000 },
-       { 0x41980c,   3, 0x04, 0x00000000 },
-       { 0x419844,   1, 0x04, 0x00000000 },
-       { 0x41984c,   1, 0x04, 0x00005bc5 },
-       { 0x419850,   4, 0x04, 0x00000000 },
-       { 0x419c98,   1, 0x04, 0x00000000 },
-       { 0x419ca8,   1, 0x04, 0x80000000 },
-       { 0x419cb4,   1, 0x04, 0x00000000 },
-       { 0x419cb8,   1, 0x04, 0x00008bf4 },
-       { 0x419cbc,   1, 0x04, 0x28137606 },
-       { 0x419cc0,   2, 0x04, 0x00000000 },
-       { 0x419bd4,   1, 0x04, 0x00800000 },
-       { 0x419bdc,   1, 0x04, 0x00000000 },
-       { 0x419d2c,   1, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
+static const struct nvc0_graph_init
+nvc8_graph_init_sm_0[] = {
        { 0x419e00,   1, 0x04, 0x00000000 },
        { 0x419ea0,   1, 0x04, 0x00000000 },
        { 0x419ea4,   1, 0x04, 0x00000100 },
@@ -108,22 +62,42 @@ nvc8_graph_init_tpc[] = {
        {}
 };
 
-static struct nvc0_graph_init *
-nvc8_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvc0_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvc8_graph_init_gpc,
-       nvc8_graph_init_tpc,
-       nvc0_graph_init_unk88xx,
-       nvc0_graph_tpc_0,
-       NULL
+static const struct nvc0_graph_pack
+nvc8_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvc0_graph_init_pd_0 },
+       { nvc0_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvc0_graph_init_prop_0 },
+       { nvc0_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvc0_graph_init_gpm_0 },
+       { nvc0_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvc0_graph_init_tex_0 },
+       { nvc0_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvc0_graph_init_wwdx_0 },
+       { nvc0_graph_init_tpccs_1 },
+       { nvc0_graph_init_mpc_0 },
+       { nvc8_graph_init_sm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       { nvc0_graph_init_pe_1 },
+       {}
 };
 
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 struct nouveau_oclass *
 nvc8_graph_oclass = &(struct nvc0_graph_oclass) {
        .base.handle = NV_ENGINE(GR, 0xc8),
@@ -135,7 +109,7 @@ nvc8_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvc8_grctx_oclass,
        .sclass = nvc8_graph_sclass,
-       .mmio = nvc8_graph_init_mmio,
+       .mmio = nvc8_graph_pack_mmio,
        .fecs.ucode = &nvc0_graph_fecs_ucode,
        .gpccs.ucode = &nvc0_graph_gpccs_ucode,
 }.base;
index 5052d7ab4d72826e733e036e69aa1f9a7a914baa..2a6a94e2a0415e6aa19748e4aa461ab7061b2c00 100644 (file)
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+nvd7_graph_init_pe_0[] = {
+       { 0x41980c,   1, 0x04, 0x00000010 },
+       { 0x419844,   1, 0x04, 0x00000000 },
+       { 0x41984c,   1, 0x04, 0x00005bc8 },
+       { 0x419850,   3, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd7_graph_init_pes_0[] = {
+       { 0x41be04,   1, 0x04, 0x00000000 },
+       { 0x41be08,   1, 0x04, 0x00000004 },
+       { 0x41be0c,   1, 0x04, 0x00000000 },
+       { 0x41be10,   1, 0x04, 0x003b8bc7 },
+       { 0x41be14,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd7_graph_init_wwdx_0[] = {
+       { 0x41bfd4,   1, 0x04, 0x00800000 },
+       { 0x41bfdc,   1, 0x04, 0x00000000 },
+       { 0x41bff8,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd7_graph_init_cbm_0[] = {
+       { 0x41becc,   1, 0x04, 0x00000000 },
+       { 0x41bee8,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_pack
+nvd7_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvd9_graph_init_pd_0 },
+       { nvd9_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvd9_graph_init_prop_0 },
+       { nvc1_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvd9_graph_init_gpm_0 },
+       { nvd9_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvd9_graph_init_tex_0 },
+       { nvd7_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvc0_graph_init_mpc_0 },
+       { nvd9_graph_init_sm_0 },
+       { nvd7_graph_init_pes_0 },
+       { nvd7_graph_init_wwdx_0 },
+       { nvd7_graph_init_cbm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvd9_graph_init_fe_1 },
+       {}
+};
 
 /*******************************************************************************
  * PGRAPH engine/subdev functions
@@ -48,108 +119,6 @@ nvd7_graph_gpccs_ucode = {
        .data.size = sizeof(nvd7_grgpc_data),
 };
 
-static struct nvc0_graph_init
-nvd7_graph_init_gpc[] = {
-       { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x4184a0,   1, 0x04, 0x00000000 },
-       { 0x4184a4,   2, 0x04, 0x00000000 },
-       { 0x418604,   1, 0x04, 0x00000000 },
-       { 0x418680,   1, 0x04, 0x00000000 },
-       { 0x418714,   1, 0x04, 0x00000000 },
-       { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
-       { 0x4188c8,   2, 0x04, 0x00000000 },
-       { 0x4188d0,   1, 0x04, 0x00010000 },
-       { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c64,   1, 0x04, 0x00000000 },
-       { 0x418c68,   1, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
-       { 0x418cb4,   2, 0x04, 0x00000000 },
-       { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418d28,   1, 0x04, 0x00000000 },
-       { 0x418f00,   1, 0x04, 0x00000000 },
-       { 0x418f08,   1, 0x04, 0x00000000 },
-       { 0x418f20,   2, 0x04, 0x00000000 },
-       { 0x418e00,   1, 0x04, 0x00000003 },
-       { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x418e1c,   1, 0x04, 0x00000000 },
-       { 0x418e20,   1, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
-       {}
-};
-
-static struct nvc0_graph_init
-nvd7_graph_init_tpc[] = {
-       { 0x419d08,   2, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
-       { 0x419ab0,   1, 0x04, 0x00000000 },
-       { 0x419ac8,   1, 0x04, 0x00000000 },
-       { 0x419ab8,   1, 0x04, 0x000000e7 },
-       { 0x419abc,   2, 0x04, 0x00000000 },
-       { 0x419ab4,   1, 0x04, 0x00000000 },
-       { 0x41980c,   1, 0x04, 0x00000010 },
-       { 0x419844,   1, 0x04, 0x00000000 },
-       { 0x41984c,   1, 0x04, 0x00005bc8 },
-       { 0x419850,   2, 0x04, 0x00000000 },
-       { 0x419c98,   1, 0x04, 0x00000000 },
-       { 0x419ca8,   1, 0x04, 0x80000000 },
-       { 0x419cb4,   1, 0x04, 0x00000000 },
-       { 0x419cb8,   1, 0x04, 0x00008bf4 },
-       { 0x419cbc,   1, 0x04, 0x28137606 },
-       { 0x419cc0,   2, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
-       { 0x419e00,   1, 0x04, 0x00000000 },
-       { 0x419ea0,   1, 0x04, 0x00000000 },
-       { 0x419ea4,   1, 0x04, 0x00000100 },
-       { 0x419ea8,   1, 0x04, 0x02001100 },
-       { 0x419eac,   1, 0x04, 0x11100702 },
-       { 0x419eb0,   1, 0x04, 0x00000003 },
-       { 0x419eb4,   4, 0x04, 0x00000000 },
-       { 0x419ec8,   1, 0x04, 0x0e063818 },
-       { 0x419ecc,   1, 0x04, 0x0e060e06 },
-       { 0x419ed0,   1, 0x04, 0x00003818 },
-       { 0x419ed4,   1, 0x04, 0x011104f1 },
-       { 0x419edc,   1, 0x04, 0x00000000 },
-       { 0x419f00,   1, 0x04, 0x00000000 },
-       { 0x419f2c,   1, 0x04, 0x00000000 },
-       {}
-};
-
-static struct nvc0_graph_init
-nvd7_graph_init_tpc_0[] = {
-       { 0x40402c,   1, 0x04, 0x00000000 },
-       { 0x4040f0,   1, 0x04, 0x00000000 },
-       { 0x404174,   1, 0x04, 0x00000000 },
-       { 0x503018,   1, 0x04, 0x00000001 },
-       {}
-};
-
-static struct nvc0_graph_init *
-nvd7_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvd9_graph_init_unk64xx,
-       nvd9_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvd7_graph_init_gpc,
-       nvd7_graph_init_tpc,
-       nve4_graph_init_unk,
-       nvc0_graph_init_unk88xx,
-       nvd7_graph_init_tpc_0,
-       NULL
-};
-
 struct nouveau_oclass *
 nvd7_graph_oclass = &(struct nvc0_graph_oclass) {
        .base.handle = NV_ENGINE(GR, 0xd7),
@@ -161,7 +130,7 @@ nvd7_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvd7_grctx_oclass,
        .sclass = nvc8_graph_sclass,
-       .mmio = nvd7_graph_init_mmio,
+       .mmio = nvd7_graph_pack_mmio,
        .fecs.ucode = &nvd7_graph_fecs_ucode,
        .gpccs.ucode = &nvd7_graph_gpccs_ucode,
 }.base;
index 652098e0df3f618129278a5f0193bf0351f4bb6b..00fdf202fb92e633e188092b59f0c754c9f3c402 100644 (file)
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-struct nvc0_graph_init
-nvd9_graph_init_unk64xx[] = {
+const struct nvc0_graph_init
+nvd9_graph_init_pd_0[] = {
+       { 0x406024,   1, 0x04, 0x00000000 },
        { 0x4064f0,   3, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvd9_graph_init_unk58xx[] = {
+const struct nvc0_graph_init
+nvd9_graph_init_ds_0[] = {
        { 0x405844,   1, 0x04, 0x00ffffff },
        { 0x405850,   1, 0x04, 0x00000000 },
        { 0x405900,   1, 0x04, 0x00002834 },
        { 0x405908,   1, 0x04, 0x00000000 },
-       { 0x405928,   1, 0x04, 0x00000000 },
-       { 0x40592c,   1, 0x04, 0x00000000 },
+       { 0x405928,   2, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_graph_init_gpc[] = {
+const struct nvc0_graph_init
+nvd9_graph_init_prop_0[] = {
        { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x4184a0,   1, 0x04, 0x00000000 },
-       { 0x4184a4,   2, 0x04, 0x00000000 },
-       { 0x418604,   1, 0x04, 0x00000000 },
-       { 0x418680,   1, 0x04, 0x00000000 },
-       { 0x418714,   1, 0x04, 0x00000000 },
-       { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
-       { 0x4188c8,   2, 0x04, 0x00000000 },
-       { 0x4188d0,   1, 0x04, 0x00010000 },
-       { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
+       { 0x4184a0,   3, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_graph_init_gpm_0[] = {
        { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c64,   1, 0x04, 0x00000000 },
-       { 0x418c68,   1, 0x04, 0x00000000 },
+       { 0x418c64,   2, 0x04, 0x00000000 },
        { 0x418c88,   1, 0x04, 0x00000000 },
        { 0x418cb4,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_graph_init_gpc_unk_1[] = {
        { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418d28,   1, 0x04, 0x00000000 },
-       { 0x418d2c,   1, 0x04, 0x00000000 },
+       { 0x418d28,   2, 0x04, 0x00000000 },
        { 0x418f00,   1, 0x04, 0x00000000 },
        { 0x418f08,   1, 0x04, 0x00000000 },
        { 0x418f20,   2, 0x04, 0x00000000 },
        { 0x418e00,   1, 0x04, 0x00000003 },
        { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x418e1c,   1, 0x04, 0x00000000 },
-       { 0x418e20,   1, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
+       { 0x418e1c,   2, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvd9_graph_init_tpc[] = {
-       { 0x419d08,   2, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
+const struct nvc0_graph_init
+nvd9_graph_init_tex_0[] = {
        { 0x419ab0,   1, 0x04, 0x00000000 },
        { 0x419ac8,   1, 0x04, 0x00000000 },
        { 0x419ab8,   1, 0x04, 0x000000e7 },
        { 0x419abc,   2, 0x04, 0x00000000 },
        { 0x419ab4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_graph_init_pe_0[] = {
        { 0x41980c,   1, 0x04, 0x00000010 },
        { 0x419810,   1, 0x04, 0x00000000 },
        { 0x419814,   1, 0x04, 0x00000004 },
@@ -100,20 +94,26 @@ nvd9_graph_init_tpc[] = {
        { 0x41984c,   1, 0x04, 0x0000a918 },
        { 0x419850,   4, 0x04, 0x00000000 },
        { 0x419880,   1, 0x04, 0x00000002 },
-       { 0x419c98,   1, 0x04, 0x00000000 },
-       { 0x419ca8,   1, 0x04, 0x80000000 },
-       { 0x419cb4,   1, 0x04, 0x00000000 },
-       { 0x419cb8,   1, 0x04, 0x00008bf4 },
-       { 0x419cbc,   1, 0x04, 0x28137606 },
-       { 0x419cc0,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_graph_init_wwdx_0[] = {
        { 0x419bd4,   1, 0x04, 0x00800000 },
        { 0x419bdc,   1, 0x04, 0x00000000 },
-       { 0x419bf8,   1, 0x04, 0x00000000 },
-       { 0x419bfc,   1, 0x04, 0x00000000 },
+       { 0x419bf8,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvd9_graph_init_tpccs_1[] = {
        { 0x419d2c,   1, 0x04, 0x00000000 },
-       { 0x419d48,   1, 0x04, 0x00000000 },
-       { 0x419d4c,   1, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
+       { 0x419d48,   2, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvd9_graph_init_sm_0[] = {
        { 0x419e00,   1, 0x04, 0x00000000 },
        { 0x419ea0,   1, 0x04, 0x00000000 },
        { 0x419ea4,   1, 0x04, 0x00000100 },
@@ -131,23 +131,49 @@ nvd9_graph_init_tpc[] = {
        {}
 };
 
-static struct nvc0_graph_init *
-nvd9_graph_init_mmio[] = {
-       nvc0_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvd9_graph_init_unk64xx,
-       nvd9_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvd9_graph_init_gpc,
-       nvd9_graph_init_tpc,
-       nvc0_graph_init_unk88xx,
-       nvc0_graph_tpc_0,
-       NULL
+const struct nvc0_graph_init
+nvd9_graph_init_fe_1[] = {
+       { 0x40402c,   1, 0x04, 0x00000000 },
+       { 0x4040f0,   1, 0x04, 0x00000000 },
+       { 0x404174,   1, 0x04, 0x00000000 },
+       {}
 };
 
+static const struct nvc0_graph_pack
+nvd9_graph_pack_mmio[] = {
+       { nvc0_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvd9_graph_init_pd_0 },
+       { nvd9_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvd9_graph_init_prop_0 },
+       { nvc1_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvd9_graph_init_gpm_0 },
+       { nvd9_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nvc0_graph_init_tpccs_0 },
+       { nvd9_graph_init_tex_0 },
+       { nvd9_graph_init_pe_0 },
+       { nvc0_graph_init_l1c_0 },
+       { nvd9_graph_init_wwdx_0 },
+       { nvd9_graph_init_tpccs_1 },
+       { nvc0_graph_init_mpc_0 },
+       { nvd9_graph_init_sm_0 },
+       { nvc0_graph_init_be_0 },
+       { nvd9_graph_init_fe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 struct nouveau_oclass *
 nvd9_graph_oclass = &(struct nvc0_graph_oclass) {
        .base.handle = NV_ENGINE(GR, 0xd9),
@@ -159,7 +185,7 @@ nvd9_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvd9_grctx_oclass,
        .sclass = nvc8_graph_sclass,
-       .mmio = nvd9_graph_init_mmio,
+       .mmio = nvd9_graph_pack_mmio,
        .fecs.ucode = &nvc0_graph_fecs_ucode,
        .gpccs.ucode = &nvc0_graph_gpccs_ucode,
 }.base;
index 05ec09c8851758b63a7f46bf09596f535008736c..f7c0112171750253214a111931e7ffe3bb9c1c81 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -38,11 +39,11 @@ nve4_graph_sclass[] = {
 };
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-struct nvc0_graph_init
-nve4_graph_init_regs[] = {
+const struct nvc0_graph_init
+nve4_graph_init_main_0[] = {
        { 0x400080,   1, 0x04, 0x003083c2 },
        { 0x400088,   1, 0x04, 0x0001ffe7 },
        { 0x40008c,   1, 0x04, 0x00000000 },
@@ -57,81 +58,59 @@ nve4_graph_init_regs[] = {
        {}
 };
 
-static struct nvc0_graph_init
-nve4_graph_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nve4_graph_init_ds_0[] = {
        { 0x405844,   1, 0x04, 0x00ffffff },
        { 0x405850,   1, 0x04, 0x00000000 },
        { 0x405900,   1, 0x04, 0x0000ff34 },
        { 0x405908,   1, 0x04, 0x00000000 },
-       { 0x405928,   1, 0x04, 0x00000000 },
-       { 0x40592c,   1, 0x04, 0x00000000 },
+       { 0x405928,   2, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_graph_init_unk70xx[] = {
+static const struct nvc0_graph_init
+nve4_graph_init_sked_0[] = {
        { 0x407010,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nve4_graph_init_unk5bxx[] = {
+static const struct nvc0_graph_init
+nve4_graph_init_cwd_0[] = {
        { 0x405b50,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_graph_init_gpc[] = {
-       { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x4184a0,   1, 0x04, 0x00000000 },
-       { 0x4184a4,   2, 0x04, 0x00000000 },
-       { 0x418604,   1, 0x04, 0x00000000 },
-       { 0x418680,   1, 0x04, 0x00000000 },
-       { 0x418714,   1, 0x04, 0x00000000 },
-       { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
-       { 0x4188c8,   2, 0x04, 0x00000000 },
-       { 0x4188d0,   1, 0x04, 0x00010000 },
-       { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c64,   1, 0x04, 0x00000000 },
-       { 0x418c68,   1, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
-       { 0x418cb4,   2, 0x04, 0x00000000 },
+static const struct nvc0_graph_init
+nve4_graph_init_gpc_unk_1[] = {
        { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418d28,   1, 0x04, 0x00000000 },
-       { 0x418d2c,   1, 0x04, 0x00000000 },
+       { 0x418d28,   2, 0x04, 0x00000000 },
        { 0x418f00,   1, 0x04, 0x00000000 },
        { 0x418f08,   1, 0x04, 0x00000000 },
        { 0x418f20,   2, 0x04, 0x00000000 },
        { 0x418e00,   1, 0x04, 0x00000060 },
        { 0x418e08,   1, 0x04, 0x00000000 },
-       { 0x418e1c,   1, 0x04, 0x00000000 },
-       { 0x418e20,   1, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
+       { 0x418e1c,   2, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nve4_graph_init_tpc[] = {
+const struct nvc0_graph_init
+nve4_graph_init_tpccs_0[] = {
        { 0x419d0c,   1, 0x04, 0x00000000 },
        { 0x419d10,   1, 0x04, 0x00000014 },
-       { 0x419ab0,   1, 0x04, 0x00000000 },
-       { 0x419ac8,   1, 0x04, 0x00000000 },
-       { 0x419ab8,   1, 0x04, 0x000000e7 },
-       { 0x419abc,   2, 0x04, 0x00000000 },
-       { 0x419ab4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nve4_graph_init_pe_0[] = {
        { 0x41980c,   1, 0x04, 0x00000010 },
        { 0x419844,   1, 0x04, 0x00000000 },
        { 0x419850,   1, 0x04, 0x00000004 },
        { 0x419854,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_graph_init_l1c_0[] = {
        { 0x419c98,   1, 0x04, 0x00000000 },
        { 0x419ca8,   1, 0x04, 0x00000000 },
        { 0x419cb0,   1, 0x04, 0x01000000 },
@@ -141,39 +120,25 @@ nve4_graph_init_tpc[] = {
        { 0x419cbc,   1, 0x04, 0x28137646 },
        { 0x419cc0,   2, 0x04, 0x00000000 },
        { 0x419c80,   1, 0x04, 0x00020232 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nve4_graph_init_sm_0[] = {
        { 0x419e00,   1, 0x04, 0x00000000 },
        { 0x419ea0,   1, 0x04, 0x00000000 },
        { 0x419ee4,   1, 0x04, 0x00000000 },
        { 0x419ea4,   1, 0x04, 0x00000100 },
        { 0x419ea8,   1, 0x04, 0x00000000 },
-       { 0x419eb4,   1, 0x04, 0x00000000 },
-       { 0x419eb8,   3, 0x04, 0x00000000 },
+       { 0x419eb4,   4, 0x04, 0x00000000 },
        { 0x419edc,   1, 0x04, 0x00000000 },
        { 0x419f00,   1, 0x04, 0x00000000 },
        { 0x419f74,   1, 0x04, 0x00000555 },
        {}
 };
 
-struct nvc0_graph_init
-nve4_graph_init_unk[] = {
-       { 0x41be04,   1, 0x04, 0x00000000 },
-       { 0x41be08,   1, 0x04, 0x00000004 },
-       { 0x41be0c,   1, 0x04, 0x00000000 },
-       { 0x41be10,   1, 0x04, 0x003b8bc7 },
-       { 0x41be14,   2, 0x04, 0x00000000 },
-       { 0x41bfd4,   1, 0x04, 0x00800000 },
-       { 0x41bfdc,   1, 0x04, 0x00000000 },
-       { 0x41bff8,   1, 0x04, 0x00000000 },
-       { 0x41bffc,   1, 0x04, 0x00000000 },
-       { 0x41becc,   1, 0x04, 0x00000000 },
-       { 0x41bee8,   1, 0x04, 0x00000000 },
-       { 0x41beec,   1, 0x04, 0x00000000 },
-       {}
-};
-
-struct nvc0_graph_init
-nve4_graph_init_unk88xx[] = {
+const struct nvc0_graph_init
+nve4_graph_init_be_0[] = {
        { 0x40880c,   1, 0x04, 0x00000000 },
        { 0x408850,   1, 0x04, 0x00000004 },
        { 0x408910,   9, 0x04, 0x00000000 },
@@ -186,6 +151,67 @@ nve4_graph_init_unk88xx[] = {
        {}
 };
 
+static const struct nvc0_graph_pack
+nve4_graph_pack_mmio[] = {
+       { nve4_graph_init_main_0 },
+       { nvc0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvd9_graph_init_pd_0 },
+       { nve4_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nve4_graph_init_sked_0 },
+       { nve4_graph_init_cwd_0 },
+       { nvd9_graph_init_prop_0 },
+       { nvc1_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvd9_graph_init_gpm_0 },
+       { nve4_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nve4_graph_init_tpccs_0 },
+       { nvd9_graph_init_tex_0 },
+       { nve4_graph_init_pe_0 },
+       { nve4_graph_init_l1c_0 },
+       { nvc0_graph_init_mpc_0 },
+       { nve4_graph_init_sm_0 },
+       { nvd7_graph_init_pes_0 },
+       { nvd7_graph_init_wwdx_0 },
+       { nvd7_graph_init_cbm_0 },
+       { nve4_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static int
+nve4_graph_fini(struct nouveau_object *object, bool suspend)
+{
+       struct nvc0_graph_priv *priv = (void *)object;
+
+       /*XXX: this is a nasty hack to power on gr on certain boards
+        *     where it's disabled by therm, somehow.  ideally it'd
+        *     be nice to know when we should be doing this, and why,
+        *     but, it's yet to be determined.  for now we test for
+        *     the particular mmio error that occurs in the situation,
+        *     and then bash therm in the way nvidia do.
+        */
+       nv_mask(priv, 0x000200, 0x08001000, 0x08001000);
+       nv_rd32(priv, 0x000200);
+       if (nv_rd32(priv, 0x400700) == 0xbadf1000) {
+               nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
+               nv_rd32(priv, 0x000200);
+               nv_mask(priv, 0x020004, 0xc0000000, 0x40000000);
+       }
+
+       return nouveau_graph_fini(&priv->base, suspend);
+}
+
 int
 nve4_graph_init(struct nouveau_object *object)
 {
@@ -210,8 +236,7 @@ nve4_graph_init(struct nouveau_object *object)
        nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
        nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
 
-       for (i = 0; oclass->mmio[i]; i++)
-               nvc0_graph_mmio(priv, oclass->mmio[i]);
+       nvc0_graph_mmio(priv, oclass->mmio);
 
        nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
 
@@ -298,25 +323,6 @@ nve4_graph_init(struct nouveau_object *object)
        return nvc0_graph_init_ctxctl(priv);
 }
 
-static struct nvc0_graph_init *
-nve4_graph_init_mmio[] = {
-       nve4_graph_init_regs,
-       nvc0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvd9_graph_init_unk64xx,
-       nve4_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nve4_graph_init_unk70xx,
-       nve4_graph_init_unk5bxx,
-       nve4_graph_init_gpc,
-       nve4_graph_init_tpc,
-       nve4_graph_init_unk,
-       nve4_graph_init_unk88xx,
-       NULL
-};
-
 #include "fuc/hubnve0.fuc.h"
 
 static struct nvc0_graph_ucode
@@ -344,11 +350,11 @@ nve4_graph_oclass = &(struct nvc0_graph_oclass) {
                .ctor = nvc0_graph_ctor,
                .dtor = nvc0_graph_dtor,
                .init = nve4_graph_init,
-               .fini = _nouveau_graph_fini,
+               .fini = nve4_graph_fini,
        },
        .cclass = &nve4_grctx_oclass,
        .sclass = nve4_graph_sclass,
-       .mmio = nve4_graph_init_mmio,
+       .mmio = nve4_graph_pack_mmio,
        .fecs.ucode = &nve4_graph_fecs_ucode,
        .gpccs.ucode = &nve4_graph_gpccs_ucode,
 }.base;
index b1acb9939d95cfe460cea8e9aa2475d85256c20f..c96762122b9b40a45f1abc05fa670879e31f9dc2 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nvc0.h"
+#include "ctxnvc0.h"
 
 /*******************************************************************************
  * Graphics object classes
@@ -38,86 +39,57 @@ nvf0_graph_sclass[] = {
 };
 
 /*******************************************************************************
- * PGRAPH engine/subdev functions
+ * PGRAPH register lists
  ******************************************************************************/
 
-struct nvc0_graph_init
-nvf0_graph_init_unk40xx[] = {
+const struct nvc0_graph_init
+nvf0_graph_init_fe_0[] = {
        { 0x40415c,   1, 0x04, 0x00000000 },
        { 0x404170,   1, 0x04, 0x00000000 },
        { 0x4041b4,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_graph_init_unk58xx[] = {
+static const struct nvc0_graph_init
+nvf0_graph_init_ds_0[] = {
        { 0x405844,   1, 0x04, 0x00ffffff },
        { 0x405850,   1, 0x04, 0x00000000 },
        { 0x405900,   1, 0x04, 0x0000ff00 },
        { 0x405908,   1, 0x04, 0x00000000 },
-       { 0x405928,   1, 0x04, 0x00000000 },
-       { 0x40592c,   1, 0x04, 0x00000000 },
+       { 0x405928,   2, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvf0_graph_init_unk70xx[] = {
+const struct nvc0_graph_init
+nvf0_graph_init_sked_0[] = {
        { 0x407010,   1, 0x04, 0x00000000 },
        { 0x407040,   1, 0x04, 0x80440424 },
        { 0x407048,   1, 0x04, 0x0000000a },
        {}
 };
 
-struct nvc0_graph_init
-nvf0_graph_init_unk5bxx[] = {
+const struct nvc0_graph_init
+nvf0_graph_init_cwd_0[] = {
        { 0x405b44,   1, 0x04, 0x00000000 },
        { 0x405b50,   1, 0x04, 0x00000000 },
        {}
 };
 
-static struct nvc0_graph_init
-nvf0_graph_init_gpc[] = {
-       { 0x418408,   1, 0x04, 0x00000000 },
-       { 0x4184a0,   1, 0x04, 0x00000000 },
-       { 0x4184a4,   2, 0x04, 0x00000000 },
-       { 0x418604,   1, 0x04, 0x00000000 },
-       { 0x418680,   1, 0x04, 0x00000000 },
-       { 0x418714,   1, 0x04, 0x00000000 },
-       { 0x418384,   1, 0x04, 0x00000000 },
-       { 0x418814,   3, 0x04, 0x00000000 },
-       { 0x418b04,   1, 0x04, 0x00000000 },
-       { 0x4188c8,   2, 0x04, 0x00000000 },
-       { 0x4188d0,   1, 0x04, 0x00010000 },
-       { 0x4188d4,   1, 0x04, 0x00000001 },
-       { 0x418910,   1, 0x04, 0x00010001 },
-       { 0x418914,   1, 0x04, 0x00000301 },
-       { 0x418918,   1, 0x04, 0x00800000 },
-       { 0x418980,   1, 0x04, 0x77777770 },
-       { 0x418984,   3, 0x04, 0x77777777 },
-       { 0x418c04,   1, 0x04, 0x00000000 },
-       { 0x418c64,   1, 0x04, 0x00000000 },
-       { 0x418c68,   1, 0x04, 0x00000000 },
-       { 0x418c88,   1, 0x04, 0x00000000 },
-       { 0x418cb4,   2, 0x04, 0x00000000 },
+const struct nvc0_graph_init
+nvf0_graph_init_gpc_unk_1[] = {
        { 0x418d00,   1, 0x04, 0x00000000 },
-       { 0x418d28,   1, 0x04, 0x00000000 },
-       { 0x418d2c,   1, 0x04, 0x00000000 },
+       { 0x418d28,   2, 0x04, 0x00000000 },
        { 0x418f00,   1, 0x04, 0x00000400 },
        { 0x418f08,   1, 0x04, 0x00000000 },
-       { 0x418f20,   1, 0x04, 0x00000000 },
-       { 0x418f24,   1, 0x04, 0x00000000 },
+       { 0x418f20,   2, 0x04, 0x00000000 },
        { 0x418e00,   1, 0x04, 0x00000000 },
        { 0x418e08,   1, 0x04, 0x00000000 },
        { 0x418e1c,   2, 0x04, 0x00000000 },
-       { 0x41900c,   1, 0x04, 0x00000000 },
-       { 0x419018,   1, 0x04, 0x00000000 },
        {}
 };
 
-struct nvc0_graph_init
-nvf0_graph_init_tpc[] = {
-       { 0x419d0c,   1, 0x04, 0x00000000 },
-       { 0x419d10,   1, 0x04, 0x00000014 },
+static const struct nvc0_graph_init
+nvf0_graph_init_tex_0[] = {
        { 0x419ab0,   1, 0x04, 0x00000000 },
        { 0x419ac8,   1, 0x04, 0x00000000 },
        { 0x419ab8,   1, 0x04, 0x000000e7 },
@@ -125,10 +97,11 @@ nvf0_graph_init_tpc[] = {
        { 0x419abc,   2, 0x04, 0x00000000 },
        { 0x419ab4,   1, 0x04, 0x00000000 },
        { 0x419aa8,   2, 0x04, 0x00000000 },
-       { 0x41980c,   1, 0x04, 0x00000010 },
-       { 0x419844,   1, 0x04, 0x00000000 },
-       { 0x419850,   1, 0x04, 0x00000004 },
-       { 0x419854,   2, 0x04, 0x00000000 },
+       {}
+};
+
+static const struct nvc0_graph_init
+nvf0_graph_init_l1c_0[] = {
        { 0x419c98,   1, 0x04, 0x00000000 },
        { 0x419ca8,   1, 0x04, 0x00000000 },
        { 0x419cb0,   1, 0x04, 0x01000000 },
@@ -139,7 +112,11 @@ nvf0_graph_init_tpc[] = {
        { 0x419cc0,   2, 0x04, 0x00000000 },
        { 0x419c80,   1, 0x04, 0x00020230 },
        { 0x419ccc,   2, 0x04, 0x00000000 },
-       { 0x419c0c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+const struct nvc0_graph_init
+nvf0_graph_init_sm_0[] = {
        { 0x419e00,   1, 0x04, 0x00000080 },
        { 0x419ea0,   1, 0x04, 0x00000000 },
        { 0x419ee4,   1, 0x04, 0x00000000 },
@@ -155,6 +132,44 @@ nvf0_graph_init_tpc[] = {
        {}
 };
 
+static const struct nvc0_graph_pack
+nvf0_graph_pack_mmio[] = {
+       { nve4_graph_init_main_0 },
+       { nvf0_graph_init_fe_0 },
+       { nvc0_graph_init_pri_0 },
+       { nvc0_graph_init_rstr2d_0 },
+       { nvd9_graph_init_pd_0 },
+       { nvf0_graph_init_ds_0 },
+       { nvc0_graph_init_scc_0 },
+       { nvf0_graph_init_sked_0 },
+       { nvf0_graph_init_cwd_0 },
+       { nvd9_graph_init_prop_0 },
+       { nvc1_graph_init_gpc_unk_0 },
+       { nvc0_graph_init_setup_0 },
+       { nvc0_graph_init_crstr_0 },
+       { nvc1_graph_init_setup_1 },
+       { nvc0_graph_init_zcull_0 },
+       { nvd9_graph_init_gpm_0 },
+       { nvf0_graph_init_gpc_unk_1 },
+       { nvc0_graph_init_gcc_0 },
+       { nve4_graph_init_tpccs_0 },
+       { nvf0_graph_init_tex_0 },
+       { nve4_graph_init_pe_0 },
+       { nvf0_graph_init_l1c_0 },
+       { nvc0_graph_init_mpc_0 },
+       { nvf0_graph_init_sm_0 },
+       { nvd7_graph_init_pes_0 },
+       { nvd7_graph_init_wwdx_0 },
+       { nvd7_graph_init_cbm_0 },
+       { nve4_graph_init_be_0 },
+       { nvc0_graph_init_fe_1 },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
 static int
 nvf0_graph_fini(struct nouveau_object *object, bool suspend)
 {
@@ -192,25 +207,6 @@ nvf0_graph_fini(struct nouveau_object *object, bool suspend)
        return nouveau_graph_fini(&priv->base, suspend);
 }
 
-static struct nvc0_graph_init *
-nvf0_graph_init_mmio[] = {
-       nve4_graph_init_regs,
-       nvf0_graph_init_unk40xx,
-       nvc0_graph_init_unk44xx,
-       nvc0_graph_init_unk78xx,
-       nvc0_graph_init_unk60xx,
-       nvd9_graph_init_unk64xx,
-       nvf0_graph_init_unk58xx,
-       nvc0_graph_init_unk80xx,
-       nvf0_graph_init_unk70xx,
-       nvf0_graph_init_unk5bxx,
-       nvf0_graph_init_gpc,
-       nvf0_graph_init_tpc,
-       nve4_graph_init_unk,
-       nve4_graph_init_unk88xx,
-       NULL
-};
-
 #include "fuc/hubnvf0.fuc.h"
 
 static struct nvc0_graph_ucode
@@ -242,7 +238,7 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
        },
        .cclass = &nvf0_grctx_oclass,
        .sclass =  nvf0_graph_sclass,
-       .mmio = nvf0_graph_init_mmio,
+       .mmio = nvf0_graph_pack_mmio,
        .fecs.ucode = &nvf0_graph_fecs_ucode,
        .gpccs.ucode = &nvf0_graph_gpccs_ucode,
 }.base;
index 5f6ede7c48928a799e3a2084371e5bb86a2388d4..92384759d2f55aaa3205b191e7d57f5efe10754f 100644 (file)
@@ -112,7 +112,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)
                snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
                         xtensa->addr >> 12);
 
-               ret = request_firmware(&fw, name, &device->pdev->dev);
+               ret = request_firmware(&fw, name, nv_device_base(device));
                if (ret) {
                        nv_warn(xtensa, "unable to load firmware %s\n", name);
                        return ret;
index e71a4325e670f69c4fce0893b973760a9522185a..9c0cd73462d953971159f94c0d643381662215bd 100644 (file)
@@ -258,6 +258,7 @@ struct nv04_display_scanoutpos {
  * 9070: NVD0_DISP
  * 9170: NVE0_DISP
  * 9270: NVF0_DISP
+ * 9470: GM107_DISP
  */
 
 #define NV50_DISP_CLASS                                              0x00005070
@@ -268,6 +269,7 @@ struct nv04_display_scanoutpos {
 #define NVD0_DISP_CLASS                                              0x00009070
 #define NVE0_DISP_CLASS                                              0x00009170
 #define NVF0_DISP_CLASS                                              0x00009270
+#define GM107_DISP_CLASS                                             0x00009470
 
 #define NV50_DISP_MTHD                                               0x00000000
 #define NV50_DISP_MTHD_HEAD                                          0x00000003
@@ -342,6 +344,7 @@ struct nv50_display_class {
  * 907a: NVD0_DISP_CURS
  * 917a: NVE0_DISP_CURS
  * 927a: NVF0_DISP_CURS
+ * 947a: GM107_DISP_CURS
  */
 
 #define NV50_DISP_CURS_CLASS                                         0x0000507a
@@ -352,6 +355,7 @@ struct nv50_display_class {
 #define NVD0_DISP_CURS_CLASS                                         0x0000907a
 #define NVE0_DISP_CURS_CLASS                                         0x0000917a
 #define NVF0_DISP_CURS_CLASS                                         0x0000927a
+#define GM107_DISP_CURS_CLASS                                        0x0000947a
 
 struct nv50_display_curs_class {
        u32 head;
@@ -365,6 +369,7 @@ struct nv50_display_curs_class {
  * 907b: NVD0_DISP_OIMM
  * 917b: NVE0_DISP_OIMM
  * 927b: NVE0_DISP_OIMM
+ * 947b: GM107_DISP_OIMM
  */
 
 #define NV50_DISP_OIMM_CLASS                                         0x0000507b
@@ -375,6 +380,7 @@ struct nv50_display_curs_class {
 #define NVD0_DISP_OIMM_CLASS                                         0x0000907b
 #define NVE0_DISP_OIMM_CLASS                                         0x0000917b
 #define NVF0_DISP_OIMM_CLASS                                         0x0000927b
+#define GM107_DISP_OIMM_CLASS                                        0x0000947b
 
 struct nv50_display_oimm_class {
        u32 head;
@@ -388,6 +394,7 @@ struct nv50_display_oimm_class {
  * 907c: NVD0_DISP_SYNC
  * 917c: NVE0_DISP_SYNC
  * 927c: NVF0_DISP_SYNC
+ * 947c: GM107_DISP_SYNC
  */
 
 #define NV50_DISP_SYNC_CLASS                                         0x0000507c
@@ -398,6 +405,7 @@ struct nv50_display_oimm_class {
 #define NVD0_DISP_SYNC_CLASS                                         0x0000907c
 #define NVE0_DISP_SYNC_CLASS                                         0x0000917c
 #define NVF0_DISP_SYNC_CLASS                                         0x0000927c
+#define GM107_DISP_SYNC_CLASS                                        0x0000947c
 
 struct nv50_display_sync_class {
        u32 pushbuf;
@@ -412,6 +420,7 @@ struct nv50_display_sync_class {
  * 907d: NVD0_DISP_MAST
  * 917d: NVE0_DISP_MAST
  * 927d: NVF0_DISP_MAST
+ * 947d: GM107_DISP_MAST
  */
 
 #define NV50_DISP_MAST_CLASS                                         0x0000507d
@@ -422,6 +431,7 @@ struct nv50_display_sync_class {
 #define NVD0_DISP_MAST_CLASS                                         0x0000907d
 #define NVE0_DISP_MAST_CLASS                                         0x0000917d
 #define NVF0_DISP_MAST_CLASS                                         0x0000927d
+#define GM107_DISP_MAST_CLASS                                        0x0000947d
 
 struct nv50_display_mast_class {
        u32 pushbuf;
@@ -435,6 +445,7 @@ struct nv50_display_mast_class {
  * 907e: NVD0_DISP_OVLY
  * 917e: NVE0_DISP_OVLY
  * 927e: NVF0_DISP_OVLY
+ * 947e: GM107_DISP_OVLY
  */
 
 #define NV50_DISP_OVLY_CLASS                                         0x0000507e
@@ -445,6 +456,7 @@ struct nv50_display_mast_class {
 #define NVD0_DISP_OVLY_CLASS                                         0x0000907e
 #define NVE0_DISP_OVLY_CLASS                                         0x0000917e
 #define NVF0_DISP_OVLY_CLASS                                         0x0000927e
+#define GM107_DISP_OVLY_CLASS                                        0x0000947e
 
 struct nv50_display_ovly_class {
        u32 pushbuf;
index 7b8ea221b00dc7bf0d88021fc5443ae059401cbb..a8a9a9cf16cb2e8e62c6f96e68e9d8ee95aeb73b 100644 (file)
@@ -40,6 +40,7 @@ enum nv_subdev_type {
 
        NVDEV_ENGINE_FIRST,
        NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
+       NVDEV_ENGINE_IFB,
        NVDEV_ENGINE_FIFO,
        NVDEV_ENGINE_SW,
        NVDEV_ENGINE_GR,
@@ -65,6 +66,7 @@ struct nouveau_device {
        struct list_head head;
 
        struct pci_dev *pdev;
+       struct platform_device *platformdev;
        u64 handle;
 
        const char *cfgopt;
@@ -84,6 +86,7 @@ struct nouveau_device {
                NV_C0    = 0xc0,
                NV_D0    = 0xd0,
                NV_E0    = 0xe0,
+               GM100    = 0x110,
        } card_type;
        u32 chipset;
        u32 crystal;
@@ -140,4 +143,32 @@ nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub)
               device->pdev->subsystem_device == sub;
 }
 
+static inline bool
+nv_device_is_pci(struct nouveau_device *device)
+{
+       return device->pdev != NULL;
+}
+
+static inline struct device *
+nv_device_base(struct nouveau_device *device)
+{
+       return nv_device_is_pci(device) ? &device->pdev->dev :
+                                         &device->platformdev->dev;
+}
+
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
+
+dma_addr_t
+nv_device_map_page(struct nouveau_device *device, struct page *page);
+
+void
+nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);
+
+int
+nv_device_get_irq(struct nouveau_device *device, bool stall);
+
 #endif
index 8897e08860853b5ea8f4db291a152534da973141..f5b5fd8e1fc9083b9f72a5b7ddb985a3fc0f6d0e 100644 (file)
@@ -33,7 +33,7 @@ nv_namedb(void *obj)
 
 int  nouveau_namedb_create_(struct nouveau_object *, struct nouveau_object *,
                            struct nouveau_oclass *, u32 pclass,
-                           struct nouveau_oclass *, u32 engcls,
+                           struct nouveau_oclass *, u64 engcls,
                            int size, void **);
 
 int  _nouveau_namedb_ctor(struct nouveau_object *, struct nouveau_object *,
index b3dd2c4c2f1ede9405fda56e08150949f8f556c1..672d3c8f4145d7b235afbebedf6f1de434bc4b08 100644 (file)
@@ -3,11 +3,20 @@
 
 #include <core/device.h>
 
-#define nouveau_device_create(p,n,s,c,d,u)                                     \
-       nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u)
+struct platform_device;
 
-int  nouveau_device_create_(struct pci_dev *, u64 name, const char *sname,
-                           const char *cfg, const char *dbg, int, void **);
+enum nv_bus_type {
+       NOUVEAU_BUS_PCI,
+       NOUVEAU_BUS_PLATFORM,
+};
+
+#define nouveau_device_create(p,t,n,s,c,d,u)                                   \
+       nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d),           \
+                              sizeof(**u), (void **)u)
+
+int  nouveau_device_create_(void *, enum nv_bus_type type, u64 name,
+                           const char *sname, const char *cfg, const char *dbg,
+                           int, void **);
 
 int nv04_identify(struct nouveau_device *);
 int nv10_identify(struct nouveau_device *);
@@ -17,6 +26,7 @@ int nv40_identify(struct nouveau_device *);
 int nv50_identify(struct nouveau_device *);
 int nvc0_identify(struct nouveau_device *);
 int nve0_identify(struct nouveau_device *);
+int gm100_identify(struct nouveau_device *);
 
 struct nouveau_device *nouveau_device_find(u64 name);
 
index 4b21fabfbddb5c1c8f79c44e28d47f7821a846d0..fd0c68804de33f7da8e890b41b7007f0e64aec12 100644 (file)
@@ -36,14 +36,15 @@ void _nouveau_disp_dtor(struct nouveau_object *);
 #define _nouveau_disp_init _nouveau_engine_init
 #define _nouveau_disp_fini _nouveau_engine_fini
 
-extern struct nouveau_oclass nv04_disp_oclass;
-extern struct nouveau_oclass nv50_disp_oclass;
-extern struct nouveau_oclass nv84_disp_oclass;
-extern struct nouveau_oclass nva0_disp_oclass;
-extern struct nouveau_oclass nv94_disp_oclass;
-extern struct nouveau_oclass nva3_disp_oclass;
-extern struct nouveau_oclass nvd0_disp_oclass;
-extern struct nouveau_oclass nve0_disp_oclass;
-extern struct nouveau_oclass nvf0_disp_oclass;
+extern struct nouveau_oclass *nv04_disp_oclass;
+extern struct nouveau_oclass *nv50_disp_oclass;
+extern struct nouveau_oclass *nv84_disp_oclass;
+extern struct nouveau_oclass *nva0_disp_oclass;
+extern struct nouveau_oclass *nv94_disp_oclass;
+extern struct nouveau_oclass *nva3_disp_oclass;
+extern struct nouveau_oclass *nvd0_disp_oclass;
+extern struct nouveau_oclass *nve0_disp_oclass;
+extern struct nouveau_oclass *nvf0_disp_oclass;
+extern struct nouveau_oclass *gm107_disp_oclass;
 
 #endif
index 97705618de979e9fe1f810ca3ee5f557d5dd19e2..871edfdf3d5ba4b91c87fafef697d61244b4e8a3 100644 (file)
@@ -63,13 +63,14 @@ extern struct nouveau_oclass nv40_graph_oclass;
 extern struct nouveau_oclass nv50_graph_oclass;
 extern struct nouveau_oclass *nvc0_graph_oclass;
 extern struct nouveau_oclass *nvc1_graph_oclass;
-extern struct nouveau_oclass *nvc3_graph_oclass;
+extern struct nouveau_oclass *nvc4_graph_oclass;
 extern struct nouveau_oclass *nvc8_graph_oclass;
 extern struct nouveau_oclass *nvd7_graph_oclass;
 extern struct nouveau_oclass *nvd9_graph_oclass;
 extern struct nouveau_oclass *nve4_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
 extern struct nouveau_oclass *nv108_graph_oclass;
+extern struct nouveau_oclass *gm107_graph_oclass;
 
 extern const struct nouveau_bitfield nv04_graph_nsource[];
 extern 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 (file)
index 0000000..bba01ab
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __NVBIOS_P0260_H__
+#define __NVBIOS_P0260_H__
+
+u32 nvbios_P0260Te(struct nouveau_bios *,
+                  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz);
+
+struct nvbios_P0260E {
+       u32 data;
+};
+
+u32 nvbios_P0260Ee(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_P0260Ep(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
+                  struct nvbios_P0260E *);
+
+struct nvbios_P0260X {
+       u32 data;
+};
+
+u32 nvbios_P0260Xe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_P0260Xp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
+                  struct nvbios_P0260X *);
+
+#endif
index c1270548fd0df050f219166ba2a425d30e9c9268..a32feb3f3fb67f0e1b662d4563ac2183805ca0b2 100644 (file)
@@ -16,6 +16,7 @@ enum dcb_connector_type {
        DCB_CONNECTOR_eDP = 0x47,
        DCB_CONNECTOR_HDMI_0 = 0x60,
        DCB_CONNECTOR_HDMI_1 = 0x61,
+       DCB_CONNECTOR_HDMI_C = 0x63,
        DCB_CONNECTOR_DMS59_DP0 = 0x64,
        DCB_CONNECTOR_DMS59_DP1 = 0x65,
        DCB_CONNECTOR_NONE = 0xff
index c5e6d1e6ac1d8adff24f25646a5109c62e541119..c086ac6d677d5badd33542e1c7a87047325e883e 100644 (file)
@@ -61,6 +61,6 @@ struct nvbios_ramcfg {
 };
 
 u8 nvbios_ramcfg_count(struct nouveau_bios *);
-u8 nvbios_ramcfg_index(struct nouveau_bios *);
+u8 nvbios_ramcfg_index(struct nouveau_subdev *);
 
 #endif
index 083541dbe9c8147fe940d36177074a77d95ea9e0..8dc5051df55dfdddadc6a33c0e315369b6017a3d 100644 (file)
@@ -31,6 +31,12 @@ struct nouveau_therm_trip_point {
        int hysteresis;
 };
 
+enum nvbios_therm_fan_mode {
+       NVBIOS_THERM_FAN_TRIP = 0,
+       NVBIOS_THERM_FAN_LINEAR = 1,
+       NVBIOS_THERM_FAN_OTHER = 2,
+};
+
 struct nvbios_therm_fan {
        u16 pwm_freq;
 
@@ -40,6 +46,7 @@ struct nvbios_therm_fan {
        u16 bump_period;
        u16 slow_down_period;
 
+       enum nvbios_therm_fan_mode fan_mode;
        struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX];
        u8 nr_fan_trip;
        u8 linear_min_temp;
index ed1ac68c38b354a58211c386e1c9bc450b8501ab..e292271a84e40384b4fd92d4a25c2f2fec025e9d 100644 (file)
@@ -9,6 +9,7 @@ struct nouveau_devinit {
        bool post;
        void (*meminit)(struct nouveau_devinit *);
        int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
+       u32  (*mmio)(struct nouveau_devinit *, u32 addr);
 };
 
 static inline struct nouveau_devinit *
@@ -28,5 +29,6 @@ extern struct nouveau_oclass *nv98_devinit_oclass;
 extern struct nouveau_oclass *nva3_devinit_oclass;
 extern struct nouveau_oclass *nvaf_devinit_oclass;
 extern struct nouveau_oclass *nvc0_devinit_oclass;
+extern struct nouveau_oclass *gm107_devinit_oclass;
 
 #endif
index d7ecafbae1ca1c1b0a43192673fbf5ae582ffa60..58c7ccdebb018787aa829961ac38f36059806ee7 100644 (file)
@@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass;
 extern struct nouveau_oclass *nvaf_fb_oclass;
 extern struct nouveau_oclass *nvc0_fb_oclass;
 extern struct nouveau_oclass *nve0_fb_oclass;
+extern struct nouveau_oclass *gm107_fb_oclass;
 
 #include <subdev/bios/ramcfg.h>
 
index a1985ed3d58d01782c03cfd1fb24cd6fdeee1e9c..c9c1950b77433a4332afa5811eb3f222124dcafc 100644 (file)
@@ -35,6 +35,7 @@ nouveau_ltcg(void *obj)
 #define _nouveau_ltcg_init _nouveau_subdev_init
 #define _nouveau_ltcg_fini _nouveau_subdev_fini
 
-extern struct nouveau_oclass nvc0_ltcg_oclass;
+extern struct nouveau_oclass *gf100_ltcg_oclass;
+extern struct nouveau_oclass *gm107_ltcg_oclass;
 
 #endif
index 3c6738edd127040337ff8fc53b6125a47e812ad7..72b176831be62ca009041d82155e21b6d9d9d1f8 100644 (file)
@@ -12,6 +12,7 @@ struct nouveau_mc_intr {
 struct nouveau_mc {
        struct nouveau_subdev base;
        bool use_msi;
+       unsigned int irq;
 };
 
 static inline struct nouveau_mc *
index 69891d4a3fe7e3f50a840e4cdc2a34196bcd0010..d4a68179e5863c383640cd9c339ce941e34d9909 100644 (file)
@@ -31,7 +31,7 @@ struct nouveau_therm {
        int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
        int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *);
        int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
-       int (*pwm_clock)(struct nouveau_therm *);
+       int (*pwm_clock)(struct nouveau_therm *, int line);
 
        int (*fan_get)(struct nouveau_therm *);
        int (*fan_set)(struct nouveau_therm *, int);
index 9ab70dfe5b02584e06de467ccd04e197cd2548d9..db9be803a87440f4274c46f791de5a4b885dcbb6 100644 (file)
@@ -59,5 +59,6 @@ int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *,
                          struct nouveau_oclass *, int size, void **);
 
 extern struct nouveau_oclass nv04_timer_oclass;
+extern struct nouveau_oclass gk20a_timer_oclass;
 
 #endif
index 191e739f30d14f1c994db7028c759238b6604048..d0ced94ca54ceb6f755934b4495985787dcb2610 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/printk.h>
 #include <linux/bitops.h>
 #include <linux/firmware.h>
 
 #include <asm/unaligned.h>
 
-static inline int
-ffsll(u64 mask)
-{
-       int i;
-       for (i = 0; i < 64; i++) {
-               if (mask & (1ULL << i))
-                       return i + 1;
-       }
-       return 0;
-}
-
 #ifndef ioread32_native
 #ifdef __BIG_ENDIAN
 #define ioread16_native ioread16be
index 7098ddd546788c3adca970af4afc1a5a8d122d1a..bdf594116f3f2a1ab49698669ccf7a2b641c91ee 100644 (file)
@@ -118,8 +118,8 @@ nouveau_bar_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       bar->iomem = ioremap(pci_resource_start(device->pdev, 3),
-                            pci_resource_len(device->pdev, 3));
+       bar->iomem = ioremap(nv_device_resource_start(device, 3),
+                            nv_device_resource_len(device, 3));
        return 0;
 }
 
index 090d594a21b36ee9633462db5f0ee838547b1557..f748ba49dfc8c941c1fae80039c7d2a24b8cea50 100644 (file)
@@ -139,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        /* BAR3 */
        start = 0x0100000000ULL;
-       limit = start + pci_resource_len(device->pdev, 3);
+       limit = start + nv_device_resource_len(device, 3);
 
        ret = nouveau_vm_new(device, start, limit, start, &vm);
        if (ret)
@@ -173,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        /* BAR1 */
        start = 0x0000000000ULL;
-       limit = start + pci_resource_len(device->pdev, 1);
+       limit = start + nv_device_resource_len(device, 1);
 
        ret = nouveau_vm_new(device, start, limit--, start, &vm);
        if (ret)
@@ -231,7 +231,7 @@ static int
 nv50_bar_init(struct nouveau_object *object)
 {
        struct nv50_bar_priv *priv = (void *)object;
-       int ret;
+       int ret, i;
 
        ret = nouveau_bar_init(&priv->base);
        if (ret)
@@ -249,6 +249,8 @@ nv50_bar_init(struct nouveau_object *object)
        nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12);
        nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4);
        nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4);
+       for (i = 0; i < 8; i++)
+               nv_wr32(priv, 0x001900 + (i * 4), 0x00000000);
        return 0;
 }
 
index bac5e754de35acdf838b571bf1d6e25eb8b5faec..3f30db62e6563d483d0a330aafe353692865c1c0 100644 (file)
@@ -84,7 +84,6 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
              struct nouveau_object **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
-       struct pci_dev *pdev = device->pdev;
        struct nvc0_bar_priv *priv;
        struct nouveau_gpuobj *mem;
        struct nouveau_vm *vm;
@@ -107,14 +106,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm);
+       ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
        if (ret)
                return ret;
 
        atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
 
        ret = nouveau_gpuobj_new(nv_object(priv), NULL,
-                                (pci_resource_len(pdev, 3) >> 12) * 8,
+                                (nv_device_resource_len(device, 3) >> 12) * 8,
                                 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
                                 &vm->pgt[0].obj[0]);
        vm->pgt[0].refcount[0] = 1;
@@ -128,8 +127,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
        nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
-       nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1));
-       nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1));
+       nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
+       nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));
 
        /* BAR1 */
        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,
        if (ret)
                return ret;
 
-       ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm);
+       ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
        if (ret)
                return ret;
 
@@ -156,8 +155,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
        nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
-       nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1));
-       nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1));
+       nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
+       nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));
 
        priv->base.alloc = nouveau_bar_alloc;
        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 (file)
index 0000000..199f4e5
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
+#include <subdev/bios/P0260.h>
+
+u32
+nvbios_P0260Te(struct nouveau_bios *bios,
+              u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
+{
+       struct bit_entry bit_P;
+       u32 data = 0x00000000;
+
+       if (!bit_entry(bios, 'P', &bit_P)) {
+               if (bit_P.version == 2 && bit_P.length > 0x63)
+                       data = nv_ro32(bios, bit_P.offset + 0x60);
+               if (data) {
+                       *ver = nv_ro08(bios, data + 0);
+                       switch (*ver) {
+                       case 0x10:
+                               *hdr = nv_ro08(bios, data + 1);
+                               *cnt = nv_ro08(bios, data + 2);
+                               *len = 4;
+                               *xnr = nv_ro08(bios, data + 3);
+                               *xsz = 4;
+                               return data;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       return 0x00000000;
+}
+
+u32
+nvbios_P0260Ee(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
+{
+       u8  hdr, cnt, xnr, xsz;
+       u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, len, &xnr, &xsz);
+       if (data && idx < cnt)
+               return data + hdr + (idx * *len);
+       return 0x00000000;
+}
+
+u32
+nvbios_P0260Ep(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,
+              struct nvbios_P0260E *info)
+{
+       u32 data = nvbios_P0260Ee(bios, idx, ver, len);
+       memset(info, 0x00, sizeof(*info));
+       switch (!!data * *ver) {
+       case 0x10:
+               info->data = nv_ro32(bios, data);
+               return data;
+       default:
+               break;
+       }
+       return 0x00000000;
+}
+
+u32
+nvbios_P0260Xe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *xsz)
+{
+       u8  hdr, cnt, len, xnr;
+       u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, &len, &xnr, xsz);
+       if (data && idx < xnr)
+               return data + hdr + (cnt * len) + (idx * *xsz);
+       return 0x00000000;
+}
+
+u32
+nvbios_P0260Xp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr,
+              struct nvbios_P0260X *info)
+{
+       u32 data = nvbios_P0260Xe(bios, idx, ver, hdr);
+       memset(info, 0x00, sizeof(*info));
+       switch (!!data * *ver) {
+       case 0x10:
+               info->data = nv_ro32(bios, data);
+               return data;
+       default:
+               break;
+       }
+       return 0x00000000;
+}
index ef0c9c4a8cc3925f9f8df1279417fc028a39f2f9..e9df94f96d7827e446828106ef68d4667e361401 100644 (file)
@@ -90,10 +90,26 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
        int i;
 
        if (device->card_type >= NV_50) {
-               if (  device->card_type < NV_C0 ||
-                   !(nv_rd32(bios, 0x022500) & 0x00000001))
-                       addr = (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8;
+               if (device->card_type >= NV_C0 && device->card_type < GM100) {
+                       if (nv_rd32(bios, 0x022500) & 0x00000001)
+                               return;
+               } else
+               if (device->card_type >= GM100) {
+                       if (nv_rd32(bios, 0x021c04) & 0x00000001)
+                               return;
+               }
+
+               addr = nv_rd32(bios, 0x619f04);
+               if (!(addr & 0x00000008)) {
+                       nv_debug(bios, "... not enabled\n");
+                       return;
+               }
+               if ( (addr & 0x00000003) != 1) {
+                       nv_debug(bios, "... not in vram\n");
+                       return;
+               }
 
+               addr = (u64)(addr >> 8) << 8;
                if (!addr) {
                        addr  = (u64)nv_rd32(bios, 0x001700) << 16;
                        addr += 0xf0000;
@@ -141,6 +157,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
                pcireg = 0x001850;
        access = nv_mask(bios, pcireg, 0x00000001, 0x00000000);
 
+       /* WARNING: PROM accesses should always be 32-bits aligned. Other
+        * accesses work on most chipset but do not on Kepler chipsets
+        */
+
        /* bail if no rom signature, with a workaround for a PROM reading
         * issue on some chipsets.  the first read after a period of
         * inactivity returns the wrong result, so retry the first header
@@ -148,31 +168,32 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
         */
        i = 16;
        do {
-               if (nv_rd08(bios, 0x300000) == 0x55)
+               if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55)
                        break;
        } while (i--);
 
-       if (!i || nv_rd08(bios, 0x300001) != 0xaa)
-               goto out;
-
-       /* additional check (see note below) - read PCI record header */
-       pcir = nv_rd08(bios, 0x300018) |
-              nv_rd08(bios, 0x300019) << 8;
-       if (nv_rd08(bios, 0x300000 + pcir) != 'P' ||
-           nv_rd08(bios, 0x300001 + pcir) != 'C' ||
-           nv_rd08(bios, 0x300002 + pcir) != 'I' ||
-           nv_rd08(bios, 0x300003 + pcir) != 'R')
+       if (!i)
                goto out;
 
        /* read entire bios image to system memory */
-       bios->size = nv_rd08(bios, 0x300002) * 512;
+       bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512;
        if (!bios->size)
                goto out;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
-               for (i = 0; i < bios->size; i++)
-                       nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i));
+               for (i = 0; i < bios->size; i+=4)
+                       nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i));
+       }
+
+       /* check the PCI record header */
+       pcir = nv_ro16(bios, 0x0018);
+       if (bios->data[pcir + 0] != 'P' ||
+           bios->data[pcir + 1] != 'C' ||
+           bios->data[pcir + 2] != 'I' ||
+           bios->data[pcir + 3] != 'R') {
+               bios->size = 0;
+               kfree(bios->data);
        }
 
 out:
index 2d9b9d7a7992111cc1d4bd0ff3e60254bf52dcb5..88606bfaf84742c3c87a26d0d8387c29fecc9d81 100644 (file)
@@ -142,9 +142,36 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
                if (*ver >= 0x40) {
                        u32 conf = nv_ro32(bios, dcb + 0x04);
                        switch (outp->type) {
+                       case DCB_OUTPUT_DP:
+                               switch (conf & 0x00e00000) {
+                               case 0x00000000:
+                                       outp->dpconf.link_bw = 0x06;
+                                       break;
+                               case 0x00200000:
+                                       outp->dpconf.link_bw = 0x0a;
+                                       break;
+                               case 0x00400000:
+                               default:
+                                       outp->dpconf.link_bw = 0x14;
+                                       break;
+                               }
+
+                               switch (conf & 0x0f000000) {
+                               case 0x0f000000:
+                                       outp->dpconf.link_nr = 4;
+                                       break;
+                               case 0x03000000:
+                                       outp->dpconf.link_nr = 2;
+                                       break;
+                               case 0x01000000:
+                               default:
+                                       outp->dpconf.link_nr = 1;
+                                       break;
+                               }
+
+                               /* fall-through... */
                        case DCB_OUTPUT_TMDS:
                        case DCB_OUTPUT_LVDS:
-                       case DCB_OUTPUT_DP:
                                outp->link = (conf & 0x00000030) >> 4;
                                outp->sorconf.link = outp->link; /*XXX*/
                                outp->extdev = 0x00;
index de201baeb053aea79a6632289a865de94fc5dc07..acaeaf79e3f0fa797aa974831d6bbb367ebc78ff 100644 (file)
@@ -118,6 +118,8 @@ init_conn(struct nvbios_init *init)
 static inline u32
 init_nvreg(struct nvbios_init *init, u32 reg)
 {
+       struct nouveau_devinit *devinit = nouveau_devinit(init->bios);
+
        /* C51 (at least) sometimes has the lower bits set which the VBIOS
         * interprets to mean that access needs to go through certain IO
         * ports instead.  The NVIDIA binary driver has been seen to access
@@ -147,6 +149,9 @@ init_nvreg(struct nvbios_init *init, u32 reg)
 
        if (reg & ~0x00fffffc)
                warn("unknown bits in register 0x%08x\n", reg);
+
+       if (devinit->mmio)
+               reg = devinit->mmio(devinit, reg);
        return reg;
 }
 
@@ -154,7 +159,7 @@ static u32
 init_rd32(struct nvbios_init *init, u32 reg)
 {
        reg = init_nvreg(init, reg);
-       if (init_exec(init))
+       if (reg != ~0 && init_exec(init))
                return nv_rd32(init->subdev, reg);
        return 0x00000000;
 }
@@ -163,7 +168,7 @@ static void
 init_wr32(struct nvbios_init *init, u32 reg, u32 val)
 {
        reg = init_nvreg(init, reg);
-       if (init_exec(init))
+       if (reg != ~0 && init_exec(init))
                nv_wr32(init->subdev, reg, val);
 }
 
@@ -171,7 +176,7 @@ static u32
 init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val)
 {
        reg = init_nvreg(init, reg);
-       if (init_exec(init)) {
+       if (reg != ~0 && init_exec(init)) {
                u32 tmp = nv_rd32(init->subdev, reg);
                nv_wr32(init->subdev, reg, (tmp & ~mask) | val);
                return tmp;
@@ -410,7 +415,7 @@ init_ram_restrict(struct nvbios_init *init)
         * in case *not* re-reading the strap causes similar breakage.
         */
        if (!init->ramcfg || init->bios->version.major < 0x70)
-               init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios);
+               init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->subdev);
        return (init->ramcfg & 0x7fffffff);
 }
 
@@ -845,9 +850,8 @@ init_idx_addr_latched(struct nvbios_init *init)
        u32 data = nv_ro32(bios, init->offset + 13);
        u8 count = nv_ro08(bios, init->offset + 17);
 
-       trace("INDEX_ADDRESS_LATCHED\t"
-             "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n",
-             creg, dreg, mask, data);
+       trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg);
+       trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data);
        init->offset += 18;
 
        while (count--) {
index 991aedda999b083ec94609ab259f63ad1260be75..6c401f70ab99ae380b6c614983a997a9244a97d9 100644 (file)
@@ -27,9 +27,9 @@
 #include <subdev/bios/ramcfg.h>
 
 static u8
-nvbios_ramcfg_strap(struct nouveau_bios *bios)
+nvbios_ramcfg_strap(struct nouveau_subdev *subdev)
 {
-       return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
+       return (nv_rd32(subdev, 0x101000) & 0x0000003c) >> 2;
 }
 
 u8
@@ -48,9 +48,10 @@ nvbios_ramcfg_count(struct nouveau_bios *bios)
 }
 
 u8
-nvbios_ramcfg_index(struct nouveau_bios *bios)
+nvbios_ramcfg_index(struct nouveau_subdev *subdev)
 {
-       u8 strap = nvbios_ramcfg_strap(bios);
+       struct nouveau_bios *bios = nouveau_bios(subdev);
+       u8 strap = nvbios_ramcfg_strap(subdev);
        u32 xlat = 0x00000000;
        struct bit_entry bit_M;
 
index 22ac6dbd6c8f7b2c249bcfb687974a3758b96c3e..d1585409407800b698cf909fea7a85c5f5c5d073 100644 (file)
@@ -164,6 +164,7 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
 
        i = 0;
        fan->nr_fan_trip = 0;
+       fan->fan_mode = NVBIOS_THERM_FAN_OTHER;
        while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) {
                s16 value = nv_ro16(bios, entry + 1);
 
@@ -174,6 +175,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
                        break;
                case 0x24:
                        fan->nr_fan_trip++;
+                       if (fan->fan_mode > NVBIOS_THERM_FAN_TRIP)
+                               fan->fan_mode = NVBIOS_THERM_FAN_TRIP;
                        cur_trip = &fan->trip[fan->nr_fan_trip - 1];
                        cur_trip->hysteresis = value & 0xf;
                        cur_trip->temp = (value & 0xff0) >> 4;
@@ -194,11 +197,19 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
                        fan->slow_down_period = value;
                        break;
                case 0x46:
+                       if (fan->fan_mode > NVBIOS_THERM_FAN_LINEAR)
+                               fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
                        fan->linear_min_temp = nv_ro08(bios, entry + 1);
                        fan->linear_max_temp = nv_ro08(bios, entry + 2);
                        break;
                }
        }
 
+       /* starting from fermi, fan management is always linear */
+       if (nv_device(bios)->card_type >= NV_C0 &&
+               fan->fan_mode == NVBIOS_THERM_FAN_OTHER) {
+               fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
+       }
+
        return 0;
 }
index 8fa34e8152c20b6ae90f2ca020f6c49a077f2cdd..239acfe876c3ddb4262d2e696cd4a59e1e06d951 100644 (file)
@@ -96,5 +96,6 @@ nouveau_devinit_create_(struct nouveau_object *parent,
        devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
        devinit->meminit = impl->meminit;
        devinit->pll_set = impl->pll_set;
+       devinit->mmio    = impl->mmio;
        return 0;
 }
index 6b56a0f4cb404c9cce29ee8e56cfee162908094a..4fe49cf4c99a37eaf32d79eecf029501cac353f7 100644 (file)
@@ -24,6 +24,8 @@
  *
  */
 
+#include <core/device.h>
+
 #define NV04_PFB_BOOT_0                                                0x00100000
 #      define NV04_PFB_BOOT_0_RAM_AMOUNT                       0x00000003
 #      define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB                  0x00000000
 #      define NV10_PFB_REFCTRL_VALID_1                         (1 << 31)
 
 static inline struct io_mapping *
-fbmem_init(struct pci_dev *pdev)
+fbmem_init(struct nouveau_device *dev)
 {
-       return io_mapping_create_wc(pci_resource_start(pdev, 1),
-                                   pci_resource_len(pdev, 1));
+       return io_mapping_create_wc(nv_device_resource_start(dev, 1),
+                                   nv_device_resource_len(dev, 1));
 }
 
 static 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 (file)
index 0000000..c69bc7f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+gm107_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r021c00 = nv_rd32(priv, 0x021c00);
+       u32 r021c04 = nv_rd32(priv, 0x021c04);
+       u64 disable = 0ULL;
+
+       if (r021c00 & 0x00000001)
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+       if (r021c00 & 0x00000004)
+               disable |= (1ULL << NVDEV_ENGINE_COPY2);
+       if (r021c04 & 0x00000001)
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+gm107_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x07),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nvc0_devinit_pll_set,
+       .disable = gm107_devinit_disable,
+}.base;
index 7037eae46e445bd5d3278dfc70119dac180cadbb..052ad690b468da81ec1a95e04eace07834f70c88 100644 (file)
@@ -38,7 +38,7 @@ nv04_devinit_meminit(struct nouveau_devinit *devinit)
        int i;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
index 98b7e6780dc7f4826c4eb946419d0ceb6cfb5d84..4a19c10e517809ab7b348803481bcb0c0e98a0eb 100644 (file)
@@ -53,7 +53,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
        int i, v;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
index 32b3d2131a7f0d14b0e37e8b9888e2b38cf937c5..3b8d657da2798445f620e9662467df8696304280 100644 (file)
@@ -46,7 +46,7 @@ nv10_devinit_meminit(struct nouveau_devinit *devinit)
                mem_width_count = 2;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
index 4689ba303b0bd6620ec080fcfe9fa3defad2f3ff..04bc9732644ccd706c72fdc055d534e61272f625 100644 (file)
@@ -37,7 +37,7 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
        struct io_mapping *fb;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
index 141c27e9f182788e3cff573a226786ee31a95c08..51d5076333ecefc8ba5167a3a2ccbedbd12a9b4a 100644 (file)
@@ -5,6 +5,7 @@
 
 struct nv50_devinit_priv {
        struct nouveau_devinit base;
+       u32 r001540;
 };
 
 int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
@@ -15,4 +16,6 @@ int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
 
 int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
 
+int  nvc0_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
 #endif
index 6dedf1dad7f7bce5b71d33dd01111cac7324621b..006cf348bda767e8219901ec63c70aadd7d89365 100644 (file)
@@ -81,6 +81,55 @@ nva3_devinit_disable(struct nouveau_devinit *devinit)
        return disable;
 }
 
+static u32
+nva3_devinit_mmio_part[] = {
+       0x100720, 0x1008bc, 4,
+       0x100a20, 0x100adc, 4,
+       0x100d80, 0x100ddc, 4,
+       0x110000, 0x110f9c, 4,
+       0x111000, 0x11103c, 8,
+       0x111080, 0x1110fc, 4,
+       0x111120, 0x1111fc, 4,
+       0x111300, 0x1114bc, 4,
+       0,
+};
+
+static u32
+nva3_devinit_mmio(struct nouveau_devinit *devinit, u32 addr)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 *mmio = nva3_devinit_mmio_part;
+
+       /* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP
+        * instructions which touch registers that may not even exist on
+        * some configurations (Quadro 400), which causes the register
+        * interface to screw up for some amount of time after attempting to
+        * write to one of these, and results in all sorts of things going
+        * horribly wrong.
+        *
+        * the binary driver avoids touching these registers at all, however,
+        * the video bios doesn't care and does what the scripts say.  it's
+        * presumed that the io-port access to priv registers isn't effected
+        * by the screw-up bug mentioned above.
+        *
+        * really, a new opcode should've been invented to handle these
+        * requirements, but whatever, it's too late for that now.
+        */
+       while (mmio[0]) {
+               if (addr >= mmio[0] && addr <= mmio[1]) {
+                       u32 part = (addr / mmio[2]) & 7;
+                       if (!priv->r001540)
+                               priv->r001540 = nv_rd32(priv, 0x001540);
+                       if (part >= hweight8((priv->r001540 >> 16) & 0xff))
+                               return ~0;
+                       return addr;
+               }
+               mmio += 3;
+       }
+
+       return addr;
+}
+
 struct nouveau_oclass *
 nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
        .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
@@ -92,4 +141,5 @@ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
        },
        .pll_set = nva3_devinit_pll_set,
        .disable = nva3_devinit_disable,
+       .mmio    = nva3_devinit_mmio,
 }.base;
index fa7e63766b1b19ae47b8557c4581b77cb0ff0a22..30c765747eeaebb2c9a1526b31306587d64e4a5e 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "nv50.h"
 
-static int
+int
 nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
        struct nv50_devinit_priv *priv = (void *)devinit;
index 822a2fbf44a5b3d601d5c79eedb7b2af68654d86..f0e8683ad8405639d0406c3dc7be0dad153395d5 100644 (file)
@@ -11,6 +11,7 @@ struct nouveau_devinit_impl {
        void (*meminit)(struct nouveau_devinit *);
        int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
        u64  (*disable)(struct nouveau_devinit *);
+       u32  (*mmio)(struct nouveau_devinit *, u32);
 };
 
 #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 (file)
index 0000000..c4840ae
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nvc0.h"
+
+struct nouveau_oclass *
+gm107_fb_oclass = &(struct nouveau_fb_impl) {
+       .base.handle = NV_SUBDEV(FB, 0x07),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_fb_ctor,
+               .dtor = nvc0_fb_dtor,
+               .init = nvc0_fb_init,
+               .fini = _nouveau_fb_fini,
+       },
+       .memtype = nvc0_fb_memtype_valid,
+       .ram = &gm107_ram_oclass,
+}.base;
index cbc7f00c1278905bcf24b2c7f8dc548c6dce7a22..1fc55c1e91a13b00869c9aa8a46ad2bd0f253e43 100644 (file)
@@ -250,10 +250,8 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (priv->r100c08_page) {
-               priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
-                                            0, PAGE_SIZE,
-                                            PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->r100c08))
+               priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
+               if (!priv->r100c08)
                        nv_warn(priv, "failed 0x100c08 page map\n");
        } else {
                nv_warn(priv, "failed 0x100c08 page alloc\n");
@@ -270,8 +268,7 @@ nv50_fb_dtor(struct nouveau_object *object)
        struct nv50_fb_priv *priv = (void *)object;
 
        if (priv->r100c08_page) {
-               pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
-                              PCI_DMA_BIDIRECTIONAL);
+               nv_device_unmap_page(device, priv->r100c08);
                __free_page(priv->r100c08_page);
        }
 
index 45470e1f0385f4682a654e0c37cb27212d3ba8eb..0670ae33ee450d7428580c280f34051b893675e1 100644 (file)
@@ -70,8 +70,7 @@ nvc0_fb_dtor(struct nouveau_object *object)
        struct nvc0_fb_priv *priv = (void *)object;
 
        if (priv->r100c10_page) {
-               pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE,
-                              PCI_DMA_BIDIRECTIONAL);
+               nv_device_unmap_page(device, priv->r100c10);
                __free_page(priv->r100c10_page);
        }
 
@@ -94,10 +93,8 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (priv->r100c10_page) {
-               priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page,
-                                            0, PAGE_SIZE,
-                                            PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->r100c10))
+               priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
+               if (!priv->r100c10)
                        return -EFAULT;
        }
 
index 9e1931eb746ff45f488a6c3be85cc5a90e445b0d..705a06d755ad2310fe10230ee1e160cceb2a9e11 100644 (file)
@@ -18,12 +18,14 @@ int  nvc0_fb_init(struct nouveau_object *);
 bool nvc0_fb_memtype_valid(struct nouveau_fb *, u32);
 
 
-#define nvc0_ram_create(p,e,o,d)                                               \
-       nvc0_ram_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nvc0_ram_create(p,e,o,m,d)                                             \
+       nvc0_ram_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
 int  nvc0_ram_create_(struct nouveau_object *, struct nouveau_object *,
-                     struct nouveau_oclass *, int, void **);
+                     struct nouveau_oclass *, u32, int, void **);
 int  nvc0_ram_get(struct nouveau_fb *, u64, u32, u32, u32,
                  struct nouveau_mem **);
 void nvc0_ram_put(struct nouveau_fb *, struct nouveau_mem **);
 
+int  nve0_ram_init(struct nouveau_object*);
+
 #endif
index edaf95dee61285d81d468060cd2b284b4da89cc0..da74c889aed47a01b9a51eec66e3e22a5ca7fe9a 100644 (file)
@@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass;
 extern struct nouveau_oclass nvaa_ram_oclass;
 extern struct nouveau_oclass nvc0_ram_oclass;
 extern struct nouveau_oclass nve0_ram_oclass;
+extern struct nouveau_oclass gm107_ram_oclass;
 
 int nouveau_sddr3_calc(struct nouveau_ram *ram);
 int 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 (file)
index 0000000..4c63635
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nvc0.h"
+
+struct gm107_ram {
+       struct nouveau_ram base;
+};
+
+static int
+gm107_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       struct gm107_ram *ram;
+       int ret;
+
+       ret = nvc0_ram_create(parent, engine, oclass, 0x021c14, &ram);
+       *pobject = nv_object(ram);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+gm107_ram_oclass = {
+       .handle = 0,
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gm107_ram_ctor,
+               .dtor = _nouveau_ram_dtor,
+               .init = nve0_ram_init,
+               .fini = _nouveau_ram_fini,
+       }
+};
index c7fdb3a9e88b06cdcfa3151abf5ae7331c04e409..ef91b6e893afc4c4ca488453ea9f19ced5fa5861 100644 (file)
@@ -91,7 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        } while (perfE.memory < freq);
 
        /* locate specific data set for the attached memory */
-       strap = nvbios_ramcfg_index(bios);
+       strap = nvbios_ramcfg_index(nv_subdev(pfb));
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
index f4ae8aa46a255948df24c3e4d2f4e259ed583d53..6eb97f16fbda97f40b1c0a9efbed47aacf030104 100644 (file)
@@ -98,7 +98,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        }
 
        /* locate specific data set for the attached memory */
-       strap = nvbios_ramcfg_index(bios);
+       strap = nvbios_ramcfg_index(nv_subdev(pfb));
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -335,21 +335,23 @@ nva3_ram_init(struct nouveau_object *object)
        /* prepare for ddr link training, and load training patterns */
        switch (ram->base.type) {
        case NV_MEM_TYPE_DDR3: {
-               static const u32 pattern[16] = {
-                       0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
-                       0x00000000, 0x11111111, 0x44444444, 0xdddddddd,
-                       0x33333333, 0x55555555, 0x77777777, 0x66666666,
-                       0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb,
-               };
-
-               nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/
-               nv_wr32(pfb, 0x1005a8, 0x0000ffff);
-               nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001);
-               for (i = 0; i < 0x30; i++) {
-                       nv_wr32(pfb, 0x10f8c0, (i << 8) | i);
-                       nv_wr32(pfb, 0x10f8e0, (i << 8) | i);
-                       nv_wr32(pfb, 0x10f900, pattern[i % 16]);
-                       nv_wr32(pfb, 0x10f920, pattern[i % 16]);
+               if (nv_device(pfb)->chipset == 0xa8) {
+                       static const u32 pattern[16] = {
+                               0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
+                               0x00000000, 0x11111111, 0x44444444, 0xdddddddd,
+                               0x33333333, 0x55555555, 0x77777777, 0x66666666,
+                               0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb,
+                       };
+
+                       nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/
+                       nv_wr32(pfb, 0x1005a8, 0x0000ffff);
+                       nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001);
+                       for (i = 0; i < 0x30; i++) {
+                               nv_wr32(pfb, 0x10f8c0, (i << 8) | i);
+                               nv_wr32(pfb, 0x10f8e0, (i << 8) | i);
+                               nv_wr32(pfb, 0x10f900, pattern[i % 16]);
+                               nv_wr32(pfb, 0x10f920, pattern[i % 16]);
+                       }
                }
        }
                break;
index 0391b824ee767d7629e333c56965366bc15347fd..8edc92224c84a2ce31b3c5115ff0f31f7c37e0e4 100644 (file)
@@ -152,7 +152,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        }
 
        /* locate specific data set for the attached memory */
-       strap = nvbios_ramcfg_index(bios);
+       strap = nvbios_ramcfg_index(nv_subdev(pfb));
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -505,7 +505,8 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
 
 int
 nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
-                struct nouveau_oclass *oclass, int size, void **pobject)
+                struct nouveau_oclass *oclass, u32 maskaddr, int size,
+                void **pobject)
 {
        struct nouveau_fb *pfb = nouveau_fb(parent);
        struct nouveau_bios *bios = nouveau_bios(pfb);
@@ -513,7 +514,7 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
        const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
        u32 parts = nv_rd32(pfb, 0x022438);
-       u32 pmask = nv_rd32(pfb, 0x022554);
+       u32 pmask = nv_rd32(pfb, maskaddr);
        u32 bsize = nv_rd32(pfb, 0x10f20c);
        u32 offset, length;
        bool uniform = true;
@@ -630,7 +631,7 @@ nvc0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_ram *ram;
        int ret;
 
-       ret = nvc0_ram_create(parent, engine, oclass, &ram);
+       ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
        *pobject = nv_object(ram);
        if (ret)
                return ret;
index 3257c522a0219026e5147d37725b1f6a30fcac21..16752192cf87acbb5e77a904fb3474e7f2de46d6 100644 (file)
@@ -950,10 +950,11 @@ nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
        }
 
        /* locate specific data set for the attached memory */
+       strap = nvbios_ramcfg_index(nv_subdev(pfb));
        ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
                                                ram->base.rammap.version,
-                                               ram->base.rammap.size, cnt, len,
-                                               nvbios_ramcfg_index(bios),
+                                               ram->base.rammap.size,
+                                               cnt, len, strap,
                                                &ram->base.ramcfg.version,
                                                &ram->base.ramcfg.size,
                                                &data->bios);
@@ -1123,7 +1124,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
        ram_exec(fuc, false);
 }
 
-static int
+int
 nve0_ram_init(struct nouveau_object *object)
 {
        struct nouveau_fb *pfb = (void *)object->parent;
@@ -1226,7 +1227,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int ret, i;
        u32 tmp;
 
-       ret = nvc0_ram_create(parent, engine, oclass, &ram);
+       ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
        *pobject = nv_object(ram);
        if (ret)
                return ret;
index c4c1d415e7feb871329c275e894558f44c60aff8..2ef7747316291c1b40bb3bfdd84d87603473c132 100644 (file)
@@ -46,7 +46,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
                u8  unk0 = !!(data & 0x02000000);
                u8  unk1 = !!(data & 0x04000000);
                u32 val = (unk1 << 16) | unk0;
-               u32 reg = regs[line >> 4]; line &= 0x0f;
+               u32 reg = regs[line >> 4];
+               u32 lsh = line & 0x0f;
 
                if ( func  == DCB_GPIO_UNUSED ||
                    (match != DCB_GPIO_UNUSED && match != func))
@@ -54,7 +55,7 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
 
                gpio->set(gpio, 0, func, line, defs);
 
-               nv_mask(priv, reg, 0x00010001 << line, val << line);
+               nv_mask(priv, reg, 0x00010001 << lsh, val << lsh);
        }
 }
 
@@ -79,7 +80,7 @@ nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
        if (nv50_gpio_location(line, &reg, &shift))
                return -EINVAL;
 
-       nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift);
+       nv_mask(gpio, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift);
        return 0;
 }
 
index c33c03d2f4af2f695e50e92078ea18c800d07eec..378e05b88e6f0c4562637d00e21aed7285c5b69f 100644 (file)
@@ -111,7 +111,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
        snprintf(port->adapter.name, sizeof(port->adapter.name),
                 "nouveau-%s-%d", device->name, index);
        port->adapter.owner = THIS_MODULE;
-       port->adapter.dev.parent = &device->pdev->dev;
+       port->adapter.dev.parent = nv_device_base(device);
        port->index = index;
        port->func = func;
        i2c_set_adapdata(&port->adapter, i2c);
index ec0b9661d614ced3dec026e3460d3eeb07905f2e..8803809f9fc5fd8d2e87d5d2a5bd688d7b50aae5 100644 (file)
@@ -50,7 +50,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_object **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
-       struct pci_dev *pdev = device->pdev;
        struct nv04_instmem_priv *priv;
        int ret, bar, vs;
 
@@ -60,13 +59,13 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        /* map bar */
-       if (pci_resource_len(pdev, 2))
+       if (nv_device_resource_len(device, 2))
                bar = 2;
        else
                bar = 3;
 
-       priv->iomem = ioremap(pci_resource_start(pdev, bar),
-                             pci_resource_len(pdev, bar));
+       priv->iomem = ioremap(nv_device_resource_start(device, bar),
+                             nv_device_resource_len(device, bar));
        if (!priv->iomem) {
                nv_error(priv, "unable to map PRAMIN BAR\n");
                return -EFAULT;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
new file mode 100644 (file)
index 0000000..f2f3338
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+
+#include "gf100.h"
+
+static void
+gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
+{
+       u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
+       u32 stat = nv_rd32(priv, base + 0x020);
+
+       if (stat) {
+               nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+               nv_wr32(priv, base + 0x020, stat);
+       }
+}
+
+static void
+gf100_ltcg_intr(struct nouveau_subdev *subdev)
+{
+       struct gf100_ltcg_priv *priv = (void *)subdev;
+       u32 mask;
+
+       mask = nv_rd32(priv, 0x00017c);
+       while (mask) {
+               u32 lts, ltc = __ffs(mask);
+               for (lts = 0; lts < priv->lts_nr; lts++)
+                       gf100_ltcg_lts_isr(priv, ltc, lts);
+               mask &= ~(1 << ltc);
+       }
+
+       /* we do something horribly wrong and upset PMFB a lot, so mask off
+        * interrupts from it after the first one until it's fixed
+        */
+       nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
+}
+
+int
+gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
+                    struct nouveau_mm_node **pnode)
+{
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
+       if (ret)
+               *pnode = NULL;
+
+       return ret;
+}
+
+void
+gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
+{
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+
+       nouveau_mm_free(&priv->tags, pnode);
+}
+
+static void
+gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+{
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       u32 last = first + count - 1;
+       int p, i;
+
+       BUG_ON((first > last) || (last >= priv->num_tags));
+
+       nv_wr32(priv, 0x17e8cc, first);
+       nv_wr32(priv, 0x17e8d0, last);
+       nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
+
+       /* wait until it's finished with clearing */
+       for (p = 0; p < priv->ltc_nr; ++p) {
+               for (i = 0; i < priv->lts_nr; ++i)
+                       nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
+       }
+}
+
+/* TODO: Figure out tag memory details and drop the over-cautious allocation.
+ */
+int
+gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
+{
+       u32 tag_size, tag_margin, tag_align;
+       int ret;
+
+       /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
+       priv->num_tags = (pfb->ram->size >> 17) / 4;
+       if (priv->num_tags > (1 << 17))
+               priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
+       priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
+
+       tag_align = priv->ltc_nr * 0x800;
+       tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
+
+       /* 4 part 4 sub: 0x2000 bytes for 56 tags */
+       /* 3 part 4 sub: 0x6000 bytes for 168 tags */
+       /*
+        * About 147 bytes per tag. Let's be safe and allocate x2, which makes
+        * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags.
+        *
+        * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %.
+        */
+       tag_size  = (priv->num_tags / 64) * 0x6000 + tag_margin;
+       tag_size += tag_align;
+       tag_size  = (tag_size + 0xfff) >> 12; /* round up */
+
+       ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
+                             &priv->tag_ram);
+       if (ret) {
+               priv->num_tags = 0;
+       } else {
+               u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
+
+               tag_base += tag_align - 1;
+               ret = do_div(tag_base, tag_align);
+
+               priv->tag_base = tag_base;
+       }
+       ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
+
+       return ret;
+}
+
+static int
+gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       struct gf100_ltcg_priv *priv;
+       struct nouveau_fb *pfb = nouveau_fb(parent);
+       u32 parts, mask;
+       int ret, i;
+
+       ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       parts = nv_rd32(priv, 0x022438);
+       mask = nv_rd32(priv, 0x022554);
+       for (i = 0; i < parts; i++) {
+               if (!(mask & (1 << i)))
+                       priv->ltc_nr++;
+       }
+       priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
+
+       ret = gf100_ltcg_init_tag_ram(pfb, priv);
+       if (ret)
+               return ret;
+
+       priv->base.tags_alloc = gf100_ltcg_tags_alloc;
+       priv->base.tags_free  = gf100_ltcg_tags_free;
+       priv->base.tags_clear = gf100_ltcg_tags_clear;
+
+       nv_subdev(priv)->intr = gf100_ltcg_intr;
+       return 0;
+}
+
+void
+gf100_ltcg_dtor(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
+
+       nouveau_mm_fini(&priv->tags);
+       nouveau_mm_free(&pfb->vram, &priv->tag_ram);
+
+       nouveau_ltcg_destroy(ltcg);
+}
+
+static int
+gf100_ltcg_init(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_ltcg_init(ltcg);
+       if (ret)
+               return ret;
+
+       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+       nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
+       if (nv_device(ltcg)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->ltc_nr);
+       nv_wr32(priv, 0x17e8d4, priv->tag_base);
+       return 0;
+}
+
+struct nouveau_oclass *
+gf100_ltcg_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(LTCG, 0xc0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gf100_ltcg_ctor,
+               .dtor = gf100_ltcg_dtor,
+               .init = gf100_ltcg_init,
+               .fini = _nouveau_ltcg_fini,
+       },
+};
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 (file)
index 0000000..87b10b8
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __NVKM_LTCG_PRIV_GF100_H__
+#define __NVKM_LTCG_PRIV_GF100_H__
+
+#include <subdev/ltcg.h>
+
+struct gf100_ltcg_priv {
+       struct nouveau_ltcg base;
+       u32 ltc_nr;
+       u32 lts_nr;
+       u32 num_tags;
+       u32 tag_base;
+       struct nouveau_mm tags;
+       struct nouveau_mm_node *tag_ram;
+};
+
+void gf100_ltcg_dtor(struct nouveau_object *);
+int  gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *);
+int  gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **);
+void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **);
+
+#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 (file)
index 0000000..e79d0e8
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+
+#include "gf100.h"
+
+static void
+gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
+{
+       u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
+       u32 stat = nv_rd32(priv, base + 0x00c);
+
+       if (stat) {
+               nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+               nv_wr32(priv, base + 0x00c, stat);
+       }
+}
+
+static void
+gm107_ltcg_intr(struct nouveau_subdev *subdev)
+{
+       struct gf100_ltcg_priv *priv = (void *)subdev;
+       u32 mask;
+
+       mask = nv_rd32(priv, 0x00017c);
+       while (mask) {
+               u32 lts, ltc = __ffs(mask);
+               for (lts = 0; lts < priv->lts_nr; lts++)
+                       gm107_ltcg_lts_isr(priv, ltc, lts);
+               mask &= ~(1 << ltc);
+       }
+
+       /* we do something horribly wrong and upset PMFB a lot, so mask off
+        * interrupts from it after the first one until it's fixed
+        */
+       nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
+}
+
+static void
+gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+{
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       u32 last = first + count - 1;
+       int p, i;
+
+       BUG_ON((first > last) || (last >= priv->num_tags));
+
+       nv_wr32(priv, 0x17e270, first);
+       nv_wr32(priv, 0x17e274, last);
+       nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */
+
+       /* wait until it's finished with clearing */
+       for (p = 0; p < priv->ltc_nr; ++p) {
+               for (i = 0; i < priv->lts_nr; ++i)
+                       nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0);
+       }
+}
+
+static int
+gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       struct gf100_ltcg_priv *priv;
+       struct nouveau_fb *pfb = nouveau_fb(parent);
+       u32 parts, mask;
+       int ret, i;
+
+       ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       parts = nv_rd32(priv, 0x022438);
+       mask = nv_rd32(priv, 0x021c14);
+       for (i = 0; i < parts; i++) {
+               if (!(mask & (1 << i)))
+                       priv->ltc_nr++;
+       }
+       priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
+
+       ret = gf100_ltcg_init_tag_ram(pfb, priv);
+       if (ret)
+               return ret;
+
+       priv->base.tags_alloc = gf100_ltcg_tags_alloc;
+       priv->base.tags_free  = gf100_ltcg_tags_free;
+       priv->base.tags_clear = gm107_ltcg_tags_clear;
+
+       nv_subdev(priv)->intr = gm107_ltcg_intr;
+       return 0;
+}
+
+static int
+gm107_ltcg_init(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_ltcg_init(ltcg);
+       if (ret)
+               return ret;
+
+       nv_wr32(priv, 0x17e27c, priv->ltc_nr);
+       nv_wr32(priv, 0x17e278, priv->tag_base);
+       return 0;
+}
+
+struct nouveau_oclass *
+gm107_ltcg_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(LTCG, 0xff),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gm107_ltcg_ctor,
+               .dtor = gf100_ltcg_dtor,
+               .init = gm107_ltcg_init,
+               .fini = _nouveau_ltcg_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
deleted file mode 100644 (file)
index cce65cc..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/ltcg.h>
-#include <subdev/fb.h>
-#include <subdev/timer.h>
-
-struct nvc0_ltcg_priv {
-       struct nouveau_ltcg base;
-       u32 part_nr;
-       u32 subp_nr;
-       u32 num_tags;
-       u32 tag_base;
-       struct nouveau_mm tags;
-       struct nouveau_mm_node *tag_ram;
-};
-
-static void
-nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp)
-{
-       u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
-       u32 stat = nv_rd32(priv, subp_base + 0x020);
-
-       if (stat) {
-               nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat);
-               nv_wr32(priv, subp_base + 0x020, stat);
-       }
-}
-
-static void
-nvc0_ltcg_intr(struct nouveau_subdev *subdev)
-{
-       struct nvc0_ltcg_priv *priv = (void *)subdev;
-       u32 units;
-
-       units = nv_rd32(priv, 0x00017c);
-       while (units) {
-               u32 subp, unit = ffs(units) - 1;
-               for (subp = 0; subp < priv->subp_nr; subp++)
-                       nvc0_ltcg_subp_isr(priv, unit, subp);
-               units &= ~(1 << unit);
-       }
-
-       /* we do something horribly wrong and upset PMFB a lot, so mask off
-        * interrupts from it after the first one until it's fixed
-        */
-       nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
-}
-
-static int
-nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
-                    struct nouveau_mm_node **pnode)
-{
-       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
-       int ret;
-
-       ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
-       if (ret)
-               *pnode = NULL;
-
-       return ret;
-}
-
-static void
-nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
-{
-       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
-
-       nouveau_mm_free(&priv->tags, pnode);
-}
-
-static void
-nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
-{
-       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
-       u32 last = first + count - 1;
-       int p, i;
-
-       BUG_ON((first > last) || (last >= priv->num_tags));
-
-       nv_wr32(priv, 0x17e8cc, first);
-       nv_wr32(priv, 0x17e8d0, last);
-       nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
-
-       /* wait until it's finished with clearing */
-       for (p = 0; p < priv->part_nr; ++p) {
-               for (i = 0; i < priv->subp_nr; ++i)
-                       nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
-       }
-}
-
-/* TODO: Figure out tag memory details and drop the over-cautious allocation.
- */
-static int
-nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
-{
-       u32 tag_size, tag_margin, tag_align;
-       int ret;
-
-       /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
-       priv->num_tags = (pfb->ram->size >> 17) / 4;
-       if (priv->num_tags > (1 << 17))
-               priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
-       priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
-
-       tag_align = priv->part_nr * 0x800;
-       tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
-
-       /* 4 part 4 sub: 0x2000 bytes for 56 tags */
-       /* 3 part 4 sub: 0x6000 bytes for 168 tags */
-       /*
-        * About 147 bytes per tag. Let's be safe and allocate x2, which makes
-        * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags.
-        *
-        * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %.
-        */
-       tag_size  = (priv->num_tags / 64) * 0x6000 + tag_margin;
-       tag_size += tag_align;
-       tag_size  = (tag_size + 0xfff) >> 12; /* round up */
-
-       ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
-                             &priv->tag_ram);
-       if (ret) {
-               priv->num_tags = 0;
-       } else {
-               u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
-
-               tag_base += tag_align - 1;
-               ret = do_div(tag_base, tag_align);
-
-               priv->tag_base = tag_base;
-       }
-       ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
-
-       return ret;
-}
-
-static int
-nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-              struct nouveau_oclass *oclass, void *data, u32 size,
-              struct nouveau_object **pobject)
-{
-       struct nvc0_ltcg_priv *priv;
-       struct nouveau_fb *pfb = nouveau_fb(parent);
-       u32 parts, mask;
-       int ret, i;
-
-       ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       parts = nv_rd32(priv, 0x022438);
-       mask = nv_rd32(priv, 0x022554);
-       for (i = 0; i < parts; i++) {
-               if (!(mask & (1 << i)))
-                       priv->part_nr++;
-       }
-       priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
-
-       ret = nvc0_ltcg_init_tag_ram(pfb, priv);
-       if (ret)
-               return ret;
-
-       priv->base.tags_alloc = nvc0_ltcg_tags_alloc;
-       priv->base.tags_free  = nvc0_ltcg_tags_free;
-       priv->base.tags_clear = nvc0_ltcg_tags_clear;
-
-       nv_subdev(priv)->intr = nvc0_ltcg_intr;
-       return 0;
-}
-
-static void
-nvc0_ltcg_dtor(struct nouveau_object *object)
-{
-       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
-       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
-       struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
-
-       nouveau_mm_fini(&priv->tags);
-       nouveau_mm_free(&pfb->vram, &priv->tag_ram);
-
-       nouveau_ltcg_destroy(ltcg);
-}
-
-static int
-nvc0_ltcg_init(struct nouveau_object *object)
-{
-       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
-       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
-       int ret;
-
-       ret = nouveau_ltcg_init(ltcg);
-       if (ret)
-               return ret;
-
-       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
-       nv_wr32(priv, 0x17e8d8, priv->part_nr);
-       if (nv_device(ltcg)->card_type >= NV_E0)
-               nv_wr32(priv, 0x17e000, priv->part_nr);
-       nv_wr32(priv, 0x17e8d4, priv->tag_base);
-       return 0;
-}
-
-struct nouveau_oclass
-nvc0_ltcg_oclass = {
-       .handle = NV_SUBDEV(LTCG, 0xc0),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nvc0_ltcg_ctor,
-               .dtor = nvc0_ltcg_dtor,
-               .init = nvc0_ltcg_init,
-               .fini = _nouveau_ltcg_fini,
-       },
-};
index b4b9943773bcfa710580244d43daf69a13d5043b..8a5555192fa5ea503d97aa11efc84ed6968c7e6d 100644 (file)
@@ -93,7 +93,7 @@ _nouveau_mc_dtor(struct nouveau_object *object)
 {
        struct nouveau_device *device = nv_device(object);
        struct nouveau_mc *pmc = (void *)object;
-       free_irq(device->pdev->irq, pmc);
+       free_irq(pmc->irq, pmc);
        if (pmc->use_msi)
                pci_disable_msi(device->pdev);
        nouveau_subdev_destroy(&pmc->base);
@@ -114,33 +114,44 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       switch (device->pdev->device & 0x0ff0) {
-       case 0x00f0:
-       case 0x02e0:
-               /* BR02? NFI how these would be handled yet exactly */
-               break;
-       default:
-               switch (device->chipset) {
-               case 0xaa: break; /* reported broken, nv also disable it */
-               default:
-                       pmc->use_msi = true;
+       if (nv_device_is_pci(device))
+               switch (device->pdev->device & 0x0ff0) {
+               case 0x00f0:
+               case 0x02e0:
+                       /* BR02? NFI how these would be handled yet exactly */
                        break;
+               default:
+                       switch (device->chipset) {
+                       case 0xaa:
+                               /* reported broken, nv also disable it */
+                               break;
+                       default:
+                               pmc->use_msi = true;
+                               break;
                }
-       }
 
-       pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", pmc->use_msi);
-       if (pmc->use_msi && oclass->msi_rearm) {
-               pmc->use_msi = pci_enable_msi(device->pdev) == 0;
-               if (pmc->use_msi) {
-                       nv_info(pmc, "MSI interrupts enabled\n");
-                       oclass->msi_rearm(pmc);
+               pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI",
+                                              pmc->use_msi);
+
+               if (pmc->use_msi && oclass->msi_rearm) {
+                       pmc->use_msi = pci_enable_msi(device->pdev) == 0;
+                       if (pmc->use_msi) {
+                               nv_info(pmc, "MSI interrupts enabled\n");
+                               oclass->msi_rearm(pmc);
+                       }
+               } else {
+                       pmc->use_msi = false;
                }
-       } else {
-               pmc->use_msi = false;
        }
 
-       ret = request_irq(device->pdev->irq, nouveau_mc_intr,
-                         IRQF_SHARED, "nouveau", pmc);
+       ret = nv_device_get_irq(device, true);
+       if (ret < 0)
+               return ret;
+       pmc->irq = ret;
+
+       ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau",
+                         pmc);
+
        if (ret < 0)
                return ret;
 
index 13c5af88a6019d8b1e976dbe8c2e919b9ec8f6fc..51fcf79604173ad9a299bde564a782d63d097be4 100644 (file)
@@ -96,7 +96,7 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version)
        acpi_handle handle;
        int rev;
 
-       handle = ACPI_HANDLE(&device->pdev->dev);
+       handle = ACPI_HANDLE(nv_device_base(device));
        if (!handle)
                return false;
 
index 80e584a1bd1cf4e4d6a32a8e3cbfd79739acd1e3..9ad01da6eacb7d5afd2c20e62440dfc84b1cf00c 100644 (file)
@@ -110,16 +110,18 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
                poll = false;
                break;
        case NOUVEAU_THERM_CTRL_AUTO:
-               if (priv->fan->bios.nr_fan_trip) {
+               switch(priv->fan->bios.fan_mode) {
+               case NVBIOS_THERM_FAN_TRIP:
                        duty = nouveau_therm_update_trip(therm);
-               } else
-               if (priv->fan->bios.linear_min_temp ||
-                   priv->fan->bios.linear_max_temp) {
+                       break;
+               case NVBIOS_THERM_FAN_LINEAR:
                        duty = nouveau_therm_update_linear(therm);
-               } else {
+                       break;
+               case NVBIOS_THERM_FAN_OTHER:
                        if (priv->cstate)
                                duty = priv->cstate;
                        poll = false;
+                       break;
                }
                immd = false;
                break;
@@ -179,7 +181,7 @@ nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
 
        /* do not allow automatic fan management if the thermal sensor is
         * not available */
-       if (priv->mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
+       if (mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
                return -EINVAL;
 
        if (priv->mode == mode)
index 95f6129eeede9e39f116844cefc8e324eced20fc..016990a8252c682f7bc7c93ead9fa8a9c5394979 100644 (file)
@@ -54,8 +54,10 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
 
        /* check that we're not already at the target duty cycle */
        duty = fan->get(therm);
-       if (duty == target)
-               goto done;
+       if (duty == target) {
+               spin_unlock_irqrestore(&fan->lock, flags);
+               return 0;
+       }
 
        /* smooth out the fanspeed increase/decrease */
        if (!immediate && duty >= 0) {
@@ -73,8 +75,15 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
 
        nv_debug(therm, "FAN update: %d\n", duty);
        ret = fan->set(therm, duty);
-       if (ret)
-               goto done;
+       if (ret) {
+               spin_unlock_irqrestore(&fan->lock, flags);
+               return ret;
+       }
+
+       /* fan speed updated, drop the fan lock before grabbing the
+        * alarm-scheduling lock and risking a deadlock
+        */
+       spin_unlock_irqrestore(&fan->lock, flags);
 
        /* schedule next fan update, if not at target speed already */
        if (list_empty(&fan->alarm.head) && target != duty) {
@@ -92,8 +101,6 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
                ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);
        }
 
-done:
-       spin_unlock_irqrestore(&fan->lock, flags);
        return ret;
 }
 
@@ -185,11 +192,8 @@ nouveau_therm_fan_set_defaults(struct nouveau_therm *therm)
        priv->fan->bios.max_duty = 100;
        priv->fan->bios.bump_period = 500;
        priv->fan->bios.slow_down_period = 2000;
-/*XXX: talk to mupuf */
-#if 0
        priv->fan->bios.linear_min_temp = 40;
        priv->fan->bios.linear_max_temp = 85;
-#endif
 }
 
 static void
@@ -235,7 +239,8 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)
        /* attempt to locate a drivable fan, and determine control method */
        ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
        if (ret == 0) {
-               if (func.log[0] & DCB_GPIO_LOG_DIR_IN) {
+               /* FIXME: is this really the place to perform such checks ? */
+               if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
                        nv_debug(therm, "GPIO_FAN is in input mode\n");
                        ret = -EINVAL;
                } else {
index 5f71db8e8992e0c38ec2c46f945450d8e9778c51..9a5c07340263305f1310d1e6a3520808c2606049 100644 (file)
@@ -67,7 +67,7 @@ nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)
        if (priv->base.bios.pwm_freq) {
                divs = 1;
                if (therm->pwm_clock)
-                       divs = therm->pwm_clock(therm);
+                       divs = therm->pwm_clock(therm, priv->func.line);
                divs /= priv->base.bios.pwm_freq;
        }
 
index 8cf7597a2182d78ac6f6a57e7ee5e997bf1713ff..321db927d638c91a82141373fd8ff6af9a7be262 100644 (file)
@@ -93,7 +93,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
 }
 
 int
-nv50_fan_pwm_clock(struct nouveau_therm *therm)
+nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)
 {
        int chipset = nv_device(therm)->chipset;
        int crystal = nv_device(therm)->crystal;
index 4dd4f81ae873d32c6aa47ae1c64d65fd252cae11..43fec17ea540b6c53af704931d4baf29d2391e4e 100644 (file)
@@ -32,10 +32,12 @@ static int
 pwm_info(struct nouveau_therm *therm, int line)
 {
        u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
+
        switch (gpio & 0x000000c0) {
        case 0x00000000: /* normal mode, possibly pwm forced off by us */
        case 0x00000040: /* nvio special */
                switch (gpio & 0x0000001f) {
+               case 0x00: return 2;
                case 0x19: return 1;
                case 0x1c: return 0;
                default:
@@ -56,8 +58,9 @@ nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
        int indx = pwm_info(therm, line);
        if (indx < 0)
                return indx;
-
-       nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
+       else if (indx < 2)
+               nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
+       /* nothing to do for indx == 2, it seems hardwired to PTHERM */
        return 0;
 }
 
@@ -67,10 +70,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
        int indx = pwm_info(therm, line);
        if (indx < 0)
                return indx;
-
-       if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
-               *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
-               *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+       else if (indx < 2) {
+               if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
+                       *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
+                       *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+                       return 0;
+               }
+       } else if (indx == 2) {
+               *divs = nv_rd32(therm, 0x0200d8) & 0x1fff;
+               *duty = nv_rd32(therm, 0x0200dc) & 0x1fff;
                return 0;
        }
 
@@ -83,16 +91,26 @@ nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
        int indx = pwm_info(therm, line);
        if (indx < 0)
                return indx;
-
-       nv_wr32(therm, 0x00e114 + (indx * 8), divs);
-       nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
+       else if (indx < 2) {
+               nv_wr32(therm, 0x00e114 + (indx * 8), divs);
+               nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
+       } else if (indx == 2) {
+               nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */
+               nv_wr32(therm, 0x0200dc, duty | 0x40000000);
+       }
        return 0;
 }
 
 static int
-nvd0_fan_pwm_clock(struct nouveau_therm *therm)
+nvd0_fan_pwm_clock(struct nouveau_therm *therm, int line)
 {
-       return (nv_device(therm)->crystal * 1000) / 20;
+       int indx = pwm_info(therm, line);
+       if (indx < 0)
+               return 0;
+       else if (indx < 2)
+               return (nv_device(therm)->crystal * 1000) / 20;
+       else
+               return nv_device(therm)->crystal * 1000 / 10;
 }
 
 static int
index 96f8f95693ce10654a1a4339a1e0eb16dba6848e..916fca5c78162488a23e65e11188cda9b2d0e0eb 100644 (file)
@@ -143,7 +143,7 @@ void nv40_therm_intr(struct nouveau_subdev *);
 int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
 int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);
 int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
-int nv50_fan_pwm_clock(struct nouveau_therm *);
+int nv50_fan_pwm_clock(struct nouveau_therm *, int);
 int nv84_temp_get(struct nouveau_therm *therm);
 int nv84_therm_fini(struct nouveau_object *object, bool suspend);
 
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 (file)
index 0000000..37484db
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv04.h"
+
+static int
+gk20a_timer_init(struct nouveau_object *object)
+{
+       struct nv04_timer_priv *priv = (void *)object;
+       u32 hi = upper_32_bits(priv->suspend_time);
+       u32 lo = lower_32_bits(priv->suspend_time);
+       int ret;
+
+       ret = nouveau_timer_init(&priv->base);
+       if (ret)
+               return ret;
+
+       nv_debug(priv, "time low        : 0x%08x\n", lo);
+       nv_debug(priv, "time high       : 0x%08x\n", hi);
+
+       /* restore the time before suspend */
+       nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
+       nv_wr32(priv, NV04_PTIMER_TIME_0, lo);
+       return 0;
+}
+
+struct nouveau_oclass
+gk20a_timer_oclass = {
+       .handle = NV_SUBDEV(TIMER, 0xff),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_timer_ctor,
+               .dtor = nv04_timer_dtor,
+               .init = gk20a_timer_init,
+               .fini = nv04_timer_fini,
+       }
+};
index c0bdd10358d76b748d4fc22e3ac480c99760cadd..240ed0b983a9714ff12da2b43133b76cb9befd20 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/timer.h>
-
-#define NV04_PTIMER_INTR_0      0x009100
-#define NV04_PTIMER_INTR_EN_0   0x009140
-#define NV04_PTIMER_NUMERATOR   0x009200
-#define NV04_PTIMER_DENOMINATOR 0x009210
-#define NV04_PTIMER_TIME_0      0x009400
-#define NV04_PTIMER_TIME_1      0x009410
-#define NV04_PTIMER_ALARM_0     0x009420
-
-struct nv04_timer_priv {
-       struct nouveau_timer base;
-       struct list_head alarms;
-       spinlock_t lock;
-       u64 suspend_time;
-};
+#include "nv04.h"
 
 static u64
 nv04_timer_read(struct nouveau_timer *ptimer)
@@ -142,35 +127,14 @@ nv04_timer_intr(struct nouveau_subdev *subdev)
        }
 }
 
-static int
-nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nv04_timer_priv *priv;
-       int ret;
-
-       ret = nouveau_timer_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.base.intr = nv04_timer_intr;
-       priv->base.read = nv04_timer_read;
-       priv->base.alarm = nv04_timer_alarm;
-       priv->base.alarm_cancel = nv04_timer_alarm_cancel;
-       priv->suspend_time = 0;
-
-       INIT_LIST_HEAD(&priv->alarms);
-       spin_lock_init(&priv->lock);
-       return 0;
-}
-
-static void
-nv04_timer_dtor(struct nouveau_object *object)
+int
+nv04_timer_fini(struct nouveau_object *object, bool suspend)
 {
        struct nv04_timer_priv *priv = (void *)object;
-       return nouveau_timer_destroy(&priv->base);
+       if (suspend)
+               priv->suspend_time = nv04_timer_read(&priv->base);
+       nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
+       return nouveau_timer_fini(&priv->base, suspend);
 }
 
 static int
@@ -257,14 +221,35 @@ nv04_timer_init(struct nouveau_object *object)
        return 0;
 }
 
-static int
-nv04_timer_fini(struct nouveau_object *object, bool suspend)
+void
+nv04_timer_dtor(struct nouveau_object *object)
 {
        struct nv04_timer_priv *priv = (void *)object;
-       if (suspend)
-               priv->suspend_time = nv04_timer_read(&priv->base);
-       nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
-       return nouveau_timer_fini(&priv->base, suspend);
+       return nouveau_timer_destroy(&priv->base);
+}
+
+int
+nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nv04_timer_priv *priv;
+       int ret;
+
+       ret = nouveau_timer_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.base.intr = nv04_timer_intr;
+       priv->base.read = nv04_timer_read;
+       priv->base.alarm = nv04_timer_alarm;
+       priv->base.alarm_cancel = nv04_timer_alarm_cancel;
+       priv->suspend_time = 0;
+
+       INIT_LIST_HEAD(&priv->alarms);
+       spin_lock_init(&priv->lock);
+       return 0;
 }
 
 struct 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 (file)
index 0000000..4bc1526
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __NVKM_TIMER_NV04_H__
+#define __NVKM_TIMER_NV04_H__
+
+#include "priv.h"
+
+#define NV04_PTIMER_INTR_0      0x009100
+#define NV04_PTIMER_INTR_EN_0   0x009140
+#define NV04_PTIMER_NUMERATOR   0x009200
+#define NV04_PTIMER_DENOMINATOR 0x009210
+#define NV04_PTIMER_TIME_0      0x009400
+#define NV04_PTIMER_TIME_1      0x009410
+#define NV04_PTIMER_ALARM_0     0x009420
+
+struct nv04_timer_priv {
+       struct nouveau_timer base;
+       struct list_head alarms;
+       spinlock_t lock;
+       u64 suspend_time;
+};
+
+int  nv04_timer_ctor(struct nouveau_object *, struct nouveau_object *,
+                    struct nouveau_oclass *, void *, u32,
+                    struct nouveau_object **);
+void nv04_timer_dtor(struct nouveau_object *);
+int  nv04_timer_fini(struct nouveau_object *, bool);
+
+#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 (file)
index 0000000..799dae3
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __NVKM_TIMER_PRIV_H__
+#define __NVKM_TIMER_PRIV_H__
+
+#include <subdev/timer.h>
+
+#endif
index 0e3270c3ffd2296caad7cdbcbaadf9fdc7044be8..41be3424c9060d83c555f2ea99719ee5d40468d6 100644 (file)
@@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
 
        /* Calculate our timings */
        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)
                regp->CRTC[NV_CIO_CRE_86] = 0x1;
        }
 
-       regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
+       regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
        /* Enable slaved mode (called MODE_TV in nv4ref.h) */
        if (lvds_output || tmds_output || tv_output)
                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)
        regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
                                NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
                                NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
-       if (crtc->fb->depth == 16)
+       if (crtc->primary->fb->depth == 16)
                regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
        if (nv_device(drm->device)->chipset >= 0x11)
                regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
@@ -609,7 +609,7 @@ static int
 nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
 {
        struct nv04_display *disp = nv04_display(crtc->dev);
-       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        int ret;
 
@@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
         * mark the lut values as dirty by setting depth==0, and it'll be
         * uploaded on the first mode_set_base()
         */
-       if (!nv_crtc->base.fb) {
+       if (!nv_crtc->base.primary->fb) {
                nv_crtc->lut.depth = 0;
                return;
        }
@@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
        /* no fb bound */
-       if (!atomic && !crtc->fb) {
+       if (!atomic && !crtc->primary->fb) {
                NV_DEBUG(drm, "No FB bound\n");
                return 0;
        }
@@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                drm_fb = passed_fb;
                fb = nouveau_framebuffer(passed_fb);
        } else {
-               drm_fb = crtc->fb;
-               fb = nouveau_framebuffer(crtc->fb);
+               drm_fb = crtc->primary->fb;
+               fb = nouveau_framebuffer(crtc->primary->fb);
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
 
        /* Update the framebuffer format. */
        regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
-       regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
+       regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
        regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
-       if (crtc->fb->depth == 16)
+       if (crtc->primary->fb->depth == 16)
                regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
        crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
        NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
@@ -1048,7 +1048,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set)
 
        /* get a pm reference here */
        ret = pm_runtime_get_sync(dev->dev);
-       if (ret < 0)
+       if (ret < 0 && ret != -EACCES)
                return ret;
 
        ret = drm_crtc_helper_set_config(set);
index 7fdc51e2a571bee85b6fcf707890c8e4138ca8d9..a2d669b4acf2452d86b32403936fb42bfaa7b11f 100644 (file)
@@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
        /* Output property. */
        if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
            (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
-            encoder->crtc->fb->depth > connector->display_info.bpc * 3)) {
+            encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
                if (nv_device(drm->device)->chipset == 0x11)
                        regp->dither = savep->dither | 0x00010000;
                else {
index 900fae01793e7884ee8033a11d6c247cbeb36678..b13f441c64314f24581bed203a9fdffd3602f624 100644 (file)
@@ -97,6 +97,7 @@ nouveau_abi16_swclass(struct nouveau_drm *drm)
        case NV_C0:
        case NV_D0:
        case NV_E0:
+       case GM100:
                return 0x906e;
        }
 
@@ -139,7 +140,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
 
        /* destroy channel object, all children will be killed too */
        if (chan->chan) {
-               abi16->handles &= ~(1 << (chan->chan->handle & 0xffff));
+               abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));
                nouveau_channel_del(&chan->chan);
        }
 
@@ -179,12 +180,21 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
                getparam->value = device->chipset;
                break;
        case NOUVEAU_GETPARAM_PCI_VENDOR:
-               getparam->value = dev->pdev->vendor;
+               if (nv_device_is_pci(device))
+                       getparam->value = dev->pdev->vendor;
+               else
+                       getparam->value = 0;
                break;
        case NOUVEAU_GETPARAM_PCI_DEVICE:
-               getparam->value = dev->pdev->device;
+               if (nv_device_is_pci(device))
+                       getparam->value = dev->pdev->device;
+               else
+                       getparam->value = 0;
                break;
        case NOUVEAU_GETPARAM_BUS_TYPE:
+               if (!nv_device_is_pci(device))
+                       getparam->value = 3;
+               else
                if (drm_pci_device_is_agp(dev))
                        getparam->value = 0;
                else
@@ -270,8 +280,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
                return nouveau_abi16_put(abi16, -EINVAL);
 
        /* allocate "abi16 channel" data and make up a handle for it */
-       init->channel = ffsll(~abi16->handles);
-       if (!init->channel--)
+       init->channel = __ffs64(~abi16->handles);
+       if (~abi16->handles == 0)
                return nouveau_abi16_put(abi16, -ENOSPC);
 
        chan = kzalloc(sizeof(*chan), GFP_KERNEL);
@@ -280,7 +290,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        INIT_LIST_HEAD(&chan->notifiers);
        list_add(&chan->head, &abi16->channels);
-       abi16->handles |= (1 << init->channel);
+       abi16->handles |= (1ULL << init->channel);
 
        /* create channel object and initialise dma and fence management */
        ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN |
index 2953c4e91e1ae9fea8fff60501dfa863d56c63ea..51666daddb948fd3650f6c14dd7d90963d8ce5dd 100644 (file)
@@ -75,7 +75,7 @@ nouveau_agp_enabled(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
 
-       if (!drm_pci_device_is_agp(dev) || !dev->agp)
+       if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp)
                return false;
 
        if (drm->agp.stat == UNKNOWN) {
index 4c3feaaa10375721627b4bb00c5f95f0e6eb8a9a..8268a4ccac159e7d7fdd38f04857572448e6b81b 100644 (file)
@@ -1474,9 +1474,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
                case 0:
                        entry->dpconf.link_bw = 162000;
                        break;
-               default:
+               case 1:
                        entry->dpconf.link_bw = 270000;
                        break;
+               default:
+                       entry->dpconf.link_bw = 540000;
+                       break;
                }
                switch ((conf & 0x0f000000) >> 24) {
                case 0xf:
@@ -2069,6 +2072,10 @@ nouveau_bios_init(struct drm_device *dev)
        struct nvbios *bios = &drm->vbios;
        int ret;
 
+       /* only relevant for PCI devices */
+       if (!dev->pdev)
+               return 0;
+
        if (!NVInitVBIOS(dev))
                return -ENODEV;
 
index 4aed1714b9ab7d289bbadc867f9af40b046825f2..b6dc85c614be402ca5d6717bea842c0448ce4b39 100644 (file)
@@ -1255,7 +1255,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                /* fallthrough, tiled memory */
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
-               mem->bus.base = pci_resource_start(dev->pdev, 1);
+               mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);
                mem->bus.is_iomem = true;
                if (nv_device(drm->device)->card_type >= NV_50) {
                        struct nouveau_bar *bar = nouveau_bar(drm->device);
@@ -1293,7 +1293,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
        struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct nouveau_device *device = nv_device(drm->device);
-       u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT;
+       u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT;
        int ret;
 
        /* 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)
 {
        struct ttm_dma_tt *ttm_dma = (void *)ttm;
        struct nouveau_drm *drm;
+       struct nouveau_device *device;
        struct drm_device *dev;
        unsigned i;
        int r;
@@ -1348,6 +1349,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
        }
 
        drm = nouveau_bdev(ttm->bdev);
+       device = nv_device(drm->device);
        dev = drm->dev;
 
 #if __OS_HAS_AGP
@@ -1368,13 +1370,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
        }
 
        for (i = 0; i < ttm->num_pages; i++) {
-               ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i],
-                                                  0, PAGE_SIZE,
-                                                  PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) {
+               ttm_dma->dma_address[i] = nv_device_map_page(device,
+                                                            ttm->pages[i]);
+               if (!ttm_dma->dma_address[i]) {
                        while (--i) {
-                               pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
-                                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                               nv_device_unmap_page(device,
+                                                    ttm_dma->dma_address[i]);
                                ttm_dma->dma_address[i] = 0;
                        }
                        ttm_pool_unpopulate(ttm);
@@ -1389,6 +1390,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
 {
        struct ttm_dma_tt *ttm_dma = (void *)ttm;
        struct nouveau_drm *drm;
+       struct nouveau_device *device;
        struct drm_device *dev;
        unsigned i;
        bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1397,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
                return;
 
        drm = nouveau_bdev(ttm->bdev);
+       device = nv_device(drm->device);
        dev = drm->dev;
 
 #if __OS_HAS_AGP
@@ -1415,8 +1418,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
 
        for (i = 0; i < ttm->num_pages; i++) {
                if (ttm_dma->dma_address[i]) {
-                       pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
-                                      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                       nv_device_unmap_page(device, ttm_dma->dma_address[i]);
                }
        }
 
index cc5152be2cf121a0901d323bf41b57886b56b27a..ccb6b452d6d00e34738efdf56e5c3fcb731e923a 100644 (file)
@@ -154,7 +154,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
                         * nfi why this exists, it came from the -nv ddx.
                         */
                        args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR;
-                       args.start = pci_resource_start(device->pdev, 1);
+                       args.start = nv_device_resource_start(device, 1);
                        args.limit = args.start + limit;
                } else {
                        args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
index 1674882d60d5e842547e420f1baf48a13d534e66..d07ce028af516ace0b20db1418a7f9ed14b78c31 100644 (file)
@@ -255,7 +255,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        }
 
        ret = pm_runtime_get_sync(connector->dev->dev);
-       if (ret < 0)
+       if (ret < 0 && ret != -EACCES)
                return conn_status;
 
        i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
@@ -960,7 +960,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
        case DCB_CONNECTOR_DP       : return DRM_MODE_CONNECTOR_DisplayPort;
        case DCB_CONNECTOR_eDP      : return DRM_MODE_CONNECTOR_eDP;
        case DCB_CONNECTOR_HDMI_0   :
-       case DCB_CONNECTOR_HDMI_1   : return DRM_MODE_CONNECTOR_HDMIA;
+       case DCB_CONNECTOR_HDMI_1   :
+       case DCB_CONNECTOR_HDMI_C   : return DRM_MODE_CONNECTOR_HDMIA;
        default:
                break;
        }
index 24011596af434276bbe1b9a82a26252229c20c5a..3ff030dc1ee35d34925b2fd5464f1236ad10d925 100644 (file)
@@ -105,7 +105,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                if (retry) ndelay(crtc->linedur_ns);
        } while (retry--);
 
-       *hpos = calc(args.hblanks, args.hblanke, args.htotal, args.hline);
+       *hpos = args.hline;
        *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
        if (stime) *stime = ns_to_ktime(args.time[0]);
        if (etime) *etime = ns_to_ktime(args.time[1]);
@@ -419,6 +419,7 @@ int
 nouveau_display_create(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nouveau_dev(dev);
        struct nouveau_display *disp;
        int ret, gen;
 
@@ -459,7 +460,7 @@ nouveau_display_create(struct drm_device *dev)
        }
 
        dev->mode_config.funcs = &nouveau_mode_config_funcs;
-       dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
+       dev->mode_config.fb_base = nv_device_resource_start(device, 1);
 
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
@@ -488,6 +489,7 @@ nouveau_display_create(struct drm_device *dev)
 
        if (drm->vbios.dcb.entries) {
                static const u16 oclass[] = {
+                       GM107_DISP_CLASS,
                        NVF0_DISP_CLASS,
                        NVE0_DISP_CLASS,
                        NVD0_DISP_CLASS,
@@ -569,7 +571,7 @@ nouveau_display_suspend(struct drm_device *dev)
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_framebuffer *nouveau_fb;
 
-               nouveau_fb = nouveau_framebuffer(crtc->fb);
+               nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
                if (!nouveau_fb || !nouveau_fb->nvbo)
                        continue;
 
@@ -596,7 +598,7 @@ nouveau_display_repin(struct drm_device *dev)
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_framebuffer *nouveau_fb;
 
-               nouveau_fb = nouveau_framebuffer(crtc->fb);
+               nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
                if (!nouveau_fb || !nouveau_fb->nvbo)
                        continue;
 
@@ -693,7 +695,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
        struct drm_device *dev = crtc->dev;
        struct nouveau_drm *drm = nouveau_drm(dev);
-       struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
+       struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
        struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
        struct nouveau_page_flip_state *s;
        struct nouveau_channel *chan = drm->channel;
@@ -767,7 +769,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                goto fail_unreserve;
 
        /* Update the crtc struct and cleanup */
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        nouveau_bo_fence(old_bo, fence);
        ttm_bo_unreserve(&old_bo->bo);
index 89c484d8ac2666d8b3c04bb818cb5eec2665bb38..7147b87c5e5d695d605c717bda5ae486941fab2a 100644 (file)
@@ -33,6 +33,7 @@
 #include <core/client.h>
 #include <core/gpuobj.h>
 #include <core/class.h>
+#include <core/option.h>
 
 #include <engine/device.h>
 #include <engine/disp.h>
@@ -81,7 +82,7 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400);
 static struct drm_driver driver;
 
 static u64
-nouveau_name(struct pci_dev *pdev)
+nouveau_pci_name(struct pci_dev *pdev)
 {
        u64 name = (u64)pci_domain_nr(pdev->bus) << 32;
        name |= pdev->bus->number << 16;
@@ -89,15 +90,30 @@ nouveau_name(struct pci_dev *pdev)
        return name | PCI_FUNC(pdev->devfn);
 }
 
+static u64
+nouveau_platform_name(struct platform_device *platformdev)
+{
+       return platformdev->id;
+}
+
+static u64
+nouveau_name(struct drm_device *dev)
+{
+       if (dev->pdev)
+               return nouveau_pci_name(dev->pdev);
+       else
+               return nouveau_platform_name(dev->platformdev);
+}
+
 static int
-nouveau_cli_create(struct pci_dev *pdev, const char *name,
+nouveau_cli_create(u64 name, const char *sname,
                   int size, void **pcli)
 {
        struct nouveau_cli *cli;
        int ret;
 
        *pcli = NULL;
-       ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config,
+       ret = nouveau_client_create_(sname, name, nouveau_config,
                                     nouveau_debug, size, pcli);
        cli = *pcli;
        if (ret) {
@@ -281,7 +297,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
        remove_conflicting_framebuffers(aper, "nouveaufb", boot);
        kfree(aper);
 
-       ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev),
+       ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
+                                   nouveau_pci_name(pdev), pci_name(pdev),
                                    nouveau_config, nouveau_debug, &device);
        if (ret)
                return ret;
@@ -300,22 +317,27 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
 
 static void
-nouveau_get_hdmi_dev(struct drm_device *dev)
+nouveau_get_hdmi_dev(struct nouveau_drm *drm)
 {
-       struct nouveau_drm *drm = dev->dev_private;
-       struct pci_dev *pdev = dev->pdev;
+       struct pci_dev *pdev = drm->dev->pdev;
+
+       if (!pdev) {
+               DRM_INFO("not a PCI device; no HDMI\n");
+               drm->hdmi_device = NULL;
+               return;
+       }
 
        /* subfunction one is a hdmi audio device? */
        drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
                                                PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
 
        if (!drm->hdmi_device) {
-               DRM_INFO("hdmi device  not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);
+               NV_DEBUG(drm, "hdmi device not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);
                return;
        }
 
        if ((drm->hdmi_device->class >> 8) != PCI_CLASS_MULTIMEDIA_HD_AUDIO) {
-               DRM_INFO("possible hdmi device  not audio %d\n", drm->hdmi_device->class);
+               NV_DEBUG(drm, "possible hdmi device not audio %d\n", drm->hdmi_device->class);
                pci_dev_put(drm->hdmi_device);
                drm->hdmi_device = NULL;
                return;
@@ -330,22 +352,24 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
        struct nouveau_drm *drm;
        int ret;
 
-       ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm);
+       ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
+                                (void **)&drm);
        if (ret)
                return ret;
 
        dev->dev_private = drm;
        drm->dev = dev;
+       nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");
 
        INIT_LIST_HEAD(&drm->clients);
        spin_lock_init(&drm->tile.lock);
 
-       nouveau_get_hdmi_dev(dev);
+       nouveau_get_hdmi_dev(drm);
 
        /* make sure AGP controller is in a consistent state before we
         * (possibly) execute vbios init tables (see nouveau_agp.h)
         */
-       if (drm_pci_device_is_agp(dev) && dev->agp) {
+       if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
                /* dummy device object, doesn't init anything, but allows
                 * agp code access to registers
                 */
@@ -486,13 +510,13 @@ nouveau_drm_remove(struct pci_dev *pdev)
 }
 
 static int
-nouveau_do_suspend(struct drm_device *dev)
+nouveau_do_suspend(struct drm_device *dev, bool runtime)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_cli *cli;
        int ret;
 
-       if (dev->mode_config.num_crtc) {
+       if (dev->mode_config.num_crtc && !runtime) {
                NV_INFO(drm, "suspending display...\n");
                ret = nouveau_display_suspend(dev);
                if (ret)
@@ -566,7 +590,7 @@ int nouveau_pmops_suspend(struct device *dev)
        if (drm_dev->mode_config.num_crtc)
                nouveau_fbcon_set_suspend(drm_dev, 1);
 
-       ret = nouveau_do_suspend(drm_dev);
+       ret = nouveau_do_suspend(drm_dev, false);
        if (ret)
                return ret;
 
@@ -646,7 +670,7 @@ static int nouveau_pmops_freeze(struct device *dev)
        if (drm_dev->mode_config.num_crtc)
                nouveau_fbcon_set_suspend(drm_dev, 1);
 
-       ret = nouveau_do_suspend(drm_dev);
+       ret = nouveau_do_suspend(drm_dev, false);
        return ret;
 }
 
@@ -671,7 +695,6 @@ static int nouveau_pmops_thaw(struct device *dev)
 static int
 nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
 {
-       struct pci_dev *pdev = dev->pdev;
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_cli *cli;
        char name[32], tmpname[TASK_COMM_LEN];
@@ -679,13 +702,15 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
 
        /* need to bring up power immediately if opening device */
        ret = pm_runtime_get_sync(dev->dev);
-       if (ret < 0)
+       if (ret < 0 && ret != -EACCES)
                return ret;
 
        get_task_comm(tmpname, current);
        snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
 
-       ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli);
+       ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli),
+                       (void **)&cli);
+
        if (ret)
                goto out_suspend;
 
@@ -762,7 +787,7 @@ long nouveau_drm_ioctl(struct file *filp,
        dev = file_priv->minor->dev;
 
        ret = pm_runtime_get_sync(dev->dev);
-       if (ret < 0)
+       if (ret < 0 && ret != -EACCES)
                return ret;
 
        ret = drm_ioctl(filp, cmd, arg);
@@ -879,7 +904,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        drm_kms_helper_poll_disable(drm_dev);
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
        nouveau_switcheroo_optimus_dsm();
-       ret = nouveau_do_suspend(drm_dev);
+       ret = nouveau_do_suspend(drm_dev, true);
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3cold);
@@ -905,8 +930,6 @@ static int nouveau_pmops_runtime_resume(struct device *dev)
        pci_set_master(pdev);
 
        ret = nouveau_do_resume(drm_dev);
-       if (drm_dev->mode_config.num_crtc)
-               nouveau_display_resume(drm_dev);
        drm_kms_helper_poll_enable(drm_dev);
        /* do magic */
        nv_mask(device, 0x88488, (1 << 25), (1 << 25));
@@ -974,6 +997,25 @@ nouveau_drm_pci_driver = {
        .driver.pm = &nouveau_pm_ops,
 };
 
+int nouveau_drm_platform_probe(struct platform_device *pdev)
+{
+       struct nouveau_device *device;
+       int ret;
+
+       ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
+                                   nouveau_platform_name(pdev),
+                                   dev_name(&pdev->dev), nouveau_config,
+                                   nouveau_debug, &device);
+
+       ret = drm_platform_init(&driver, pdev);
+       if (ret) {
+               nouveau_object_ref(NULL, (struct nouveau_object **)&device);
+               return ret;
+       }
+
+       return ret;
+}
+
 static int __init
 nouveau_drm_init(void)
 {
index 23ca7a517246feda3e7dfae782683c88c2bc64a5..7efbafaf7c1da76a10b320acfcf3965dd249d11a 100644 (file)
@@ -161,10 +161,7 @@ int nouveau_pmops_resume(struct device *);
 #define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
 #define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)
 #define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args)
-#define NV_DEBUG(cli, fmt, args...) do {                                       \
-       if (drm_debug & DRM_UT_DRIVER)                                         \
-               nv_info((cli), fmt, ##args);                                   \
-} while (0)
+#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)
 
 extern int nouveau_modeset;
 
index 7903e0ed3c75c74fa2d2b46a71ee01a50289de68..64a42cfd371735fe6958147d9f07f6e235a5e417 100644 (file)
@@ -528,10 +528,10 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
        struct nouveau_drm *drm = nouveau_drm(dev);
        if (drm->fbcon) {
                console_lock();
-               if (state == 0)
+               if (state == 1)
                        nouveau_fbcon_save_disable_accel(dev);
                fb_set_suspend(drm->fbcon->helper.fbdev, state);
-               if (state == 1)
+               if (state == 0)
                        nouveau_fbcon_restore_accel(dev);
                console_unlock();
        }
index 4aff04fa483c5e82acf1c66b1e63833bc23391cf..19fd767bab100d9acc90765af696be81241b71a5 100644 (file)
@@ -383,8 +383,9 @@ nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
        long value;
        int ret;
 
-       if (strict_strtol(buf, 10, &value) == -EINVAL)
-               return -EINVAL;
+       ret = kstrtol(buf, 10, &value);
+       if (ret)
+               return ret;
 
        ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value);
        if (ret)
@@ -587,18 +588,14 @@ nouveau_hwmon_init(struct drm_device *dev)
 
        /* set the default attributes */
        ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
-       if (ret) {
-               if (ret)
-                       goto error;
-       }
+       if (ret)
+               goto error;
 
        /* if the card has a working thermal sensor */
        if (therm->temp_get(therm) >= 0) {
                ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
-               if (ret) {
-                       if (ret)
-                               goto error;
-               }
+               if (ret)
+                       goto error;
        }
 
        /* if the card has a pwm fan */
index 89201a17ce752357444ec9f5ad0a4a42a84a79f8..75dda2b07176143605bf97f4c62f513ce0060385 100644 (file)
@@ -30,7 +30,7 @@
 static inline struct drm_device *
 drm_device(struct device *d)
 {
-       return pci_get_drvdata(to_pci_dev(d));
+       return dev_get_drvdata(d);
 }
 
 #define snappendf(p,r,f,a...) do {                                             \
@@ -132,9 +132,10 @@ nouveau_sysfs_fini(struct drm_device *dev)
 {
        struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nv_device(drm->device);
 
        if (sysfs->ctrl) {
-               device_remove_file(&dev->pdev->dev, &dev_attr_pstate);
+               device_remove_file(nv_device_base(device), &dev_attr_pstate);
                nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL);
        }
 
@@ -146,6 +147,7 @@ int
 nouveau_sysfs_init(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nv_device(drm->device);
        struct nouveau_sysfs *sysfs;
        int ret;
 
@@ -156,7 +158,7 @@ nouveau_sysfs_init(struct drm_device *dev)
        ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL,
                                 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl);
        if (ret == 0)
-               device_create_file(&dev->pdev->dev, &dev_attr_pstate);
+               device_create_file(nv_device_base(device), &dev_attr_pstate);
 
        return 0;
 }
index be3a3c9feafa96d7565c2d4efe2acdaeae309b60..ab0228f640a5e86f1554402bcf5816d2e8a9a986 100644 (file)
@@ -354,21 +354,26 @@ int
 nouveau_ttm_init(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
+       struct nouveau_device *device = nv_device(drm->device);
        u32 bits;
        int ret;
 
        bits = nouveau_vmmgr(drm->device)->dma_bits;
-       if ( drm->agp.stat == ENABLED ||
-           !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
-               bits = 32;
-
-       ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
-       if (ret)
-               return ret;
-
-       ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
-       if (ret)
-               pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32));
+       if (nv_device_is_pci(device)) {
+               if (drm->agp.stat == ENABLED ||
+                    !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
+                       bits = 32;
+
+               ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
+               if (ret)
+                       return ret;
+
+               ret = pci_set_consistent_dma_mask(dev->pdev,
+                                                 DMA_BIT_MASK(bits));
+               if (ret)
+                       pci_set_consistent_dma_mask(dev->pdev,
+                                                   DMA_BIT_MASK(32));
+       }
 
        ret = nouveau_ttm_global_init(drm);
        if (ret)
@@ -396,8 +401,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
                return ret;
        }
 
-       drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1),
-                                        pci_resource_len(dev->pdev, 1));
+       drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1),
+                                        nv_device_resource_len(device, 1));
 
        /* GART init */
        if (drm->agp.stat != ENABLED) {
index 471347edc27eb869816e5d5cfed1ccd01f4c7b6f..fb84da3cb50d50a31f905052b4b85c2cbaf54143 100644 (file)
@@ -84,6 +84,11 @@ nouveau_vga_init(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
        bool runtime = false;
+
+       /* only relevant for PCI devices */
+       if (!dev->pdev)
+               return;
+
        vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
 
        if (nouveau_runtime_pm == 1)
index 2dccafc6e9db573814e43acff007c36c2c0da97b..58af547b0b930e2ea64e74b0966c7a81e11fba54 100644 (file)
@@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
        nv_connector = nouveau_crtc_connector_get(nv_crtc);
        connector = &nv_connector->base;
        if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
-               if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
+               if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
                        mode = DITHERING_MODE_DYNAMIC2X2;
        } else {
                mode = nv_connector->dithering_mode;
@@ -785,7 +785,8 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
 
                if (update) {
                        nv50_display_flip_stop(crtc);
-                       nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+                       nv50_display_flip_next(crtc, crtc->primary->fb,
+                                              NULL, 1);
                }
        }
 
@@ -1028,7 +1029,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
        }
 
        nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
-       nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+       nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
 }
 
 static bool
@@ -1042,7 +1043,7 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
 static int
 nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
 {
-       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
        struct nv50_head *head = nv50_head(crtc);
        int ret;
 
@@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
        nv50_crtc_set_dither(nv_crtc, false);
        nv50_crtc_set_scale(nv_crtc, false);
        nv50_crtc_set_color_vibrance(nv_crtc, false);
-       nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
+       nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
        return 0;
 }
 
@@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        int ret;
 
-       if (!crtc->fb) {
+       if (!crtc->primary->fb) {
                NV_DEBUG(drm, "No FB bound\n");
                return 0;
        }
@@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                return ret;
 
        nv50_display_flip_stop(crtc);
-       nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
-       nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+       nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
+       nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
        return 0;
 }
 
index 4313bb0a49a62a70039e1bd952a402e2ac54221e..355157e4f78dd36a40b7b56020f06e82a6ae76db 100644 (file)
@@ -245,7 +245,7 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc,
        copy_timings_drm_to_omap(&omap_crtc->timings, mode);
        omap_crtc->full_update = true;
 
-       return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
+       return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        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,
        struct drm_plane *plane = omap_crtc->plane;
        struct drm_display_mode *mode = &crtc->mode;
 
-       return omap_plane_mode_set(plane, crtc, crtc->fb,
+       return omap_plane_mode_set(plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16,
@@ -308,14 +308,14 @@ static void page_flip_worker(struct work_struct *work)
        struct drm_gem_object *bo;
 
        mutex_lock(&crtc->mutex);
-       omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
+       omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        crtc->x << 16, crtc->y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16,
                        vblank_cb, crtc);
        mutex_unlock(&crtc->mutex);
 
-       bo = omap_framebuffer_bo(crtc->fb, 0);
+       bo = omap_framebuffer_bo(crtc->primary->fb, 0);
        drm_gem_object_unreference_unlocked(bo);
 }
 
@@ -336,9 +336,10 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       struct drm_plane *primary = crtc->primary;
        struct drm_gem_object *bo;
 
-       DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1,
+       DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
                        fb->base.id, event);
 
        if (omap_crtc->old_fb) {
@@ -347,7 +348,7 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
        }
 
        omap_crtc->event = event;
-       crtc->fb = fb;
+       primary->fb = fb;
 
        /*
         * Hold a reference temporarily until the crtc is updated
index f466c4aaee9464c7ca4c16d684a4e7d4bfec5584..0d5e9b7e8bbf7d65aec424d1607ad487e4b251ef 100644 (file)
@@ -312,7 +312,7 @@ struct drm_connector *omap_framebuffer_get_next_connector(
                if (connector != from) {
                        struct drm_encoder *encoder = connector->encoder;
                        struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
-                       if (crtc && crtc->fb == fb)
+                       if (crtc && crtc->primary->fb == fb)
                                return connector;
 
                }
index 798bde2e5881db484fd3797013aa11a04f11c902..41bdd174657e6ea34c4ad8a703d3288e721d919f 100644 (file)
@@ -527,7 +527,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
        bool recreate_primary = false;
        int ret;
        int surf_id;
-       if (!crtc->fb) {
+       if (!crtc->primary->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
@@ -536,7 +536,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
                qfb = to_qxl_framebuffer(old_fb);
                old_bo = gem_to_qxl_bo(qfb->obj);
        }
-       qfb = to_qxl_framebuffer(crtc->fb);
+       qfb = to_qxl_framebuffer(crtc->primary->fb);
        bo = gem_to_qxl_bo(qfb->obj);
        if (!m)
                /* and do we care? */
@@ -609,14 +609,14 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
        struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct qxl_device *qdev = dev->dev_private;
-       if (crtc->fb) {
-               struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb);
+       if (crtc->primary->fb) {
+               struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->primary->fb);
                struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
                int ret;
                ret = qxl_bo_reserve(bo, false);
                qxl_bo_unpin(bo);
                qxl_bo_unreserve(bo);
-               crtc->fb = NULL;
+               crtc->primary->fb = NULL;
        }
 
        qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
index 29c02e0e857f1ef69f0bbbcc161ac087c7965583..d52c27527b9a638a09307f75a8bd4b91a56c7aef 100644 (file)
@@ -433,6 +433,7 @@ static int qxl_sync_obj_flush(void *sync_obj)
 
 static void qxl_sync_obj_unref(void **sync_obj)
 {
+       *sync_obj = NULL;
 }
 
 static void *qxl_sync_obj_ref(void *sync_obj)
index daa4dd375ab15367266d6f0041af84386d6699bb..fb187c78978f8d5a139359381870aaea8ad1cc91 100644 (file)
@@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        int r;
 
        /* no fb bound */
-       if (!atomic && !crtc->fb) {
+       if (!atomic && !crtc->primary->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
@@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                target_fb = fb;
        }
        else {
-               radeon_fb = to_radeon_framebuffer(crtc->fb);
-               target_fb = crtc->fb;
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+               target_fb = crtc->primary->fb;
        }
 
        /* 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,
        /* set pageflip to happen anywhere in vblank interval */
        WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
 
-       if (!atomic && fb && fb != crtc->fb) {
+       if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
                r = radeon_bo_reserve(rbo, false);
@@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        int r;
 
        /* no fb bound */
-       if (!atomic && !crtc->fb) {
+       if (!atomic && !crtc->primary->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
@@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
                target_fb = fb;
        }
        else {
-               radeon_fb = to_radeon_framebuffer(crtc->fb);
-               target_fb = crtc->fb;
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+               target_fb = crtc->primary->fb;
        }
 
        obj = radeon_fb->obj;
@@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        /* set pageflip to happen anywhere in vblank interval */
        WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
 
-       if (!atomic && fb && fb != crtc->fb) {
+       if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
                r = radeon_bo_reserve(rbo, false);
@@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
        int i;
 
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->fb) {
+       if (crtc->primary->fb) {
                int r;
                struct radeon_framebuffer *radeon_fb;
                struct radeon_bo *rbo;
 
-               radeon_fb = to_radeon_framebuffer(crtc->fb);
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
                r = radeon_bo_reserve(rbo, false);
                if (unlikely(r))
index 4ad7643fce5fe9bdb8a479727400ae173475bb37..8b0ab170cef9036aaec2d1c11f9980e0e5284943 100644 (file)
@@ -142,101 +142,69 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
        return recv_bytes;
 }
 
-static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
-                                     u16 address, u8 *send, u8 send_bytes, u8 delay)
-{
-       struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
-       int ret;
-       u8 msg[20];
-       int msg_bytes = send_bytes + 4;
-       u8 ack;
-       unsigned retry;
-
-       if (send_bytes > 16)
-               return -1;
+#define HEADER_SIZE 4
 
-       msg[0] = address;
-       msg[1] = address >> 8;
-       msg[2] = DP_AUX_NATIVE_WRITE << 4;
-       msg[3] = (msg_bytes << 4) | (send_bytes - 1);
-       memcpy(&msg[4], send, send_bytes);
-
-       for (retry = 0; retry < 7; retry++) {
-               ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
-                                           msg, msg_bytes, NULL, 0, delay, &ack);
-               if (ret == -EBUSY)
-                       continue;
-               else if (ret < 0)
-                       return ret;
-               ack >>= 4;
-               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-                       return send_bytes;
-               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       usleep_range(400, 500);
-               else
-                       return -EIO;
-       }
-
-       return -EIO;
-}
-
-static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
-                                    u16 address, u8 *recv, int recv_bytes, u8 delay)
+static ssize_t
+radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 {
-       struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
-       u8 msg[4];
-       int msg_bytes = 4;
-       u8 ack;
+       struct radeon_i2c_chan *chan =
+               container_of(aux, struct radeon_i2c_chan, aux);
        int ret;
-       unsigned retry;
-
-       msg[0] = address;
-       msg[1] = address >> 8;
-       msg[2] = DP_AUX_NATIVE_READ << 4;
-       msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
-
-       for (retry = 0; retry < 7; retry++) {
-               ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
-                                           msg, msg_bytes, recv, recv_bytes, delay, &ack);
-               if (ret == -EBUSY)
-                       continue;
-               else if (ret < 0)
-                       return ret;
-               ack >>= 4;
-               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-                       return ret;
-               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       usleep_range(400, 500);
-               else if (ret == 0)
-                       return -EPROTO;
-               else
-                       return -EIO;
+       u8 tx_buf[20];
+       size_t tx_size;
+       u8 ack, delay = 0;
+
+       if (WARN_ON(msg->size > 16))
+               return -E2BIG;
+
+       tx_buf[0] = msg->address & 0xff;
+       tx_buf[1] = msg->address >> 8;
+       tx_buf[2] = msg->request << 4;
+       tx_buf[3] = msg->size - 1;
+
+       switch (msg->request & ~DP_AUX_I2C_MOT) {
+       case DP_AUX_NATIVE_WRITE:
+       case DP_AUX_I2C_WRITE:
+               tx_size = HEADER_SIZE + msg->size;
+               tx_buf[3] |= tx_size << 4;
+               memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size);
+               ret = radeon_process_aux_ch(chan,
+                                           tx_buf, tx_size, NULL, 0, delay, &ack);
+               if (ret >= 0)
+                       /* Return payload size. */
+                       ret = msg->size;
+               break;
+       case DP_AUX_NATIVE_READ:
+       case DP_AUX_I2C_READ:
+               tx_size = HEADER_SIZE;
+               tx_buf[3] |= tx_size << 4;
+               ret = radeon_process_aux_ch(chan,
+                                           tx_buf, tx_size, msg->buffer, msg->size, delay, &ack);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
 
-       return -EIO;
-}
+       if (ret > 0)
+               msg->reply = ack >> 4;
 
-static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector,
-                                u16 reg, u8 val)
-{
-       radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0);
+       return ret;
 }
 
-static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector,
-                              u16 reg)
+void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
 {
-       u8 val = 0;
-
-       radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0);
+       struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
 
-       return val;
+       dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev;
+       dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer;
 }
 
 int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                         u8 write_byte, u8 *read_byte)
 {
        struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-       struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter;
+       struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter);
        u16 address = algo_data->address;
        u8 msg[5];
        u8 reply[2];
@@ -246,34 +214,30 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        int ret;
        u8 ack;
 
-       /* Set up the command byte */
-       if (mode & MODE_I2C_READ)
-               msg[2] = DP_AUX_I2C_READ << 4;
-       else
-               msg[2] = DP_AUX_I2C_WRITE << 4;
-
-       if (!(mode & MODE_I2C_STOP))
-               msg[2] |= DP_AUX_I2C_MOT << 4;
-
+       /* Set up the address */
        msg[0] = address;
        msg[1] = address >> 8;
 
-       switch (mode) {
-       case MODE_I2C_WRITE:
+       /* Set up the command byte */
+       if (mode & MODE_I2C_READ) {
+               msg[2] = DP_AUX_I2C_READ << 4;
+               msg_bytes = 4;
+               msg[3] = msg_bytes << 4;
+       } else {
+               msg[2] = DP_AUX_I2C_WRITE << 4;
                msg_bytes = 5;
                msg[3] = msg_bytes << 4;
                msg[4] = write_byte;
-               break;
-       case MODE_I2C_READ:
-               msg_bytes = 4;
-               msg[3] = msg_bytes << 4;
-               break;
-       default:
-               msg_bytes = 4;
-               msg[3] = 3 << 4;
-               break;
        }
 
+       /* special handling for start/stop */
+       if (mode & (MODE_I2C_START | MODE_I2C_STOP))
+               msg[3] = 3 << 4;
+
+       /* Set MOT bit for all but stop */
+       if ((mode & MODE_I2C_STOP) == 0)
+               msg[2] |= DP_AUX_I2C_MOT << 4;
+
        for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(auxch,
                                            msg, msg_bytes, reply, reply_bytes, 0, &ack);
@@ -472,11 +436,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
        if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
                return;
 
-       if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0))
+       if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3))
                DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
 
-       if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0))
+       if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3))
                DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
 }
@@ -487,8 +451,8 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
        u8 msg[DP_DPCD_SIZE];
        int ret, i;
 
-       ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg,
-                                       DP_DPCD_SIZE, 0);
+       ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg,
+                              DP_DPCD_SIZE);
        if (ret > 0) {
                memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
                DRM_DEBUG_KMS("DPCD: ");
@@ -510,6 +474,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *dig_connector;
        int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
        u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
        u8 tmp;
@@ -517,9 +482,15 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
        if (!ASIC_IS_DCE4(rdev))
                return panel_mode;
 
+       if (!radeon_connector->con_priv)
+               return panel_mode;
+
+       dig_connector = radeon_connector->con_priv;
+
        if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
                /* DP bridge chips */
-               tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+               drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
+                                 DP_EDP_CONFIGURATION_CAP, &tmp);
                if (tmp & 1)
                        panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
                else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
@@ -529,7 +500,8 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
                        panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
        } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                /* eDP */
-               tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+               drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
+                                 DP_EDP_CONFIGURATION_CAP, &tmp);
                if (tmp & 1)
                        panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
        }
@@ -577,37 +549,42 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
-                                     u8 link_status[DP_LINK_STATUS_SIZE])
-{
-       int ret;
-       ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS,
-                                       link_status, DP_LINK_STATUS_SIZE, 100);
-       if (ret <= 0) {
-               return false;
-       }
-
-       DRM_DEBUG_KMS("link status %6ph\n", link_status);
-       return true;
-}
-
 bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
 {
        u8 link_status[DP_LINK_STATUS_SIZE];
        struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
 
-       if (!radeon_dp_get_link_status(radeon_connector, link_status))
+       if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0)
                return false;
        if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count))
                return false;
        return true;
 }
 
+void radeon_dp_set_rx_power_state(struct drm_connector *connector,
+                                 u8 power_state)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *dig_connector;
+
+       if (!radeon_connector->con_priv)
+               return;
+
+       dig_connector = radeon_connector->con_priv;
+
+       /* power up/down the sink */
+       if (dig_connector->dpcd[0] >= 0x11) {
+               drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux,
+                                  DP_SET_POWER, power_state);
+               usleep_range(1000, 2000);
+       }
+}
+
+
 struct radeon_dp_link_train_info {
        struct radeon_device *rdev;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct radeon_connector *radeon_connector;
        int enc_id;
        int dp_clock;
        int dp_lane_count;
@@ -617,6 +594,7 @@ struct radeon_dp_link_train_info {
        u8 link_status[DP_LINK_STATUS_SIZE];
        u8 tries;
        bool use_dpencoder;
+       struct drm_dp_aux *aux;
 };
 
 static 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)
                                       0, dp_info->train_set[0]); /* sets all lanes at once */
 
        /* set the vs/emph on the sink */
-       radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET,
-                                  dp_info->train_set, dp_info->dp_lane_count, 0);
+       drm_dp_dpcd_write(dp_info->aux, DP_TRAINING_LANE0_SET,
+                         dp_info->train_set, dp_info->dp_lane_count);
 }
 
 static 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)
        }
 
        /* enable training pattern on the sink */
-       radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp);
+       drm_dp_dpcd_writeb(dp_info->aux, DP_TRAINING_PATTERN_SET, tp);
 }
 
 static 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)
        u8 tmp;
 
        /* power up the sink */
-       if (dp_info->dpcd[0] >= 0x11) {
-               radeon_write_dpcd_reg(dp_info->radeon_connector,
-                                     DP_SET_POWER, DP_SET_POWER_D0);
-               usleep_range(1000, 2000);
-       }
+       radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0);
 
        /* possibly enable downspread on the sink */
        if (dp_info->dpcd[3] & 0x1)
-               radeon_write_dpcd_reg(dp_info->radeon_connector,
-                                     DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
+               drm_dp_dpcd_writeb(dp_info->aux,
+                                  DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
        else
-               radeon_write_dpcd_reg(dp_info->radeon_connector,
-                                     DP_DOWNSPREAD_CTRL, 0);
+               drm_dp_dpcd_writeb(dp_info->aux,
+                                  DP_DOWNSPREAD_CTRL, 0);
 
        if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
            (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
-               radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+               drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1);
        }
 
        /* set the lane count on the sink */
        tmp = dp_info->dp_lane_count;
        if (drm_dp_enhanced_frame_cap(dp_info->dpcd))
                tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-       radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp);
+       drm_dp_dpcd_writeb(dp_info->aux, DP_LANE_COUNT_SET, tmp);
 
        /* set the link rate on the sink */
        tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock);
-       radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
+       drm_dp_dpcd_writeb(dp_info->aux, DP_LINK_BW_SET, tmp);
 
        /* start training on the source */
        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)
                                          dp_info->dp_clock, dp_info->enc_id, 0);
 
        /* disable the training pattern on the sink */
-       radeon_write_dpcd_reg(dp_info->radeon_connector,
-                             DP_TRAINING_PATTERN_SET,
-                             DP_TRAINING_PATTERN_DISABLE);
+       drm_dp_dpcd_writeb(dp_info->aux,
+                          DP_TRAINING_PATTERN_SET,
+                          DP_TRAINING_PATTERN_DISABLE);
 
        return 0;
 }
@@ -723,9 +697,9 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
        udelay(400);
 
        /* disable the training pattern on the sink */
-       radeon_write_dpcd_reg(dp_info->radeon_connector,
-                             DP_TRAINING_PATTERN_SET,
-                             DP_TRAINING_PATTERN_DISABLE);
+       drm_dp_dpcd_writeb(dp_info->aux,
+                          DP_TRAINING_PATTERN_SET,
+                          DP_TRAINING_PATTERN_DISABLE);
 
        /* disable the training pattern on the source */
        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)
        while (1) {
                drm_dp_link_train_clock_recovery_delay(dp_info->dpcd);
 
-               if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+               if (drm_dp_dpcd_read_link_status(dp_info->aux,
+                                                dp_info->link_status) <= 0) {
                        DRM_ERROR("displayport link status failed\n");
                        break;
                }
@@ -819,7 +794,8 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info)
        while (1) {
                drm_dp_link_train_channel_eq_delay(dp_info->dpcd);
 
-               if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+               if (drm_dp_dpcd_read_link_status(dp_info->aux,
+                                                dp_info->link_status) <= 0) {
                        DRM_ERROR("displayport link status failed\n");
                        break;
                }
@@ -902,7 +878,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
        else
                dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A;
 
-       tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT);
+       drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp);
        if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
                dp_info.tp3_supported = true;
        else
@@ -912,9 +888,9 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
        dp_info.rdev = rdev;
        dp_info.encoder = encoder;
        dp_info.connector = connector;
-       dp_info.radeon_connector = radeon_connector;
        dp_info.dp_lane_count = dig_connector->dp_lane_count;
        dp_info.dp_clock = dig_connector->dp_clock;
+       dp_info.aux = &dig_connector->dp_i2c_bus->aux;
 
        if (radeon_dp_link_train_init(&dp_info))
                goto done;
index 607dc14d195e3540f103bf798d2e6f0e10e5634f..e6eb5097597f6088dde34638ee9b94cca5bc8950 100644 (file)
@@ -1633,10 +1633,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        struct radeon_connector *radeon_connector = NULL;
        struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+       bool travis_quirk = false;
 
        if (connector) {
                radeon_connector = to_radeon_connector(connector);
                radeon_dig_connector = radeon_connector->con_priv;
+               if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+                    ENCODER_OBJECT_ID_TRAVIS) &&
+                   (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
+                   !ASIC_IS_DCE5(rdev))
+                       travis_quirk = true;
        }
 
        switch (mode) {
@@ -1657,17 +1663,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                        atombios_external_encoder_setup(encoder, ext_encoder,
                                                                        EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
                        }
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                } else if (ASIC_IS_DCE4(rdev)) {
                        /* setup and enable the encoder */
                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-                       /* enable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                } else {
                        /* setup and enable the encoder and transmitter */
                        atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1675,68 +1677,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                                             ATOM_TRANSMITTER_ACTION_POWER_ON);
                                radeon_dig_connector->edp_on = true;
                        }
+               }
+               /* enable the transmitter */
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+                       /* DP_SET_POWER_D0 is set in radeon_dp_link_train */
                        radeon_dp_link_train(encoder, connector);
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
+               if (ASIC_IS_DCE4(rdev)) {
+                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+               }
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
+                   connector && !travis_quirk)
+                       radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
                if (ASIC_IS_DCE4(rdev)) {
                        /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
                } else {
                        /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
                        atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
-                       if (ASIC_IS_DCE4(rdev))
-                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       if (travis_quirk)
+                               radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                                atombios_set_edp_panel_power(connector,
                                                             ATOM_TRANSMITTER_ACTION_POWER_OFF);
                                radeon_dig_connector->edp_on = false;
                        }
                }
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-               break;
-       }
-}
-
-static void
-radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
-                            struct drm_encoder *ext_encoder,
-                            int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       default:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
-               } else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
-               } else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
                break;
        }
 }
@@ -1747,7 +1737,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
 
        DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1807,9 +1796,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                return;
        }
 
-       if (ext_encoder)
-               radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
-
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 
 }
index 0ae991d3289ab1ef9082d2f2767ad8fac15da613..62fefbbaf263c5a6d73b56e4c876680cd2a8a1dc 100644 (file)
@@ -2029,6 +2029,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 5:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                break;
                        case 6:
@@ -2049,6 +2050,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 9:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                break;
                        case 10:
@@ -2071,6 +2073,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 13:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                break;
                        case 14:
@@ -2093,6 +2096,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 27:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                break;
                        case 28:
@@ -2247,6 +2251,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 5:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                break;
                        case 6:
@@ -2267,6 +2272,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 9:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                break;
                        case 10:
@@ -2289,6 +2295,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 13:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                break;
                        case 14:
@@ -2311,6 +2318,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 27:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                break;
                        case 28:
@@ -2467,6 +2475,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 5:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                        break;
                                case 6:
@@ -2487,6 +2496,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 9:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                        break;
                                case 10:
@@ -2509,6 +2519,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 13:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                        break;
                                case 14:
@@ -2531,6 +2542,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 27:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                        break;
                                case 28:
@@ -2593,6 +2605,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 5:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                        break;
                                case 6:
@@ -2613,6 +2626,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 9:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                        break;
                                case 10:
@@ -2635,6 +2649,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 13:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                        break;
                                case 14:
@@ -2657,6 +2672,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 27:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                        break;
                                case 28:
@@ -2813,6 +2829,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 5:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P2) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                break;
                        case 6:
@@ -2828,11 +2845,13 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                                 TILE_SPLIT(split_equal_to_row_size));
                                break;
                        case 8:
-                               gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED);
+                               gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+                                               PIPE_CONFIG(ADDR_SURF_P2);
                                break;
                        case 9:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P2));
                                break;
                        case 10:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
@@ -2854,6 +2873,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 13:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P2) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                break;
                        case 14:
@@ -2876,7 +2896,8 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 27:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P2));
                                break;
                        case 28:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
index 030f8e49c5ee18513cd061897639a991ce06dfad..b6c32640df20bed4e954ec5ee2b12a4e43053251 100644 (file)
@@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
 
        if (rdev->mode_info.crtcs[0]->base.enabled) {
                mode1 = &rdev->mode_info.crtcs[0]->base.mode;
-               pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
+               pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
        }
        if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
                if (rdev->mode_info.crtcs[1]->base.enabled) {
                        mode2 = &rdev->mode_info.crtcs[1]->base.mode;
-                       pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+                       pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
                }
        }
 
index 82d4f865546ed9024b4078d67bfdd947f08a1060..c566b486ca08a79d72256dd3696b0992c07b481f 100644 (file)
@@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
 
        if (crtc && crtc->enabled) {
                drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                                        crtc->x, crtc->y, crtc->fb);
+                                        crtc->x, crtc->y, crtc->primary->fb);
        }
 }
 
@@ -1595,6 +1595,7 @@ radeon_add_atom_connector(struct drm_device *dev,
        uint32_t subpixel_order = SubPixelNone;
        bool shared_ddc = false;
        bool is_dp_bridge = false;
+       bool has_aux = false;
 
        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
                return;
@@ -1672,7 +1673,9 @@ radeon_add_atom_connector(struct drm_device *dev,
                                radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
                        else
                                radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
-                       if (!radeon_dig_connector->dp_i2c_bus)
+                       if (radeon_dig_connector->dp_i2c_bus)
+                               has_aux = true;
+                       else
                                DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
@@ -1895,7 +1898,9 @@ radeon_add_atom_connector(struct drm_device *dev,
                                if (!radeon_dig_connector->dp_i2c_bus)
                                        DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
                                radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
-                               if (!radeon_connector->ddc_bus)
+                               if (radeon_connector->ddc_bus)
+                                       has_aux = true;
+                               else
                                        DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                        }
                        subpixel_order = SubPixelHorizontalRGB;
@@ -1939,7 +1944,9 @@ radeon_add_atom_connector(struct drm_device *dev,
                        if (i2c_bus->valid) {
                                /* add DP i2c bus */
                                radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
-                               if (!radeon_dig_connector->dp_i2c_bus)
+                               if (radeon_dig_connector->dp_i2c_bus)
+                                       has_aux = true;
+                               else
                                        DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
                                radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                                if (!radeon_connector->ddc_bus)
@@ -2000,6 +2007,10 @@ radeon_add_atom_connector(struct drm_device *dev,
 
        connector->display_info.subpixel_order = subpixel_order;
        drm_sysfs_connector_add(connector);
+
+       if (has_aux)
+               radeon_dp_aux_init(radeon_connector);
+
        return;
 
 failed:
index 2e72dcd94b13fc4d30b56328c15140b77152d178..15f954cd81cb17169ffaccc4dfeae2f5619023e9 100644 (file)
@@ -1424,7 +1424,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
        /* unpin the front buffers */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
+               struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb);
                struct radeon_bo *robj;
 
                if (rfb == NULL || rfb->obj == NULL) {
index fbd8b930f2bec75276a5baf781653e658a023eaa..5701fbb36b3cb25a711916238cd13385a437241f 100644 (file)
@@ -369,7 +369,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        work->event = event;
        work->rdev = rdev;
        work->crtc_id = radeon_crtc->crtc_id;
-       old_radeon_fb = to_radeon_framebuffer(crtc->fb);
+       old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
        new_radeon_fb = to_radeon_framebuffer(fb);
        /* schedule unpin of the old buffer */
        obj = old_radeon_fb->obj;
@@ -460,7 +460,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        /* update crtc fb */
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        r = drm_vblank_get(dev, radeon_crtc->crtc_id);
        if (r) {
index 4392b7c95ee6d88ead4e4b6e27c27d82dcf58671..e8b0284e34bb266e410521d0302e6b751fa6e04a 100644 (file)
@@ -79,7 +79,8 @@
  *   2.35.0 - Add CIK macrotile mode array query
  *   2.36.0 - Fix CIK DCE tiling setup
  *   2.37.0 - allow GS ring setup on r6xx/r7xx
- *   2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN)
+ *   2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN),
+ *            CIK: 1D and linear tiling modes contain valid PIPE_CONFIG
  */
 #define KMS_DRIVER_MAJOR       2
 #define KMS_DRIVER_MINOR       38
index 6f1dfac1750749d4da74c45e6f5cae7fba90f6ee..3e49342a20e602e50f22c3068c543b7e19e9dab7 100644 (file)
@@ -575,10 +575,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                if (r)
                        return r;
 
-               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-               if (r)
-                       return r;
-
                /* map the ib pool buffer read only into
                 * virtual address space */
                bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
index 0b158f98d287136df1a4c3db11724798d2973d9f..cafb1ccf2ec3213b2dc394314dbece153d88ef00 100644 (file)
@@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 
        DRM_DEBUG_KMS("\n");
        /* no fb bound */
-       if (!atomic && !crtc->fb) {
+       if (!atomic && !crtc->primary->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
@@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
                target_fb = fb;
        }
        else {
-               radeon_fb = to_radeon_framebuffer(crtc->fb);
-               target_fb = crtc->fb;
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+               target_fb = crtc->primary->fb;
        }
 
        switch (target_fb->bits_per_pixel) {
@@ -444,7 +444,7 @@ retry:
                 * We don't shutdown the display controller because new buffer
                 * will end up in same spot.
                 */
-               if (!atomic && fb && fb != crtc->fb) {
+               if (!atomic && fb && fb != crtc->primary->fb) {
                        struct radeon_bo *old_rbo;
                        unsigned long nsize, osize;
 
@@ -555,7 +555,7 @@ retry:
        WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
        WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
 
-       if (!atomic && fb && fb != crtc->fb) {
+       if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
                r = radeon_bo_reserve(rbo, false);
@@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                }
        }
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (crtc->primary->fb->bits_per_pixel) {
        case 8:
                format = 2;
                break;
@@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
 static void radeon_crtc_disable(struct drm_crtc *crtc)
 {
        radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->fb) {
+       if (crtc->primary->fb) {
                int r;
                struct radeon_framebuffer *radeon_fb;
                struct radeon_bo *rbo;
 
-               radeon_fb = to_radeon_framebuffer(crtc->fb);
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
                r = radeon_bo_reserve(rbo, false);
                if (unlikely(r))
index 402dbe32c23483afb3524d3397e3ce1b7c3cc281..832d9fa1a4c4ec9f665c9c99c545b0a3451c38c4 100644 (file)
@@ -192,6 +192,7 @@ struct radeon_i2c_chan {
                struct i2c_algo_dp_aux_data dp;
        } algo;
        struct radeon_i2c_bus_rec rec;
+       struct drm_dp_aux aux;
 };
 
 /* mostly for macs, but really any system without connector tables */
@@ -690,6 +691,9 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
                                    struct drm_connector *connector);
+extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
+                                        u8 power_state);
+extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
 extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
 extern void radeon_atom_encoder_init(struct radeon_device *rdev);
 extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev);
index fbf4be316d0b675f89be45db4d820952af079287..299267db2898634fae3830c7be1180b1188ec737 100644 (file)
@@ -299,7 +299,7 @@ static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
 {
        struct drm_crtc *crtc = &rcrtc->crtc;
 
-       rcar_du_plane_compute_base(rcrtc->plane, crtc->fb);
+       rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
        rcar_du_plane_update_base(rcrtc->plane);
 }
 
@@ -358,10 +358,10 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
        const struct rcar_du_format_info *format;
        int ret;
 
-       format = rcar_du_format_info(crtc->fb->pixel_format);
+       format = rcar_du_format_info(crtc->primary->fb->pixel_format);
        if (format == NULL) {
                dev_dbg(rcdu->dev, "mode_set: unsupported format %08x\n",
-                       crtc->fb->pixel_format);
+                       crtc->primary->fb->pixel_format);
                ret = -EINVAL;
                goto error;
        }
@@ -377,7 +377,7 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
        rcrtc->plane->width = mode->hdisplay;
        rcrtc->plane->height = mode->vdisplay;
 
-       rcar_du_plane_compute_base(rcrtc->plane, crtc->fb);
+       rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
 
        rcrtc->outputs = 0;
 
@@ -510,7 +510,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
        rcar_du_crtc_update_base(rcrtc);
 
        if (event) {
index 0428076f1ce8723d025e64cdea77df33777288b6..e9e5e6d368cca5271a7260967ac63328ffc80ad6 100644 (file)
@@ -173,7 +173,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
        if (scrtc->started)
                return;
 
-       format = shmob_drm_format_info(crtc->fb->pixel_format);
+       format = shmob_drm_format_info(crtc->primary->fb->pixel_format);
        if (WARN_ON(format == NULL))
                return;
 
@@ -247,7 +247,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
        lcdc_write(sdev, LDDDSR, value);
 
        /* Setup planes. */
-       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+       drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
                if (plane->crtc == crtc)
                        shmob_drm_plane_setup(plane);
        }
@@ -303,7 +303,7 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
                                        int x, int y)
 {
        struct drm_crtc *crtc = &scrtc->crtc;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct shmob_drm_device *sdev = crtc->dev->dev_private;
        struct drm_gem_cma_object *gem;
        unsigned int bpp;
@@ -382,15 +382,15 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
        const struct shmob_drm_format_info *format;
        void *cache;
 
-       format = shmob_drm_format_info(crtc->fb->pixel_format);
+       format = shmob_drm_format_info(crtc->primary->fb->pixel_format);
        if (format == NULL) {
                dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n",
-                       crtc->fb->pixel_format);
+                       crtc->primary->fb->pixel_format);
                return -EINVAL;
        }
 
        scrtc->format = format;
-       scrtc->line_size = crtc->fb->pitches[0];
+       scrtc->line_size = crtc->primary->fb->pitches[0];
 
        if (sdev->meram) {
                /* 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,
                }
 
                cache = sh_mobile_meram_cache_alloc(sdev->meram, mdata,
-                                                   crtc->fb->pitches[0],
+                                                   crtc->primary->fb->pitches[0],
                                                    adjusted_mode->vdisplay,
                                                    format->meram,
                                                    &scrtc->line_size);
@@ -489,7 +489,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
        shmob_drm_crtc_update_base(scrtc);
 
        if (event) {
index 9336006b475d70b7494f1694d8661c07c2cd882a..36c717af6cf90830324a3538ac05dfd4306f3ccb 100644 (file)
@@ -235,14 +235,14 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
        if (!dc->event)
                return;
 
-       bo = tegra_fb_get_plane(crtc->fb, 0);
+       bo = tegra_fb_get_plane(crtc->primary->fb, 0);
 
        /* check if new start address has been latched */
        tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
        base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
        tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
 
-       if (base == bo->paddr + crtc->fb->offsets[0]) {
+       if (base == bo->paddr + crtc->primary->fb->offsets[0]) {
                spin_lock_irqsave(&drm->event_lock, flags);
                drm_send_vblank_event(drm, dc->pipe, dc->event);
                drm_vblank_put(drm, dc->pipe);
@@ -284,7 +284,7 @@ static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        }
 
        tegra_dc_set_base(dc, 0, 0, fb);
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        return 0;
 }
@@ -645,7 +645,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_display_mode *adjusted,
                               int x, int y, struct drm_framebuffer *old_fb)
 {
-       struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
+       struct tegra_bo *bo = tegra_fb_get_plane(crtc->primary->fb, 0);
        struct tegra_dc *dc = to_tegra_dc(crtc);
        struct tegra_dc_window window;
        unsigned long div, value;
@@ -682,9 +682,9 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
        window.dst.y = 0;
        window.dst.w = mode->hdisplay;
        window.dst.h = mode->vdisplay;
-       window.format = tegra_dc_format(crtc->fb->pixel_format);
-       window.bits_per_pixel = crtc->fb->bits_per_pixel;
-       window.stride[0] = crtc->fb->pitches[0];
+       window.format = tegra_dc_format(crtc->primary->fb->pixel_format);
+       window.bits_per_pixel = crtc->primary->fb->bits_per_pixel;
+       window.stride[0] = crtc->primary->fb->pitches[0];
        window.base[0] = bo->paddr;
 
        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,
 {
        struct tegra_dc *dc = to_tegra_dc(crtc);
 
-       return tegra_dc_set_base(dc, x, y, crtc->fb);
+       return tegra_dc_set_base(dc, x, y, crtc->primary->fb);
 }
 
 static void tegra_crtc_prepare(struct drm_crtc *crtc)
index d36efc13b16fbd0dd2d34be0561acd53e1282289..d642d4a0213491d099d5a7a4184fc273dc789a8f 100644 (file)
@@ -74,7 +74,7 @@ static void set_scanout(struct drm_crtc *crtc, int n)
                drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
                drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
        }
-       tilcdc_crtc->scanout[n] = crtc->fb;
+       tilcdc_crtc->scanout[n] = crtc->primary->fb;
        drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
        tilcdc_crtc->dirty &= ~stat[n];
        pm_runtime_put_sync(dev->dev);
@@ -84,7 +84,7 @@ static void update_scanout(struct drm_crtc *crtc)
 {
        struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
        struct drm_device *dev = crtc->dev;
-       struct drm_framebuffer *fb = crtc->fb;
+       struct drm_framebuffer *fb = crtc->primary->fb;
        struct drm_gem_cma_object *gem;
        unsigned int depth, bpp;
 
@@ -159,7 +159,7 @@ static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
                return -EBUSY;
        }
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
        tilcdc_crtc->event = event;
        update_scanout(crtc);
 
@@ -339,7 +339,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
        if (priv->rev == 2) {
                unsigned int depth, bpp;
 
-               drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp);
+               drm_fb_get_bpp_depth(crtc->primary->fb->pixel_format, &depth, &bpp);
                switch (bpp) {
                case 16:
                        break;
index 53b51c4e671a76cfc7f01cf73c5bba39531ead74..d2a0533527896bcd0b7bcf3124e37f54dc9a9f9e 100644 (file)
@@ -270,6 +270,52 @@ ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
 }
 EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
 
+/**
+ * ttm_ref_object_exists - Check whether a caller has a valid ref object
+ * (has opened) a base object.
+ *
+ * @tfile: Pointer to a struct ttm_object_file identifying the caller.
+ * @base: Pointer to a struct base object.
+ *
+ * Checks wether the caller identified by @tfile has put a valid USAGE
+ * reference object on the base object identified by @base.
+ */
+bool ttm_ref_object_exists(struct ttm_object_file *tfile,
+                          struct ttm_base_object *base)
+{
+       struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
+       struct drm_hash_item *hash;
+       struct ttm_ref_object *ref;
+
+       rcu_read_lock();
+       if (unlikely(drm_ht_find_item_rcu(ht, base->hash.key, &hash) != 0))
+               goto out_false;
+
+       /*
+        * Verify that the ref object is really pointing to our base object.
+        * Our base object could actually be dead, and the ref object pointing
+        * to another base object with the same handle.
+        */
+       ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+       if (unlikely(base != ref->obj))
+               goto out_false;
+
+       /*
+        * Verify that the ref->obj pointer was actually valid!
+        */
+       rmb();
+       if (unlikely(atomic_read(&ref->kref.refcount) == 0))
+               goto out_false;
+
+       rcu_read_unlock();
+       return true;
+
+ out_false:
+       rcu_read_unlock();
+       return false;
+}
+EXPORT_SYMBOL(ttm_ref_object_exists);
+
 int ttm_ref_object_add(struct ttm_object_file *tfile,
                       struct ttm_base_object *base,
                       enum ttm_ref_type ref_type, bool *existed)
index 2ae1eb7d16355b3036e880d4edcaaa0981cbc414..cddc4fcf35cf4056e17c235b825ff87bd2e546eb 100644 (file)
@@ -310,7 +310,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
 
 {
        struct drm_device *dev = crtc->dev;
-       struct udl_framebuffer *ufb = to_udl_fb(crtc->fb);
+       struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
        struct udl_device *udl = dev->dev_private;
        char *buf;
        char *wrptr;
index 1e80152674b50ed62a73e3544c19855de29af070..701d5207def6fb286a18be2b14270491baf96f28 100644 (file)
@@ -462,7 +462,6 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
        struct vmw_resource *tmp;
        struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
 
@@ -474,7 +473,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
        if (unlikely(vmw_user_context_size == 0))
                vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -521,7 +520,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
 out_err:
        vmw_resource_unreference(&res);
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 
 }
index a75840211b3c9682da3be63df8a54385de238824..70ddce8358b0be2ff564b27599eb4cd537153483 100644 (file)
@@ -52,11 +52,10 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
                            struct ttm_placement *placement,
                            bool interruptible)
 {
-       struct vmw_master *vmaster = dev_priv->active_master;
        struct ttm_buffer_object *bo = &buf->base;
        int ret;
 
-       ret = ttm_write_lock(&vmaster->lock, interruptible);
+       ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
        if (unlikely(ret != 0))
                return ret;
 
@@ -71,7 +70,7 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
        ttm_bo_unreserve(bo);
 
 err:
-       ttm_write_unlock(&vmaster->lock);
+       ttm_write_unlock(&dev_priv->reservation_sem);
        return ret;
 }
 
@@ -95,12 +94,11 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
                              struct vmw_dma_buffer *buf,
                              bool pin, bool interruptible)
 {
-       struct vmw_master *vmaster = dev_priv->active_master;
        struct ttm_buffer_object *bo = &buf->base;
        struct ttm_placement *placement;
        int ret;
 
-       ret = ttm_write_lock(&vmaster->lock, interruptible);
+       ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
        if (unlikely(ret != 0))
                return ret;
 
@@ -143,7 +141,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
 err_unreserve:
        ttm_bo_unreserve(bo);
 err:
-       ttm_write_unlock(&vmaster->lock);
+       ttm_write_unlock(&dev_priv->reservation_sem);
        return ret;
 }
 
@@ -198,7 +196,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
                                struct vmw_dma_buffer *buf,
                                bool pin, bool interruptible)
 {
-       struct vmw_master *vmaster = dev_priv->active_master;
        struct ttm_buffer_object *bo = &buf->base;
        struct ttm_placement placement;
        int ret = 0;
@@ -209,7 +206,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
                placement = vmw_vram_placement;
        placement.lpfn = bo->num_pages;
 
-       ret = ttm_write_lock(&vmaster->lock, interruptible);
+       ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
        if (unlikely(ret != 0))
                return ret;
 
@@ -232,7 +229,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
 
        ttm_bo_unreserve(bo);
 err_unlock:
-       ttm_write_unlock(&vmaster->lock);
+       ttm_write_unlock(&dev_priv->reservation_sem);
 
        return ret;
 }
index c35715f26f400d5b63bfa66551dbbfd0abf7e2b0..c7009581bb23a825dc0fa7ba7706710035e5ed4f 100644 (file)
 
 static const struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
                      vmw_kms_cursor_bypass_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
@@ -159,29 +159,28 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
 
        VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
                      vmw_fence_obj_signaled_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(VMW_FENCE_EVENT,
-                     vmw_fence_event_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_UNLOCKED | DRM_RENDER_ALLOW),
+       VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
 
        /* these allow direct access to the framebuffers mark as master only */
        VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
@@ -194,19 +193,19 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
                      DRM_MASTER | DRM_UNLOCKED),
        VMW_IOCTL_DEF(VMW_CREATE_SHADER,
                      vmw_shader_define_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_UNREF_SHADER,
                      vmw_shader_destroy_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
                      vmw_gb_surface_define_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
                      vmw_gb_surface_reference_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_SYNCCPU,
                      vmw_user_dmabuf_synccpu_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED),
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -606,6 +605,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        mutex_init(&dev_priv->release_mutex);
        mutex_init(&dev_priv->binding_mutex);
        rwlock_init(&dev_priv->resource_lock);
+       ttm_lock_init(&dev_priv->reservation_sem);
 
        for (i = vmw_res_context; i < vmw_res_max; ++i) {
                idr_init(&dev_priv->res_idr[i]);
@@ -981,12 +981,70 @@ out_no_tfile:
        return ret;
 }
 
-static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
-                              unsigned long arg)
+static struct vmw_master *vmw_master_check(struct drm_device *dev,
+                                          struct drm_file *file_priv,
+                                          unsigned int flags)
+{
+       int ret;
+       struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+       struct vmw_master *vmaster;
+
+       if (file_priv->minor->type != DRM_MINOR_LEGACY ||
+           !(flags & DRM_AUTH))
+               return NULL;
+
+       ret = mutex_lock_interruptible(&dev->master_mutex);
+       if (unlikely(ret != 0))
+               return ERR_PTR(-ERESTARTSYS);
+
+       if (file_priv->is_master) {
+               mutex_unlock(&dev->master_mutex);
+               return NULL;
+       }
+
+       /*
+        * Check if we were previously master, but now dropped.
+        */
+       if (vmw_fp->locked_master) {
+               mutex_unlock(&dev->master_mutex);
+               DRM_ERROR("Dropped master trying to access ioctl that "
+                         "requires authentication.\n");
+               return ERR_PTR(-EACCES);
+       }
+       mutex_unlock(&dev->master_mutex);
+
+       /*
+        * Taking the drm_global_mutex after the TTM lock might deadlock
+        */
+       if (!(flags & DRM_UNLOCKED)) {
+               DRM_ERROR("Refusing locked ioctl access.\n");
+               return ERR_PTR(-EDEADLK);
+       }
+
+       /*
+        * Take the TTM lock. Possibly sleep waiting for the authenticating
+        * master to become master again, or for a SIGTERM if the
+        * authenticating master exits.
+        */
+       vmaster = vmw_master(file_priv->master);
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               vmaster = ERR_PTR(ret);
+
+       return vmaster;
+}
+
+static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
+                             unsigned long arg,
+                             long (*ioctl_func)(struct file *, unsigned int,
+                                                unsigned long))
 {
        struct drm_file *file_priv = filp->private_data;
        struct drm_device *dev = file_priv->minor->dev;
        unsigned int nr = DRM_IOCTL_NR(cmd);
+       struct vmw_master *vmaster;
+       unsigned int flags;
+       long ret;
 
        /*
         * Do extra checking on driver private ioctls.
@@ -995,18 +1053,44 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
        if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
            && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
                const struct drm_ioctl_desc *ioctl =
-                   &vmw_ioctls[nr - DRM_COMMAND_BASE];
+                       &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
                if (unlikely(ioctl->cmd_drv != cmd)) {
                        DRM_ERROR("Invalid command format, ioctl %d\n",
                                  nr - DRM_COMMAND_BASE);
                        return -EINVAL;
                }
+               flags = ioctl->flags;
+       } else if (!drm_ioctl_flags(nr, &flags))
+               return -EINVAL;
+
+       vmaster = vmw_master_check(dev, file_priv, flags);
+       if (unlikely(IS_ERR(vmaster))) {
+               DRM_INFO("IOCTL ERROR %d\n", nr);
+               return PTR_ERR(vmaster);
        }
 
-       return drm_ioctl(filp, cmd, arg);
+       ret = ioctl_func(filp, cmd, arg);
+       if (vmaster)
+               ttm_read_unlock(&vmaster->lock);
+
+       return ret;
+}
+
+static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
+                              unsigned long arg)
+{
+       return vmw_generic_ioctl(filp, cmd, arg, &drm_ioctl);
 }
 
+#ifdef CONFIG_COMPAT
+static long vmw_compat_ioctl(struct file *filp, unsigned int cmd,
+                            unsigned long arg)
+{
+       return vmw_generic_ioctl(filp, cmd, arg, &drm_compat_ioctl);
+}
+#endif
+
 static void vmw_lastclose(struct drm_device *dev)
 {
        struct drm_crtc *crtc;
@@ -1175,12 +1259,11 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 {
        struct vmw_private *dev_priv =
                container_of(nb, struct vmw_private, pm_nb);
-       struct vmw_master *vmaster = dev_priv->active_master;
 
        switch (val) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
-               ttm_suspend_lock(&vmaster->lock);
+               ttm_suspend_lock(&dev_priv->reservation_sem);
 
                /**
                 * This empties VRAM and unbinds all GMR bindings.
@@ -1194,7 +1277,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
        case PM_POST_HIBERNATION:
        case PM_POST_SUSPEND:
        case PM_POST_RESTORE:
-               ttm_suspend_unlock(&vmaster->lock);
+               ttm_suspend_unlock(&dev_priv->reservation_sem);
 
                break;
        case PM_RESTORE_PREPARE:
@@ -1315,14 +1398,14 @@ static const struct file_operations vmwgfx_driver_fops = {
        .poll = vmw_fops_poll,
        .read = vmw_fops_read,
 #if defined(CONFIG_COMPAT)
-       .compat_ioctl = drm_compat_ioctl,
+       .compat_ioctl = vmw_compat_ioctl,
 #endif
        .llseek = noop_llseek,
 };
 
 static struct drm_driver driver = {
        .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-       DRIVER_MODESET | DRIVER_PRIME,
+       DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER,
        .load = vmw_driver_load,
        .unload = vmw_driver_unload,
        .lastclose = vmw_lastclose,
index 07831554dad7acc3dae34f36e3a96e7b7f5299af..6b252a887ae2dd1bd91f12b452c4fa54b0a77c40 100644 (file)
@@ -40,9 +40,9 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20140228"
+#define VMWGFX_DRIVER_DATE "20140325"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 5
+#define VMWGFX_DRIVER_MINOR 6
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -486,6 +486,11 @@ struct vmw_private {
        struct mutex release_mutex;
        uint32_t num_3d_resources;
 
+       /*
+        * Replace this with an rwsem as soon as we have down_xx_interruptible()
+        */
+       struct ttm_lock reservation_sem;
+
        /*
         * Query processing. These members
         * are protected by the cmdbuf mutex.
index efb575a7996c2aed35e7046a47fd61acdbc167a0..931490b9cfed04b1365a87fb2d83c0526e114fdd 100644 (file)
@@ -2712,7 +2712,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
        /*
@@ -2729,7 +2728,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -2745,6 +2744,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
        vmw_kms_cursor_post_execbuf(dev_priv);
 
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 }
index ed5ce2a41bbf02f34a8fabc8307985fe9763ed94..9699bd174ae4ab8b89c88460559b7fb6fb2a31e7 100644 (file)
@@ -377,14 +377,13 @@ static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
 
        ne_placement.lpfn = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
-       /* interuptable? */
-       ret = ttm_write_lock(&vmw_priv->fbdev_master.lock, false);
-       if (unlikely(ret != 0))
-               return ret;
+       (void) ttm_write_lock(&vmw_priv->reservation_sem, false);
 
        vmw_bo = kmalloc(sizeof(*vmw_bo), GFP_KERNEL);
-       if (!vmw_bo)
+       if (!vmw_bo) {
+               ret = -ENOMEM;
                goto err_unlock;
+       }
 
        ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size,
                              &ne_placement,
index 47b70949bf3af6683bb74552c0b91fa7b06d7a82..37881ecf5d7a9f74c49d4e1c018abc1cc2a9dffd 100644 (file)
@@ -226,7 +226,6 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
        struct drm_vmw_present_arg *arg =
                (struct drm_vmw_present_arg *)data;
        struct vmw_surface *surface;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct drm_vmw_rect __user *clips_ptr;
        struct drm_vmw_rect *clips = NULL;
        struct drm_framebuffer *fb;
@@ -271,7 +270,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
        }
        vfb = vmw_framebuffer_to_vfb(fb);
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                goto out_no_ttm_lock;
 
@@ -291,7 +290,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
        vmw_surface_unreference(&surface);
 
 out_no_surface:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 out_no_ttm_lock:
        drm_framebuffer_unreference(fb);
 out_no_fb:
@@ -311,7 +310,6 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
        struct drm_vmw_fence_rep __user *user_fence_rep =
                (struct drm_vmw_fence_rep __user *)
                (unsigned long)arg->fence_rep;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct drm_vmw_rect __user *clips_ptr;
        struct drm_vmw_rect *clips = NULL;
        struct drm_framebuffer *fb;
@@ -361,7 +359,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
                goto out_no_ttm_lock;
        }
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                goto out_no_ttm_lock;
 
@@ -369,7 +367,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
                               vfb, user_fence_rep,
                               clips, num_clips);
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 out_no_ttm_lock:
        drm_framebuffer_unreference(fb);
 out_no_fb:
index 8a650413dea57c8e50212b41f8be00abba3ee8af..a2dde5ad81385bf932dd398bd522d1a950098f85 100644 (file)
@@ -468,7 +468,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
        num_units = 0;
        list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
                            head) {
-               if (crtc->fb != &framebuffer->base)
+               if (crtc->primary->fb != &framebuffer->base)
                        continue;
                units[num_units++] = vmw_crtc_to_du(crtc);
        }
@@ -596,7 +596,6 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                  unsigned num_clips)
 {
        struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct vmw_framebuffer_surface *vfbs =
                vmw_framebuffer_to_vfbs(framebuffer);
        struct drm_clip_rect norect;
@@ -611,7 +610,7 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 
        drm_modeset_lock_all(dev_priv->dev);
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0)) {
                drm_modeset_unlock_all(dev_priv->dev);
                return ret;
@@ -632,7 +631,7 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                   flags, color,
                                   clips, num_clips, inc, NULL);
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 
        drm_modeset_unlock_all(dev_priv->dev);
 
@@ -883,7 +882,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
 
        num_units = 0;
        list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-               if (crtc->fb != &framebuffer->base)
+               if (crtc->primary->fb != &framebuffer->base)
                        continue;
                units[num_units++] = vmw_crtc_to_du(crtc);
        }
@@ -954,7 +953,6 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
                                 unsigned num_clips)
 {
        struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct vmw_framebuffer_dmabuf *vfbd =
                vmw_framebuffer_to_vfbd(framebuffer);
        struct drm_clip_rect norect;
@@ -962,7 +960,7 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 
        drm_modeset_lock_all(dev_priv->dev);
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0)) {
                drm_modeset_unlock_all(dev_priv->dev);
                return ret;
@@ -989,7 +987,7 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
                                          clips, num_clips, increment, NULL);
        }
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 
        drm_modeset_unlock_all(dev_priv->dev);
 
@@ -1245,7 +1243,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
 
        num_units = 0;
        list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-               if (crtc->fb != &vfb->base)
+               if (crtc->primary->fb != &vfb->base)
                        continue;
                units[num_units++] = vmw_crtc_to_du(crtc);
        }
@@ -1382,7 +1380,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
 
        num_units = 0;
        list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-               if (crtc->fb != &vfb->base)
+               if (crtc->primary->fb != &vfb->base)
                        continue;
                units[num_units++] = vmw_crtc_to_du(crtc);
        }
@@ -1725,7 +1723,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
                     uint32_t page_flip_flags)
 {
        struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-       struct drm_framebuffer *old_fb = crtc->fb;
+       struct drm_framebuffer *old_fb = crtc->primary->fb;
        struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
        struct drm_file *file_priv ;
        struct vmw_fence_obj *fence = NULL;
@@ -1743,7 +1741,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
        if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
                return -EINVAL;
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        /* do a full screen dirty update */
        clips.x1 = clips.y1 = 0;
@@ -1783,7 +1781,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
        return ret;
 
 out_no_fence:
-       crtc->fb = old_fb;
+       crtc->primary->fb = old_fb;
        return ret;
 }
 
@@ -2022,7 +2020,6 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct drm_vmw_update_layout_arg *arg =
                (struct drm_vmw_update_layout_arg *)data;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        void __user *user_rects;
        struct drm_vmw_rect *rects;
        unsigned rects_size;
@@ -2030,7 +2027,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
        int i;
        struct drm_mode_config *mode_config = &dev->mode_config;
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -2072,6 +2069,6 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 out_free:
        kfree(rects);
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 }
index a055a26819c2b6b7963d6d245576e17b8d9a7500..b2b9bd23aeee620fee8610c490e41a6ef297997e 100644 (file)
@@ -93,7 +93,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
                if (crtc == NULL)
                        return 0;
-               fb = entry->base.crtc.fb;
+               fb = entry->base.crtc.primary->fb;
 
                return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
                                          fb->bits_per_pixel, fb->depth);
@@ -101,7 +101,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
        if (!list_empty(&lds->active)) {
                entry = list_entry(lds->active.next, typeof(*entry), active);
-               fb = entry->base.crtc.fb;
+               fb = entry->base.crtc.primary->fb;
 
                vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
                                   fb->bits_per_pixel, fb->depth);
@@ -259,7 +259,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
                connector->encoder = NULL;
                encoder->crtc = NULL;
-               crtc->fb = NULL;
+               crtc->primary->fb = NULL;
                crtc->enabled = false;
 
                vmw_ldu_del_active(dev_priv, ldu);
@@ -280,7 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
        vmw_fb_off(dev_priv);
 
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
        encoder->crtc = crtc;
        connector->encoder = encoder;
        crtc->x = set->x;
index 9757b57f8388d7a29fa51d04f61f5076fd149793..01d68f0a69dca74067b1dab583ab860711d6933a 100644 (file)
@@ -538,8 +538,13 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
                return -EPERM;
 
        vmw_user_bo = vmw_user_dma_buffer(bo);
-       return (vmw_user_bo->prime.base.tfile == tfile ||
-               vmw_user_bo->prime.base.shareable) ? 0 : -EPERM;
+
+       /* Check that the caller has opened the object. */
+       if (likely(ttm_ref_object_exists(tfile, &vmw_user_bo->prime.base)))
+               return 0;
+
+       DRM_ERROR("Could not grant buffer access.\n");
+       return -EPERM;
 }
 
 /**
@@ -676,10 +681,9 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
        struct drm_vmw_dmabuf_rep *rep = &arg->rep;
        struct vmw_dma_buffer *dma_buf;
        uint32_t handle;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -696,7 +700,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
        vmw_dmabuf_unreference(&dma_buf);
 
 out_no_dmabuf:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 
        return ret;
 }
@@ -873,7 +877,6 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
        struct vmw_resource *tmp;
        struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
        /*
@@ -884,7 +887,7 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
        if (unlikely(vmw_user_stream_size == 0))
                vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128;
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -932,7 +935,7 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 out_err:
        vmw_resource_unreference(&res);
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 }
 
@@ -985,14 +988,13 @@ int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_mode_create_dumb *args)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct vmw_dma_buffer *dma_buf;
        int ret;
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -1004,7 +1006,7 @@ int vmw_dumb_create(struct drm_file *file_priv,
 
        vmw_dmabuf_unreference(&dma_buf);
 out_no_dmabuf:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 }
 
index 22406c8651ead6caa629ce6ae2de963bdd0a35d7..a95d3a0cabe448672237b3c42bc8b182272effeb 100644 (file)
@@ -307,7 +307,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
                connector->encoder = NULL;
                encoder->crtc = NULL;
-               crtc->fb = NULL;
+               crtc->primary->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
                crtc->enabled = false;
@@ -368,7 +368,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
                connector->encoder = NULL;
                encoder->crtc = NULL;
-               crtc->fb = NULL;
+               crtc->primary->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
                crtc->enabled = false;
@@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
        connector->encoder = encoder;
        encoder->crtc = crtc;
        crtc->mode = *mode;
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
        crtc->x = set->x;
        crtc->y = set->y;
        crtc->enabled = true;
@@ -572,5 +572,5 @@ void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
        BUG_ON(!sou->base.is_implicit);
 
        dev_priv->sou_priv->implicit_fb =
-               vmw_framebuffer_to_vfb(sou->base.crtc.fb);
+               vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
 }
index ee3856578a12589d8b12e4133666d04134ad729a..c1559eeaffe9fe637eb2a1e31b1b070b6af29b76 100644 (file)
@@ -449,7 +449,6 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
        struct drm_vmw_shader_create_arg *arg =
                (struct drm_vmw_shader_create_arg *)data;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        struct vmw_dma_buffer *buffer = NULL;
        SVGA3dShaderType shader_type;
        int ret;
@@ -487,14 +486,14 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
                goto out_bad_arg;
        }
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                goto out_bad_arg;
 
        ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
                               shader_type, tfile, &arg->shader_handle);
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
 out_bad_arg:
        vmw_dmabuf_unreference(&buffer);
        return ret;
index e7af580ab977f5932629b8d45e5d5e68a52942a5..4ecdbf3e59da22ae8e6f887cddbaad1307bff299 100644 (file)
  * @base:           The TTM base object handling user-space visibility.
  * @srf:            The surface metadata.
  * @size:           TTM accounting size for the surface.
+ * @master:         master of the creating client. Used for security check.
  */
 struct vmw_user_surface {
        struct ttm_prime_object prime;
        struct vmw_surface srf;
        uint32_t size;
+       struct drm_master *master;
 };
 
 /**
@@ -624,6 +626,8 @@ static void vmw_user_surface_free(struct vmw_resource *res)
        struct vmw_private *dev_priv = srf->res.dev_priv;
        uint32_t size = user_srf->size;
 
+       if (user_srf->master)
+               drm_master_put(&user_srf->master);
        kfree(srf->offsets);
        kfree(srf->sizes);
        kfree(srf->snooper.image);
@@ -697,7 +701,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        struct vmw_surface_offset *cur_offset;
        uint32_t num_sizes;
        uint32_t size;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        const struct svga3d_surface_desc *desc;
 
        if (unlikely(vmw_user_surface_size == 0))
@@ -723,7 +726,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -820,6 +823,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 
        user_srf->prime.base.shareable = false;
        user_srf->prime.base.tfile = NULL;
+       if (drm_is_primary_client(file_priv))
+               user_srf->master = drm_master_get(file_priv->master);
 
        /**
         * From this point, the generic resource management functions
@@ -862,7 +867,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        rep->sid = user_srf->prime.base.hash.key;
        vmw_resource_unreference(&res);
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return 0;
 out_no_copy:
        kfree(srf->offsets);
@@ -873,7 +878,81 @@ out_no_sizes:
 out_no_user_srf:
        ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
+       return ret;
+}
+
+
+static int
+vmw_surface_handle_reference(struct vmw_private *dev_priv,
+                            struct drm_file *file_priv,
+                            uint32_t u_handle,
+                            enum drm_vmw_handle_type handle_type,
+                            struct ttm_base_object **base_p)
+{
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_user_surface *user_srf;
+       uint32_t handle;
+       struct ttm_base_object *base;
+       int ret;
+
+       if (handle_type == DRM_VMW_HANDLE_PRIME) {
+               ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
+               if (unlikely(ret != 0))
+                       return ret;
+       } else {
+               if (unlikely(drm_is_render_client(file_priv))) {
+                       DRM_ERROR("Render client refused legacy "
+                                 "surface reference.\n");
+                       return -EACCES;
+               }
+               handle = u_handle;
+       }
+
+       ret = -EINVAL;
+       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
+       if (unlikely(base == NULL)) {
+               DRM_ERROR("Could not find surface to reference.\n");
+               goto out_no_lookup;
+       }
+
+       if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
+               DRM_ERROR("Referenced object is not a surface.\n");
+               goto out_bad_resource;
+       }
+
+       if (handle_type != DRM_VMW_HANDLE_PRIME) {
+               user_srf = container_of(base, struct vmw_user_surface,
+                                       prime.base);
+
+               /*
+                * Make sure the surface creator has the same
+                * authenticating master.
+                */
+               if (drm_is_primary_client(file_priv) &&
+                   user_srf->master != file_priv->master) {
+                       DRM_ERROR("Trying to reference surface outside of"
+                                 " master domain.\n");
+                       ret = -EACCES;
+                       goto out_bad_resource;
+               }
+
+               ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Could not add a reference to a surface.\n");
+                       goto out_bad_resource;
+               }
+       }
+
+       *base_p = base;
+       return 0;
+
+out_bad_resource:
+       ttm_base_object_unref(&base);
+out_no_lookup:
+       if (handle_type == DRM_VMW_HANDLE_PRIME)
+               (void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
+
        return ret;
 }
 
@@ -898,27 +977,16 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
        struct vmw_user_surface *user_srf;
        struct drm_vmw_size __user *user_sizes;
        struct ttm_base_object *base;
-       int ret = -EINVAL;
-
-       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
-       if (unlikely(base == NULL)) {
-               DRM_ERROR("Could not find surface to reference.\n");
-               return -EINVAL;
-       }
+       int ret;
 
-       if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
-               goto out_bad_resource;
+       ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
+                                          req->handle_type, &base);
+       if (unlikely(ret != 0))
+               return ret;
 
        user_srf = container_of(base, struct vmw_user_surface, prime.base);
        srf = &user_srf->srf;
 
-       ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
-                                TTM_REF_USAGE, NULL);
-       if (unlikely(ret != 0)) {
-               DRM_ERROR("Could not add a reference to a surface.\n");
-               goto out_no_reference;
-       }
-
        rep->flags = srf->flags;
        rep->format = srf->format;
        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,
        if (unlikely(ret != 0)) {
                DRM_ERROR("copy_to_user failed %p %u\n",
                          user_sizes, srf->num_sizes);
+               ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
                ret = -EFAULT;
        }
-out_bad_resource:
-out_no_reference:
+
        ttm_base_object_unref(&base);
 
        return ret;
@@ -1173,7 +1241,6 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
        int ret;
        uint32_t size;
-       struct vmw_master *vmaster = vmw_master(file_priv->master);
        const struct svga3d_surface_desc *desc;
        uint32_t backup_handle;
 
@@ -1189,7 +1256,7 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ret = ttm_read_lock(&dev_priv->reservation_sem, true);
        if (unlikely(ret != 0))
                return ret;
 
@@ -1228,6 +1295,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
 
        user_srf->prime.base.shareable = false;
        user_srf->prime.base.tfile = NULL;
+       if (drm_is_primary_client(file_priv))
+               user_srf->master = drm_master_get(file_priv->master);
 
        /**
         * From this point, the generic resource management functions
@@ -1283,12 +1352,12 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
 
        vmw_resource_unreference(&res);
 
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return 0;
 out_no_user_srf:
        ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
 out_unlock:
-       ttm_read_unlock(&vmaster->lock);
+       ttm_read_unlock(&dev_priv->reservation_sem);
        return ret;
 }
 
@@ -1315,14 +1384,10 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
        uint32_t backup_handle;
        int ret = -EINVAL;
 
-       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
-       if (unlikely(base == NULL)) {
-               DRM_ERROR("Could not find surface to reference.\n");
-               return -EINVAL;
-       }
-
-       if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
-               goto out_bad_resource;
+       ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
+                                          req->handle_type, &base);
+       if (unlikely(ret != 0))
+               return ret;
 
        user_srf = container_of(base, struct vmw_user_surface, prime.base);
        srf = &user_srf->srf;
@@ -1331,13 +1396,6 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
                goto out_bad_resource;
        }
 
-       ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
-                                TTM_REF_USAGE, NULL);
-       if (unlikely(ret != 0)) {
-               DRM_ERROR("Could not add a reference to a GB surface.\n");
-               goto out_bad_resource;
-       }
-
        mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
        ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
                                        &backup_handle);
@@ -1346,8 +1404,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not add a reference to a GB surface "
                          "backup buffer.\n");
-               (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
-                                                req->sid,
+               (void) ttm_ref_object_base_unref(tfile, base->hash.key,
                                                 TTM_REF_USAGE);
                goto out_bad_resource;
        }
index 22be104fbda97526980481011ad5250121b52948..39a7519a2853b5678503fc5aae4b5653a62f3001 100644 (file)
@@ -120,7 +120,7 @@ static int ipu_page_flip(struct drm_crtc *crtc,
 
        ipu_crtc->newfb = fb;
        ipu_crtc->page_flip_event = event;
-       crtc->fb = fb;
+       crtc->primary->fb = fb;
 
        return 0;
 }
@@ -192,7 +192,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
                return ret;
        }
 
-       return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->fb,
+       return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->primary->fb,
                                  0, 0, mode->hdisplay, mode->vdisplay,
                                  x, y, mode->hdisplay, mode->vdisplay);
 }
@@ -218,7 +218,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
 
        if (ipu_crtc->newfb) {
                ipu_crtc->newfb = NULL;
-               ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.fb,
+               ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.primary->fb,
                                ipu_crtc->plane[0]->x, ipu_crtc->plane[0]->y);
                ipu_crtc_handle_pageflip(ipu_crtc);
        }
index 34b642a12f8bb2cb6163b1fa05eeca184aef135b..5128dc399d361c62f39df5ad7cd685bcb497de28 100644 (file)
@@ -68,7 +68,7 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
 
        cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        if (!cma_obj) {
-               DRM_LOG_KMS("entry is null.\n");
+               DRM_DEBUG_KMS("entry is null.\n");
                return -EFAULT;
        }
 
index 75c8a8e7efc03ad42f2a2f44e60b61d273d62c18..fcf2d48ac6d16b5f5ec31b11671b73bd68a98e8e 100644 (file)
@@ -29,11 +29,4 @@ config EXYNOS_LCD_S6E8AX0
          If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
          LCD control driver.
 
-config EXYNOS_DP
-       bool "EXYNOS DP driver support"
-       depends on OF && ARCH_EXYNOS
-       default n
-       help
-         This enables support for DP device.
-
 endif # EXYNOS_VIDEO
index ec7772e452a936c2ffe9c3e71ae116a9b9d2a80c..b5b1bd228abb80a8da816cceabdfd54289a0e699 100644 (file)
@@ -5,4 +5,3 @@
 obj-$(CONFIG_EXYNOS_MIPI_DSI)          += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
                                        exynos_mipi_dsi_lowlevel.o
 obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)       += s6e8ax0.o
-obj-$(CONFIG_EXYNOS_DP)                        += exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
deleted file mode 100644 (file)
index 5e1a715..0000000
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Samsung SoC DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-
-#include "exynos_dp_core.h"
-
-static int exynos_dp_init_dp(struct exynos_dp_device *dp)
-{
-       exynos_dp_reset(dp);
-
-       exynos_dp_swreset(dp);
-
-       exynos_dp_init_analog_param(dp);
-       exynos_dp_init_interrupt(dp);
-
-       /* SW defined function Normal operation */
-       exynos_dp_enable_sw_function(dp);
-
-       exynos_dp_config_interrupt(dp);
-       exynos_dp_init_analog_func(dp);
-
-       exynos_dp_init_hpd(dp);
-       exynos_dp_init_aux(dp);
-
-       return 0;
-}
-
-static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
-{
-       int timeout_loop = 0;
-
-       while (exynos_dp_get_plug_in_status(dp) != 0) {
-               timeout_loop++;
-               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-                       dev_err(dp->dev, "failed to get hpd plug status\n");
-                       return -ETIMEDOUT;
-               }
-               usleep_range(10, 11);
-       }
-
-       return 0;
-}
-
-static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-       int i;
-       unsigned char sum = 0;
-
-       for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-               sum = sum + edid_data[i];
-
-       return sum;
-}
-
-static int exynos_dp_read_edid(struct exynos_dp_device *dp)
-{
-       unsigned char edid[EDID_BLOCK_LENGTH * 2];
-       unsigned int extend_block = 0;
-       unsigned char sum;
-       unsigned char test_vector;
-       int retval;
-
-       /*
-        * EDID device address is 0x50.
-        * However, if necessary, you must have set upper address
-        * into E-EDID in I2C device, 0x30.
-        */
-
-       /* Read Extension Flag, Number of 128-byte EDID extension blocks */
-       retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-                               EDID_EXTENSION_FLAG,
-                               &extend_block);
-       if (retval)
-               return retval;
-
-       if (extend_block > 0) {
-               dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-               /* Read EDID data */
-               retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-                                               EDID_HEADER_PATTERN,
-                                               EDID_BLOCK_LENGTH,
-                                               &edid[EDID_HEADER_PATTERN]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = exynos_dp_calc_edid_check_sum(edid);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               /* Read additional EDID data */
-               retval = exynos_dp_read_bytes_from_i2c(dp,
-                               I2C_EDID_DEVICE_ADDR,
-                               EDID_BLOCK_LENGTH,
-                               EDID_BLOCK_LENGTH,
-                               &edid[EDID_BLOCK_LENGTH]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
-                                       &test_vector);
-               if (test_vector & DPCD_TEST_EDID_READ) {
-                       exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TEST_EDID_CHECKSUM,
-                               edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-                       exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TEST_RESPONSE,
-                               DPCD_TEST_EDID_CHECKSUM_WRITE);
-               }
-       } else {
-               dev_info(dp->dev, "EDID data does not include any extensions.\n");
-
-               /* Read EDID data */
-               retval = exynos_dp_read_bytes_from_i2c(dp,
-                               I2C_EDID_DEVICE_ADDR,
-                               EDID_HEADER_PATTERN,
-                               EDID_BLOCK_LENGTH,
-                               &edid[EDID_HEADER_PATTERN]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = exynos_dp_calc_edid_check_sum(edid);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_TEST_REQUEST,
-                       &test_vector);
-               if (test_vector & DPCD_TEST_EDID_READ) {
-                       exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TEST_EDID_CHECKSUM,
-                               edid[EDID_CHECKSUM]);
-                       exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TEST_RESPONSE,
-                               DPCD_TEST_EDID_CHECKSUM_WRITE);
-               }
-       }
-
-       dev_err(dp->dev, "EDID Read success!\n");
-       return 0;
-}
-
-static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
-{
-       u8 buf[12];
-       int i;
-       int retval;
-
-       /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-       retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
-                               12, buf);
-       if (retval)
-               return retval;
-
-       /* Read EDID */
-       for (i = 0; i < 3; i++) {
-               retval = exynos_dp_read_edid(dp);
-               if (!retval)
-                       break;
-       }
-
-       return retval;
-}
-
-static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
-                                               bool enable)
-{
-       u8 data;
-
-       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
-
-       if (enable)
-               exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-                       DPCD_ENHANCED_FRAME_EN |
-                       DPCD_LANE_COUNT_SET(data));
-       else
-               exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-                       DPCD_LANE_COUNT_SET(data));
-}
-
-static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
-{
-       u8 data;
-       int retval;
-
-       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-       retval = DPCD_ENHANCED_FRAME_CAP(data);
-
-       return retval;
-}
-
-static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
-{
-       u8 data;
-
-       data = exynos_dp_is_enhanced_mode_available(dp);
-       exynos_dp_enable_rx_to_enhanced_mode(dp, data);
-       exynos_dp_enable_enhanced_mode(dp, data);
-}
-
-static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
-{
-       exynos_dp_set_training_pattern(dp, DP_NONE);
-
-       exynos_dp_write_byte_to_dpcd(dp,
-               DPCD_ADDR_TRAINING_PATTERN_SET,
-               DPCD_TRAINING_PATTERN_DISABLED);
-}
-
-static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
-                                       int pre_emphasis, int lane)
-{
-       switch (lane) {
-       case 0:
-               exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
-               break;
-       case 1:
-               exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
-               break;
-
-       case 2:
-               exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
-               break;
-
-       case 3:
-               exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
-               break;
-       }
-}
-
-static int exynos_dp_link_start(struct exynos_dp_device *dp)
-{
-       u8 buf[4];
-       int lane, lane_count, pll_tries, retval;
-
-       lane_count = dp->link_train.lane_count;
-
-       dp->link_train.lt_state = CLOCK_RECOVERY;
-       dp->link_train.eq_loop = 0;
-
-       for (lane = 0; lane < lane_count; lane++)
-               dp->link_train.cr_loop[lane] = 0;
-
-       /* Set link rate and count as you want to establish*/
-       exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
-       exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
-
-       /* Setup RX configuration */
-       buf[0] = dp->link_train.link_rate;
-       buf[1] = dp->link_train.lane_count;
-       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
-                               2, buf);
-       if (retval)
-               return retval;
-
-       /* Set TX pre-emphasis to minimum */
-       for (lane = 0; lane < lane_count; lane++)
-               exynos_dp_set_lane_lane_pre_emphasis(dp,
-                       PRE_EMPHASIS_LEVEL_0, lane);
-
-       /* Wait for PLL lock */
-       pll_tries = 0;
-       while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-               if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
-                       dev_err(dp->dev, "Wait for PLL lock timed out\n");
-                       return -ETIMEDOUT;
-               }
-
-               pll_tries++;
-               usleep_range(90, 120);
-       }
-
-       /* Set training pattern 1 */
-       exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
-
-       /* Set RX training pattern */
-       retval = exynos_dp_write_byte_to_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
-       if (retval)
-               return retval;
-
-       for (lane = 0; lane < lane_count; lane++)
-               buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
-                           DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
-
-       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-                       lane_count, buf);
-
-       return retval;
-}
-
-static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
-{
-       int shift = (lane & 1) * 4;
-       u8 link_value = link_status[lane>>1];
-
-       return (link_value >> shift) & 0xf;
-}
-
-static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
-{
-       int lane;
-       u8 lane_status;
-
-       for (lane = 0; lane < lane_count; lane++) {
-               lane_status = exynos_dp_get_lane_status(link_status, lane);
-               if ((lane_status & DPCD_LANE_CR_DONE) == 0)
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
-                               int lane_count)
-{
-       int lane;
-       u8 lane_status;
-
-       if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
-               return -EINVAL;
-
-       for (lane = 0; lane < lane_count; lane++) {
-               lane_status = exynos_dp_get_lane_status(link_status, lane);
-               lane_status &= DPCD_CHANNEL_EQ_BITS;
-               if (lane_status != DPCD_CHANNEL_EQ_BITS)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
-                                                       int lane)
-{
-       int shift = (lane & 1) * 4;
-       u8 link_value = adjust_request[lane>>1];
-
-       return (link_value >> shift) & 0x3;
-}
-
-static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
-                                       u8 adjust_request[2],
-                                       int lane)
-{
-       int shift = (lane & 1) * 4;
-       u8 link_value = adjust_request[lane>>1];
-
-       return ((link_value >> shift) & 0xc) >> 2;
-}
-
-static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
-                                       u8 training_lane_set, int lane)
-{
-       switch (lane) {
-       case 0:
-               exynos_dp_set_lane0_link_training(dp, training_lane_set);
-               break;
-       case 1:
-               exynos_dp_set_lane1_link_training(dp, training_lane_set);
-               break;
-
-       case 2:
-               exynos_dp_set_lane2_link_training(dp, training_lane_set);
-               break;
-
-       case 3:
-               exynos_dp_set_lane3_link_training(dp, training_lane_set);
-               break;
-       }
-}
-
-static unsigned int exynos_dp_get_lane_link_training(
-                               struct exynos_dp_device *dp,
-                               int lane)
-{
-       u32 reg;
-
-       switch (lane) {
-       case 0:
-               reg = exynos_dp_get_lane0_link_training(dp);
-               break;
-       case 1:
-               reg = exynos_dp_get_lane1_link_training(dp);
-               break;
-       case 2:
-               reg = exynos_dp_get_lane2_link_training(dp);
-               break;
-       case 3:
-               reg = exynos_dp_get_lane3_link_training(dp);
-               break;
-       default:
-               WARN_ON(1);
-               return 0;
-       }
-
-       return reg;
-}
-
-static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
-{
-       exynos_dp_training_pattern_dis(dp);
-       exynos_dp_set_enhanced_mode(dp);
-
-       dp->link_train.lt_state = FAILED;
-}
-
-static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
-                                       u8 adjust_request[2])
-{
-       int lane, lane_count;
-       u8 voltage_swing, pre_emphasis, training_lane;
-
-       lane_count = dp->link_train.lane_count;
-       for (lane = 0; lane < lane_count; lane++) {
-               voltage_swing = exynos_dp_get_adjust_request_voltage(
-                                               adjust_request, lane);
-               pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-                                               adjust_request, lane);
-               training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-                               DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-               if (voltage_swing == VOLTAGE_LEVEL_3)
-                       training_lane |= DPCD_MAX_SWING_REACHED;
-               if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-                       training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-
-               dp->link_train.training_lane[lane] = training_lane;
-       }
-}
-
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
-{
-       int lane, lane_count, retval;
-       u8 voltage_swing, pre_emphasis, training_lane;
-       u8 link_status[2], adjust_request[2];
-
-       usleep_range(100, 101);
-
-       lane_count = dp->link_train.lane_count;
-
-       retval =  exynos_dp_read_bytes_from_dpcd(dp,
-                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-       if (retval)
-               return retval;
-
-       retval =  exynos_dp_read_bytes_from_dpcd(dp,
-                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-       if (retval)
-               return retval;
-
-       if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-               /* set training pattern 2 for EQ */
-               exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
-
-               retval = exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TRAINING_PATTERN_SET,
-                               DPCD_SCRAMBLING_DISABLED |
-                               DPCD_TRAINING_PATTERN_2);
-               if (retval)
-                       return retval;
-
-               dev_info(dp->dev, "Link Training Clock Recovery success\n");
-               dp->link_train.lt_state = EQUALIZER_TRAINING;
-       } else {
-               for (lane = 0; lane < lane_count; lane++) {
-                       training_lane = exynos_dp_get_lane_link_training(
-                                                       dp, lane);
-                       voltage_swing = exynos_dp_get_adjust_request_voltage(
-                                                       adjust_request, lane);
-                       pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-                                                       adjust_request, lane);
-
-                       if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
-                                       voltage_swing &&
-                           DPCD_PRE_EMPHASIS_GET(training_lane) ==
-                                       pre_emphasis)
-                               dp->link_train.cr_loop[lane]++;
-
-                       if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
-                           voltage_swing == VOLTAGE_LEVEL_3 ||
-                           pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-                               dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
-                                       dp->link_train.cr_loop[lane],
-                                       voltage_swing, pre_emphasis);
-                               exynos_dp_reduce_link_rate(dp);
-                               return -EIO;
-                       }
-               }
-       }
-
-       exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-       for (lane = 0; lane < lane_count; lane++)
-               exynos_dp_set_lane_link_training(dp,
-                       dp->link_train.training_lane[lane], lane);
-
-       retval = exynos_dp_write_bytes_to_dpcd(dp,
-                       DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
-                       dp->link_train.training_lane);
-       if (retval)
-               return retval;
-
-       return retval;
-}
-
-static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
-{
-       int lane, lane_count, retval;
-       u32 reg;
-       u8 link_align, link_status[2], adjust_request[2];
-
-       usleep_range(400, 401);
-
-       lane_count = dp->link_train.lane_count;
-
-       retval = exynos_dp_read_bytes_from_dpcd(dp,
-                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-       if (retval)
-               return retval;
-
-       if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
-               exynos_dp_reduce_link_rate(dp);
-               return -EIO;
-       }
-
-       retval = exynos_dp_read_bytes_from_dpcd(dp,
-                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-       if (retval)
-               return retval;
-
-       retval = exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
-       if (retval)
-               return retval;
-
-       exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-       if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
-               /* traing pattern Set to Normal */
-               exynos_dp_training_pattern_dis(dp);
-
-               dev_info(dp->dev, "Link Training success!\n");
-
-               exynos_dp_get_link_bandwidth(dp, &reg);
-               dp->link_train.link_rate = reg;
-               dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-                       dp->link_train.link_rate);
-
-               exynos_dp_get_lane_count(dp, &reg);
-               dp->link_train.lane_count = reg;
-               dev_dbg(dp->dev, "final lane count = %.2x\n",
-                       dp->link_train.lane_count);
-
-               /* set enhanced mode if available */
-               exynos_dp_set_enhanced_mode(dp);
-               dp->link_train.lt_state = FINISHED;
-
-               return 0;
-       }
-
-       /* not all locked */
-       dp->link_train.eq_loop++;
-
-       if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-               dev_err(dp->dev, "EQ Max loop\n");
-               exynos_dp_reduce_link_rate(dp);
-               return -EIO;
-       }
-
-       for (lane = 0; lane < lane_count; lane++)
-               exynos_dp_set_lane_link_training(dp,
-                       dp->link_train.training_lane[lane], lane);
-
-       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-                       lane_count, dp->link_train.training_lane);
-
-       return retval;
-}
-
-static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
-                                       u8 *bandwidth)
-{
-       u8 data;
-
-       /*
-        * For DP rev.1.1, Maximum link rate of Main Link lanes
-        * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
-        */
-       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
-       *bandwidth = data;
-}
-
-static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
-                                       u8 *lane_count)
-{
-       u8 data;
-
-       /*
-        * For DP rev.1.1, Maximum number of Main Link lanes
-        * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
-        */
-       exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-       *lane_count = DPCD_MAX_LANE_COUNT(data);
-}
-
-static void exynos_dp_init_training(struct exynos_dp_device *dp,
-                       enum link_lane_count_type max_lane,
-                       enum link_rate_type max_rate)
-{
-       /*
-        * MACRO_RST must be applied after the PLL_LOCK to avoid
-        * the DP inter pair skew issue for at least 10 us
-        */
-       exynos_dp_reset_macro(dp);
-
-       /* Initialize by reading RX's DPCD */
-       exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
-       exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
-
-       if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
-          (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
-               dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
-                       dp->link_train.link_rate);
-               dp->link_train.link_rate = LINK_RATE_1_62GBPS;
-       }
-
-       if (dp->link_train.lane_count == 0) {
-               dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
-                       dp->link_train.lane_count);
-               dp->link_train.lane_count = (u8)LANE_COUNT1;
-       }
-
-       /* Setup TX lane count & rate */
-       if (dp->link_train.lane_count > max_lane)
-               dp->link_train.lane_count = max_lane;
-       if (dp->link_train.link_rate > max_rate)
-               dp->link_train.link_rate = max_rate;
-
-       /* All DP analog module power up */
-       exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-}
-
-static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
-{
-       int retval = 0, training_finished = 0;
-
-       dp->link_train.lt_state = START;
-
-       /* Process here */
-       while (!retval && !training_finished) {
-               switch (dp->link_train.lt_state) {
-               case START:
-                       retval = exynos_dp_link_start(dp);
-                       if (retval)
-                               dev_err(dp->dev, "LT link start failed!\n");
-                       break;
-               case CLOCK_RECOVERY:
-                       retval = exynos_dp_process_clock_recovery(dp);
-                       if (retval)
-                               dev_err(dp->dev, "LT CR failed!\n");
-                       break;
-               case EQUALIZER_TRAINING:
-                       retval = exynos_dp_process_equalizer_training(dp);
-                       if (retval)
-                               dev_err(dp->dev, "LT EQ failed!\n");
-                       break;
-               case FINISHED:
-                       training_finished = 1;
-                       break;
-               case FAILED:
-                       return -EREMOTEIO;
-               }
-       }
-       if (retval)
-               dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
-
-       return retval;
-}
-
-static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
-                               u32 count,
-                               u32 bwtype)
-{
-       int i;
-       int retval;
-
-       for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
-               exynos_dp_init_training(dp, count, bwtype);
-               retval = exynos_dp_sw_link_training(dp);
-               if (retval == 0)
-                       break;
-
-               usleep_range(100, 110);
-       }
-
-       return retval;
-}
-
-static int exynos_dp_config_video(struct exynos_dp_device *dp)
-{
-       int retval = 0;
-       int timeout_loop = 0;
-       int done_count = 0;
-
-       exynos_dp_config_video_slave_mode(dp);
-
-       exynos_dp_set_video_color_format(dp);
-
-       if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-               dev_err(dp->dev, "PLL is not locked yet.\n");
-               return -EINVAL;
-       }
-
-       for (;;) {
-               timeout_loop++;
-               if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
-                       break;
-               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-                       dev_err(dp->dev, "Timeout of video streamclk ok\n");
-                       return -ETIMEDOUT;
-               }
-
-               usleep_range(1, 2);
-       }
-
-       /* Set to use the register calculated M/N video */
-       exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
-
-       /* For video bist, Video timing must be generated by register */
-       exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
-
-       /* Disable video mute */
-       exynos_dp_enable_video_mute(dp, 0);
-
-       /* Configure video slave mode */
-       exynos_dp_enable_video_master(dp, 0);
-
-       /* Enable video */
-       exynos_dp_start_video(dp);
-
-       timeout_loop = 0;
-
-       for (;;) {
-               timeout_loop++;
-               if (exynos_dp_is_video_stream_on(dp) == 0) {
-                       done_count++;
-                       if (done_count > 10)
-                               break;
-               } else if (done_count) {
-                       done_count = 0;
-               }
-               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-                       dev_err(dp->dev, "Timeout of video streamclk ok\n");
-                       return -ETIMEDOUT;
-               }
-
-               usleep_range(1000, 1001);
-       }
-
-       if (retval != 0)
-               dev_err(dp->dev, "Video stream is not detected!\n");
-
-       return retval;
-}
-
-static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
-{
-       u8 data;
-
-       if (enable) {
-               exynos_dp_enable_scrambling(dp);
-
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       &data);
-               exynos_dp_write_byte_to_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
-       } else {
-               exynos_dp_disable_scrambling(dp);
-
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       &data);
-               exynos_dp_write_byte_to_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       (u8)(data | DPCD_SCRAMBLING_DISABLED));
-       }
-}
-
-static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
-{
-       struct exynos_dp_device *dp = arg;
-
-       enum dp_irq_type irq_type;
-
-       irq_type = exynos_dp_get_irq_type(dp);
-       switch (irq_type) {
-       case DP_IRQ_TYPE_HP_CABLE_IN:
-               dev_dbg(dp->dev, "Received irq - cable in\n");
-               schedule_work(&dp->hotplug_work);
-               exynos_dp_clear_hotplug_interrupts(dp);
-               break;
-       case DP_IRQ_TYPE_HP_CABLE_OUT:
-               dev_dbg(dp->dev, "Received irq - cable out\n");
-               exynos_dp_clear_hotplug_interrupts(dp);
-               break;
-       case DP_IRQ_TYPE_HP_CHANGE:
-               /*
-                * We get these change notifications once in a while, but there
-                * is nothing we can do with them. Just ignore it for now and
-                * only handle cable changes.
-                */
-               dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
-               exynos_dp_clear_hotplug_interrupts(dp);
-               break;
-       default:
-               dev_err(dp->dev, "Received irq - unknown type!\n");
-               break;
-       }
-       return IRQ_HANDLED;
-}
-
-static void exynos_dp_hotplug(struct work_struct *work)
-{
-       struct exynos_dp_device *dp;
-       int ret;
-
-       dp = container_of(work, struct exynos_dp_device, hotplug_work);
-
-       ret = exynos_dp_detect_hpd(dp);
-       if (ret) {
-               /* Cable has been disconnected, we're done */
-               return;
-       }
-
-       ret = exynos_dp_handle_edid(dp);
-       if (ret) {
-               dev_err(dp->dev, "unable to handle edid\n");
-               return;
-       }
-
-       ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-                                       dp->video_info->link_rate);
-       if (ret) {
-               dev_err(dp->dev, "unable to do link train\n");
-               return;
-       }
-
-       exynos_dp_enable_scramble(dp, 1);
-       exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-       exynos_dp_enable_enhanced_mode(dp, 1);
-
-       exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-       exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-       exynos_dp_init_video(dp);
-       ret = exynos_dp_config_video(dp);
-       if (ret)
-               dev_err(dp->dev, "unable to config video\n");
-}
-
-static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-       struct device_node *dp_node = dev->of_node;
-       struct video_info *dp_video_config;
-
-       dp_video_config = devm_kzalloc(dev,
-                               sizeof(*dp_video_config), GFP_KERNEL);
-       if (!dp_video_config) {
-               dev_err(dev, "memory allocation for video config failed\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       dp_video_config->h_sync_polarity =
-               of_property_read_bool(dp_node, "hsync-active-high");
-
-       dp_video_config->v_sync_polarity =
-               of_property_read_bool(dp_node, "vsync-active-high");
-
-       dp_video_config->interlaced =
-               of_property_read_bool(dp_node, "interlaced");
-
-       if (of_property_read_u32(dp_node, "samsung,color-space",
-                               &dp_video_config->color_space)) {
-               dev_err(dev, "failed to get color-space\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(dp_node, "samsung,dynamic-range",
-                               &dp_video_config->dynamic_range)) {
-               dev_err(dev, "failed to get dynamic-range\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
-                               &dp_video_config->ycbcr_coeff)) {
-               dev_err(dev, "failed to get ycbcr-coeff\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(dp_node, "samsung,color-depth",
-                               &dp_video_config->color_depth)) {
-               dev_err(dev, "failed to get color-depth\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(dp_node, "samsung,link-rate",
-                               &dp_video_config->link_rate)) {
-               dev_err(dev, "failed to get link-rate\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(dp_node, "samsung,lane-count",
-                               &dp_video_config->lane_count)) {
-               dev_err(dev, "failed to get lane-count\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       return dp_video_config;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-       struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
-       u32 phy_base;
-       int ret = 0;
-
-       dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
-       if (!dp_phy_node) {
-               dp->phy = devm_phy_get(dp->dev, "dp");
-               if (IS_ERR(dp->phy))
-                       return PTR_ERR(dp->phy);
-               else
-                       return 0;
-       }
-
-       if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
-               dev_err(dp->dev, "failed to get reg for dptx-phy\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
-                               &dp->enable_mask)) {
-               dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       dp->phy_addr = ioremap(phy_base, SZ_4);
-       if (!dp->phy_addr) {
-               dev_err(dp->dev, "failed to ioremap dp-phy\n");
-               ret = -ENOMEM;
-               goto err;
-       }
-
-err:
-       of_node_put(dp_phy_node);
-
-       return ret;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-       if (dp->phy) {
-               phy_power_on(dp->phy);
-       } else if (dp->phy_addr) {
-               u32 reg;
-
-               reg = __raw_readl(dp->phy_addr);
-               reg |= dp->enable_mask;
-               __raw_writel(reg, dp->phy_addr);
-       }
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-       if (dp->phy) {
-               phy_power_off(dp->phy);
-       } else if (dp->phy_addr) {
-               u32 reg;
-
-               reg = __raw_readl(dp->phy_addr);
-               reg &= ~(dp->enable_mask);
-               __raw_writel(reg, dp->phy_addr);
-       }
-}
-
-static int exynos_dp_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct exynos_dp_device *dp;
-
-       int ret = 0;
-
-       dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
-                               GFP_KERNEL);
-       if (!dp) {
-               dev_err(&pdev->dev, "no memory for device data\n");
-               return -ENOMEM;
-       }
-
-       dp->dev = &pdev->dev;
-
-       dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
-       if (IS_ERR(dp->video_info))
-               return PTR_ERR(dp->video_info);
-
-       ret = exynos_dp_dt_parse_phydata(dp);
-       if (ret)
-               return ret;
-
-       dp->clock = devm_clk_get(&pdev->dev, "dp");
-       if (IS_ERR(dp->clock)) {
-               dev_err(&pdev->dev, "failed to get clock\n");
-               return PTR_ERR(dp->clock);
-       }
-
-       clk_prepare_enable(dp->clock);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(dp->reg_base))
-               return PTR_ERR(dp->reg_base);
-
-       dp->irq = platform_get_irq(pdev, 0);
-       if (dp->irq == -ENXIO) {
-               dev_err(&pdev->dev, "failed to get irq\n");
-               return -ENODEV;
-       }
-
-       INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
-
-       exynos_dp_phy_init(dp);
-
-       exynos_dp_init_dp(dp);
-
-       ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
-                               "exynos-dp", dp);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to request irq\n");
-               return ret;
-       }
-
-       platform_set_drvdata(pdev, dp);
-
-       return 0;
-}
-
-static int exynos_dp_remove(struct platform_device *pdev)
-{
-       struct exynos_dp_device *dp = platform_get_drvdata(pdev);
-
-       flush_work(&dp->hotplug_work);
-
-       exynos_dp_phy_exit(dp);
-
-       clk_disable_unprepare(dp->clock);
-
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos_dp_suspend(struct device *dev)
-{
-       struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-       disable_irq(dp->irq);
-
-       flush_work(&dp->hotplug_work);
-
-       exynos_dp_phy_exit(dp);
-
-       clk_disable_unprepare(dp->clock);
-
-       return 0;
-}
-
-static int exynos_dp_resume(struct device *dev)
-{
-       struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-       exynos_dp_phy_init(dp);
-
-       clk_prepare_enable(dp->clock);
-
-       exynos_dp_init_dp(dp);
-
-       enable_irq(dp->irq);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_dp_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
-};
-
-static const struct of_device_id exynos_dp_match[] = {
-       { .compatible = "samsung,exynos5-dp" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_match);
-
-static struct platform_driver exynos_dp_driver = {
-       .probe          = exynos_dp_probe,
-       .remove         = exynos_dp_remove,
-       .driver         = {
-               .name   = "exynos-dp",
-               .owner  = THIS_MODULE,
-               .pm     = &exynos_dp_pm_ops,
-               .of_match_table = exynos_dp_match,
-       },
-};
-
-module_platform_driver(exynos_dp_driver);
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
deleted file mode 100644 (file)
index 607e36d..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Header file for Samsung DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef _EXYNOS_DP_CORE_H
-#define _EXYNOS_DP_CORE_H
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
-       LINK_RATE_1_62GBPS = 0x06,
-       LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
-       LANE_COUNT1 = 1,
-       LANE_COUNT2 = 2,
-       LANE_COUNT4 = 4
-};
-
-enum link_training_state {
-       START,
-       CLOCK_RECOVERY,
-       EQUALIZER_TRAINING,
-       FINISHED,
-       FAILED
-};
-
-enum voltage_swing_level {
-       VOLTAGE_LEVEL_0,
-       VOLTAGE_LEVEL_1,
-       VOLTAGE_LEVEL_2,
-       VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
-       PRE_EMPHASIS_LEVEL_0,
-       PRE_EMPHASIS_LEVEL_1,
-       PRE_EMPHASIS_LEVEL_2,
-       PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
-       PRBS7,
-       D10_2,
-       TRAINING_PTN1,
-       TRAINING_PTN2,
-       DP_NONE
-};
-
-enum color_space {
-       COLOR_RGB,
-       COLOR_YCBCR422,
-       COLOR_YCBCR444
-};
-
-enum color_depth {
-       COLOR_6,
-       COLOR_8,
-       COLOR_10,
-       COLOR_12
-};
-
-enum color_coefficient {
-       COLOR_YCBCR601,
-       COLOR_YCBCR709
-};
-
-enum dynamic_range {
-       VESA,
-       CEA
-};
-
-enum pll_status {
-       PLL_UNLOCKED,
-       PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
-       CALCULATED_M,
-       REGISTER_M
-};
-
-enum video_timing_recognition_type {
-       VIDEO_TIMING_FROM_CAPTURE,
-       VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
-       AUX_BLOCK,
-       CH0_BLOCK,
-       CH1_BLOCK,
-       CH2_BLOCK,
-       CH3_BLOCK,
-       ANALOG_TOTAL,
-       POWER_ALL
-};
-
-enum dp_irq_type {
-       DP_IRQ_TYPE_HP_CABLE_IN,
-       DP_IRQ_TYPE_HP_CABLE_OUT,
-       DP_IRQ_TYPE_HP_CHANGE,
-       DP_IRQ_TYPE_UNKNOWN,
-};
-
-struct video_info {
-       char *name;
-
-       bool h_sync_polarity;
-       bool v_sync_polarity;
-       bool interlaced;
-
-       enum color_space color_space;
-       enum dynamic_range dynamic_range;
-       enum color_coefficient ycbcr_coeff;
-       enum color_depth color_depth;
-
-       enum link_rate_type link_rate;
-       enum link_lane_count_type lane_count;
-};
-
-struct link_train {
-       int eq_loop;
-       int cr_loop[4];
-
-       u8 link_rate;
-       u8 lane_count;
-       u8 training_lane[4];
-
-       enum link_training_state lt_state;
-};
-
-struct exynos_dp_device {
-       struct device           *dev;
-       struct clk              *clock;
-       unsigned int            irq;
-       void __iomem            *reg_base;
-       void __iomem            *phy_addr;
-       unsigned int            enable_mask;
-
-       struct video_info       *video_info;
-       struct link_train       link_train;
-       struct work_struct      hotplug_work;
-       struct phy              *phy;
-};
-
-/* exynos_dp_reg.c */
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_stop_video(struct exynos_dp_device *dp);
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
-void exynos_dp_reset(struct exynos_dp_device *dp);
-void exynos_dp_swreset(struct exynos_dp_device *dp);
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-                               enum analog_power_block block,
-                               bool enable);
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
-void exynos_dp_init_hpd(struct exynos_dp_device *dp);
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
-void exynos_dp_reset_aux(struct exynos_dp_device *dp);
-void exynos_dp_init_aux(struct exynos_dp_device *dp);
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned char data);
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned char *data);
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char data[]);
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char data[]);
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr);
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr,
-                               unsigned int *data);
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char edid[]);
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-                                enum pattern_set pattern);
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-                               u32 training_lane);
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-                               u32 training_lane);
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-                               u32 training_lane);
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-                               u32 training_lane);
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
-void exynos_dp_reset_macro(struct exynos_dp_device *dp);
-void exynos_dp_init_video(struct exynos_dp_device *dp);
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-                       enum clock_recovery_m_value_type type,
-                       u32 m_value,
-                       u32 n_value);
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_start_video(struct exynos_dp_device *dp);
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
-
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR                   0x50
-#define I2C_E_EDID_DEVICE_ADDR                 0x30
-
-#define EDID_BLOCK_LENGTH                      0x80
-#define EDID_HEADER_PATTERN                    0x00
-#define EDID_EXTENSION_FLAG                    0x7e
-#define EDID_CHECKSUM                          0x7f
-
-/* Definition for DPCD Register */
-#define DPCD_ADDR_DPCD_REV                     0x0000
-#define DPCD_ADDR_MAX_LINK_RATE                        0x0001
-#define DPCD_ADDR_MAX_LANE_COUNT               0x0002
-#define DPCD_ADDR_LINK_BW_SET                  0x0100
-#define DPCD_ADDR_LANE_COUNT_SET               0x0101
-#define DPCD_ADDR_TRAINING_PATTERN_SET         0x0102
-#define DPCD_ADDR_TRAINING_LANE0_SET           0x0103
-#define DPCD_ADDR_LANE0_1_STATUS               0x0202
-#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED    0x0204
-#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1       0x0206
-#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3       0x0207
-#define DPCD_ADDR_TEST_REQUEST                 0x0218
-#define DPCD_ADDR_TEST_RESPONSE                        0x0260
-#define DPCD_ADDR_TEST_EDID_CHECKSUM           0x0261
-#define DPCD_ADDR_SINK_POWER_STATE             0x0600
-
-/* DPCD_ADDR_MAX_LANE_COUNT */
-#define DPCD_ENHANCED_FRAME_CAP(x)             (((x) >> 7) & 0x1)
-#define DPCD_MAX_LANE_COUNT(x)                 ((x) & 0x1f)
-
-/* DPCD_ADDR_LANE_COUNT_SET */
-#define DPCD_ENHANCED_FRAME_EN                 (0x1 << 7)
-#define DPCD_LANE_COUNT_SET(x)                 ((x) & 0x1f)
-
-/* DPCD_ADDR_TRAINING_PATTERN_SET */
-#define DPCD_SCRAMBLING_DISABLED               (0x1 << 5)
-#define DPCD_SCRAMBLING_ENABLED                        (0x0 << 5)
-#define DPCD_TRAINING_PATTERN_2                        (0x2 << 0)
-#define DPCD_TRAINING_PATTERN_1                        (0x1 << 0)
-#define DPCD_TRAINING_PATTERN_DISABLED         (0x0 << 0)
-
-/* DPCD_ADDR_TRAINING_LANE0_SET */
-#define DPCD_MAX_PRE_EMPHASIS_REACHED          (0x1 << 5)
-#define DPCD_PRE_EMPHASIS_SET(x)               (((x) & 0x3) << 3)
-#define DPCD_PRE_EMPHASIS_GET(x)               (((x) >> 3) & 0x3)
-#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0      (0x0 << 3)
-#define DPCD_MAX_SWING_REACHED                 (0x1 << 2)
-#define DPCD_VOLTAGE_SWING_SET(x)              (((x) & 0x3) << 0)
-#define DPCD_VOLTAGE_SWING_GET(x)              (((x) >> 0) & 0x3)
-#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0     (0x0 << 0)
-
-/* DPCD_ADDR_LANE0_1_STATUS */
-#define DPCD_LANE_SYMBOL_LOCKED                        (0x1 << 2)
-#define DPCD_LANE_CHANNEL_EQ_DONE              (0x1 << 1)
-#define DPCD_LANE_CR_DONE                      (0x1 << 0)
-#define DPCD_CHANNEL_EQ_BITS                   (DPCD_LANE_CR_DONE|     \
-                                                DPCD_LANE_CHANNEL_EQ_DONE|\
-                                                DPCD_LANE_SYMBOL_LOCKED)
-
-/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
-#define DPCD_LINK_STATUS_UPDATED               (0x1 << 7)
-#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED    (0x1 << 6)
-#define DPCD_INTERLANE_ALIGN_DONE              (0x1 << 0)
-
-/* DPCD_ADDR_TEST_REQUEST */
-#define DPCD_TEST_EDID_READ                    (0x1 << 2)
-
-/* DPCD_ADDR_TEST_RESPONSE */
-#define DPCD_TEST_EDID_CHECKSUM_WRITE          (0x1 << 2)
-
-/* DPCD_ADDR_SINK_POWER_STATE */
-#define DPCD_SET_POWER_STATE_D0                        (0x1 << 0)
-#define DPCD_SET_POWER_STATE_D4                        (0x2 << 0)
-
-#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
deleted file mode 100644 (file)
index b70da50..0000000
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * Samsung DP (Display port) register interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include "exynos_dp_core.h"
-#include "exynos_dp_reg.h"
-
-#define COMMON_INT_MASK_1      0
-#define COMMON_INT_MASK_2      0
-#define COMMON_INT_MASK_3      0
-#define COMMON_INT_MASK_4      (HOTPLUG_CHG | HPD_LOST | PLUG)
-#define INT_STA_MASK           INT_HPD
-
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
-{
-       u32 reg;
-
-       if (enable) {
-               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-               reg |= HDCP_VIDEO_MUTE;
-               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-       } else {
-               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-               reg &= ~HDCP_VIDEO_MUTE;
-               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-       }
-}
-
-void exynos_dp_stop_video(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-       reg &= ~VIDEO_EN;
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
-{
-       u32 reg;
-
-       if (enable)
-               reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
-                       LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
-       else
-               reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
-                       LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
-
-       writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
-}
-
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = TX_TERMINAL_CTRL_50_OHM;
-       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
-
-       reg = SEL_24M | TX_DVDD_BIT_1_0625V;
-       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
-
-       reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
-       writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
-
-       reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
-               TX_CUR1_2X | TX_CUR_16_MA;
-       writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
-
-       reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
-               CH1_AMP_400_MV | CH0_AMP_400_MV;
-       writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
-}
-
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
-{
-       /* Set interrupt pin assertion polarity as high */
-       writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
-
-       /* Clear pending regisers */
-       writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-       writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
-       writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
-       writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-       writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
-
-       /* 0:mask,1: unmask */
-       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-       writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-       writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-void exynos_dp_reset(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       exynos_dp_stop_video(dp);
-       exynos_dp_enable_video_mute(dp, 0);
-
-       reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
-               AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
-               HDCP_FUNC_EN_N | SW_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-       reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
-               SERDES_FIFO_FUNC_EN_N |
-               LS_CLK_DOMAIN_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-
-       usleep_range(20, 30);
-
-       exynos_dp_lane_swap(dp, 0);
-
-       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-       writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-       writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-       writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
-       writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
-
-       writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
-       writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
-
-       writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
-
-       writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-       writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
-       writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
-
-       writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
-       writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
-
-       writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_swreset(struct exynos_dp_device *dp)
-{
-       writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
-}
-
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       /* 0: mask, 1: unmask */
-       reg = COMMON_INT_MASK_1;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-
-       reg = COMMON_INT_MASK_2;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-
-       reg = COMMON_INT_MASK_3;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-
-       reg = COMMON_INT_MASK_4;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-
-       reg = INT_STA_MASK;
-       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-       if (reg & PLL_LOCK)
-               return PLL_LOCKED;
-       else
-               return PLL_UNLOCKED;
-}
-
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
-{
-       u32 reg;
-
-       if (enable) {
-               reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-               reg |= DP_PLL_PD;
-               writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-       } else {
-               reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-               reg &= ~DP_PLL_PD;
-               writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-       }
-}
-
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-                               enum analog_power_block block,
-                               bool enable)
-{
-       u32 reg;
-
-       switch (block) {
-       case AUX_BLOCK:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= AUX_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~AUX_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case CH0_BLOCK:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= CH0_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~CH0_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case CH1_BLOCK:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= CH1_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~CH1_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case CH2_BLOCK:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= CH2_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~CH2_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case CH3_BLOCK:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= CH3_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~CH3_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case ANALOG_TOTAL:
-               if (enable) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg |= DP_PHY_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-                       reg &= ~DP_PHY_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       case POWER_ALL:
-               if (enable) {
-                       reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
-                               CH1_PD | CH0_PD;
-                       writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-               } else {
-                       writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
-               }
-               break;
-       default:
-               break;
-       }
-}
-
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
-{
-       u32 reg;
-       int timeout_loop = 0;
-
-       exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-
-       reg = PLL_LOCK_CHG;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-       reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
-       writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-
-       /* Power up PLL */
-       if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-               exynos_dp_set_pll_power_down(dp, 0);
-
-               while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-                       timeout_loop++;
-                       if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-                               dev_err(dp->dev, "failed to get pll lock status\n");
-                               return;
-                       }
-                       usleep_range(10, 20);
-               }
-       }
-
-       /* Enable Serdes FIFO function and Link symbol clock domain module */
-       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-       reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
-               | AUX_FUNC_EN_N);
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = HOTPLUG_CHG | HPD_LOST | PLUG;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-       reg = INT_HPD;
-       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-}
-
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       exynos_dp_clear_hotplug_interrupts(dp);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-       reg &= ~(F_HPD | HPD_CTRL);
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-}
-
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       /* Parse hotplug interrupt status register */
-       reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-       if (reg & PLUG)
-               return DP_IRQ_TYPE_HP_CABLE_IN;
-
-       if (reg & HPD_LOST)
-               return DP_IRQ_TYPE_HP_CABLE_OUT;
-
-       if (reg & HOTPLUG_CHG)
-               return DP_IRQ_TYPE_HP_CHANGE;
-
-       return DP_IRQ_TYPE_UNKNOWN;
-}
-
-void exynos_dp_reset_aux(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       /* Disable AUX channel module */
-       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-       reg |= AUX_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_init_aux(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       /* Clear inerrupts related to AUX channel */
-       reg = RPLY_RECEIV | AUX_ERR;
-       writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-
-       exynos_dp_reset_aux(dp);
-
-       /* Disable AUX transaction H/W retry */
-       reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
-               AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
-       writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
-
-       /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
-       reg = DEFER_CTRL_EN | DEFER_COUNT(1);
-       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
-
-       /* Enable AUX channel module */
-       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-       reg &= ~AUX_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-       if (reg & HPD_STATUS)
-               return 0;
-
-       return -EINVAL;
-}
-
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-       reg &= ~SW_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-}
-
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
-{
-       int reg;
-       int retval = 0;
-       int timeout_loop = 0;
-
-       /* Enable AUX CH operation */
-       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-       reg |= AUX_EN;
-       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-       /* Is AUX CH command reply received? */
-       reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-       while (!(reg & RPLY_RECEIV)) {
-               timeout_loop++;
-               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-                       dev_err(dp->dev, "AUX CH command reply failed!\n");
-                       return -ETIMEDOUT;
-               }
-               reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-               usleep_range(10, 11);
-       }
-
-       /* Clear interrupt source for AUX CH command reply */
-       writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
-
-       /* Clear interrupt source for AUX CH access error */
-       reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-       if (reg & AUX_ERR) {
-               writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
-               return -EREMOTEIO;
-       }
-
-       /* Check AUX CH error access status */
-       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
-       if ((reg & AUX_STATUS_MASK) != 0) {
-               dev_err(dp->dev, "AUX CH error happens: %d\n\n",
-                       reg & AUX_STATUS_MASK);
-               return -EREMOTEIO;
-       }
-
-       return retval;
-}
-
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned char data)
-{
-       u32 reg;
-       int i;
-       int retval;
-
-       for (i = 0; i < 3; i++) {
-               /* Clear AUX CH data buffer */
-               reg = BUF_CLR;
-               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-               /* Select DPCD device address */
-               reg = AUX_ADDR_7_0(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-               reg = AUX_ADDR_15_8(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-               reg = AUX_ADDR_19_16(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-               /* Write data buffer */
-               reg = (unsigned int)data;
-               writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-               /*
-                * Set DisplayPort transaction and write 1 byte
-                * If bit 3 is 1, DisplayPort transaction.
-                * If Bit 3 is 0, I2C transaction.
-                */
-               reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-               /* Start AUX transaction */
-               retval = exynos_dp_start_aux_transaction(dp);
-               if (retval == 0)
-                       break;
-               else
-                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                               __func__);
-       }
-
-       return retval;
-}
-
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned char *data)
-{
-       u32 reg;
-       int i;
-       int retval;
-
-       for (i = 0; i < 3; i++) {
-               /* Clear AUX CH data buffer */
-               reg = BUF_CLR;
-               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-               /* Select DPCD device address */
-               reg = AUX_ADDR_7_0(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-               reg = AUX_ADDR_15_8(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-               reg = AUX_ADDR_19_16(reg_addr);
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-               /*
-                * Set DisplayPort transaction and read 1 byte
-                * If bit 3 is 1, DisplayPort transaction.
-                * If Bit 3 is 0, I2C transaction.
-                */
-               reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-               /* Start AUX transaction */
-               retval = exynos_dp_start_aux_transaction(dp);
-               if (retval == 0)
-                       break;
-               else
-                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                               __func__);
-       }
-
-       /* Read data buffer */
-       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-       *data = (unsigned char)(reg & 0xff);
-
-       return retval;
-}
-
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char data[])
-{
-       u32 reg;
-       unsigned int start_offset;
-       unsigned int cur_data_count;
-       unsigned int cur_data_idx;
-       int i;
-       int retval = 0;
-
-       /* Clear AUX CH data buffer */
-       reg = BUF_CLR;
-       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-       start_offset = 0;
-       while (start_offset < count) {
-               /* Buffer size of AUX CH is 16 * 4bytes */
-               if ((count - start_offset) > 16)
-                       cur_data_count = 16;
-               else
-                       cur_data_count = count - start_offset;
-
-               for (i = 0; i < 3; i++) {
-                       /* Select DPCD device address */
-                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-                       for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-                            cur_data_idx++) {
-                               reg = data[start_offset + cur_data_idx];
-                               writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
-                                                         + 4 * cur_data_idx);
-                       }
-
-                       /*
-                        * Set DisplayPort transaction and write
-                        * If bit 3 is 1, DisplayPort transaction.
-                        * If Bit 3 is 0, I2C transaction.
-                        */
-                       reg = AUX_LENGTH(cur_data_count) |
-                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-                       /* Start AUX transaction */
-                       retval = exynos_dp_start_aux_transaction(dp);
-                       if (retval == 0)
-                               break;
-                       else
-                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                                       __func__);
-               }
-
-               start_offset += cur_data_count;
-       }
-
-       return retval;
-}
-
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char data[])
-{
-       u32 reg;
-       unsigned int start_offset;
-       unsigned int cur_data_count;
-       unsigned int cur_data_idx;
-       int i;
-       int retval = 0;
-
-       /* Clear AUX CH data buffer */
-       reg = BUF_CLR;
-       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-       start_offset = 0;
-       while (start_offset < count) {
-               /* Buffer size of AUX CH is 16 * 4bytes */
-               if ((count - start_offset) > 16)
-                       cur_data_count = 16;
-               else
-                       cur_data_count = count - start_offset;
-
-               /* AUX CH Request Transaction process */
-               for (i = 0; i < 3; i++) {
-                       /* Select DPCD device address */
-                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-                       /*
-                        * Set DisplayPort transaction and read
-                        * If bit 3 is 1, DisplayPort transaction.
-                        * If Bit 3 is 0, I2C transaction.
-                        */
-                       reg = AUX_LENGTH(cur_data_count) |
-                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-                       /* Start AUX transaction */
-                       retval = exynos_dp_start_aux_transaction(dp);
-                       if (retval == 0)
-                               break;
-                       else
-                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                                       __func__);
-               }
-
-               for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-                   cur_data_idx++) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-                                                + 4 * cur_data_idx);
-                       data[start_offset + cur_data_idx] =
-                               (unsigned char)reg;
-               }
-
-               start_offset += cur_data_count;
-       }
-
-       return retval;
-}
-
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr)
-{
-       u32 reg;
-       int retval;
-
-       /* Set EDID device address */
-       reg = device_addr;
-       writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-       writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-       writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-       /* Set offset from base address of EDID device */
-       writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-       /*
-        * Set I2C transaction and write address
-        * If bit 3 is 1, DisplayPort transaction.
-        * If Bit 3 is 0, I2C transaction.
-        */
-       reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
-               AUX_TX_COMM_WRITE;
-       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-       /* Start AUX transaction */
-       retval = exynos_dp_start_aux_transaction(dp);
-       if (retval != 0)
-               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-
-       return retval;
-}
-
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr,
-                               unsigned int *data)
-{
-       u32 reg;
-       int i;
-       int retval;
-
-       for (i = 0; i < 3; i++) {
-               /* Clear AUX CH data buffer */
-               reg = BUF_CLR;
-               writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-               /* Select EDID device */
-               retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-               if (retval != 0)
-                       continue;
-
-               /*
-                * Set I2C transaction and read data
-                * If bit 3 is 1, DisplayPort transaction.
-                * If Bit 3 is 0, I2C transaction.
-                */
-               reg = AUX_TX_COMM_I2C_TRANSACTION |
-                       AUX_TX_COMM_READ;
-               writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-               /* Start AUX transaction */
-               retval = exynos_dp_start_aux_transaction(dp);
-               if (retval == 0)
-                       break;
-               else
-                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                               __func__);
-       }
-
-       /* Read data */
-       if (retval == 0)
-               *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-       return retval;
-}
-
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-                               unsigned int device_addr,
-                               unsigned int reg_addr,
-                               unsigned int count,
-                               unsigned char edid[])
-{
-       u32 reg;
-       unsigned int i, j;
-       unsigned int cur_data_idx;
-       unsigned int defer = 0;
-       int retval = 0;
-
-       for (i = 0; i < count; i += 16) {
-               for (j = 0; j < 3; j++) {
-                       /* Clear AUX CH data buffer */
-                       reg = BUF_CLR;
-                       writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-                       /* Set normal AUX CH command */
-                       reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-                       reg &= ~ADDR_ONLY;
-                       writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-                       /*
-                        * If Rx sends defer, Tx sends only reads
-                        * request without sending address
-                        */
-                       if (!defer)
-                               retval = exynos_dp_select_i2c_device(dp,
-                                               device_addr, reg_addr + i);
-                       else
-                               defer = 0;
-
-                       if (retval == 0) {
-                               /*
-                                * Set I2C transaction and write data
-                                * If bit 3 is 1, DisplayPort transaction.
-                                * If Bit 3 is 0, I2C transaction.
-                                */
-                               reg = AUX_LENGTH(16) |
-                                       AUX_TX_COMM_I2C_TRANSACTION |
-                                       AUX_TX_COMM_READ;
-                               writel(reg, dp->reg_base +
-                                       EXYNOS_DP_AUX_CH_CTL_1);
-
-                               /* Start AUX transaction */
-                               retval = exynos_dp_start_aux_transaction(dp);
-                               if (retval == 0)
-                                       break;
-                               else
-                                       dev_dbg(dp->dev,
-                                               "%s: Aux Transaction fail!\n",
-                                               __func__);
-                       }
-                       /* Check if Rx sends defer */
-                       reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
-                       if (reg == AUX_RX_COMM_AUX_DEFER ||
-                               reg == AUX_RX_COMM_I2C_DEFER) {
-                               dev_err(dp->dev, "Defer: %d\n\n", reg);
-                               defer = 1;
-                       }
-               }
-
-               for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
-                       reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-                                                + 4 * cur_data_idx);
-                       edid[i + cur_data_idx] = (unsigned char)reg;
-               }
-       }
-
-       return retval;
-}
-
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
-{
-       u32 reg;
-
-       reg = bwtype;
-       if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
-               writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-}
-
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-       *bwtype = reg;
-}
-
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
-{
-       u32 reg;
-
-       reg = count;
-       writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-}
-
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-       *count = reg;
-}
-
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
-{
-       u32 reg;
-
-       if (enable) {
-               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-               reg |= ENHANCED;
-               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-       } else {
-               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-               reg &= ~ENHANCED;
-               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-       }
-}
-
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-                                enum pattern_set pattern)
-{
-       u32 reg;
-
-       switch (pattern) {
-       case PRBS7:
-               reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
-               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-               break;
-       case D10_2:
-               reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
-               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-               break;
-       case TRAINING_PTN1:
-               reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
-               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-               break;
-       case TRAINING_PTN2:
-               reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
-               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-               break;
-       case DP_NONE:
-               reg = SCRAMBLING_ENABLE |
-                       LINK_QUAL_PATTERN_SET_DISABLE |
-                       SW_TRAINING_PATTERN_SET_NORMAL;
-               writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-               break;
-       default:
-               break;
-       }
-}
-
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-       reg &= ~PRE_EMPHASIS_SET_MASK;
-       reg |= level << PRE_EMPHASIS_SET_SHIFT;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-       reg &= ~PRE_EMPHASIS_SET_MASK;
-       reg |= level << PRE_EMPHASIS_SET_SHIFT;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-       reg &= ~PRE_EMPHASIS_SET_MASK;
-       reg |= level << PRE_EMPHASIS_SET_SHIFT;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-       reg &= ~PRE_EMPHASIS_SET_MASK;
-       reg |= level << PRE_EMPHASIS_SET_SHIFT;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-                                       u32 training_lane)
-{
-       u32 reg;
-
-       reg = training_lane;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-                                       u32 training_lane)
-{
-       u32 reg;
-
-       reg = training_lane;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-                                       u32 training_lane)
-{
-       u32 reg;
-
-       reg = training_lane;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-                                       u32 training_lane)
-{
-       u32 reg;
-
-       reg = training_lane;
-       writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-       return reg;
-}
-
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-       return reg;
-}
-
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-       return reg;
-}
-
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-       return reg;
-}
-
-void exynos_dp_reset_macro(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
-       reg |= MACRO_RST;
-       writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-       /* 10 us is the minimum reset time. */
-       usleep_range(10, 20);
-
-       reg &= ~MACRO_RST;
-       writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-}
-
-void exynos_dp_init_video(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
-       writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-       reg = 0x0;
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-       reg = CHA_CRI(4) | CHA_CTRL;
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-       reg = 0x0;
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-       reg = VID_HRES_TH(2) | VID_VRES_TH(0);
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
-}
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       /* Configure the input color depth, color space, dynamic range */
-       reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
-               (dp->video_info->color_depth << IN_BPC_SHIFT) |
-               (dp->video_info->color_space << IN_COLOR_F_SHIFT);
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
-
-       /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-       reg &= ~IN_YC_COEFFI_MASK;
-       if (dp->video_info->ycbcr_coeff)
-               reg |= IN_YC_COEFFI_ITU709;
-       else
-               reg |= IN_YC_COEFFI_ITU601;
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-}
-
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-       if (!(reg & DET_STA)) {
-               dev_dbg(dp->dev, "Input stream clock not detected.\n");
-               return -EINVAL;
-       }
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-       dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
-
-       if (reg & CHA_STA) {
-               dev_dbg(dp->dev, "Input stream clk is changing\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-               enum clock_recovery_m_value_type type,
-               u32 m_value,
-               u32 n_value)
-{
-       u32 reg;
-
-       if (type == REGISTER_M) {
-               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-               reg |= FIX_M_VID;
-               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-               reg = m_value & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
-               reg = (m_value >> 8) & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
-               reg = (m_value >> 16) & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
-
-               reg = n_value & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
-               reg = (n_value >> 8) & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
-               reg = (n_value >> 16) & 0xff;
-               writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
-       } else  {
-               reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-               reg &= ~FIX_M_VID;
-               writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-               writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
-               writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
-               writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
-       }
-}
-
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
-{
-       u32 reg;
-
-       if (type == VIDEO_TIMING_FROM_CAPTURE) {
-               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-               reg &= ~FORMAT_SEL;
-               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-       } else {
-               reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-               reg |= FORMAT_SEL;
-               writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-       }
-}
-
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
-{
-       u32 reg;
-
-       if (enable) {
-               reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-               reg &= ~VIDEO_MODE_MASK;
-               reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
-               writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-       } else {
-               reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-               reg &= ~VIDEO_MODE_MASK;
-               reg |= VIDEO_MODE_SLAVE_MODE;
-               writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-       }
-}
-
-void exynos_dp_start_video(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-       reg |= VIDEO_EN;
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-       writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-       if (!(reg & STRM_VALID)) {
-               dev_dbg(dp->dev, "Input video stream is not detected.\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-       reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
-       reg |= MASTER_VID_FUNC_EN_N;
-       writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-       reg &= ~INTERACE_SCAN_CFG;
-       reg |= (dp->video_info->interlaced << 2);
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-       reg &= ~VSYNC_POLARITY_CFG;
-       reg |= (dp->video_info->v_sync_polarity << 1);
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-       reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-       reg &= ~HSYNC_POLARITY_CFG;
-       reg |= (dp->video_info->h_sync_polarity << 0);
-       writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-       reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
-       writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-       reg &= ~SCRAMBLING_DISABLE;
-       writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
-
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
-{
-       u32 reg;
-
-       reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-       reg |= SCRAMBLING_DISABLE;
-       writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
deleted file mode 100644 (file)
index 2e9bd0e..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Register definition file for Samsung DP driver
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _EXYNOS_DP_REG_H
-#define _EXYNOS_DP_REG_H
-
-#define EXYNOS_DP_TX_SW_RESET                  0x14
-#define EXYNOS_DP_FUNC_EN_1                    0x18
-#define EXYNOS_DP_FUNC_EN_2                    0x1C
-#define EXYNOS_DP_VIDEO_CTL_1                  0x20
-#define EXYNOS_DP_VIDEO_CTL_2                  0x24
-#define EXYNOS_DP_VIDEO_CTL_3                  0x28
-
-#define EXYNOS_DP_VIDEO_CTL_8                  0x3C
-#define EXYNOS_DP_VIDEO_CTL_10                 0x44
-
-#define EXYNOS_DP_LANE_MAP                     0x35C
-
-#define EXYNOS_DP_ANALOG_CTL_1                 0x370
-#define EXYNOS_DP_ANALOG_CTL_2                 0x374
-#define EXYNOS_DP_ANALOG_CTL_3                 0x378
-#define EXYNOS_DP_PLL_FILTER_CTL_1             0x37C
-#define EXYNOS_DP_TX_AMP_TUNING_CTL            0x380
-
-#define EXYNOS_DP_AUX_HW_RETRY_CTL             0x390
-
-#define EXYNOS_DP_COMMON_INT_STA_1             0x3C4
-#define EXYNOS_DP_COMMON_INT_STA_2             0x3C8
-#define EXYNOS_DP_COMMON_INT_STA_3             0x3CC
-#define EXYNOS_DP_COMMON_INT_STA_4             0x3D0
-#define EXYNOS_DP_INT_STA                      0x3DC
-#define EXYNOS_DP_COMMON_INT_MASK_1            0x3E0
-#define EXYNOS_DP_COMMON_INT_MASK_2            0x3E4
-#define EXYNOS_DP_COMMON_INT_MASK_3            0x3E8
-#define EXYNOS_DP_COMMON_INT_MASK_4            0x3EC
-#define EXYNOS_DP_INT_STA_MASK                 0x3F8
-#define EXYNOS_DP_INT_CTL                      0x3FC
-
-#define EXYNOS_DP_SYS_CTL_1                    0x600
-#define EXYNOS_DP_SYS_CTL_2                    0x604
-#define EXYNOS_DP_SYS_CTL_3                    0x608
-#define EXYNOS_DP_SYS_CTL_4                    0x60C
-
-#define EXYNOS_DP_PKT_SEND_CTL                 0x640
-#define EXYNOS_DP_HDCP_CTL                     0x648
-
-#define EXYNOS_DP_LINK_BW_SET                  0x680
-#define EXYNOS_DP_LANE_COUNT_SET               0x684
-#define EXYNOS_DP_TRAINING_PTN_SET             0x688
-#define EXYNOS_DP_LN0_LINK_TRAINING_CTL                0x68C
-#define EXYNOS_DP_LN1_LINK_TRAINING_CTL                0x690
-#define EXYNOS_DP_LN2_LINK_TRAINING_CTL                0x694
-#define EXYNOS_DP_LN3_LINK_TRAINING_CTL                0x698
-
-#define EXYNOS_DP_DEBUG_CTL                    0x6C0
-#define EXYNOS_DP_HPD_DEGLITCH_L               0x6C4
-#define EXYNOS_DP_HPD_DEGLITCH_H               0x6C8
-#define EXYNOS_DP_LINK_DEBUG_CTL               0x6E0
-
-#define EXYNOS_DP_M_VID_0                      0x700
-#define EXYNOS_DP_M_VID_1                      0x704
-#define EXYNOS_DP_M_VID_2                      0x708
-#define EXYNOS_DP_N_VID_0                      0x70C
-#define EXYNOS_DP_N_VID_1                      0x710
-#define EXYNOS_DP_N_VID_2                      0x714
-
-#define EXYNOS_DP_PLL_CTL                      0x71C
-#define EXYNOS_DP_PHY_PD                       0x720
-#define EXYNOS_DP_PHY_TEST                     0x724
-
-#define EXYNOS_DP_VIDEO_FIFO_THRD              0x730
-#define EXYNOS_DP_AUDIO_MARGIN                 0x73C
-
-#define EXYNOS_DP_M_VID_GEN_FILTER_TH          0x764
-#define EXYNOS_DP_M_AUD_GEN_FILTER_TH          0x778
-#define EXYNOS_DP_AUX_CH_STA                   0x780
-#define EXYNOS_DP_AUX_CH_DEFER_CTL             0x788
-#define EXYNOS_DP_AUX_RX_COMM                  0x78C
-#define EXYNOS_DP_BUFFER_DATA_CTL              0x790
-#define EXYNOS_DP_AUX_CH_CTL_1                 0x794
-#define EXYNOS_DP_AUX_ADDR_7_0                 0x798
-#define EXYNOS_DP_AUX_ADDR_15_8                        0x79C
-#define EXYNOS_DP_AUX_ADDR_19_16               0x7A0
-#define EXYNOS_DP_AUX_CH_CTL_2                 0x7A4
-
-#define EXYNOS_DP_BUF_DATA_0                   0x7C0
-
-#define EXYNOS_DP_SOC_GENERAL_CTL              0x800
-
-/* EXYNOS_DP_TX_SW_RESET */
-#define RESET_DP_TX                            (0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_1 */
-#define MASTER_VID_FUNC_EN_N                   (0x1 << 7)
-#define SLAVE_VID_FUNC_EN_N                    (0x1 << 5)
-#define AUD_FIFO_FUNC_EN_N                     (0x1 << 4)
-#define AUD_FUNC_EN_N                          (0x1 << 3)
-#define HDCP_FUNC_EN_N                         (0x1 << 2)
-#define CRC_FUNC_EN_N                          (0x1 << 1)
-#define SW_FUNC_EN_N                           (0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_2 */
-#define SSC_FUNC_EN_N                          (0x1 << 7)
-#define AUX_FUNC_EN_N                          (0x1 << 2)
-#define SERDES_FIFO_FUNC_EN_N                  (0x1 << 1)
-#define LS_CLK_DOMAIN_FUNC_EN_N                        (0x1 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define VIDEO_EN                               (0x1 << 7)
-#define HDCP_VIDEO_MUTE                                (0x1 << 6)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define IN_D_RANGE_MASK                                (0x1 << 7)
-#define IN_D_RANGE_SHIFT                       (7)
-#define IN_D_RANGE_CEA                         (0x1 << 7)
-#define IN_D_RANGE_VESA                                (0x0 << 7)
-#define IN_BPC_MASK                            (0x7 << 4)
-#define IN_BPC_SHIFT                           (4)
-#define IN_BPC_12_BITS                         (0x3 << 4)
-#define IN_BPC_10_BITS                         (0x2 << 4)
-#define IN_BPC_8_BITS                          (0x1 << 4)
-#define IN_BPC_6_BITS                          (0x0 << 4)
-#define IN_COLOR_F_MASK                                (0x3 << 0)
-#define IN_COLOR_F_SHIFT                       (0)
-#define IN_COLOR_F_YCBCR444                    (0x2 << 0)
-#define IN_COLOR_F_YCBCR422                    (0x1 << 0)
-#define IN_COLOR_F_RGB                         (0x0 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_3 */
-#define IN_YC_COEFFI_MASK                      (0x1 << 7)
-#define IN_YC_COEFFI_SHIFT                     (7)
-#define IN_YC_COEFFI_ITU709                    (0x1 << 7)
-#define IN_YC_COEFFI_ITU601                    (0x0 << 7)
-#define VID_CHK_UPDATE_TYPE_MASK               (0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_SHIFT              (4)
-#define VID_CHK_UPDATE_TYPE_1                  (0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_0                  (0x0 << 4)
-
-/* EXYNOS_DP_VIDEO_CTL_8 */
-#define VID_HRES_TH(x)                         (((x) & 0xf) << 4)
-#define VID_VRES_TH(x)                         (((x) & 0xf) << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_10 */
-#define FORMAT_SEL                             (0x1 << 4)
-#define INTERACE_SCAN_CFG                      (0x1 << 2)
-#define VSYNC_POLARITY_CFG                     (0x1 << 1)
-#define HSYNC_POLARITY_CFG                     (0x1 << 0)
-
-/* EXYNOS_DP_LANE_MAP */
-#define LANE3_MAP_LOGIC_LANE_0                 (0x0 << 6)
-#define LANE3_MAP_LOGIC_LANE_1                 (0x1 << 6)
-#define LANE3_MAP_LOGIC_LANE_2                 (0x2 << 6)
-#define LANE3_MAP_LOGIC_LANE_3                 (0x3 << 6)
-#define LANE2_MAP_LOGIC_LANE_0                 (0x0 << 4)
-#define LANE2_MAP_LOGIC_LANE_1                 (0x1 << 4)
-#define LANE2_MAP_LOGIC_LANE_2                 (0x2 << 4)
-#define LANE2_MAP_LOGIC_LANE_3                 (0x3 << 4)
-#define LANE1_MAP_LOGIC_LANE_0                 (0x0 << 2)
-#define LANE1_MAP_LOGIC_LANE_1                 (0x1 << 2)
-#define LANE1_MAP_LOGIC_LANE_2                 (0x2 << 2)
-#define LANE1_MAP_LOGIC_LANE_3                 (0x3 << 2)
-#define LANE0_MAP_LOGIC_LANE_0                 (0x0 << 0)
-#define LANE0_MAP_LOGIC_LANE_1                 (0x1 << 0)
-#define LANE0_MAP_LOGIC_LANE_2                 (0x2 << 0)
-#define LANE0_MAP_LOGIC_LANE_3                 (0x3 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_1 */
-#define TX_TERMINAL_CTRL_50_OHM                        (0x1 << 4)
-
-/* EXYNOS_DP_ANALOG_CTL_2 */
-#define SEL_24M                                        (0x1 << 3)
-#define TX_DVDD_BIT_1_0625V                    (0x4 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_3 */
-#define DRIVE_DVDD_BIT_1_0625V                 (0x4 << 5)
-#define VCO_BIT_600_MICRO                      (0x5 << 0)
-
-/* EXYNOS_DP_PLL_FILTER_CTL_1 */
-#define PD_RING_OSC                            (0x1 << 6)
-#define AUX_TERMINAL_CTRL_50_OHM               (0x2 << 4)
-#define TX_CUR1_2X                             (0x1 << 2)
-#define TX_CUR_16_MA                           (0x3 << 0)
-
-/* EXYNOS_DP_TX_AMP_TUNING_CTL */
-#define CH3_AMP_400_MV                         (0x0 << 24)
-#define CH2_AMP_400_MV                         (0x0 << 16)
-#define CH1_AMP_400_MV                         (0x0 << 8)
-#define CH0_AMP_400_MV                         (0x0 << 0)
-
-/* EXYNOS_DP_AUX_HW_RETRY_CTL */
-#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)       (((x) & 0x7) << 8)
-#define AUX_HW_RETRY_INTERVAL_MASK             (0x3 << 3)
-#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
-#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
-#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS        (0x2 << 3)
-#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS        (0x3 << 3)
-#define AUX_HW_RETRY_COUNT_SEL(x)              (((x) & 0x7) << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_1 */
-#define VSYNC_DET                              (0x1 << 7)
-#define PLL_LOCK_CHG                           (0x1 << 6)
-#define SPDIF_ERR                              (0x1 << 5)
-#define SPDIF_UNSTBL                           (0x1 << 4)
-#define VID_FORMAT_CHG                         (0x1 << 3)
-#define AUD_CLK_CHG                            (0x1 << 2)
-#define VID_CLK_CHG                            (0x1 << 1)
-#define SW_INT                                 (0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_2 */
-#define ENC_EN_CHG                             (0x1 << 6)
-#define HW_BKSV_RDY                            (0x1 << 3)
-#define HW_SHA_DONE                            (0x1 << 2)
-#define HW_AUTH_STATE_CHG                      (0x1 << 1)
-#define HW_AUTH_DONE                           (0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_3 */
-#define AFIFO_UNDER                            (0x1 << 7)
-#define AFIFO_OVER                             (0x1 << 6)
-#define R0_CHK_FLAG                            (0x1 << 5)
-
-/* EXYNOS_DP_COMMON_INT_STA_4 */
-#define PSR_ACTIVE                             (0x1 << 7)
-#define PSR_INACTIVE                           (0x1 << 6)
-#define SPDIF_BI_PHASE_ERR                     (0x1 << 5)
-#define HOTPLUG_CHG                            (0x1 << 2)
-#define HPD_LOST                               (0x1 << 1)
-#define PLUG                                   (0x1 << 0)
-
-/* EXYNOS_DP_INT_STA */
-#define INT_HPD                                        (0x1 << 6)
-#define HW_TRAINING_FINISH                     (0x1 << 5)
-#define RPLY_RECEIV                            (0x1 << 1)
-#define AUX_ERR                                        (0x1 << 0)
-
-/* EXYNOS_DP_INT_CTL */
-#define SOFT_INT_CTRL                          (0x1 << 2)
-#define INT_POL1                               (0x1 << 1)
-#define INT_POL0                               (0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_1 */
-#define DET_STA                                        (0x1 << 2)
-#define FORCE_DET                              (0x1 << 1)
-#define DET_CTRL                               (0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_2 */
-#define CHA_CRI(x)                             (((x) & 0xf) << 4)
-#define CHA_STA                                        (0x1 << 2)
-#define FORCE_CHA                              (0x1 << 1)
-#define CHA_CTRL                               (0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_3 */
-#define HPD_STATUS                             (0x1 << 6)
-#define F_HPD                                  (0x1 << 5)
-#define HPD_CTRL                               (0x1 << 4)
-#define HDCP_RDY                               (0x1 << 3)
-#define STRM_VALID                             (0x1 << 2)
-#define F_VALID                                        (0x1 << 1)
-#define VALID_CTRL                             (0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_4 */
-#define FIX_M_AUD                              (0x1 << 4)
-#define ENHANCED                               (0x1 << 3)
-#define FIX_M_VID                              (0x1 << 2)
-#define M_VID_UPDATE_CTRL                      (0x3 << 0)
-
-/* EXYNOS_DP_TRAINING_PTN_SET */
-#define SCRAMBLER_TYPE                         (0x1 << 9)
-#define HW_LINK_TRAINING_PATTERN               (0x1 << 8)
-#define SCRAMBLING_DISABLE                     (0x1 << 5)
-#define SCRAMBLING_ENABLE                      (0x0 << 5)
-#define LINK_QUAL_PATTERN_SET_MASK             (0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_PRBS7            (0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_D10_2            (0x1 << 2)
-#define LINK_QUAL_PATTERN_SET_DISABLE          (0x0 << 2)
-#define SW_TRAINING_PATTERN_SET_MASK           (0x3 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN2           (0x2 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN1           (0x1 << 0)
-#define SW_TRAINING_PATTERN_SET_NORMAL         (0x0 << 0)
-
-/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
-#define PRE_EMPHASIS_SET_MASK                  (0x3 << 3)
-#define PRE_EMPHASIS_SET_SHIFT                 (3)
-
-/* EXYNOS_DP_DEBUG_CTL */
-#define PLL_LOCK                               (0x1 << 4)
-#define F_PLL_LOCK                             (0x1 << 3)
-#define PLL_LOCK_CTRL                          (0x1 << 2)
-#define PN_INV                                 (0x1 << 0)
-
-/* EXYNOS_DP_PLL_CTL */
-#define DP_PLL_PD                              (0x1 << 7)
-#define DP_PLL_RESET                           (0x1 << 6)
-#define DP_PLL_LOOP_BIT_DEFAULT                        (0x1 << 4)
-#define DP_PLL_REF_BIT_1_1250V                 (0x5 << 0)
-#define DP_PLL_REF_BIT_1_2500V                 (0x7 << 0)
-
-/* EXYNOS_DP_PHY_PD */
-#define DP_PHY_PD                              (0x1 << 5)
-#define AUX_PD                                 (0x1 << 4)
-#define CH3_PD                                 (0x1 << 3)
-#define CH2_PD                                 (0x1 << 2)
-#define CH1_PD                                 (0x1 << 1)
-#define CH0_PD                                 (0x1 << 0)
-
-/* EXYNOS_DP_PHY_TEST */
-#define MACRO_RST                              (0x1 << 5)
-#define CH1_TEST                               (0x1 << 1)
-#define CH0_TEST                               (0x1 << 0)
-
-/* EXYNOS_DP_AUX_CH_STA */
-#define AUX_BUSY                               (0x1 << 4)
-#define AUX_STATUS_MASK                                (0xf << 0)
-
-/* EXYNOS_DP_AUX_CH_DEFER_CTL */
-#define DEFER_CTRL_EN                          (0x1 << 7)
-#define DEFER_COUNT(x)                         (((x) & 0x7f) << 0)
-
-/* EXYNOS_DP_AUX_RX_COMM */
-#define AUX_RX_COMM_I2C_DEFER                  (0x2 << 2)
-#define AUX_RX_COMM_AUX_DEFER                  (0x2 << 0)
-
-/* EXYNOS_DP_BUFFER_DATA_CTL */
-#define BUF_CLR                                        (0x1 << 7)
-#define BUF_DATA_COUNT(x)                      (((x) & 0x1f) << 0)
-
-/* EXYNOS_DP_AUX_CH_CTL_1 */
-#define AUX_LENGTH(x)                          (((x - 1) & 0xf) << 4)
-#define AUX_TX_COMM_MASK                       (0xf << 0)
-#define AUX_TX_COMM_DP_TRANSACTION             (0x1 << 3)
-#define AUX_TX_COMM_I2C_TRANSACTION            (0x0 << 3)
-#define AUX_TX_COMM_MOT                                (0x1 << 2)
-#define AUX_TX_COMM_WRITE                      (0x0 << 0)
-#define AUX_TX_COMM_READ                       (0x1 << 0)
-
-/* EXYNOS_DP_AUX_ADDR_7_0 */
-#define AUX_ADDR_7_0(x)                                (((x) >> 0) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_15_8 */
-#define AUX_ADDR_15_8(x)                       (((x) >> 8) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_19_16 */
-#define AUX_ADDR_19_16(x)                      (((x) >> 16) & 0x0f)
-
-/* EXYNOS_DP_AUX_CH_CTL_2 */
-#define ADDR_ONLY                              (0x1 << 1)
-#define AUX_EN                                 (0x1 << 0)
-
-/* EXYNOS_DP_SOC_GENERAL_CTL */
-#define AUDIO_MODE_SPDIF_MODE                  (0x1 << 8)
-#define AUDIO_MODE_MASTER_MODE                 (0x0 << 8)
-#define MASTER_VIDEO_INTERLACE_EN              (0x1 << 4)
-#define VIDEO_MASTER_CLK_SEL                   (0x1 << 2)
-#define VIDEO_MASTER_MODE_EN                   (0x1 << 1)
-#define VIDEO_MODE_MASK                                (0x1 << 0)
-#define VIDEO_MODE_SLAVE_MODE                  (0x1 << 0)
-#define VIDEO_MODE_MASTER_MODE                 (0x0 << 0)
-
-#endif /* _EXYNOS_DP_REG_H */
diff --git a/include/drm/bridge/ptn3460.h b/include/drm/bridge/ptn3460.h
new file mode 100644 (file)
index 0000000..ff62344
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DRM_BRIDGE_PTN3460_H_
+#define _DRM_BRIDGE_PTN3460_H_
+
+struct drm_device;
+struct drm_encoder;
+struct i2c_client;
+struct device_node;
+
+#if defined(CONFIG_DRM_PTN3460) || defined(CONFIG_DRM_PTN3460_MODULE)
+
+int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
+               struct i2c_client *client, struct device_node *node);
+#else
+
+static inline int ptn3460_init(struct drm_device *dev,
+               struct drm_encoder *encoder, struct i2c_client *client,
+               struct device_node *node)
+{
+       return 0;
+}
+
+#endif
+
+#endif
index daac00a93126c87d5787bfe59f7b61f6a95639cc..a7c2a862b4f48ab286f20b3860ea8eeb442bd1a9 100644 (file)
@@ -88,46 +88,41 @@ struct videomode;
 #include <drm/drm_hashtab.h>
 #include <drm/drm_mm.h>
 
-#define DRM_UT_CORE            0x01
-#define DRM_UT_DRIVER          0x02
-#define DRM_UT_KMS             0x04
-#define DRM_UT_PRIME           0x08
 /*
- * Three debug levels are defined.
- * drm_core, drm_driver, drm_kms
- * drm_core level can be used in the generic drm code. For example:
- *     drm_ioctl, drm_mm, drm_memory
- * The macro definition of DRM_DEBUG is used.
- *     DRM_DEBUG(fmt, args...)
- *     The debug info by using the DRM_DEBUG can be obtained by adding
- *     the boot option of "drm.debug=1".
+ * 4 debug categories are defined:
+ *
+ * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
+ *      This is the category used by the DRM_DEBUG() macro.
+ *
+ * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
+ *        This is the category used by the DRM_DEBUG_DRIVER() macro.
  *
- * drm_driver level can be used in the specific drm driver. It is used
- * to add the debug info related with the drm driver. For example:
- * i915_drv, i915_dma, i915_gem, radeon_drv,
- *     The macro definition of DRM_DEBUG_DRIVER can be used.
- *     DRM_DEBUG_DRIVER(fmt, args...)
- *     The debug info by using the DRM_DEBUG_DRIVER can be obtained by
- *     adding the boot option of "drm.debug=0x02"
+ * KMS: used in the modesetting code.
+ *     This is the category used by the DRM_DEBUG_KMS() macro.
  *
- * drm_kms level can be used in the KMS code related with specific drm driver.
- * It is used to add the debug info related with KMS mode. For example:
- * the connector/crtc ,
- *     The macro definition of DRM_DEBUG_KMS can be used.
- *     DRM_DEBUG_KMS(fmt, args...)
- *     The debug info by using the DRM_DEBUG_KMS can be obtained by
- *     adding the boot option of "drm.debug=0x04"
+ * PRIME: used in the prime code.
+ *       This is the category used by the DRM_DEBUG_PRIME() macro.
  *
- * If we add the boot option of "drm.debug=0x06", we can get the debug info by
- * using the DRM_DEBUG_KMS and DRM_DEBUG_DRIVER.
- * If we add the boot option of "drm.debug=0x05", we can get the debug info by
- * using the DRM_DEBUG_KMS and DRM_DEBUG.
+ * Enabling verbose debug messages is done through the drm.debug parameter,
+ * each category being enabled by a bit.
+ *
+ * drm.debug=0x1 will enable CORE messages
+ * drm.debug=0x2 will enable DRIVER messages
+ * drm.debug=0x3 will enable CORE and DRIVER messages
+ * ...
+ * drm.debug=0xf will enable all messages
+ *
+ * An interesting feature is that it's possible to enable verbose logging at
+ * run-time by echoing the debug value in its sysfs node:
+ *   # echo 0xf > /sys/module/drm/parameters/debug
  */
+#define DRM_UT_CORE            0x01
+#define DRM_UT_DRIVER          0x02
+#define DRM_UT_KMS             0x04
+#define DRM_UT_PRIME           0x08
 
-extern __printf(4, 5)
-void drm_ut_debug_printk(unsigned int request_level,
-                        const char *prefix,
-                        const char *function_name,
+extern __printf(2, 3)
+void drm_ut_debug_printk(const char *function_name,
                         const char *format, ...);
 extern __printf(2, 3)
 int drm_err(const char *func, const char *format, ...);
@@ -212,55 +207,30 @@ int drm_err(const char *func, const char *format, ...);
 #if DRM_DEBUG_CODE
 #define DRM_DEBUG(fmt, args...)                                                \
        do {                                                            \
-               drm_ut_debug_printk(DRM_UT_CORE, DRM_NAME,              \
-                                       __func__, fmt, ##args);         \
+               if (unlikely(drm_debug & DRM_UT_CORE))                  \
+                       drm_ut_debug_printk(__func__, fmt, ##args);     \
        } while (0)
 
 #define DRM_DEBUG_DRIVER(fmt, args...)                                 \
        do {                                                            \
-               drm_ut_debug_printk(DRM_UT_DRIVER, DRM_NAME,            \
-                                       __func__, fmt, ##args);         \
+               if (unlikely(drm_debug & DRM_UT_DRIVER))                \
+                       drm_ut_debug_printk(__func__, fmt, ##args);     \
        } while (0)
-#define DRM_DEBUG_KMS(fmt, args...)                            \
+#define DRM_DEBUG_KMS(fmt, args...)                                    \
        do {                                                            \
-               drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME,               \
-                                        __func__, fmt, ##args);        \
+               if (unlikely(drm_debug & DRM_UT_KMS))                   \
+                       drm_ut_debug_printk(__func__, fmt, ##args);     \
        } while (0)
 #define DRM_DEBUG_PRIME(fmt, args...)                                  \
        do {                                                            \
-               drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME,             \
-                                       __func__, fmt, ##args);         \
-       } while (0)
-#define DRM_LOG(fmt, args...)                                          \
-       do {                                                            \
-               drm_ut_debug_printk(DRM_UT_CORE, NULL,                  \
-                                       NULL, fmt, ##args);             \
-       } while (0)
-#define DRM_LOG_KMS(fmt, args...)                                      \
-       do {                                                            \
-               drm_ut_debug_printk(DRM_UT_KMS, NULL,                   \
-                                       NULL, fmt, ##args);             \
-       } while (0)
-#define DRM_LOG_MODE(fmt, args...)                                     \
-       do {                                                            \
-               drm_ut_debug_printk(DRM_UT_MODE, NULL,                  \
-                                       NULL, fmt, ##args);             \
-       } while (0)
-#define DRM_LOG_DRIVER(fmt, args...)                                   \
-       do {                                                            \
-               drm_ut_debug_printk(DRM_UT_DRIVER, NULL,                \
-                                       NULL, fmt, ##args);             \
+               if (unlikely(drm_debug & DRM_UT_PRIME))                 \
+                       drm_ut_debug_printk(__func__, fmt, ##args);     \
        } while (0)
 #else
 #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0)
 #define DRM_DEBUG_KMS(fmt, args...)    do { } while (0)
 #define DRM_DEBUG_PRIME(fmt, args...)  do { } while (0)
 #define DRM_DEBUG(fmt, arg...)          do { } while (0)
-#define DRM_LOG(fmt, arg...)           do { } while (0)
-#define DRM_LOG_KMS(fmt, args...) do { } while (0)
-#define DRM_LOG_MODE(fmt, arg...) do { } while (0)
-#define DRM_LOG_DRIVER(fmt, arg...) do { } while (0)
-
 #endif
 
 /*@}*/
@@ -435,9 +405,15 @@ struct drm_prime_file_private {
 struct drm_file {
        unsigned always_authenticated :1;
        unsigned authenticated :1;
-       unsigned is_master :1; /* this file private is a master for a minor */
+       /* Whether we're master for a minor. Protected by master_mutex */
+       unsigned is_master :1;
        /* true when the client has asked us to expose stereo 3D mode flags */
        unsigned stereo_allowed :1;
+       /*
+        * true if client understands CRTC primary planes and cursor planes
+        * in the plane list
+        */
+       unsigned universal_planes:1;
 
        struct pid *pid;
        kuid_t uid;
@@ -714,29 +690,29 @@ struct drm_gem_object {
 
 #include <drm/drm_crtc.h>
 
-/* per-master structure */
+/**
+ * struct drm_master - drm master structure
+ *
+ * @refcount: Refcount for this master object.
+ * @minor: Link back to minor char device we are master for. Immutable.
+ * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex.
+ * @unique_len: Length of unique field. Protected by drm_global_mutex.
+ * @unique_size: Amount allocated. Protected by drm_global_mutex.
+ * @magiclist: Hash of used authentication tokens. Protected by struct_mutex.
+ * @magicfree: List of used authentication tokens. Protected by struct_mutex.
+ * @lock: DRI lock information.
+ * @driver_priv: Pointer to driver-private information.
+ */
 struct drm_master {
-
-       struct kref refcount; /* refcount for this master */
-
-       struct list_head head; /**< each minor contains a list of masters */
-       struct drm_minor *minor; /**< link back to minor we are a master for */
-
-       char *unique;                   /**< Unique identifier: e.g., busid */
-       int unique_len;                 /**< Length of unique field */
-       int unique_size;                /**< amount allocated */
-
-       int blocked;                    /**< Blocked due to VC switch? */
-
-       /** \name Authentication */
-       /*@{ */
+       struct kref refcount;
+       struct drm_minor *minor;
+       char *unique;
+       int unique_len;
+       int unique_size;
        struct drm_open_hash magiclist;
        struct list_head magicfree;
-       /*@} */
-
-       struct drm_lock_data lock;      /**< Information on hardware lock */
-
-       void *driver_priv; /**< Private structure for driver to use */
+       struct drm_lock_data lock;
+       void *driver_priv;
 };
 
 /* Size of ringbuffer for vblank timestamps. Just double-buffer
@@ -1051,8 +1027,8 @@ struct drm_minor {
        struct list_head debugfs_list;
        struct mutex debugfs_lock; /* Protects debugfs_list. */
 
-       struct drm_master *master; /* currently active master for this node */
-       struct list_head master_list;
+       /* currently active master for this node. Protected by master_mutex */
+       struct drm_master *master;
        struct drm_mode_group mode_group;
 };
 
@@ -1102,6 +1078,7 @@ struct drm_device {
        /*@{ */
        spinlock_t count_lock;          /**< For inuse, drm_device::open_count, drm_device::buf_use */
        struct mutex struct_mutex;      /**< For others */
+       struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */
        /*@} */
 
        /** \name Usage Counters */
@@ -1232,11 +1209,21 @@ static inline bool drm_modeset_is_locked(struct drm_device *dev)
        return mutex_is_locked(&dev->mode_config.mutex);
 }
 
-static inline bool drm_is_render_client(struct drm_file *file_priv)
+static inline bool drm_is_render_client(const struct drm_file *file_priv)
 {
        return file_priv->minor->type == DRM_MINOR_RENDER;
 }
 
+static inline bool drm_is_control_client(const struct drm_file *file_priv)
+{
+       return file_priv->minor->type == DRM_MINOR_CONTROL;
+}
+
+static inline bool drm_is_primary_client(const struct drm_file *file_priv)
+{
+       return file_priv->minor->type == DRM_MINOR_LEGACY;
+}
+
 /******************************************************************/
 /** \name Internal function definitions */
 /*@{*/
@@ -1247,6 +1234,7 @@ extern long drm_ioctl(struct file *filp,
 extern long drm_compat_ioctl(struct file *filp,
                             unsigned int cmd, unsigned long arg);
 extern int drm_lastclose(struct drm_device *dev);
+extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
 
                                /* Device support (drm_fops.h) */
 extern struct mutex drm_global_mutex;
@@ -1426,6 +1414,7 @@ extern void drm_put_dev(struct drm_device *dev);
 extern void drm_unplug_dev(struct drm_device *dev);
 extern unsigned int drm_debug;
 extern unsigned int drm_rnodes;
+extern unsigned int drm_universal_planes;
 
 extern unsigned int drm_vblank_offdelay;
 extern unsigned int drm_timestamp_precision;
index 27f828c9d7f282b92328be2e0b5146750e0cfb3f..e55fccbe7c42373940ff8fee459d076cd5e6d4bf 100644 (file)
@@ -270,6 +270,8 @@ struct drm_crtc_funcs {
  * @dev: parent DRM device
  * @head: list management
  * @base: base KMS object for ID tracking etc.
+ * @primary: primary plane for this CRTC
+ * @cursor: cursor plane for this CRTC
  * @enabled: is this CRTC enabled?
  * @mode: current mode timings
  * @hwmode: mode timings as programmed to hw regs
@@ -305,8 +307,9 @@ struct drm_crtc {
 
        struct drm_mode_object base;
 
-       /* framebuffer the connector is currently bound to */
-       struct drm_framebuffer *fb;
+       /* primary and cursor planes for CRTC */
+       struct drm_plane *primary;
+       struct drm_plane *cursor;
 
        /* Temporary tracking of the old fb while a modeset is ongoing. Used
         * by drm_mode_set_config_internal to implement correct refcounting. */
@@ -541,6 +544,12 @@ struct drm_plane_funcs {
                            struct drm_property *property, uint64_t val);
 };
 
+enum drm_plane_type {
+       DRM_PLANE_TYPE_OVERLAY,
+       DRM_PLANE_TYPE_PRIMARY,
+       DRM_PLANE_TYPE_CURSOR,
+};
+
 /**
  * drm_plane - central DRM plane control structure
  * @dev: DRM device this plane belongs to
@@ -553,6 +562,7 @@ struct drm_plane_funcs {
  * @fb: currently bound fb
  * @funcs: helper functions
  * @properties: property tracking for this plane
+ * @type: type of plane (overlay, primary, cursor)
  */
 struct drm_plane {
        struct drm_device *dev;
@@ -570,6 +580,8 @@ struct drm_plane {
        const struct drm_plane_funcs *funcs;
 
        struct drm_object_properties properties;
+
+       enum drm_plane_type type;
 };
 
 /**
@@ -732,7 +744,15 @@ struct drm_mode_config {
        struct list_head bridge_list;
        int num_encoder;
        struct list_head encoder_list;
-       int num_plane;
+
+       /*
+        * Track # of overlay planes separately from # of total planes.  By
+        * default we only advertise overlay planes to userspace; if userspace
+        * sets the "universal plane" capability bit, we'll go ahead and
+        * expose all planes.
+        */
+       int num_overlay_plane;
+       int num_total_plane;
        struct list_head plane_list;
 
        int num_crtc;
@@ -754,6 +774,7 @@ struct drm_mode_config {
        struct list_head property_blob_list;
        struct drm_property *edid_property;
        struct drm_property *dpms_property;
+       struct drm_property *plane_type_property;
 
        /* DVI-I properties */
        struct drm_property *dvi_i_subconnector_property;
@@ -806,6 +827,11 @@ extern void drm_modeset_lock_all(struct drm_device *dev);
 extern void drm_modeset_unlock_all(struct drm_device *dev);
 extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
 
+extern int drm_crtc_init_with_planes(struct drm_device *dev,
+                                    struct drm_crtc *crtc,
+                                    struct drm_plane *primary,
+                                    void *cursor,
+                                    const struct drm_crtc_funcs *funcs);
 extern int drm_crtc_init(struct drm_device *dev,
                         struct drm_crtc *crtc,
                         const struct drm_crtc_funcs *funcs);
@@ -857,14 +883,25 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
        return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
 }
 
+extern int drm_universal_plane_init(struct drm_device *dev,
+                                   struct drm_plane *plane,
+                                   unsigned long possible_crtcs,
+                                   const struct drm_plane_funcs *funcs,
+                                   const uint32_t *formats,
+                                   uint32_t format_count,
+                                   enum drm_plane_type type);
 extern int drm_plane_init(struct drm_device *dev,
                          struct drm_plane *plane,
                          unsigned long possible_crtcs,
                          const struct drm_plane_funcs *funcs,
                          const uint32_t *formats, uint32_t format_count,
-                         bool priv);
+                         bool is_primary);
 extern void drm_plane_cleanup(struct drm_plane *plane);
 extern void drm_plane_force_disable(struct drm_plane *plane);
+extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
+                                  int x, int y,
+                                  const struct drm_display_mode *mode,
+                                  const struct drm_framebuffer *fb);
 
 extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
@@ -1036,4 +1073,9 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
        return mo ? obj_to_encoder(mo) : NULL;
 }
 
+/* Plane list iterator for legacy (overlay only) planes. */
+#define drm_for_each_legacy_plane(plane, planelist) \
+       list_for_each_entry(plane, planelist, head) \
+               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
new file mode 100644 (file)
index 0000000..09824be
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011-2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef DRM_PLANE_HELPER_H
+#define DRM_PLANE_HELPER_H
+
+/**
+ * DOC: plane helpers
+ *
+ * Helper functions to assist with creation and handling of CRTC primary
+ * planes.
+ */
+
+extern int drm_primary_helper_update(struct drm_plane *plane,
+                                    struct drm_crtc *crtc,
+                                    struct drm_framebuffer *fb,
+                                    int crtc_x, int crtc_y,
+                                    unsigned int crtc_w, unsigned int crtc_h,
+                                    uint32_t src_x, uint32_t src_y,
+                                    uint32_t src_w, uint32_t src_h);
+extern int drm_primary_helper_disable(struct drm_plane *plane);
+extern void drm_primary_helper_destroy(struct drm_plane *plane);
+extern const struct drm_plane_funcs drm_primary_helper_funcs;
+extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
+                                                        uint32_t *formats,
+                                                        int num_formats);
+
+
+#endif
index 884613ee00ad88bd6d60a2393d4021c70ac97551..87ac5e6ca5519bfc1e48081efd050532d51c61dd 100644 (file)
  *
  **************************************************************************/
 
-#ifndef _PSB_DRM_H_
-#define _PSB_DRM_H_
-
-/*
- *     Manage the LUT for an output
- */
-struct drm_psb_dpst_lut_arg {
-       uint8_t lut[256];
-       int output_id;
-};
-
-/*
- *     Validate modes
- */
-struct drm_psb_mode_operation_arg {
-       u32 obj_id;
-       u16 operation;
-       struct drm_mode_modeinfo mode;
-       u64 data;
-};
-
-/*
- *     Query the stolen memory for smarter management of
- *     memory by the server
- */
-struct drm_psb_stolen_memory_arg {
-       u32 base;
-       u32 size;
-};
-
-struct drm_psb_get_pipe_from_crtc_id_arg {
-       /** ID of CRTC being requested **/
-       u32 crtc_id;
-       /** pipe of requested CRTC **/
-       u32 pipe;
-};
-
-struct drm_psb_gem_create {
-       __u64 size;
-       __u32 handle;
-       __u32 flags;
-#define GMA_GEM_CREATE_STOLEN          1       /* Stolen memory can be used */
-};
-
-struct drm_psb_gem_mmap {
-       __u32 handle;
-       __u32 pad;
-       /**
-        * Fake offset to use for subsequent mmap call
-        *
-        * This is a fixed-size type for 32/64 compatibility.
-        */
-       __u64 offset;
-};
-
-/* Controlling the kernel modesetting buffers */
-
-#define DRM_GMA_GEM_CREATE     0x00            /* Create a GEM object */
-#define DRM_GMA_GEM_MMAP       0x01            /* Map GEM memory */
-#define DRM_GMA_STOLEN_MEMORY  0x02            /* Report stolen memory */
-#define DRM_GMA_2D_OP          0x03            /* Will be merged later */
-#define DRM_GMA_GAMMA          0x04            /* Set gamma table */
-#define DRM_GMA_ADB            0x05            /* Get backlight */
-#define DRM_GMA_DPST_BL                0x06            /* Set backlight */
-#define DRM_GMA_MODE_OPERATION 0x07            /* Mode validation/DC set */
-#define        PSB_MODE_OPERATION_MODE_VALID   0x01
-#define DRM_GMA_GET_PIPE_FROM_CRTC_ID  0x08    /* CRTC to physical pipe# */
-
+#ifndef _GMA_DRM_H_
+#define _GMA_DRM_H_
 
 #endif
index 0097cc03034e18b10e5ad9cdc34b9019eb821314..ed953f98f0e1446ce01630c005e406f941282347 100644 (file)
@@ -244,6 +244,10 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
 extern int ttm_ref_object_add(struct ttm_object_file *tfile,
                              struct ttm_base_object *base,
                              enum ttm_ref_type ref_type, bool *existed);
+
+extern bool ttm_ref_object_exists(struct ttm_object_file *tfile,
+                                 struct ttm_base_object *base);
+
 /**
  * ttm_ref_object_base_unref
  *
index b06c8ed687079759ea7e585589aac199ac288e22..9abbeb924cbb74a7e0bfba97d178831e92590d4f 100644 (file)
@@ -619,6 +619,15 @@ struct drm_gem_open {
 #define  DRM_PRIME_CAP_EXPORT          0x2
 #define DRM_CAP_TIMESTAMP_MONOTONIC    0x6
 #define DRM_CAP_ASYNC_PAGE_FLIP                0x7
+/*
+ * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight
+ * combination for the hardware cursor. The intention is that a hardware
+ * agnostic userspace can query a cursor plane size to use.
+ *
+ * Note that the cross-driver contract is to merely return a valid size;
+ * drivers are free to attach another meaning on top, eg. i915 returns the
+ * maximum plane size.
+ */
 #define DRM_CAP_CURSOR_WIDTH           0x8
 #define DRM_CAP_CURSOR_HEIGHT          0x9
 
@@ -637,6 +646,14 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_STEREO_3D       1
 
+/**
+ * DRM_CLIENT_CAP_UNIVERSAL_PLANES
+ *
+ * If set to 1, the DRM core will expose all planes (overlay, primary, and
+ * cursor) to userspace.
+ */
+#define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
        __u64 capability;
index 87792a5fee3bad7d143de81555a56ede7e532f1a..4fc66f6b12ced39a20d5c03fd820d1b513cd507d 100644 (file)
 #define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
 #define DRM_VMW_PARAM_MAX_MOB_SIZE     10
 
+/**
+ * enum drm_vmw_handle_type - handle type for ref ioctls
+ *
+ */
+enum drm_vmw_handle_type {
+       DRM_VMW_HANDLE_LEGACY = 0,
+       DRM_VMW_HANDLE_PRIME = 1
+};
+
 /**
  * struct drm_vmw_getparam_arg
  *
@@ -177,6 +186,7 @@ struct drm_vmw_surface_create_req {
  * struct drm_wmv_surface_arg
  *
  * @sid: Surface id of created surface or surface to destroy or reference.
+ * @handle_type: Handle type for DRM_VMW_REF_SURFACE Ioctl.
  *
  * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
  * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
@@ -185,7 +195,7 @@ struct drm_vmw_surface_create_req {
 
 struct drm_vmw_surface_arg {
        int32_t sid;
-       uint32_t pad64;
+       enum drm_vmw_handle_type handle_type;
 };
 
 /**
This page took 0.795687 seconds and 5 git commands to generate.