Merge Linus master into drm-next
authorDave Airlie <airlied@redhat.com>
Mon, 20 Apr 2015 01:32:26 +0000 (11:32 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 20 Apr 2015 03:05:20 +0000 (13:05 +1000)
The merge is clean, but the arm build fails afterwards,
due to API changes in the regulator tree.

I've included the patch into the merge to fix the build.

Signed-off-by: Dave Airlie <airlied@redhat.com>
1  2 
Documentation/DocBook/drm.tmpl
Documentation/devicetree/bindings/vendor-prefixes.txt
MAINTAINERS
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/msm/dsi/dsi_host.c

index f4976cd7b32bac2c3b91983caa2872495812e8cf,0cad3ce957ffe160277186b91a69c32b70cdf88f..9765a4c0829df4307efaf773d8b887b35270ad31
@@@ -1293,7 -1293,7 +1293,7 @@@ int max_width, max_height;</synopsis
            </para>
            <para>
              If a page flip can be successfully scheduled the driver must set the
-             <code>drm_crtc-&lt;fb</code> field to the new framebuffer pointed to
+             <code>drm_crtc-&gt;fb</code> field to the new framebuffer pointed to
              by <code>fb</code>. This is important so that the reference counting
              on framebuffers stays balanced.
            </para>
@@@ -3979,11 -3979,6 +3979,11 @@@ int num_ioctls;</synopsis
  !Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_disable_interrupts
  !Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_enable_interrupts
        </sect2>
 +      <sect2>
 +        <title>Intel GVT-g Guest Support(vGPU)</title>
 +!Pdrivers/gpu/drm/i915/i915_vgpu.c Intel GVT-g guest support
 +!Idrivers/gpu/drm/i915/i915_vgpu.c
 +      </sect2>
      </sect1>
      <sect1>
        <title>Display Hardware Handling</title>
        <title>Frame Buffer Compression (FBC)</title>
  !Pdrivers/gpu/drm/i915/intel_fbc.c Frame Buffer Compression (FBC)
  !Idrivers/gpu/drm/i915/intel_fbc.c
 +      </sect2>
 +      <sect2>
 +        <title>Display Refresh Rate Switching (DRRS)</title>
 +!Pdrivers/gpu/drm/i915/intel_dp.c Display Refresh Rate Switching (DRRS)
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_set_drrs_state
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_enable
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_disable
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_invalidate
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_flush
 +!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_drrs_init
 +
        </sect2>
        <sect2>
          <title>DPIO</title>
        <sect2>
          <title>Buffer Object Eviction</title>
        <para>
 -        This section documents the interface function for evicting buffer
 +        This section documents the interface functions for evicting buffer
          objects to make space available in the virtual gpu address spaces.
          Note that this is mostly orthogonal to shrinking buffer objects
          caches, which has the goal to make main memory (shared with the gpu
        </para>
  !Idrivers/gpu/drm/i915/i915_gem_evict.c
        </sect2>
 +      <sect2>
 +        <title>Buffer Object Memory Shrinking</title>
 +      <para>
 +        This section documents the interface function for shrinking memory
 +        usage of buffer object caches. Shrinking is used to make main memory
 +        available.  Note that this is mostly orthogonal to evicting buffer
 +        objects, which has the goal to make space in gpu virtual address
 +        spaces.
 +      </para>
 +!Idrivers/gpu/drm/i915/i915_gem_shrinker.c
 +      </sect2>
      </sect1>
  
      <sect1>
index 772b24f8638814a7398abdcb374eb11a04c4a237,b13aa55b7a6f71fdc6d325426ca3ed5bfece7ad2..4f8edb205e130a6b53375b23df03a07f45bd2363
@@@ -17,7 -17,6 +17,7 @@@ altr  Altera Corp
  amcc  Applied Micro Circuits Corporation (APM, formally AMCC)
  amd   Advanced Micro Devices (AMD), Inc.
  amlogic       Amlogic, Inc.
 +ampire        Ampire Co., Ltd.
  ams   AMS AG
  amstaos       AMS-Taos Inc.
  apm   Applied Micro Circuits Corporation (APM)
@@@ -38,6 -37,7 +38,7 @@@ capella       Capella Microsystems, In
  cavium        Cavium, Inc.
  cdns  Cadence Design Systems Inc.
  chipidea      Chipidea, Inc
+ chipone               ChipOne
  chipspark     ChipSPARK
  chrp  Common Hardware Reference Platform
  chunghwa      Chunghwa Picture Tubes Ltd.
@@@ -79,6 -79,7 +80,7 @@@ geniatech     Geniatech, Inc
  giantplus     Giantplus Technology Co., Ltd.
  globalscale   Globalscale Technologies, Inc.
  gmt   Global Mixed-mode Technology, Inc.
+ goodix        Shenzhen Huiding Technology Co., Ltd.
  google        Google, Inc.
  gumstix       Gumstix, Inc.
  gw    Gateworks Corporation
@@@ -126,6 -127,7 +128,7 @@@ mxicy      Macronix International Co., Ltd
  national      National Semiconductor
  neonode               Neonode Inc.
  netgear       NETGEAR
+ netlogic      Broadcom Corporation (formerly NetLogic Microsystems)
  newhaven      Newhaven Display International
  nintendo      Nintendo
  nokia Nokia
@@@ -133,7 -135,6 +136,7 @@@ nvidia     NVIDI
  nxp   NXP Semiconductors
  onnn  ON Semiconductor Corp.
  opencores     OpenCores.org
 +ortustech     Ortus Technology Co., Ltd.
  ovti  OmniVision Technologies
  panasonic     Panasonic Corporation
  parade        Parade Technologies Inc.
@@@ -169,6 -170,7 +172,7 @@@ sii        Seiko Instruments, Inc
  silergy       Silergy Corp.
  sirf  SiRF Technology, Inc.
  sitronix      Sitronix Technology Corporation
+ skyworks      Skyworks Solutions, Inc.
  smsc  Standard Microsystems Corporation
  snps  Synopsys, Inc.
  solidrun      SolidRun
@@@ -196,6 -198,7 +200,7 @@@ voipac     Voipac Technologies s.r.o
  winbond Winbond Electronics corp.
  wlf   Wolfson Microelectronics
  wm    Wondermedia Technologies, Inc.
+ x-powers      X-Powers
  xes   Extreme Engineering Solutions (X-ES)
  xillybus      Xillybus Ltd.
  xlnx  Xilinx
diff --combined MAINTAINERS
index 652004223eadc99a0249dcc6eb8742d09342db40,db335f98cad02316e89c29b72ec89aa0860a8947..ce3eb0faffe62f9c9ba86663e0ae2b952144d6c4
@@@ -569,6 -569,12 +569,12 @@@ L:       nios2-dev@lists.rocketboards.org (mo
  S:    Maintained
  F:    drivers/mailbox/mailbox-altera.c
  
+ ALTERA PIO DRIVER
+ M:    Tien Hock Loh <thloh@altera.com>
+ L:    linux-gpio@vger.kernel.org
+ S:    Maintained
+ F:    drivers/gpio/gpio-altera.c
  ALTERA TRIPLE SPEED ETHERNET DRIVER
  M:    Vince Bridgers <vbridger@opensource.altera.com>
  L:    netdev@vger.kernel.org
@@@ -625,16 -631,16 +631,16 @@@ F:      drivers/iommu/amd_iommu*.[ch
  F:    include/linux/amd-iommu.h
  
  AMD KFD
- M:      Oded Gabbay <oded.gabbay@amd.com>
- L:      dri-devel@lists.freedesktop.org
- T:      git git://people.freedesktop.org/~gabbayo/linux.git
- S:      Supported
- F:      drivers/gpu/drm/amd/amdkfd/
+ M:    Oded Gabbay <oded.gabbay@amd.com>
+ L:    dri-devel@lists.freedesktop.org
+ T:    git git://people.freedesktop.org/~gabbayo/linux.git
+ S:    Supported
+ F:    drivers/gpu/drm/amd/amdkfd/
  F:    drivers/gpu/drm/amd/include/cik_structs.h
  F:    drivers/gpu/drm/amd/include/kgd_kfd_interface.h
- F:      drivers/gpu/drm/radeon/radeon_kfd.c
- F:      drivers/gpu/drm/radeon/radeon_kfd.h
- F:      include/uapi/linux/kfd_ioctl.h
+ F:    drivers/gpu/drm/radeon/radeon_kfd.c
+ F:    drivers/gpu/drm/radeon/radeon_kfd.h
+ F:    include/uapi/linux/kfd_ioctl.h
  
  AMD MICROCODE UPDATE SUPPORT
  M:    Borislav Petkov <bp@alien8.de>
@@@ -724,7 -730,7 +730,7 @@@ F: staging/iio/trigger/iio-trig-bfin-ti
  
  ANDROID DRIVERS
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- M:    Arve Hjønnevåg <arve@android.com>
+ M:    Arve Hjønnevåg <arve@android.com>
  M:    Riley Andrews <riandrews@android.com>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/gregkh/staging.git
  L:    devel@driverdev.osuosl.org
@@@ -1215,6 -1221,7 +1221,7 @@@ F:      arch/arm/mach-orion5x/ts78xx-
  ARM/Mediatek SoC support
  M:    Matthias Brugger <matthias.bgg@gmail.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ L:    linux-mediatek@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  F:    arch/arm/boot/dts/mt6*
  F:    arch/arm/boot/dts/mt8*
@@@ -1468,6 -1475,8 +1475,8 @@@ F:      drivers/clocksource/arm_global_timer
  F:    drivers/i2c/busses/i2c-st.c
  F:    drivers/media/rc/st_rc.c
  F:    drivers/mmc/host/sdhci-st.c
+ F:    drivers/phy/phy-miphy28lp.c
+ F:    drivers/phy/phy-miphy365x.c
  F:    drivers/phy/phy-stih407-usb.c
  F:    drivers/phy/phy-stih41x-usb.c
  F:    drivers/pinctrl/pinctrl-st.c
@@@ -1762,7 -1771,7 +1771,7 @@@ S:      Supporte
  F:    drivers/tty/serial/atmel_serial.c
  
  ATMEL Audio ALSA driver
- M:    Bo Shen <voice.shen@atmel.com>
+ M:    Nicolas Ferre <nicolas.ferre@atmel.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  S:    Supported
  F:    sound/soc/atmel
@@@ -1913,16 -1922,14 +1922,14 @@@ S:   Maintaine
  F:    drivers/media/radio/radio-aztech*
  
  B43 WIRELESS DRIVER
- M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
  W:    http://wireless.kernel.org/en/users/Drivers/b43
- S:    Maintained
+ S:    Odd Fixes
  F:    drivers/net/wireless/b43/
  
  B43LEGACY WIRELESS DRIVER
  M:    Larry Finger <Larry.Finger@lwfinger.net>
- M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
  W:    http://wireless.kernel.org/en/users/Drivers/b43
@@@ -1965,10 -1972,10 +1972,10 @@@ F:   Documentation/filesystems/befs.tx
  F:    fs/befs/
  
  BECKHOFF CX5020 ETHERCAT MASTER DRIVER
- M: Dariusz Marcinkiewicz <reksio@newterm.pl>
- L: netdev@vger.kernel.org
- S: Maintained
- F: drivers/net/ethernet/ec_bhf.c
+ M:    Dariusz Marcinkiewicz <reksio@newterm.pl>
+ L:    netdev@vger.kernel.org
+ S:    Maintained
+ F:    drivers/net/ethernet/ec_bhf.c
  
  BFS FILE SYSTEM
  M:    "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
@@@ -2518,11 -2525,18 +2525,18 @@@ F:   Documentation/zh_CN
  
  CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
  M:    Peter Chen <Peter.Chen@freescale.com>
- T:    git git://github.com/hzpeterchen/linux-usb.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/chipidea/
  
+ CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
+ M:    Hans de Goede <hdegoede@redhat.com>
+ L:    linux-input@vger.kernel.org
+ S:    Maintained
+ F:    Documentation/devicetree/bindings/input/touchscreen/chipone_icn8318.txt
+ F:    drivers/input/touchscreen/chipone_icn8318.c
  CHROME HARDWARE PLATFORM SUPPORT
  M:    Olof Johansson <olof@lixom.net>
  S:    Maintained
@@@ -2816,6 -2830,7 +2830,7 @@@ L:      linux-crypto@vger.kernel.or
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
  S:    Maintained
  F:    Documentation/crypto/
+ F:    Documentation/DocBook/crypto-API.tmpl
  F:    arch/*/crypto/
  F:    crypto/
  F:    drivers/crypto/
@@@ -2886,11 -2901,11 +2901,11 @@@ S:   Supporte
  F:    drivers/net/ethernet/chelsio/cxgb3/
  
  CXGB3 ISCSI DRIVER (CXGB3I)
- M:      Karen Xie <kxie@chelsio.com>
- L:      linux-scsi@vger.kernel.org
- W:      http://www.chelsio.com
- S:      Supported
- F:      drivers/scsi/cxgbi/cxgb3i
+ M:    Karen Xie <kxie@chelsio.com>
+ L:    linux-scsi@vger.kernel.org
+ W:    http://www.chelsio.com
+ S:    Supported
+ F:    drivers/scsi/cxgbi/cxgb3i
  
  CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
  M:    Steve Wise <swise@chelsio.com>
@@@ -2907,11 -2922,11 +2922,11 @@@ S:   Supporte
  F:    drivers/net/ethernet/chelsio/cxgb4/
  
  CXGB4 ISCSI DRIVER (CXGB4I)
- M:      Karen Xie <kxie@chelsio.com>
- L:      linux-scsi@vger.kernel.org
- W:      http://www.chelsio.com
- S:      Supported
- F:      drivers/scsi/cxgbi/cxgb4i
+ M:    Karen Xie <kxie@chelsio.com>
+ L:    linux-scsi@vger.kernel.org
+ W:    http://www.chelsio.com
+ S:    Supported
+ F:    drivers/scsi/cxgbi/cxgb4i
  
  CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
  M:    Steve Wise <swise@chelsio.com>
@@@ -3137,12 -3152,15 +3152,15 @@@ S:   Supporte
  F:    Documentation/hwmon/da90??
  F:    drivers/gpio/gpio-da90??.c
  F:    drivers/hwmon/da90??-hwmon.c
+ F:    drivers/iio/adc/da91??-*.c
  F:    drivers/input/misc/da90??_onkey.c
  F:    drivers/input/touchscreen/da9052_tsi.c
  F:    drivers/leds/leds-da90??.c
  F:    drivers/mfd/da903x.c
  F:    drivers/mfd/da90??-*.c
+ F:    drivers/mfd/da91??-*.c
  F:    drivers/power/da9052-battery.c
+ F:    drivers/power/da91??-*.c
  F:    drivers/regulator/da903x.c
  F:    drivers/regulator/da9???-regulator.[ch]
  F:    drivers/rtc/rtc-da90??.c
@@@ -3152,6 -3170,7 +3170,7 @@@ F:      include/linux/mfd/da903x.
  F:    include/linux/mfd/da9052/
  F:    include/linux/mfd/da9055/
  F:    include/linux/mfd/da9063/
+ F:    include/linux/mfd/da9150/
  F:    include/sound/da[79]*.h
  F:    sound/soc/codecs/da[79]*.[ch]
  
@@@ -3272,7 -3291,9 +3291,9 @@@ S:      Maintaine
  F:    Documentation/
  X:    Documentation/ABI/
  X:    Documentation/devicetree/
- X:    Documentation/[a-z][a-z]_[A-Z][A-Z]/
+ X:    Documentation/acpi
+ X:    Documentation/power
+ X:    Documentation/spi
  T:    git git://git.lwn.net/linux-2.6.git docs-next
  
  DOUBLETALK DRIVER
@@@ -3396,6 -3417,7 +3417,6 @@@ T:      git git://people.freedesktop.org/~ai
  S:    Supported
  F:    drivers/gpu/drm/rcar-du/
  F:    drivers/gpu/drm/shmobile/
 -F:    include/linux/platform_data/rcar-du.h
  F:    include/linux/platform_data/shmob_drm.h
  
  DSBR100 USB FM RADIO DRIVER
@@@ -4162,6 -4184,12 +4183,12 @@@ F:    sound/soc/fsl/fsl
  F:    sound/soc/fsl/imx*
  F:    sound/soc/fsl/mpc8610_hpcd.c
  
+ FREESCALE QORIQ MANAGEMENT COMPLEX DRIVER
+ M:    J. German Rivera <German.Rivera@freescale.com>
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
+ F:    drivers/staging/fsl-mc/
  FREEVXFS FILESYSTEM
  M:    Christoph Hellwig <hch@infradead.org>
  W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
@@@ -4311,6 -4339,15 +4338,15 @@@ S:    Supporte
  F:    drivers/phy/
  F:    include/linux/phy/
  
+ GENERIC PM DOMAINS
+ M:    "Rafael J. Wysocki" <rjw@rjwysocki.net>
+ M:    Kevin Hilman <khilman@kernel.org>
+ M:    Ulf Hansson <ulf.hansson@linaro.org>
+ L:    linux-pm@vger.kernel.org
+ S:    Supported
+ F:    drivers/base/power/domain*.c
+ F:    include/linux/pm_domain.h
  GENERIC UIO DRIVER FOR PCI DEVICES
  M:    "Michael S. Tsirkin" <mst@redhat.com>
  L:    kvm@vger.kernel.org
@@@ -4324,10 -4361,10 +4360,10 @@@ F:   scripts/get_maintainer.p
  
  GFS2 FILE SYSTEM
  M:    Steven Whitehouse <swhiteho@redhat.com>
+ M:    Bob Peterson <rpeterso@redhat.com>
  L:    cluster-devel@redhat.com
  W:    http://sources.redhat.com/cluster/
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
  S:    Supported
  F:    Documentation/filesystems/gfs2*.txt
  F:    fs/gfs2/
@@@ -4947,6 -4984,7 +4983,7 @@@ S:      Maintaine
  F:    drivers/iio/
  F:    drivers/staging/iio/
  F:    include/linux/iio/
+ F:    tools/iio/
  
  IKANOS/ADI EAGLE ADSL USB DRIVER
  M:    Matthieu Castet <castet.matthieu@free.fr>
@@@ -5192,7 -5230,7 +5229,7 @@@ F:      arch/x86/kernel/tboot.
  INTEL WIRELESS WIMAX CONNECTION 2400
  M:    Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  M:    linux-wimax@intel.com
- L:     wimax@linuxwimax.org (subscribers-only)
+ L:    wimax@linuxwimax.org (subscribers-only)
  S:    Supported
  W:    http://linuxwimax.org
  F:    Documentation/wimax/README.i2400m
@@@ -5270,6 -5308,13 +5307,13 @@@ F:    drivers/char/ipmi
  F:    include/linux/ipmi*
  F:    include/uapi/linux/ipmi*
  
+ QCOM AUDIO (ASoC) DRIVERS
+ M:    Patrick Lai <plai@codeaurora.org>
+ M:    Banajit Goswami <bgoswami@codeaurora.org>
+ L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
+ S:    Supported
+ F:    sound/soc/qcom/
  IPS SCSI RAID DRIVER
  M:    Adaptec OEM Raid Solutions <aacraid@adaptec.com>
  L:    linux-scsi@vger.kernel.org
@@@ -5590,6 -5635,8 +5634,8 @@@ S:      Supporte
  F:    Documentation/*/kvm*.txt
  F:    Documentation/virtual/kvm/
  F:    arch/*/kvm/
+ F:    arch/x86/kernel/kvm.c
+ F:    arch/x86/kernel/kvmclock.c
  F:    arch/*/include/asm/kvm*
  F:    include/linux/kvm*
  F:    include/uapi/linux/kvm*
@@@ -5886,7 -5933,7 +5932,7 @@@ F:      arch/powerpc/platforms/512x
  F:    arch/powerpc/platforms/52xx/
  
  LINUX FOR POWERPC EMBEDDED PPC4XX
- M:  Alistair Popple <alistair@popple.id.au>
+ M:    Alistair Popple <alistair@popple.id.au>
  M:    Matt Porter <mporter@kernel.crashing.org>
  W:    http://www.penguinppc.org/
  L:    linuxppc-dev@lists.ozlabs.org
@@@ -6321,6 -6368,7 +6367,7 @@@ F:      drivers/scsi/megaraid
  
  MELLANOX ETHERNET DRIVER (mlx4_en)
  M:    Amir Vadai <amirv@mellanox.com>
+ M:    Ido Shamay <idos@mellanox.com>
  L:    netdev@vger.kernel.org
  S:    Supported
  W:    http://www.mellanox.com
@@@ -6358,7 -6406,7 +6405,7 @@@ S:      Supporte
  F:    drivers/watchdog/mena21_wdt.c
  
  MEN CHAMELEON BUS (mcb)
- M:    Johannes Thumshirn <johannes.thumshirn@men.de>
+ M:    Johannes Thumshirn <johannes.thumshirn@men.de>
  S:    Supported
  F:    drivers/mcb/
  F:    include/linux/mcb.h
@@@ -6563,10 -6611,8 +6610,8 @@@ F:     drivers/mfd
  F:    include/linux/mfd/
  
  MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
- M:    Chris Ball <chris@printf.net>
  M:    Ulf Hansson <ulf.hansson@linaro.org>
  L:    linux-mmc@vger.kernel.org
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
  T:    git git://git.linaro.org/people/ulf.hansson/mmc.git
  S:    Maintained
  F:    drivers/mmc/
@@@ -6942,6 -6988,13 +6987,13 @@@ S:    Supporte
  F:    drivers/block/nvme*
  F:    include/linux/nvme.h
  
+ NXP-NCI NFC DRIVER
+ M:    Clément Perrochaud <clement.perrochaud@effinnov.com>
+ R:    Charles Gorand <charles.gorand@effinnov.com>
+ L:    linux-nfc@lists.01.org (moderated for non-subscribers)
+ S:    Supported
+ F:    drivers/nfc/nxp-nci
  NXP TDA998X DRM DRIVER
  M:    Russell King <rmk+kernel@arm.linux.org.uk>
  S:    Supported
@@@ -7918,10 -7971,10 +7970,10 @@@ L:   rtc-linux@googlegroups.co
  S:    Maintained
  
  QAT DRIVER
- M:      Tadeusz Struk <tadeusz.struk@intel.com>
- L:      qat-linux@intel.com
- S:      Supported
- F:      drivers/crypto/qat/
+ M:    Tadeusz Struk <tadeusz.struk@intel.com>
+ L:    qat-linux@intel.com
+ S:    Supported
+ F:    drivers/crypto/qat/
  
  QIB DRIVER
  M:    Mike Marciniszyn <infinipath@intel.com>
@@@ -8072,11 -8125,17 +8124,17 @@@ S:   Maintaine
  F:    drivers/net/wireless/rt2x00/
  
  RAMDISK RAM BLOCK DEVICE DRIVER
- M:    Nick Piggin <npiggin@kernel.dk>
+ M:    Jens Axboe <axboe@kernel.dk>
  S:    Maintained
  F:    Documentation/blockdev/ramdisk.txt
  F:    drivers/block/brd.c
  
+ PERSISTENT MEMORY DRIVER
+ M:    Ross Zwisler <ross.zwisler@linux.intel.com>
+ L:    linux-nvdimm@lists.01.org
+ S:    Supported
+ F:    drivers/block/pmem.c
  RANDOM NUMBER DRIVER
  M:    "Theodore Ts'o" <tytso@mit.edu>
  S:    Maintained
@@@ -8148,6 -8207,7 +8206,7 @@@ X:      kernel/torture.
  
  REAL TIME CLOCK (RTC) SUBSYSTEM
  M:    Alessandro Zummo <a.zummo@towertech.it>
+ M:    Alexandre Belloni <alexandre.belloni@free-electrons.com>
  L:    rtc-linux@googlegroups.com
  Q:    http://patchwork.ozlabs.org/project/rtc-linux/list/
  S:    Maintained
@@@ -8359,7 -8419,6 +8418,6 @@@ F:      block/partitions/ibm.
  
  S390 NETWORK DRIVERS
  M:    Ursula Braun <ursula.braun@de.ibm.com>
- M:    Frank Blaschka <blaschka@linux.vnet.ibm.com>
  M:    linux390@de.ibm.com
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
@@@ -8567,6 -8626,7 +8625,7 @@@ F:      include/uapi/linux/timex.
  F:    kernel/time/clocksource.c
  F:    kernel/time/time*.c
  F:    kernel/time/ntp.c
+ F:    tools/testing/selftests/timers/
  
  SC1200 WDT DRIVER
  M:    Zwane Mwaikambo <zwanem@gmail.com>
@@@ -8618,11 -8678,9 +8677,9 @@@ F:     drivers/scsi/sg.
  F:    include/scsi/sg.h
  
  SCSI SUBSYSTEM
- M:    "James E.J. Bottomley" <JBottomley@parallels.com>
+ M:    "James E.J. Bottomley" <JBottomley@odin.com>
  L:    linux-scsi@vger.kernel.org
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
  S:    Maintained
  F:    drivers/scsi/
  F:    include/scsi/
@@@ -8675,10 -8733,8 +8732,8 @@@ S:     Maintaine
  F:    drivers/mmc/host/sdricoh_cs.c
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
- M:    Chris Ball <chris@printf.net>
  L:    linux-mmc@vger.kernel.org
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
- S:    Maintained
+ S:    Orphan
  F:    drivers/mmc/host/sdhci.*
  F:    drivers/mmc/host/sdhci-pltfm.[ch]
  
@@@ -8694,18 -8750,12 +8749,12 @@@ F:   include/linux/seccomp.
  K:    \bsecure_computing
  K:    \bTIF_SECCOMP\b
  
- SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
- M:    Anton Vorontsov <anton@enomsg.org>
- L:    linuxppc-dev@lists.ozlabs.org
- L:    linux-mmc@vger.kernel.org
- S:    Maintained
- F:    drivers/mmc/host/sdhci-pltfm.[ch]
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
  M:    Ben Dooks <ben-linux@fluff.org>
+ M:    Jaehoon Chung <jh80.chung@samsung.com>
  L:    linux-mmc@vger.kernel.org
  S:    Maintained
- F:    drivers/mmc/host/sdhci-s3c.c
+ F:    drivers/mmc/host/sdhci-s3c*
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
  M:    Viresh Kumar <viresh.linux@gmail.com>
@@@ -9372,6 -9422,14 +9421,14 @@@ L:    linux-fbdev@vger.kernel.or
  S:    Maintained
  F:    drivers/staging/sm7xxfb/
  
+ STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
+ M:    Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+ M:    Teddy Wang <teddy.wang@siliconmotion.com>
+ M:    Sudip Mukherjee <sudip@vectorindia.org>
+ L:    linux-fbdev@vger.kernel.org
+ S:    Maintained
+ F:    drivers/staging/sm750fb/
  STAGING - SLICOSS
  M:    Lior Dotan <liodot@gmail.com>
  M:    Christopher Harrer <charrer@alacritech.com>
@@@ -9834,7 -9892,7 +9891,7 @@@ F:      include/linux/wl12xx.
  
  TIPC NETWORK LAYER
  M:    Jon Maloy <jon.maloy@ericsson.com>
- M:    Allan Stephens <allan.stephens@windriver.com>
+ M:    Ying Xue <ying.xue@windriver.com>
  L:    netdev@vger.kernel.org (core kernel code)
  L:    tipc-discussion@lists.sourceforge.net (user apps, general discussion)
  W:    http://tipc.sourceforge.net/
@@@ -9938,6 -9996,7 +9995,7 @@@ F:      drivers/media/pci/tw68
  TPM DEVICE DRIVER
  M:    Peter Huewe <peterhuewe@gmx.de>
  M:    Marcel Selhorst <tpmdd@selhorst.net>
+ R:    Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
  W:    http://tpmdd.sourceforge.net
  L:    tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
  Q:    git git://github.com/PeterHuewe/linux-tpmdd.git
@@@ -10091,11 -10150,11 +10149,11 @@@ F:        include/linux/cdrom.
  F:    include/uapi/linux/cdrom.h
  
  UNISYS S-PAR DRIVERS
- M:     Benjamin Romer <benjamin.romer@unisys.com>
- M:     David Kershner <david.kershner@unisys.com>
- L:     sparmaintainer@unisys.com (Unisys internal)
- S:     Supported
- F:     drivers/staging/unisys/
+ M:    Benjamin Romer <benjamin.romer@unisys.com>
+ M:    David Kershner <david.kershner@unisys.com>
+ L:    sparmaintainer@unisys.com (Unisys internal)
+ S:    Supported
+ F:    drivers/staging/unisys/
  
  UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
  M:    Vinayak Holikatti <vinholikatti@gmail.com>
@@@ -10143,6 -10202,12 +10201,12 @@@ S: Maintaine
  F:    drivers/net/usb/cdc_*.c
  F:    include/uapi/linux/usb/cdc.h
  
+ USB CHAOSKEY DRIVER
+ M:    Keith Packard <keithp@keithp.com>
+ L:    linux-usb@vger.kernel.org
+ S:    Maintained
+ F:    drivers/usb/misc/chaoskey.c
  USB CYPRESS C67X00 DRIVER
  M:    Peter Korsgaard <jacmet@sunsite.dk>
  L:    linux-usb@vger.kernel.org
@@@ -10223,7 -10288,7 +10287,7 @@@ F:   drivers/usb/host/ohci
  
  USB OTG FSM (Finite State Machine)
  M:    Peter Chen <Peter.Chen@freescale.com>
- T:    git git://github.com/hzpeterchen/linux-usb.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/common/usb-otg-fsm.c
@@@ -10646,7 -10711,7 +10710,7 @@@ F:   drivers/media/rc/winbond-cir.
  WIMAX STACK
  M:    Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  M:    linux-wimax@intel.com
- L:     wimax@linuxwimax.org (subscribers-only)
+ L:    wimax@linuxwimax.org (subscribers-only)
  S:    Supported
  W:    http://linuxwimax.org
  F:    Documentation/wimax/README.wimax
@@@ -10937,6 -11002,7 +11001,7 @@@ L:   linux-mm@kvack.or
  S:    Maintained
  F:    mm/zsmalloc.c
  F:    include/linux/zsmalloc.h
+ F:    Documentation/vm/zsmalloc.txt
  
  ZSWAP COMPRESSED SWAP CACHING
  M:    Seth Jennings <sjennings@variantweb.net>
index 3403edea9076b0233d459fc675c92b119cb922bb,b6f076b213bcfde496a61824335b68d1760b5613..3007b44e6bf4494c36e06f65210efa98ea5b4a86
@@@ -660,9 -660,6 +660,9 @@@ int drm_crtc_init_with_planes(struct dr
        struct drm_mode_config *config = &dev->mode_config;
        int ret;
  
 +      WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
 +      WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
 +
        crtc->dev = dev;
        crtc->funcs = funcs;
        crtc->invert_dimensions = false;
@@@ -2002,32 -1999,21 +2002,32 @@@ int drm_mode_getcrtc(struct drm_device 
                return -ENOENT;
  
        drm_modeset_lock_crtc(crtc, crtc->primary);
 -      crtc_resp->x = crtc->x;
 -      crtc_resp->y = crtc->y;
        crtc_resp->gamma_size = crtc->gamma_size;
        if (crtc->primary->fb)
                crtc_resp->fb_id = crtc->primary->fb->base.id;
        else
                crtc_resp->fb_id = 0;
  
 -      if (crtc->enabled) {
 -
 -              drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
 -              crtc_resp->mode_valid = 1;
 +      if (crtc->state) {
 +              crtc_resp->x = crtc->primary->state->src_x >> 16;
 +              crtc_resp->y = crtc->primary->state->src_y >> 16;
 +              if (crtc->state->enable) {
 +                      drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
 +                      crtc_resp->mode_valid = 1;
  
 +              } else {
 +                      crtc_resp->mode_valid = 0;
 +              }
        } else {
 -              crtc_resp->mode_valid = 0;
 +              crtc_resp->x = crtc->x;
 +              crtc_resp->y = crtc->y;
 +              if (crtc->enabled) {
 +                      drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
 +                      crtc_resp->mode_valid = 1;
 +
 +              } else {
 +                      crtc_resp->mode_valid = 0;
 +              }
        }
        drm_modeset_unlock_crtc(crtc);
  
@@@ -2135,7 -2121,7 +2135,7 @@@ int drm_mode_getconnector(struct drm_de
        connector = drm_connector_find(dev, out_resp->connector_id);
        if (!connector) {
                ret = -ENOENT;
-               goto out;
+               goto out_unlock;
        }
  
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
  
  out:
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
+ out_unlock:
        mutex_unlock(&dev->mode_config.mutex);
  
        return ret;
@@@ -2278,6 -2266,8 +2280,6 @@@ int drm_mode_getencoder(struct drm_devi
        crtc = drm_encoder_get_crtc(encoder);
        if (crtc)
                enc_resp->crtc_id = crtc->base.id;
 -      else if (encoder->crtc)
 -              enc_resp->crtc_id = encoder->crtc->base.id;
        else
                enc_resp->crtc_id = 0;
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@@ -2412,27 -2402,6 +2414,27 @@@ int drm_mode_getplane(struct drm_devic
        return 0;
  }
  
 +/**
 + * drm_plane_check_pixel_format - Check if the plane supports the pixel format
 + * @plane: plane to check for format support
 + * @format: the pixel format
 + *
 + * Returns:
 + * Zero of @plane has @format in its list of supported pixel formats, -EINVAL
 + * otherwise.
 + */
 +int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
 +{
 +      unsigned int i;
 +
 +      for (i = 0; i < plane->format_count; i++) {
 +              if (format == plane->format_types[i])
 +                      return 0;
 +      }
 +
 +      return -EINVAL;
 +}
 +
  /*
   * setplane_internal - setplane handler for internal callers
   *
@@@ -2453,6 -2422,7 +2455,6 @@@ static int __setplane_internal(struct d
  {
        int ret = 0;
        unsigned int fb_width, fb_height;
 -      unsigned int i;
  
        /* No fb means shut it down */
        if (!fb) {
        }
  
        /* Check whether this plane supports the fb pixel format. */
 -      for (i = 0; i < plane->format_count; i++)
 -              if (fb->pixel_format == plane->format_types[i])
 -                      break;
 -      if (i == plane->format_count) {
 +      ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
 +      if (ret) {
                DRM_DEBUG_KMS("Invalid pixel format %s\n",
                              drm_get_format_name(fb->pixel_format));
 -              ret = -EINVAL;
                goto out;
        }
  
 +      /* Give drivers some help against integer overflows */
 +      if (crtc_w > INT_MAX ||
 +          crtc_x > INT_MAX - (int32_t) crtc_w ||
 +          crtc_h > INT_MAX ||
 +          crtc_y > INT_MAX - (int32_t) crtc_h) {
 +              DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
 +                            crtc_w, crtc_h, crtc_x, crtc_y);
 +              return -ERANGE;
 +      }
 +
 +
        fb_width = fb->width << 16;
        fb_height = fb->height << 16;
  
@@@ -2577,6 -2539,17 +2579,6 @@@ int drm_mode_setplane(struct drm_devic
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
  
 -      /* Give drivers some help against integer overflows */
 -      if (plane_req->crtc_w > INT_MAX ||
 -          plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
 -          plane_req->crtc_h > INT_MAX ||
 -          plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
 -              DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
 -                            plane_req->crtc_w, plane_req->crtc_h,
 -                            plane_req->crtc_x, plane_req->crtc_y);
 -              return -ERANGE;
 -      }
 -
        /*
         * First, find the plane, crtc, and fb objects.  If not available,
         * we don't bother to call the driver.
@@@ -2802,23 -2775,6 +2804,23 @@@ int drm_mode_setcrtc(struct drm_device 
  
                drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  
 +              /*
 +               * Check whether the primary plane supports the fb pixel format.
 +               * Drivers not implementing the universal planes API use a
 +               * default formats list provided by the DRM core which doesn't
 +               * match real hardware capabilities. Skip the check in that
 +               * case.
 +               */
 +              if (!crtc->primary->format_default) {
 +                      ret = drm_plane_check_pixel_format(crtc->primary,
 +                                                         fb->pixel_format);
 +                      if (ret) {
 +                              DRM_DEBUG_KMS("Invalid pixel format %s\n",
 +                                      drm_get_format_name(fb->pixel_format));
 +                              goto out;
 +                      }
 +              }
 +
                ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
                                              mode, fb);
                if (ret)
@@@ -3296,12 -3252,6 +3298,12 @@@ static int framebuffer_check(const stru
                        DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
                        return -EINVAL;
                }
 +
 +              if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
 +                      DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
 +                                    r->modifier[i], i);
 +                      return -EINVAL;
 +              }
        }
  
        return 0;
@@@ -3316,7 -3266,7 +3318,7 @@@ internal_framebuffer_create(struct drm_
        struct drm_framebuffer *fb;
        int ret;
  
 -      if (r->flags & ~DRM_MODE_FB_INTERLACED) {
 +      if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
                DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
                return ERR_PTR(-EINVAL);
        }
                return ERR_PTR(-EINVAL);
        }
  
 +      if (r->flags & DRM_MODE_FB_MODIFIERS &&
 +          !dev->mode_config.allow_fb_modifiers) {
 +              DRM_DEBUG_KMS("driver does not support fb modifiers\n");
 +              return ERR_PTR(-EINVAL);
 +      }
 +
        ret = framebuffer_check(r);
        if (ret)
                return ERR_PTR(ret);
@@@ -5599,7 -5543,6 +5601,7 @@@ struct drm_tile_group *drm_mode_get_til
        mutex_unlock(&dev->mode_config.idr_mutex);
        return NULL;
  }
 +EXPORT_SYMBOL(drm_mode_get_tile_group);
  
  /**
   * drm_mode_create_tile_group - create a tile group from a displayid description
@@@ -5638,4 -5581,3 +5640,4 @@@ struct drm_tile_group *drm_mode_create_
        mutex_unlock(&dev->mode_config.idr_mutex);
        return tg;
  }
 +EXPORT_SYMBOL(drm_mode_create_tile_group);
index 82f8be4b6745969804163e6cab7cf63199b0c22b,5c66b568bb8162345046fcce0118c5bf74eddc2f..c24c3f1ff8a30ca042dba35c82c8e7b179d5d891
@@@ -346,6 -346,7 +346,6 @@@ static const struct intel_device_info i
  };
  
  static const struct intel_device_info intel_cherryview_info = {
 -      .is_preliminary = 1,
        .gen = 8, .num_pipes = 3,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
@@@ -368,19 -369,6 +368,19 @@@ static const struct intel_device_info i
        IVB_CURSOR_OFFSETS,
  };
  
 +static const struct intel_device_info intel_skylake_gt3_info = {
 +      .is_preliminary = 1,
 +      .is_skylake = 1,
 +      .gen = 9, .num_pipes = 3,
 +      .need_gfx_hws = 1, .has_hotplug = 1,
 +      .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 +      .has_llc = 1,
 +      .has_ddi = 1,
 +      .has_fbc = 1,
 +      GEN_DEFAULT_PIPEOFFSETS,
 +      IVB_CURSOR_OFFSETS,
 +};
 +
  /*
   * Make sure any device matches here are from most specific to most
   * general.  For example, since the Quanta match is based on the subsystem
        INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), \
        INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), \
        INTEL_CHV_IDS(&intel_cherryview_info),  \
 -      INTEL_SKL_IDS(&intel_skylake_info)
 +      INTEL_SKL_GT1_IDS(&intel_skylake_info), \
 +      INTEL_SKL_GT2_IDS(&intel_skylake_info), \
 +      INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info)      \
  
  static const struct pci_device_id pciidlist[] = {             /* aka */
        INTEL_PCI_IDS,
@@@ -567,7 -553,6 +567,7 @@@ static int i915_drm_suspend(struct drm_
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
        pci_power_t opregion_target_state;
 +      int error;
  
        /* ignore lid events during suspend */
        mutex_lock(&dev_priv->modeset_restore_lock);
  
        pci_save_state(dev->pdev);
  
 -      /* If KMS is active, we do the leavevt stuff here */
 -      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 -              int error;
 -
 -              error = i915_gem_suspend(dev);
 -              if (error) {
 -                      dev_err(&dev->pdev->dev,
 -                              "GEM idle failed, resume might fail\n");
 -                      return error;
 -              }
 +      error = i915_gem_suspend(dev);
 +      if (error) {
 +              dev_err(&dev->pdev->dev,
 +                      "GEM idle failed, resume might fail\n");
 +              return error;
 +      }
  
 -              intel_suspend_gt_powersave(dev);
 +      intel_suspend_gt_powersave(dev);
  
 -              /*
 -               * Disable CRTCs directly since we want to preserve sw state
 -               * for _thaw. Also, power gate the CRTC power wells.
 -               */
 -              drm_modeset_lock_all(dev);
 -              for_each_crtc(dev, crtc)
 -                      intel_crtc_control(crtc, false);
 -              drm_modeset_unlock_all(dev);
 +      /*
 +       * Disable CRTCs directly since we want to preserve sw state
 +       * for _thaw. Also, power gate the CRTC power wells.
 +       */
 +      drm_modeset_lock_all(dev);
 +      for_each_crtc(dev, crtc)
 +              intel_crtc_control(crtc, false);
 +      drm_modeset_unlock_all(dev);
  
 -              intel_dp_mst_suspend(dev);
 +      intel_dp_mst_suspend(dev);
  
 -              intel_runtime_pm_disable_interrupts(dev_priv);
 -              intel_hpd_cancel_work(dev_priv);
 +      intel_runtime_pm_disable_interrupts(dev_priv);
 +      intel_hpd_cancel_work(dev_priv);
  
 -              intel_suspend_encoders(dev_priv);
 +      intel_suspend_encoders(dev_priv);
  
 -              intel_suspend_hw(dev);
 -      }
 +      intel_suspend_hw(dev);
  
        i915_gem_suspend_gtt_mappings(dev);
  
@@@ -689,48 -679,53 +689,48 @@@ static int i915_drm_resume(struct drm_d
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 -      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 -              mutex_lock(&dev->struct_mutex);
 -              i915_gem_restore_gtt_mappings(dev);
 -              mutex_unlock(&dev->struct_mutex);
 -      }
 +      mutex_lock(&dev->struct_mutex);
 +      i915_gem_restore_gtt_mappings(dev);
 +      mutex_unlock(&dev->struct_mutex);
  
        i915_restore_state(dev);
        intel_opregion_setup(dev);
  
 -      /* KMS EnterVT equivalent */
 -      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 -              intel_init_pch_refclk(dev);
 -              drm_mode_config_reset(dev);
 +      intel_init_pch_refclk(dev);
 +      drm_mode_config_reset(dev);
  
 -              mutex_lock(&dev->struct_mutex);
 -              if (i915_gem_init_hw(dev)) {
 -                      DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n");
 -                      atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
 -              }
 -              mutex_unlock(&dev->struct_mutex);
 +      mutex_lock(&dev->struct_mutex);
 +      if (i915_gem_init_hw(dev)) {
 +              DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n");
 +              atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
 +      }
 +      mutex_unlock(&dev->struct_mutex);
  
 -              /* We need working interrupts for modeset enabling ... */
 -              intel_runtime_pm_enable_interrupts(dev_priv);
 +      /* We need working interrupts for modeset enabling ... */
 +      intel_runtime_pm_enable_interrupts(dev_priv);
  
 -              intel_modeset_init_hw(dev);
 +      intel_modeset_init_hw(dev);
  
 -              spin_lock_irq(&dev_priv->irq_lock);
 -              if (dev_priv->display.hpd_irq_setup)
 -                      dev_priv->display.hpd_irq_setup(dev);
 -              spin_unlock_irq(&dev_priv->irq_lock);
 +      spin_lock_irq(&dev_priv->irq_lock);
 +      if (dev_priv->display.hpd_irq_setup)
 +              dev_priv->display.hpd_irq_setup(dev);
 +      spin_unlock_irq(&dev_priv->irq_lock);
  
 -              drm_modeset_lock_all(dev);
 -              intel_modeset_setup_hw_state(dev, true);
 -              drm_modeset_unlock_all(dev);
 +      drm_modeset_lock_all(dev);
 +      intel_modeset_setup_hw_state(dev, true);
 +      drm_modeset_unlock_all(dev);
  
 -              intel_dp_mst_resume(dev);
 +      intel_dp_mst_resume(dev);
  
 -              /*
 -               * ... but also need to make sure that hotplug processing
 -               * doesn't cause havoc. Like in the driver load code we don't
 -               * bother with the tiny race here where we might loose hotplug
 -               * notifications.
 -               * */
 -              intel_hpd_init(dev_priv);
 -              /* Config may have changed between suspend and resume */
 -              drm_helper_hpd_irq_event(dev);
 -      }
 +      /*
 +       * ... but also need to make sure that hotplug processing
 +       * doesn't cause havoc. Like in the driver load code we don't
 +       * bother with the tiny race here where we might loose hotplug
 +       * notifications.
 +       * */
 +      intel_hpd_init(dev_priv);
 +      /* Config may have changed between suspend and resume */
 +      drm_helper_hpd_irq_event(dev);
  
        intel_opregion_init(dev);
  
@@@ -866,29 -861,38 +866,29 @@@ int i915_reset(struct drm_device *dev
         * was running at the time of the reset (i.e. we weren't VT
         * switched away).
         */
 -      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 -              /* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset */
 -              dev_priv->gpu_error.reload_in_reset = true;
  
 -              ret = i915_gem_init_hw(dev);
 +      /* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset */
 +      dev_priv->gpu_error.reload_in_reset = true;
  
 -              dev_priv->gpu_error.reload_in_reset = false;
 +      ret = i915_gem_init_hw(dev);
  
 -              mutex_unlock(&dev->struct_mutex);
 -              if (ret) {
 -                      DRM_ERROR("Failed hw init on reset %d\n", ret);
 -                      return ret;
 -              }
 +      dev_priv->gpu_error.reload_in_reset = false;
  
 -              /*
 -               * FIXME: This races pretty badly against concurrent holders of
 -               * ring interrupts. This is possible since we've started to drop
 -               * dev->struct_mutex in select places when waiting for the gpu.
 -               */
 -
 -              /*
 -               * rps/rc6 re-init is necessary to restore state lost after the
 -               * reset and the re-install of gt irqs. Skip for ironlake per
 -               * previous concerns that it doesn't respond well to some forms
 -               * of re-init after reset.
 -               */
 -              if (INTEL_INFO(dev)->gen > 5)
 -                      intel_enable_gt_powersave(dev);
 -      } else {
 -              mutex_unlock(&dev->struct_mutex);
 +      mutex_unlock(&dev->struct_mutex);
 +      if (ret) {
 +              DRM_ERROR("Failed hw init on reset %d\n", ret);
 +              return ret;
        }
  
 +      /*
 +       * rps/rc6 re-init is necessary to restore state lost after the
 +       * reset and the re-install of gt irqs. Skip for ironlake per
 +       * previous concerns that it doesn't respond well to some forms
 +       * of re-init after reset.
 +       */
 +      if (INTEL_INFO(dev)->gen > 5)
 +              intel_enable_gt_powersave(dev);
 +
        return 0;
  }
  
@@@ -1091,6 -1095,7 +1091,7 @@@ static void vlv_save_gunit_s0ix_state(s
        /* Gunit-Display CZ domain, 0x182028-0x1821CF */
        s->gu_ctl0              = I915_READ(VLV_GU_CTL0);
        s->gu_ctl1              = I915_READ(VLV_GU_CTL1);
+       s->pcbr                 = I915_READ(VLV_PCBR);
        s->clock_gate_dis2      = I915_READ(VLV_GUNIT_CLOCK_GATE2);
  
        /*
@@@ -1185,6 -1190,7 +1186,7 @@@ static void vlv_restore_gunit_s0ix_stat
        /* Gunit-Display CZ domain, 0x182028-0x1821CF */
        I915_WRITE(VLV_GU_CTL0,                 s->gu_ctl0);
        I915_WRITE(VLV_GU_CTL1,                 s->gu_ctl1);
+       I915_WRITE(VLV_PCBR,                    s->pcbr);
        I915_WRITE(VLV_GUNIT_CLOCK_GATE2,       s->clock_gate_dis2);
  }
  
@@@ -1193,19 -1199,7 +1195,7 @@@ int vlv_force_gfx_clock(struct drm_i915
        u32 val;
        int err;
  
-       val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
-       WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
  #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
-       /* Wait for a previous force-off to settle */
-       if (force_on) {
-               err = wait_for(!COND, 20);
-               if (err) {
-                       DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
-                                 I915_READ(VLV_GTLC_SURVIVABILITY_REG));
-                       return err;
-               }
-       }
  
        val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
        val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
@@@ -1646,9 -1640,11 +1636,9 @@@ static int __init i915_init(void
  
        if (!(driver.driver_features & DRIVER_MODESET)) {
                driver.get_vblank_timestamp = NULL;
 -#ifndef CONFIG_DRM_I915_UMS
                /* Silently fail loading to not upset userspace. */
                DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
                return 0;
 -#endif
        }
  
        /*
  
  static void __exit i915_exit(void)
  {
 -#ifndef CONFIG_DRM_I915_UMS
        if (!(driver.driver_features & DRIVER_MODESET))
                return; /* Never loaded a driver. */
 -#endif
  
        drm_pci_exit(&driver, &i915_pci_driver);
  }
index e326ac9730cf9c557a80d31dbf58706bca9e0b62,b4faa2df9d3d8151c4e7aff8853be20937414096..8ae6f7f06b3a089e6503d626d629e87eb63746bf
@@@ -31,7 -31,6 +31,7 @@@
  #define _I915_DRV_H_
  
  #include <uapi/drm/i915_drm.h>
 +#include <uapi/drm/drm_fourcc.h>
  
  #include "i915_reg.h"
  #include "intel_bios.h"
@@@ -56,7 -55,7 +56,7 @@@
  
  #define DRIVER_NAME           "i915"
  #define DRIVER_DESC           "Intel Graphics"
 -#define DRIVER_DATE           "20150130"
 +#define DRIVER_DATE           "20150327"
  
  #undef WARN_ON
  /* Many gcc seem to no see through this and fall over :( */
@@@ -70,9 -69,6 +70,9 @@@
  #define WARN_ON(x) WARN((x), "WARN_ON(" #x ")")
  #endif
  
 +#undef WARN_ON_ONCE
 +#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(" #x ")")
 +
  #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \
                             (long) (x), __func__);
  
@@@ -226,14 -222,9 +226,14 @@@ enum hpd_pin 
  
  #define for_each_pipe(__dev_priv, __p) \
        for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++)
 -#define for_each_plane(pipe, p) \
 -      for ((p) = 0; (p) < INTEL_INFO(dev)->num_sprites[(pipe)] + 1; (p)++)
 -#define for_each_sprite(p, s) for ((s) = 0; (s) < INTEL_INFO(dev)->num_sprites[(p)]; (s)++)
 +#define for_each_plane(__dev_priv, __pipe, __p)                               \
 +      for ((__p) = 0;                                                 \
 +           (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \
 +           (__p)++)
 +#define for_each_sprite(__dev_priv, __p, __s)                         \
 +      for ((__s) = 0;                                                 \
 +           (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)];        \
 +           (__s)++)
  
  #define for_each_crtc(dev, crtc) \
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                            &(dev)->mode_config.encoder_list,   \
                            base.head)
  
 +#define for_each_intel_connector(dev, intel_connector)                \
 +      list_for_each_entry(intel_connector,                    \
 +                          &dev->mode_config.connector_list,   \
 +                          base.head)
 +
 +
  #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
        list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
                if ((intel_encoder)->base.crtc == (__crtc))
@@@ -427,8 -412,6 +427,8 @@@ struct drm_i915_error_state 
        u32 forcewake;
        u32 error; /* gen6+ */
        u32 err_int; /* gen7 */
 +      u32 fault_data0; /* gen8, gen9 */
 +      u32 fault_data1; /* gen8, gen9 */
        u32 done_reg;
        u32 gac_eco;
        u32 gam_ecochk;
@@@ -546,7 -529,7 +546,7 @@@ struct drm_i915_display_funcs 
         * Returns true on success, false on failure.
         */
        bool (*find_dpll)(const struct intel_limit *limit,
 -                        struct intel_crtc *crtc,
 +                        struct intel_crtc_state *crtc_state,
                          int target, int refclk,
                          struct dpll *match_clock,
                          struct dpll *best_clock);
                                 struct drm_crtc *crtc,
                                 uint32_t sprite_width, uint32_t sprite_height,
                                 int pixel_size, bool enable, bool scaled);
 -      void (*modeset_global_resources)(struct drm_device *dev);
 +      void (*modeset_global_resources)(struct drm_atomic_state *state);
        /* Returns the active state of the crtc, and if the crtc is active,
         * fills out the pipe-config with the hw state. */
        bool (*get_pipe_config)(struct intel_crtc *,
@@@ -709,18 -692,7 +709,18 @@@ struct intel_device_info 
        int trans_offsets[I915_MAX_TRANSCODERS];
        int palette_offsets[I915_MAX_PIPES];
        int cursor_offsets[I915_MAX_PIPES];
 -      unsigned int eu_total;
 +
 +      /* Slice/subslice/EU info */
 +      u8 slice_total;
 +      u8 subslice_total;
 +      u8 subslice_per_slice;
 +      u8 eu_total;
 +      u8 eu_per_subslice;
 +      /* For each slice, which subslice(s) has(have) 7 EUs (bitfield)? */
 +      u8 subslice_7eu[3];
 +      u8 has_slice_pg:1;
 +      u8 has_subslice_pg:1;
 +      u8 has_eu_pg:1;
  };
  
  #undef DEFINE_FLAG
@@@ -799,20 -771,11 +799,20 @@@ struct intel_context 
        struct list_head link;
  };
  
 +enum fb_op_origin {
 +      ORIGIN_GTT,
 +      ORIGIN_CPU,
 +      ORIGIN_CS,
 +      ORIGIN_FLIP,
 +};
 +
  struct i915_fbc {
 -      unsigned long size;
 +      unsigned long uncompressed_size;
        unsigned threshold;
        unsigned int fb_id;
 -      enum plane plane;
 +      unsigned int possible_framebuffer_bits;
 +      unsigned int busy_bits;
 +      struct intel_crtc *crtc;
        int y;
  
        struct drm_mm_node compressed_fb;
         * possible. */
        bool enabled;
  
 -      /* On gen8 some rings cannont perform fbc clean operation so for now
 -       * we are doing this on SW with mmio.
 -       * This variable works in the opposite information direction
 -       * of ring->fbc_dirty telling software on frontbuffer tracking
 -       * to perform the cache clean on sw side.
 -       */
 -      bool need_sw_cache_clean;
 -
        struct intel_fbc_work {
                struct delayed_work work;
                struct drm_crtc *crtc;
@@@ -917,21 -888,150 +917,21 @@@ struct intel_gmbus 
  };
  
  struct i915_suspend_saved_registers {
 -      u8 saveLBB;
 -      u32 saveDSPACNTR;
 -      u32 saveDSPBCNTR;
        u32 saveDSPARB;
 -      u32 savePIPEACONF;
 -      u32 savePIPEBCONF;
 -      u32 savePIPEASRC;
 -      u32 savePIPEBSRC;
 -      u32 saveFPA0;
 -      u32 saveFPA1;
 -      u32 saveDPLL_A;
 -      u32 saveDPLL_A_MD;
 -      u32 saveHTOTAL_A;
 -      u32 saveHBLANK_A;
 -      u32 saveHSYNC_A;
 -      u32 saveVTOTAL_A;
 -      u32 saveVBLANK_A;
 -      u32 saveVSYNC_A;
 -      u32 saveBCLRPAT_A;
 -      u32 saveTRANSACONF;
 -      u32 saveTRANS_HTOTAL_A;
 -      u32 saveTRANS_HBLANK_A;
 -      u32 saveTRANS_HSYNC_A;
 -      u32 saveTRANS_VTOTAL_A;
 -      u32 saveTRANS_VBLANK_A;
 -      u32 saveTRANS_VSYNC_A;
 -      u32 savePIPEASTAT;
 -      u32 saveDSPASTRIDE;
 -      u32 saveDSPASIZE;
 -      u32 saveDSPAPOS;
 -      u32 saveDSPAADDR;
 -      u32 saveDSPASURF;
 -      u32 saveDSPATILEOFF;
 -      u32 savePFIT_PGM_RATIOS;
 -      u32 saveBLC_HIST_CTL;
 -      u32 saveBLC_PWM_CTL;
 -      u32 saveBLC_PWM_CTL2;
 -      u32 saveBLC_CPU_PWM_CTL;
 -      u32 saveBLC_CPU_PWM_CTL2;
 -      u32 saveFPB0;
 -      u32 saveFPB1;
 -      u32 saveDPLL_B;
 -      u32 saveDPLL_B_MD;
 -      u32 saveHTOTAL_B;
 -      u32 saveHBLANK_B;
 -      u32 saveHSYNC_B;
 -      u32 saveVTOTAL_B;
 -      u32 saveVBLANK_B;
 -      u32 saveVSYNC_B;
 -      u32 saveBCLRPAT_B;
 -      u32 saveTRANSBCONF;
 -      u32 saveTRANS_HTOTAL_B;
 -      u32 saveTRANS_HBLANK_B;
 -      u32 saveTRANS_HSYNC_B;
 -      u32 saveTRANS_VTOTAL_B;
 -      u32 saveTRANS_VBLANK_B;
 -      u32 saveTRANS_VSYNC_B;
 -      u32 savePIPEBSTAT;
 -      u32 saveDSPBSTRIDE;
 -      u32 saveDSPBSIZE;
 -      u32 saveDSPBPOS;
 -      u32 saveDSPBADDR;
 -      u32 saveDSPBSURF;
 -      u32 saveDSPBTILEOFF;
 -      u32 saveVGA0;
 -      u32 saveVGA1;
 -      u32 saveVGA_PD;
 -      u32 saveVGACNTRL;
 -      u32 saveADPA;
        u32 saveLVDS;
        u32 savePP_ON_DELAYS;
        u32 savePP_OFF_DELAYS;
 -      u32 saveDVOA;
 -      u32 saveDVOB;
 -      u32 saveDVOC;
        u32 savePP_ON;
        u32 savePP_OFF;
        u32 savePP_CONTROL;
        u32 savePP_DIVISOR;
 -      u32 savePFIT_CONTROL;
 -      u32 save_palette_a[256];
 -      u32 save_palette_b[256];
        u32 saveFBC_CONTROL;
 -      u32 saveIER;
 -      u32 saveIIR;
 -      u32 saveIMR;
 -      u32 saveDEIER;
 -      u32 saveDEIMR;
 -      u32 saveGTIER;
 -      u32 saveGTIMR;
 -      u32 saveFDI_RXA_IMR;
 -      u32 saveFDI_RXB_IMR;
        u32 saveCACHE_MODE_0;
        u32 saveMI_ARB_STATE;
        u32 saveSWF0[16];
        u32 saveSWF1[16];
        u32 saveSWF2[3];
 -      u8 saveMSR;
 -      u8 saveSR[8];
 -      u8 saveGR[25];
 -      u8 saveAR_INDEX;
 -      u8 saveAR[21];
 -      u8 saveDACMASK;
 -      u8 saveCR[37];
        uint64_t saveFENCE[I915_MAX_NUM_FENCES];
 -      u32 saveCURACNTR;
 -      u32 saveCURAPOS;
 -      u32 saveCURABASE;
 -      u32 saveCURBCNTR;
 -      u32 saveCURBPOS;
 -      u32 saveCURBBASE;
 -      u32 saveCURSIZE;
 -      u32 saveDP_B;
 -      u32 saveDP_C;
 -      u32 saveDP_D;
 -      u32 savePIPEA_GMCH_DATA_M;
 -      u32 savePIPEB_GMCH_DATA_M;
 -      u32 savePIPEA_GMCH_DATA_N;
 -      u32 savePIPEB_GMCH_DATA_N;
 -      u32 savePIPEA_DP_LINK_M;
 -      u32 savePIPEB_DP_LINK_M;
 -      u32 savePIPEA_DP_LINK_N;
 -      u32 savePIPEB_DP_LINK_N;
 -      u32 saveFDI_RXA_CTL;
 -      u32 saveFDI_TXA_CTL;
 -      u32 saveFDI_RXB_CTL;
 -      u32 saveFDI_TXB_CTL;
 -      u32 savePFA_CTL_1;
 -      u32 savePFB_CTL_1;
 -      u32 savePFA_WIN_SZ;
 -      u32 savePFB_WIN_SZ;
 -      u32 savePFA_WIN_POS;
 -      u32 savePFB_WIN_POS;
 -      u32 savePCH_DREF_CONTROL;
 -      u32 saveDISP_ARB_CTL;
 -      u32 savePIPEA_DATA_M1;
 -      u32 savePIPEA_DATA_N1;
 -      u32 savePIPEA_LINK_M1;
 -      u32 savePIPEA_LINK_N1;
 -      u32 savePIPEB_DATA_M1;
 -      u32 savePIPEB_DATA_N1;
 -      u32 savePIPEB_LINK_M1;
 -      u32 savePIPEB_LINK_N1;
 -      u32 saveMCHBAR_RENDER_STANDBY;
        u32 savePCH_PORT_HOTPLUG;
        u16 saveGCDGMBUS;
  };
@@@ -994,6 -1094,7 +994,7 @@@ struct vlv_s0ix_state 
        /* Display 2 CZ domain */
        u32 gu_ctl0;
        u32 gu_ctl1;
+       u32 pcbr;
        u32 clock_gate_dis2;
  };
  
@@@ -1027,12 -1128,13 +1028,12 @@@ struct intel_gen6_power_mgmt 
        u8 max_freq_softlimit;  /* Max frequency permitted by the driver */
        u8 max_freq;            /* Maximum frequency, RP0 if not overclocking */
        u8 min_freq;            /* AKA RPn. Minimum frequency */
 +      u8 idle_freq;           /* Frequency to request when we are idle */
        u8 efficient_freq;      /* AKA RPe. Pre-determined balanced frequency */
        u8 rp1_freq;            /* "less than" RP0 power/freqency */
        u8 rp0_freq;            /* Non-overclocked max frequency. */
        u32 cz_freq;
  
 -      u32 ei_interrupt_count;
 -
        int last_adj;
        enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
  
@@@ -1069,6 -1171,9 +1070,6 @@@ struct intel_ilk_power_mgmt 
  
        int c_m;
        int r_t;
 -
 -      struct drm_i915_gem_object *pwrctx;
 -      struct drm_i915_gem_object *renderctx;
  };
  
  struct drm_i915_private;
@@@ -1350,7 -1455,6 +1351,7 @@@ struct intel_vbt_data 
        bool edp_initialized;
        bool edp_support;
        int edp_bpp;
 +      bool edp_low_vswing;
        struct edp_power_seq edp_pps;
  
        struct {
@@@ -1411,25 -1515,6 +1412,25 @@@ struct ilk_wm_values 
        enum intel_ddb_partitioning partitioning;
  };
  
 +struct vlv_wm_values {
 +      struct {
 +              uint16_t primary;
 +              uint16_t sprite[2];
 +              uint8_t cursor;
 +      } pipe[3];
 +
 +      struct {
 +              uint16_t plane;
 +              uint8_t cursor;
 +      } sr;
 +
 +      struct {
 +              uint8_t cursor;
 +              uint8_t sprite[2];
 +              uint8_t primary;
 +      } ddl[3];
 +};
 +
  struct skl_ddb_entry {
        uint16_t start, end;    /* in number of blocks, 'end' is exclusive */
  };
@@@ -1556,10 -1641,6 +1557,10 @@@ struct i915_workarounds 
        u32 count;
  };
  
 +struct i915_virtual_gpu {
 +      bool active;
 +};
 +
  struct drm_i915_private {
        struct drm_device *dev;
        struct kmem_cache *slab;
  
        struct intel_uncore uncore;
  
 +      struct i915_virtual_gpu vgpu;
 +
        struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
  
  
                union {
                        struct ilk_wm_values hw;
                        struct skl_wm_values skl_hw;
 +                      struct vlv_wm_values vlv;
                };
        } wm;
  
@@@ -2064,7 -2142,7 +2065,7 @@@ struct drm_i915_gem_request 
        u32 tail;
  
        /**
 -       * Context related to this request
 +       * Context and ring buffer related to this request
         * Contexts are refcounted, so when this request is associated with a
         * context, we must increment the context's refcount, to guarantee that
         * it persists while any request is linked to it. Requests themselves
         * context.
         */
        struct intel_context *ctx;
 +      struct intel_ringbuffer *ringbuf;
  
        /** Batch buffer related to this request if any */
        struct drm_i915_gem_object *batch_obj;
        /** file_priv list entry for this request */
        struct list_head client_list;
  
 +      /** process identifier submitting this request */
 +      struct pid *pid;
 +
        uint32_t uniq;
  
        /**
@@@ -2278,7 -2352,6 +2279,7 @@@ struct drm_i915_cmd_table 
  })
  #define INTEL_INFO(p)         (&__I915__(p)->info)
  #define INTEL_DEVID(p)        (INTEL_INFO(p)->device_id)
 +#define INTEL_REVID(p)        (__I915__(p)->dev->pdev->revision)
  
  #define IS_I830(dev)          (INTEL_DEVID(dev) == 0x3577)
  #define IS_845G(dev)          (INTEL_DEVID(dev) == 0x2562)
  #define IS_IVB_GT1(dev)               (INTEL_DEVID(dev) == 0x0156 || \
                                 INTEL_DEVID(dev) == 0x0152 || \
                                 INTEL_DEVID(dev) == 0x015a)
 -#define IS_SNB_GT1(dev)               (INTEL_DEVID(dev) == 0x0102 || \
 -                               INTEL_DEVID(dev) == 0x0106 || \
 -                               INTEL_DEVID(dev) == 0x010A)
  #define IS_VALLEYVIEW(dev)    (INTEL_INFO(dev)->is_valleyview)
  #define IS_CHERRYVIEW(dev)    (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
  #define IS_HASWELL(dev)       (INTEL_INFO(dev)->is_haswell)
                                 INTEL_DEVID(dev) == 0x0A1E)
  #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
  
 +#define SKL_REVID_A0          (0x0)
 +#define SKL_REVID_B0          (0x1)
 +#define SKL_REVID_C0          (0x2)
 +#define SKL_REVID_D0          (0x3)
 +#define SKL_REVID_E0          (0x4)
 +
  /*
   * The genX designation typically refers to the render engine, so render
   * capability related checks should use IS_GEN, while display and other checks
  #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
  
  #define GT_FREQUENCY_MULTIPLIER 50
 +#define GEN9_FREQ_SCALER 3
  
  #include "i915_trace.h"
  
@@@ -2438,11 -2507,14 +2439,11 @@@ extern int i915_max_ioctl
  
  extern int i915_suspend_legacy(struct drm_device *dev, pm_message_t state);
  extern int i915_resume_legacy(struct drm_device *dev);
 -extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
 -extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
  
  /* i915_params.c */
  struct i915_params {
        int modeset;
        int panel_ignore_lid;
 -      unsigned int powersave;
        int semaphores;
        unsigned int lvds_downclock;
        int lvds_channel_mode;
        bool enable_hangcheck;
        bool fastboot;
        bool prefault_disable;
 +      bool load_detect_test;
        bool reset;
        bool disable_display;
        bool disable_vtd_wa;
        int use_mmio_flip;
 -      bool mmio_debug;
 +      int mmio_debug;
        bool verbose_state_checks;
        bool nuclear_pageflip;
  };
@@@ -2520,10 -2591,6 +2521,10 @@@ void intel_uncore_forcewake_get(struct 
  void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv,
                                enum forcewake_domains domains);
  void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
 +static inline bool intel_vgpu_active(struct drm_device *dev)
 +{
 +      return to_i915(dev)->vgpu.active;
 +}
  
  void
  i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
@@@ -2602,6 -2669,12 +2603,6 @@@ int i915_gem_get_aperture_ioctl(struct 
  int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
  void i915_gem_load(struct drm_device *dev);
 -unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
 -                            long target,
 -                            unsigned flags);
 -#define I915_SHRINK_PURGEABLE 0x1
 -#define I915_SHRINK_UNBOUND 0x2
 -#define I915_SHRINK_BOUND 0x4
  void *i915_gem_object_alloc(struct drm_device *dev);
  void i915_gem_object_free(struct drm_i915_gem_object *obj);
  void i915_gem_object_init(struct drm_i915_gem_object *obj,
@@@ -2618,16 -2691,20 +2619,16 @@@ void i915_gem_vma_destroy(struct i915_v
  #define PIN_GLOBAL 0x4
  #define PIN_OFFSET_BIAS 0x8
  #define PIN_OFFSET_MASK (~4095)
 -int __must_check i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
 -                                        struct i915_address_space *vm,
 -                                        uint32_t alignment,
 -                                        uint64_t flags,
 -                                        const struct i915_ggtt_view *view);
 -static inline
 -int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
 -                                   struct i915_address_space *vm,
 -                                   uint32_t alignment,
 -                                   uint64_t flags)
 -{
 -      return i915_gem_object_pin_view(obj, vm, alignment, flags,
 -                                              &i915_ggtt_view_normal);
 -}
 +int __must_check
 +i915_gem_object_pin(struct drm_i915_gem_object *obj,
 +                  struct i915_address_space *vm,
 +                  uint32_t alignment,
 +                  uint64_t flags);
 +int __must_check
 +i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
 +                       const struct i915_ggtt_view *view,
 +                       uint32_t alignment,
 +                       uint64_t flags);
  
  int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
                  u32 flags);
@@@ -2767,10 -2844,8 +2768,10 @@@ i915_gem_object_set_to_cpu_domain(struc
  int __must_check
  i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     u32 alignment,
 -                                   struct intel_engine_cs *pipelined);
 -void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj);
 +                                   struct intel_engine_cs *pipelined,
 +                                   const struct i915_ggtt_view *view);
 +void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
 +                                            const struct i915_ggtt_view *view);
  int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
                                int align);
  int i915_gem_open(struct drm_device *dev, struct drm_file *file);
@@@ -2793,46 -2868,60 +2794,46 @@@ struct dma_buf *i915_gem_prime_export(s
  
  void i915_gem_restore_fences(struct drm_device *dev);
  
 -unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
 -                                     struct i915_address_space *vm,
 -                                     enum i915_ggtt_view_type view);
 -static inline
 -unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
 -                                struct i915_address_space *vm)
 +unsigned long
 +i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
 +                            const struct i915_ggtt_view *view);
 +unsigned long
 +i915_gem_obj_offset(struct drm_i915_gem_object *o,
 +                  struct i915_address_space *vm);
 +static inline unsigned long
 +i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *o)
  {
 -      return i915_gem_obj_offset_view(o, vm, I915_GGTT_VIEW_NORMAL);
 +      return i915_gem_obj_ggtt_offset_view(o, &i915_ggtt_view_normal);
  }
 +
  bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o);
 -bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o,
 -                           struct i915_address_space *vm,
 -                           enum i915_ggtt_view_type view);
 -static inline
 +bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
 +                                const struct i915_ggtt_view *view);
  bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
 -                      struct i915_address_space *vm)
 -{
 -      return i915_gem_obj_bound_view(o, vm, I915_GGTT_VIEW_NORMAL);
 -}
 +                      struct i915_address_space *vm);
  
  unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
                                struct i915_address_space *vm);
 -struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
 -                                        struct i915_address_space *vm,
 -                                        const struct i915_ggtt_view *view);
 -static inline
 -struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
 -                                   struct i915_address_space *vm)
 -{
 -      return i915_gem_obj_to_vma_view(obj, vm, &i915_ggtt_view_normal);
 -}
 -
  struct i915_vma *
 -i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj,
 -                                     struct i915_address_space *vm,
 -                                     const struct i915_ggtt_view *view);
 +i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
 +                  struct i915_address_space *vm);
 +struct i915_vma *
 +i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
 +                        const struct i915_ggtt_view *view);
  
 -static inline
  struct i915_vma *
  i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
 -                                struct i915_address_space *vm)
 -{
 -      return i915_gem_obj_lookup_or_create_vma_view(obj, vm,
 -                                              &i915_ggtt_view_normal);
 -}
 +                                struct i915_address_space *vm);
 +struct i915_vma *
 +i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
 +                                     const struct i915_ggtt_view *view);
  
 -struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
 -static inline bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) {
 -      struct i915_vma *vma;
 -      list_for_each_entry(vma, &obj->vma_list, vma_link)
 -              if (vma->pin_count > 0)
 -                      return true;
 -      return false;
 +static inline struct i915_vma *
 +i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
 +{
 +      return i915_gem_obj_to_ggtt_view(obj, &i915_ggtt_view_normal);
  }
 +bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj);
  
  /* Some GGTT VM helpers */
  #define i915_obj_to_ggtt(obj) \
@@@ -2855,7 -2944,13 +2856,7 @@@ i915_vm_to_ppgtt(struct i915_address_sp
  
  static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj)
  {
 -      return i915_gem_obj_bound(obj, i915_obj_to_ggtt(obj));
 -}
 -
 -static inline unsigned long
 -i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *obj)
 -{
 -      return i915_gem_obj_offset(obj, i915_obj_to_ggtt(obj));
 +      return i915_gem_obj_ggtt_bound_view(obj, &i915_ggtt_view_normal);
  }
  
  static inline unsigned long
@@@ -2879,13 -2974,7 +2880,13 @@@ i915_gem_object_ggtt_unbind(struct drm_
        return i915_vma_unbind(i915_gem_obj_to_ggtt(obj));
  }
  
 -void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
 +void i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
 +                                   const struct i915_ggtt_view *view);
 +static inline void
 +i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj)
 +{
 +      i915_gem_object_ggtt_unpin_view(obj, &i915_ggtt_view_normal);
 +}
  
  /* i915_gem_context.c */
  int __must_check i915_gem_context_init(struct drm_device *dev);
@@@ -2957,17 -3046,6 +2958,17 @@@ i915_gem_object_create_stolen_for_preal
                                               u32 gtt_offset,
                                               u32 size);
  
 +/* i915_gem_shrinker.c */
 +unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
 +                            long target,
 +                            unsigned flags);
 +#define I915_SHRINK_PURGEABLE 0x1
 +#define I915_SHRINK_UNBOUND 0x2
 +#define I915_SHRINK_BOUND 0x4
 +unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
 +void i915_gem_shrinker_init(struct drm_i915_private *dev_priv);
 +
 +
  /* i915_gem_tiling.c */
  static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
  {
@@@ -3043,6 -3121,10 +3044,6 @@@ int i915_parse_cmds(struct intel_engine
  extern int i915_save_state(struct drm_device *dev);
  extern int i915_restore_state(struct drm_device *dev);
  
 -/* i915_ums.c */
 -void i915_save_display_reg(struct drm_device *dev);
 -void i915_restore_display_reg(struct drm_device *dev);
 -
  /* i915_sysfs.c */
  void i915_setup_sysfs(struct drm_device *dev_priv);
  void i915_teardown_sysfs(struct drm_device *dev_priv);
@@@ -3114,7 -3196,8 +3115,7 @@@ extern void i915_redisable_vga(struct d
  extern void i915_redisable_vga_power_on(struct drm_device *dev);
  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
  extern void intel_init_pch_refclk(struct drm_device *dev);
 -extern void gen6_set_rps(struct drm_device *dev, u8 val);
 -extern void valleyview_set_rps(struct drm_device *dev, u8 val);
 +extern void intel_set_rps(struct drm_device *dev, u8 val);
  extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
                                  bool enable);
  extern void intel_detect_pch(struct drm_device *dev);
@@@ -3127,6 -3210,8 +3128,6 @@@ int i915_reg_read_ioctl(struct drm_devi
  int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file);
  
 -void intel_notify_mmio_flip(struct intel_engine_cs *ring);
 -
  /* overlay */
  extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
  extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
index b3070a4501ab59e3009758cb9ab624af8343a258,d776621c8521aafbb566666ff09b2bc2e0d9389f..5fda6c70b42391ecfb81dd67e6170caf27854b54
@@@ -12,7 -12,6 +12,6 @@@
  
  #undef TRACE_SYSTEM
  #define TRACE_SYSTEM i915
- #define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
  #define TRACE_INCLUDE_FILE i915_trace
  
  /* pipe updates */
@@@ -115,7 -114,7 +114,7 @@@ TRACE_EVENT(i915_vma_bind
            TP_STRUCT__entry(
                             __field(struct drm_i915_gem_object *, obj)
                             __field(struct i915_address_space *, vm)
 -                           __field(u32, offset)
 +                           __field(u64, offset)
                             __field(u32, size)
                             __field(unsigned, flags)
                             ),
                           __entry->flags = flags;
                           ),
  
 -          TP_printk("obj=%p, offset=%08x size=%x%s vm=%p",
 +          TP_printk("obj=%p, offset=%016llx size=%x%s vm=%p",
                      __entry->obj, __entry->offset, __entry->size,
                      __entry->flags & PIN_MAPPABLE ? ", mappable" : "",
                      __entry->vm)
@@@ -141,7 -140,7 +140,7 @@@ TRACE_EVENT(i915_vma_unbind
            TP_STRUCT__entry(
                             __field(struct drm_i915_gem_object *, obj)
                             __field(struct i915_address_space *, vm)
 -                           __field(u32, offset)
 +                           __field(u64, offset)
                             __field(u32, size)
                             ),
  
                           __entry->size = vma->node.size;
                           ),
  
 -          TP_printk("obj=%p, offset=%08x size=%x vm=%p",
 +          TP_printk("obj=%p, offset=%016llx size=%x vm=%p",
                      __entry->obj, __entry->offset, __entry->size, __entry->vm)
  );
  
 +#define VM_TO_TRACE_NAME(vm) \
 +      (i915_is_ggtt(vm) ? "G" : \
 +                    "P")
 +
 +DECLARE_EVENT_CLASS(i915_va,
 +      TP_PROTO(struct i915_address_space *vm, u64 start, u64 length, const char *name),
 +      TP_ARGS(vm, start, length, name),
 +
 +      TP_STRUCT__entry(
 +              __field(struct i915_address_space *, vm)
 +              __field(u64, start)
 +              __field(u64, end)
 +              __string(name, name)
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->vm = vm;
 +              __entry->start = start;
 +              __entry->end = start + length - 1;
 +              __assign_str(name, name);
 +      ),
 +
 +      TP_printk("vm=%p (%s), 0x%llx-0x%llx",
 +                __entry->vm, __get_str(name),  __entry->start, __entry->end)
 +);
 +
 +DEFINE_EVENT(i915_va, i915_va_alloc,
 +           TP_PROTO(struct i915_address_space *vm, u64 start, u64 length, const char *name),
 +           TP_ARGS(vm, start, length, name)
 +);
 +
 +DECLARE_EVENT_CLASS(i915_page_table_entry,
 +      TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift),
 +      TP_ARGS(vm, pde, start, pde_shift),
 +
 +      TP_STRUCT__entry(
 +              __field(struct i915_address_space *, vm)
 +              __field(u32, pde)
 +              __field(u64, start)
 +              __field(u64, end)
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->vm = vm;
 +              __entry->pde = pde;
 +              __entry->start = start;
 +              __entry->end = ((start + (1ULL << pde_shift)) & ~((1ULL << pde_shift)-1)) - 1;
 +      ),
 +
 +      TP_printk("vm=%p, pde=%d (0x%llx-0x%llx)",
 +                __entry->vm, __entry->pde, __entry->start, __entry->end)
 +);
 +
 +DEFINE_EVENT(i915_page_table_entry, i915_page_table_entry_alloc,
 +           TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift),
 +           TP_ARGS(vm, pde, start, pde_shift)
 +);
 +
 +/* Avoid extra math because we only support two sizes. The format is defined by
 + * bitmap_scnprintf. Each 32 bits is 8 HEX digits followed by comma */
 +#define TRACE_PT_SIZE(bits) \
 +      ((((bits) == 1024) ? 288 : 144) + 1)
 +
 +DECLARE_EVENT_CLASS(i915_page_table_entry_update,
 +      TP_PROTO(struct i915_address_space *vm, u32 pde,
 +               struct i915_page_table_entry *pt, u32 first, u32 count, u32 bits),
 +      TP_ARGS(vm, pde, pt, first, count, bits),
 +
 +      TP_STRUCT__entry(
 +              __field(struct i915_address_space *, vm)
 +              __field(u32, pde)
 +              __field(u32, first)
 +              __field(u32, last)
 +              __dynamic_array(char, cur_ptes, TRACE_PT_SIZE(bits))
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->vm = vm;
 +              __entry->pde = pde;
 +              __entry->first = first;
 +              __entry->last = first + count - 1;
 +              scnprintf(__get_str(cur_ptes),
 +                        TRACE_PT_SIZE(bits),
 +                        "%*pb",
 +                        bits,
 +                        pt->used_ptes);
 +      ),
 +
 +      TP_printk("vm=%p, pde=%d, updating %u:%u\t%s",
 +                __entry->vm, __entry->pde, __entry->last, __entry->first,
 +                __get_str(cur_ptes))
 +);
 +
 +DEFINE_EVENT(i915_page_table_entry_update, i915_page_table_entry_map,
 +      TP_PROTO(struct i915_address_space *vm, u32 pde,
 +               struct i915_page_table_entry *pt, u32 first, u32 count, u32 bits),
 +      TP_ARGS(vm, pde, pt, first, count, bits)
 +);
 +
  TRACE_EVENT(i915_gem_object_change_domain,
            TP_PROTO(struct drm_i915_gem_object *obj, u32 old_read, u32 old_write),
            TP_ARGS(obj, old_read, old_write),
index 744db4d0c68fb39cf9448edbabb85acfb6a6c76b,ba243db3584008ae9d7c4b39e0bbaa1bbab96583..897f17db08af4deaae8d5582495ce1d23b318534
  #include <drm/drm_fb_helper.h>
  #include <drm/drm_dp_mst_helper.h>
  #include <drm/drm_rect.h>
 +#include <drm/drm_atomic.h>
  
- #define DIV_ROUND_CLOSEST_ULL(ll, d)  \
- ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
  /**
   * _wait_for - magic (register) wait macro
   *
@@@ -57,8 -53,8 +54,8 @@@
                                ret__ = -ETIMEDOUT;                     \
                        break;                                          \
                }                                                       \
 -              if (W && drm_can_sleep())  {                            \
 -                      msleep(W);                                      \
 +              if ((W) && drm_can_sleep()) {                           \
 +                      usleep_range((W)*1000, (W)*2000);               \
                } else {                                                \
                        cpu_relax();                                    \
                }                                                       \
@@@ -259,7 -255,6 +256,7 @@@ struct intel_plane_state 
  };
  
  struct intel_initial_plane_config {
 +      struct intel_framebuffer *fb;
        unsigned int tiling;
        int size;
        u32 base;
@@@ -465,6 -460,7 +462,6 @@@ struct intel_crtc 
  
        struct drm_i915_gem_object *cursor_bo;
        uint32_t cursor_addr;
 -      int16_t cursor_width, cursor_height;
        uint32_t cursor_cntl;
        uint32_t cursor_size;
        uint32_t cursor_base;
@@@ -501,20 -497,16 +498,20 @@@ struct intel_plane_wm_parameters 
        uint8_t bytes_per_pixel;
        bool enabled;
        bool scaled;
 +      u64 tiling;
 +      unsigned int rotation;
  };
  
  struct intel_plane {
        struct drm_plane base;
        int plane;
        enum pipe pipe;
 -      struct drm_i915_gem_object *obj;
        bool can_scale;
        int max_downscale;
  
 +      /* FIXME convert to properties */
 +      struct drm_intel_sprite_colorkey ckey;
 +
        /* Since we need to change the watermarks before/after
         * enabling/disabling the planes, we need to store the parameters here
         * as the other pieces of the struct may not reflect the values we want
        void (*update_plane)(struct drm_plane *plane,
                             struct drm_crtc *crtc,
                             struct drm_framebuffer *fb,
 -                           struct drm_i915_gem_object *obj,
                             int crtc_x, int crtc_y,
                             unsigned int crtc_w, unsigned int crtc_h,
                             uint32_t x, uint32_t y,
                           struct intel_plane_state *state);
        void (*commit_plane)(struct drm_plane *plane,
                             struct intel_plane_state *state);
 -      int (*update_colorkey)(struct drm_plane *plane,
 -                             struct drm_intel_sprite_colorkey *key);
 -      void (*get_colorkey)(struct drm_plane *plane,
 -                           struct drm_intel_sprite_colorkey *key);
  };
  
  struct intel_watermark_params {
@@@ -563,7 -560,6 +560,7 @@@ struct cxsr_latency 
  };
  
  #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 +#define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, base)
  #define to_intel_connector(x) container_of(x, struct intel_connector, base)
  #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
  #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
@@@ -593,26 -589,6 +590,26 @@@ struct intel_hdmi 
  struct intel_dp_mst_encoder;
  #define DP_MAX_DOWNSTREAM_PORTS               0x10
  
 +/*
 + * enum link_m_n_set:
 + *    When platform provides two set of M_N registers for dp, we can
 + *    program them and switch between them incase of DRRS.
 + *    But When only one such register is provided, we have to program the
 + *    required divider value on that registers itself based on the DRRS state.
 + *
 + * M1_N1      : Program dp_m_n on M1_N1 registers
 + *                      dp_m2_n2 on M2_N2 registers (If supported)
 + *
 + * M2_N2      : Program dp_m2_n2 on M1_N1 registers
 + *                      M2_N2 registers are not supported
 + */
 +
 +enum link_m_n_set {
 +      /* Sets the m1_n1 and m2_n2 */
 +      M1_N1 = 0,
 +      M2_N2
 +};
 +
  struct intel_dp {
        uint32_t output_reg;
        uint32_t aux_ch_ctl_reg;
        uint32_t color_range;
        bool color_range_auto;
        uint8_t link_bw;
 +      uint8_t rate_select;
        uint8_t lane_count;
        uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
        uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
        uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 +      /* sink rates as reported by DP_SUPPORTED_LINK_RATES */
 +      uint8_t num_sink_rates;
 +      int sink_rates[DP_MAX_SUPPORTED_RATES];
        struct drm_dp_aux aux;
        uint8_t train_set[4];
        int panel_power_up_delay;
@@@ -735,7 -707,7 +732,7 @@@ intel_get_crtc_for_plane(struct drm_dev
  struct intel_unpin_work {
        struct work_struct work;
        struct drm_crtc *crtc;
 -      struct drm_i915_gem_object *old_fb_obj;
 +      struct drm_framebuffer *old_fb;
        struct drm_i915_gem_object *pending_flip_obj;
        struct drm_pending_vblank_event *event;
        atomic_t pending;
@@@ -842,8 -814,7 +839,8 @@@ static inline bool intel_irqs_enabled(s
  }
  
  int intel_get_crtc_scanline(struct intel_crtc *crtc);
 -void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);
 +void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
 +                                   unsigned int pipe_mask);
  
  /* intel_crt.c */
  void intel_crt_init(struct drm_device *dev);
@@@ -878,8 -849,7 +875,8 @@@ void intel_ddi_set_vc_payload_alloc(str
  
  /* intel_frontbuffer.c */
  void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
 -                           struct intel_engine_cs *ring);
 +                           struct intel_engine_cs *ring,
 +                           enum fb_op_origin origin);
  void intel_frontbuffer_flip_prepare(struct drm_device *dev,
                                    unsigned frontbuffer_bits);
  void intel_frontbuffer_flip_complete(struct drm_device *dev,
@@@ -904,14 -874,10 +901,14 @@@ void intel_frontbuffer_flip(struct drm_
        intel_frontbuffer_flush(dev, frontbuffer_bits);
  }
  
 -int intel_fb_align_height(struct drm_device *dev, int height,
 -                        unsigned int tiling);
 +unsigned int intel_fb_align_height(struct drm_device *dev,
 +                                 unsigned int height,
 +                                 uint32_t pixel_format,
 +                                 uint64_t fb_format_modifier);
  void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
  
 +u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
 +                            uint32_t pixel_format);
  
  /* intel_audio.c */
  void intel_init_audio(struct drm_device *dev);
@@@ -930,8 -896,6 +927,8 @@@ void intel_crtc_restore_mode(struct drm
  void intel_crtc_control(struct drm_crtc *crtc, bool enable);
  void intel_crtc_update_dpms(struct drm_crtc *crtc);
  void intel_encoder_destroy(struct drm_encoder *encoder);
 +int intel_connector_init(struct intel_connector *);
 +struct intel_connector *intel_connector_alloc(void);
  void intel_connector_dpms(struct drm_connector *, int mode);
  bool intel_connector_get_hw_state(struct intel_connector *connector);
  void intel_modeset_check_state(struct drm_device *dev);
@@@ -961,12 -925,11 +958,12 @@@ bool intel_get_load_detect_pipe(struct 
                                struct intel_load_detect_pipe *old,
                                struct drm_modeset_acquire_ctx *ctx);
  void intel_release_load_detect_pipe(struct drm_connector *connector,
 -                                  struct intel_load_detect_pipe *old);
 +                                  struct intel_load_detect_pipe *old,
 +                                  struct drm_modeset_acquire_ctx *ctx);
  int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                               struct drm_framebuffer *fb,
 +                             const struct drm_plane_state *plane_state,
                               struct intel_engine_cs *pipelined);
 -void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
  struct drm_framebuffer *
  __intel_framebuffer_create(struct drm_device *dev,
                           struct drm_mode_fb_cmd2 *mode_cmd,
@@@ -976,11 -939,9 +973,11 @@@ void intel_finish_page_flip(struct drm_
  void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
  void intel_check_page_flip(struct drm_device *dev, int pipe);
  int intel_prepare_plane_fb(struct drm_plane *plane,
 -                         struct drm_framebuffer *fb);
 +                         struct drm_framebuffer *fb,
 +                         const struct drm_plane_state *new_state);
  void intel_cleanup_plane_fb(struct drm_plane *plane,
 -                          struct drm_framebuffer *fb);
 +                          struct drm_framebuffer *fb,
 +                          const struct drm_plane_state *old_state);
  int intel_plane_atomic_get_property(struct drm_plane *plane,
                                    const struct drm_plane_state *state,
                                    struct drm_property *property,
@@@ -990,19 -951,6 +987,19 @@@ int intel_plane_atomic_set_property(str
                                    struct drm_property *property,
                                    uint64_t val);
  
 +unsigned int
 +intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
 +                uint64_t fb_format_modifier);
 +
 +static inline bool
 +intel_rotation_90_or_270(unsigned int rotation)
 +{
 +      return rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270));
 +}
 +
 +bool intel_wm_need_update(struct drm_plane *plane,
 +                        struct drm_plane_state *state);
 +
  /* shared dpll functions */
  struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
  void assert_shared_dpll(struct drm_i915_private *dev_priv,
@@@ -1042,7 -990,7 +1039,7 @@@ void hsw_enable_pc8(struct drm_i915_pri
  void hsw_disable_pc8(struct drm_i915_private *dev_priv);
  void intel_dp_get_m_n(struct intel_crtc *crtc,
                      struct intel_crtc_state *pipe_config);
 -void intel_dp_set_m_n(struct intel_crtc *crtc);
 +void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
  int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
  void
  ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
@@@ -1057,9 -1005,6 +1054,9 @@@ void intel_mode_from_pipe_config(struc
  void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
  void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
  
 +unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 +                                   struct drm_i915_gem_object *obj);
 +
  /* intel_dp.c */
  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
  bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
@@@ -1069,6 -1014,7 +1066,6 @@@ void intel_dp_complete_link_train(struc
  void intel_dp_stop_link_train(struct intel_dp *intel_dp);
  void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
  void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 -void intel_dp_check_link_status(struct intel_dp *intel_dp);
  int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc);
  bool intel_dp_compute_config(struct intel_encoder *encoder,
                             struct intel_crtc_state *pipe_config);
@@@ -1083,11 -1029,17 +1080,11 @@@ void intel_edp_panel_off(struct intel_d
  void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector);
  void intel_dp_mst_suspend(struct drm_device *dev);
  void intel_dp_mst_resume(struct drm_device *dev);
 -int intel_dp_max_link_bw(struct intel_dp *intel_dp);
 +int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 +int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
  void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
  void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
  uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
 -void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes);
 -int intel_update_plane(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);
 -int intel_disable_plane(struct drm_plane *plane);
  void intel_plane_destroy(struct drm_plane *plane);
  void intel_edp_drrs_enable(struct intel_dp *intel_dp);
  void intel_edp_drrs_disable(struct intel_dp *intel_dp);
@@@ -1142,11 -1094,7 +1139,11 @@@ bool intel_fbc_enabled(struct drm_devic
  void intel_fbc_update(struct drm_device *dev);
  void intel_fbc_init(struct drm_i915_private *dev_priv);
  void intel_fbc_disable(struct drm_device *dev);
 -void bdw_fbc_sw_flush(struct drm_device *dev, u32 value);
 +void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 +                        unsigned int frontbuffer_bits,
 +                        enum fb_op_origin origin);
 +void intel_fbc_flush(struct drm_i915_private *dev_priv,
 +                   unsigned int frontbuffer_bits);
  
  /* intel_hdmi.c */
  void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port);
@@@ -1262,9 -1210,8 +1259,9 @@@ void intel_enable_gt_powersave(struct d
  void intel_disable_gt_powersave(struct drm_device *dev);
  void intel_suspend_gt_powersave(struct drm_device *dev);
  void intel_reset_gt_powersave(struct drm_device *dev);
 -void ironlake_teardown_rc6(struct drm_device *dev);
  void gen6_update_ring_freq(struct drm_device *dev);
 +void gen6_rps_busy(struct drm_i915_private *dev_priv);
 +void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
  void gen6_rps_idle(struct drm_i915_private *dev_priv);
  void gen6_rps_boost(struct drm_i915_private *dev_priv);
  void ilk_wm_get_hw_state(struct drm_device *dev);
@@@ -1281,9 -1228,14 +1278,9 @@@ bool intel_sdvo_init(struct drm_device 
  int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
  void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
                               enum plane plane);
 -int intel_plane_set_property(struct drm_plane *plane,
 -                           struct drm_property *prop,
 -                           uint64_t val);
  int intel_plane_restore(struct drm_plane *plane);
  int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
                              struct drm_file *file_priv);
 -int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 -                            struct drm_file *file_priv);
  bool intel_pipe_update_start(struct intel_crtc *crtc,
                             uint32_t *start_vbl_count);
  void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
@@@ -1306,17 -1258,6 +1303,17 @@@ int intel_connector_atomic_get_property
  struct drm_crtc_state *intel_crtc_duplicate_state(struct drm_crtc *crtc);
  void intel_crtc_destroy_state(struct drm_crtc *crtc,
                               struct drm_crtc_state *state);
 +static inline struct intel_crtc_state *
 +intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 +                          struct intel_crtc *crtc)
 +{
 +      struct drm_crtc_state *crtc_state;
 +      crtc_state = drm_atomic_get_crtc_state(state, &crtc->base);
 +      if (IS_ERR(crtc_state))
 +              return ERR_PTR(PTR_ERR(crtc_state));
 +
 +      return to_intel_crtc_state(crtc_state);
 +}
  
  /* intel_atomic_plane.c */
  struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane);
index fdc54e3eff552a1faa68acca1a8d6cc1a6b864b7,0000000000000000000000000000000000000000..956b22492c9a8f81db4ad38abc1a4edbb477bd38
mode 100644,000000..100644
--- /dev/null
@@@ -1,1993 -1,0 +1,1993 @@@
-                       regulator_set_optimum_mode(s[i].consumer,
-                                               regs[i].disable_load);
 +/*
 + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 and
 + * only version 2 as published by the Free Software Foundation.
 + *
 + * 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/clk.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/gpio.h>
 +#include <linux/interrupt.h>
 +#include <linux/of_device.h>
 +#include <linux/of_gpio.h>
 +#include <linux/of_irq.h>
 +#include <linux/regulator/consumer.h>
 +#include <linux/spinlock.h>
 +#include <video/mipi_display.h>
 +
 +#include "dsi.h"
 +#include "dsi.xml.h"
 +
 +#define MSM_DSI_VER_MAJOR_V2  0x02
 +#define MSM_DSI_VER_MAJOR_6G  0x03
 +#define MSM_DSI_6G_VER_MINOR_V1_0     0x10000000
 +#define MSM_DSI_6G_VER_MINOR_V1_1     0x10010000
 +#define MSM_DSI_6G_VER_MINOR_V1_1_1   0x10010001
 +#define MSM_DSI_6G_VER_MINOR_V1_2     0x10020000
 +#define MSM_DSI_6G_VER_MINOR_V1_3_1   0x10030001
 +
 +#define DSI_6G_REG_SHIFT      4
 +
 +#define DSI_REGULATOR_MAX     8
 +struct dsi_reg_entry {
 +      char name[32];
 +      int min_voltage;
 +      int max_voltage;
 +      int enable_load;
 +      int disable_load;
 +};
 +
 +struct dsi_reg_config {
 +      int num;
 +      struct dsi_reg_entry regs[DSI_REGULATOR_MAX];
 +};
 +
 +struct dsi_config {
 +      u32 major;
 +      u32 minor;
 +      u32 io_offset;
 +      enum msm_dsi_phy_type phy_type;
 +      struct dsi_reg_config reg_cfg;
 +};
 +
 +static const struct dsi_config dsi_cfgs[] = {
 +      {MSM_DSI_VER_MAJOR_V2, 0, 0, MSM_DSI_PHY_UNKNOWN},
 +      { /* 8974 v1 */
 +              .major = MSM_DSI_VER_MAJOR_6G,
 +              .minor = MSM_DSI_6G_VER_MINOR_V1_0,
 +              .io_offset = DSI_6G_REG_SHIFT,
 +              .phy_type = MSM_DSI_PHY_28NM,
 +              .reg_cfg = {
 +                      .num = 4,
 +                      .regs = {
 +                              {"gdsc", -1, -1, -1, -1},
 +                              {"vdd", 3000000, 3000000, 150000, 100},
 +                              {"vdda", 1200000, 1200000, 100000, 100},
 +                              {"vddio", 1800000, 1800000, 100000, 100},
 +                      },
 +              },
 +      },
 +      { /* 8974 v2 */
 +              .major = MSM_DSI_VER_MAJOR_6G,
 +              .minor = MSM_DSI_6G_VER_MINOR_V1_1,
 +              .io_offset = DSI_6G_REG_SHIFT,
 +              .phy_type = MSM_DSI_PHY_28NM,
 +              .reg_cfg = {
 +                      .num = 4,
 +                      .regs = {
 +                              {"gdsc", -1, -1, -1, -1},
 +                              {"vdd", 3000000, 3000000, 150000, 100},
 +                              {"vdda", 1200000, 1200000, 100000, 100},
 +                              {"vddio", 1800000, 1800000, 100000, 100},
 +                      },
 +              },
 +      },
 +      { /* 8974 v3 */
 +              .major = MSM_DSI_VER_MAJOR_6G,
 +              .minor = MSM_DSI_6G_VER_MINOR_V1_1_1,
 +              .io_offset = DSI_6G_REG_SHIFT,
 +              .phy_type = MSM_DSI_PHY_28NM,
 +              .reg_cfg = {
 +                      .num = 4,
 +                      .regs = {
 +                              {"gdsc", -1, -1, -1, -1},
 +                              {"vdd", 3000000, 3000000, 150000, 100},
 +                              {"vdda", 1200000, 1200000, 100000, 100},
 +                              {"vddio", 1800000, 1800000, 100000, 100},
 +                      },
 +              },
 +      },
 +      { /* 8084 */
 +              .major = MSM_DSI_VER_MAJOR_6G,
 +              .minor = MSM_DSI_6G_VER_MINOR_V1_2,
 +              .io_offset = DSI_6G_REG_SHIFT,
 +              .phy_type = MSM_DSI_PHY_28NM,
 +              .reg_cfg = {
 +                      .num = 4,
 +                      .regs = {
 +                              {"gdsc", -1, -1, -1, -1},
 +                              {"vdd", 3000000, 3000000, 150000, 100},
 +                              {"vdda", 1200000, 1200000, 100000, 100},
 +                              {"vddio", 1800000, 1800000, 100000, 100},
 +                      },
 +              },
 +      },
 +      { /* 8916 */
 +              .major = MSM_DSI_VER_MAJOR_6G,
 +              .minor = MSM_DSI_6G_VER_MINOR_V1_3_1,
 +              .io_offset = DSI_6G_REG_SHIFT,
 +              .phy_type = MSM_DSI_PHY_28NM,
 +              .reg_cfg = {
 +                      .num = 4,
 +                      .regs = {
 +                              {"gdsc", -1, -1, -1, -1},
 +                              {"vdd", 2850000, 2850000, 100000, 100},
 +                              {"vdda", 1200000, 1200000, 100000, 100},
 +                              {"vddio", 1800000, 1800000, 100000, 100},
 +                      },
 +              },
 +      },
 +};
 +
 +static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 +{
 +      u32 ver;
 +      u32 ver_6g;
 +
 +      if (!major || !minor)
 +              return -EINVAL;
 +
 +      /* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
 +       * makes all other registers 4-byte shifted down.
 +       */
 +      ver_6g = msm_readl(base + REG_DSI_6G_HW_VERSION);
 +      if (ver_6g == 0) {
 +              ver = msm_readl(base + REG_DSI_VERSION);
 +              ver = FIELD(ver, DSI_VERSION_MAJOR);
 +              if (ver <= MSM_DSI_VER_MAJOR_V2) {
 +                      /* old versions */
 +                      *major = ver;
 +                      *minor = 0;
 +                      return 0;
 +              } else {
 +                      return -EINVAL;
 +              }
 +      } else {
 +              ver = msm_readl(base + DSI_6G_REG_SHIFT + REG_DSI_VERSION);
 +              ver = FIELD(ver, DSI_VERSION_MAJOR);
 +              if (ver == MSM_DSI_VER_MAJOR_6G) {
 +                      /* 6G version */
 +                      *major = ver;
 +                      *minor = ver_6g;
 +                      return 0;
 +              } else {
 +                      return -EINVAL;
 +              }
 +      }
 +}
 +
 +#define DSI_ERR_STATE_ACK                     0x0000
 +#define DSI_ERR_STATE_TIMEOUT                 0x0001
 +#define DSI_ERR_STATE_DLN0_PHY                        0x0002
 +#define DSI_ERR_STATE_FIFO                    0x0004
 +#define DSI_ERR_STATE_MDP_FIFO_UNDERFLOW      0x0008
 +#define DSI_ERR_STATE_INTERLEAVE_OP_CONTENTION        0x0010
 +#define DSI_ERR_STATE_PLL_UNLOCKED            0x0020
 +
 +#define DSI_CLK_CTRL_ENABLE_CLKS      \
 +              (DSI_CLK_CTRL_AHBS_HCLK_ON | DSI_CLK_CTRL_AHBM_SCLK_ON | \
 +              DSI_CLK_CTRL_PCLK_ON | DSI_CLK_CTRL_DSICLK_ON | \
 +              DSI_CLK_CTRL_BYTECLK_ON | DSI_CLK_CTRL_ESCCLK_ON | \
 +              DSI_CLK_CTRL_FORCE_ON_DYN_AHBM_HCLK)
 +
 +struct msm_dsi_host {
 +      struct mipi_dsi_host base;
 +
 +      struct platform_device *pdev;
 +      struct drm_device *dev;
 +
 +      int id;
 +
 +      void __iomem *ctrl_base;
 +      struct regulator_bulk_data supplies[DSI_REGULATOR_MAX];
 +      struct clk *mdp_core_clk;
 +      struct clk *ahb_clk;
 +      struct clk *axi_clk;
 +      struct clk *mmss_misc_ahb_clk;
 +      struct clk *byte_clk;
 +      struct clk *esc_clk;
 +      struct clk *pixel_clk;
 +      u32 byte_clk_rate;
 +
 +      struct gpio_desc *disp_en_gpio;
 +      struct gpio_desc *te_gpio;
 +
 +      const struct dsi_config *cfg;
 +
 +      struct completion dma_comp;
 +      struct completion video_comp;
 +      struct mutex dev_mutex;
 +      struct mutex cmd_mutex;
 +      struct mutex clk_mutex;
 +      spinlock_t intr_lock; /* Protect interrupt ctrl register */
 +
 +      u32 err_work_state;
 +      struct work_struct err_work;
 +      struct workqueue_struct *workqueue;
 +
 +      struct drm_gem_object *tx_gem_obj;
 +      u8 *rx_buf;
 +
 +      struct drm_display_mode *mode;
 +
 +      /* Panel info */
 +      struct device_node *panel_node;
 +      unsigned int channel;
 +      unsigned int lanes;
 +      enum mipi_dsi_pixel_format format;
 +      unsigned long mode_flags;
 +
 +      u32 dma_cmd_ctrl_restore;
 +
 +      bool registered;
 +      bool power_on;
 +      int irq;
 +};
 +
 +static u32 dsi_get_bpp(const enum mipi_dsi_pixel_format fmt)
 +{
 +      switch (fmt) {
 +      case MIPI_DSI_FMT_RGB565:               return 16;
 +      case MIPI_DSI_FMT_RGB666_PACKED:        return 18;
 +      case MIPI_DSI_FMT_RGB666:
 +      case MIPI_DSI_FMT_RGB888:
 +      default:                                return 24;
 +      }
 +}
 +
 +static inline u32 dsi_read(struct msm_dsi_host *msm_host, u32 reg)
 +{
 +      return msm_readl(msm_host->ctrl_base + msm_host->cfg->io_offset + reg);
 +}
 +static inline void dsi_write(struct msm_dsi_host *msm_host, u32 reg, u32 data)
 +{
 +      msm_writel(data, msm_host->ctrl_base + msm_host->cfg->io_offset + reg);
 +}
 +
 +static int dsi_host_regulator_enable(struct msm_dsi_host *msm_host);
 +static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host);
 +
 +static const struct dsi_config *dsi_get_config(struct msm_dsi_host *msm_host)
 +{
 +      const struct dsi_config *cfg;
 +      struct regulator *gdsc_reg;
 +      int i, ret;
 +      u32 major = 0, minor = 0;
 +
 +      gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
 +      if (IS_ERR_OR_NULL(gdsc_reg)) {
 +              pr_err("%s: cannot get gdsc\n", __func__);
 +              goto fail;
 +      }
 +      ret = regulator_enable(gdsc_reg);
 +      if (ret) {
 +              pr_err("%s: unable to enable gdsc\n", __func__);
 +              regulator_put(gdsc_reg);
 +              goto fail;
 +      }
 +      ret = clk_prepare_enable(msm_host->ahb_clk);
 +      if (ret) {
 +              pr_err("%s: unable to enable ahb_clk\n", __func__);
 +              regulator_disable(gdsc_reg);
 +              regulator_put(gdsc_reg);
 +              goto fail;
 +      }
 +
 +      ret = dsi_get_version(msm_host->ctrl_base, &major, &minor);
 +
 +      clk_disable_unprepare(msm_host->ahb_clk);
 +      regulator_disable(gdsc_reg);
 +      regulator_put(gdsc_reg);
 +      if (ret) {
 +              pr_err("%s: Invalid version\n", __func__);
 +              goto fail;
 +      }
 +
 +      for (i = 0; i < ARRAY_SIZE(dsi_cfgs); i++) {
 +              cfg = dsi_cfgs + i;
 +              if ((cfg->major == major) && (cfg->minor == minor))
 +                      return cfg;
 +      }
 +      pr_err("%s: Version %x:%x not support\n", __func__, major, minor);
 +
 +fail:
 +      return NULL;
 +}
 +
 +static inline struct msm_dsi_host *to_msm_dsi_host(struct mipi_dsi_host *host)
 +{
 +      return container_of(host, struct msm_dsi_host, base);
 +}
 +
 +static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host)
 +{
 +      struct regulator_bulk_data *s = msm_host->supplies;
 +      const struct dsi_reg_entry *regs = msm_host->cfg->reg_cfg.regs;
 +      int num = msm_host->cfg->reg_cfg.num;
 +      int i;
 +
 +      DBG("");
 +      for (i = num - 1; i >= 0; i--)
 +              if (regs[i].disable_load >= 0)
-                       ret = regulator_set_optimum_mode(s[i].consumer,
-                                                       regs[i].enable_load);
++                      regulator_set_load(s[i].consumer,
++                                         regs[i].disable_load);
 +
 +      regulator_bulk_disable(num, s);
 +}
 +
 +static int dsi_host_regulator_enable(struct msm_dsi_host *msm_host)
 +{
 +      struct regulator_bulk_data *s = msm_host->supplies;
 +      const struct dsi_reg_entry *regs = msm_host->cfg->reg_cfg.regs;
 +      int num = msm_host->cfg->reg_cfg.num;
 +      int ret, i;
 +
 +      DBG("");
 +      for (i = 0; i < num; i++) {
 +              if (regs[i].enable_load >= 0) {
-               regulator_set_optimum_mode(s[i].consumer, regs[i].disable_load);
++                      ret = regulator_set_load(s[i].consumer,
++                                               regs[i].enable_load);
 +                      if (ret < 0) {
 +                              pr_err("regulator %d set op mode failed, %d\n",
 +                                      i, ret);
 +                              goto fail;
 +                      }
 +              }
 +      }
 +
 +      ret = regulator_bulk_enable(num, s);
 +      if (ret < 0) {
 +              pr_err("regulator enable failed, %d\n", ret);
 +              goto fail;
 +      }
 +
 +      return 0;
 +
 +fail:
 +      for (i--; i >= 0; i--)
++              regulator_set_load(s[i].consumer, regs[i].disable_load);
 +      return ret;
 +}
 +
 +static int dsi_regulator_init(struct msm_dsi_host *msm_host)
 +{
 +      struct regulator_bulk_data *s = msm_host->supplies;
 +      const struct dsi_reg_entry *regs = msm_host->cfg->reg_cfg.regs;
 +      int num = msm_host->cfg->reg_cfg.num;
 +      int i, ret;
 +
 +      for (i = 0; i < num; i++)
 +              s[i].supply = regs[i].name;
 +
 +      ret = devm_regulator_bulk_get(&msm_host->pdev->dev, num, s);
 +      if (ret < 0) {
 +              pr_err("%s: failed to init regulator, ret=%d\n",
 +                                              __func__, ret);
 +              return ret;
 +      }
 +
 +      for (i = 0; i < num; i++) {
 +              if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
 +                      ret = regulator_set_voltage(s[i].consumer,
 +                              regs[i].min_voltage, regs[i].max_voltage);
 +                      if (ret < 0) {
 +                              pr_err("regulator %d set voltage failed, %d\n",
 +                                      i, ret);
 +                              return ret;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int dsi_clk_init(struct msm_dsi_host *msm_host)
 +{
 +      struct device *dev = &msm_host->pdev->dev;
 +      int ret = 0;
 +
 +      msm_host->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk");
 +      if (IS_ERR(msm_host->mdp_core_clk)) {
 +              ret = PTR_ERR(msm_host->mdp_core_clk);
 +              pr_err("%s: Unable to get mdp core clk. ret=%d\n",
 +                      __func__, ret);
 +              goto exit;
 +      }
 +
 +      msm_host->ahb_clk = devm_clk_get(dev, "iface_clk");
 +      if (IS_ERR(msm_host->ahb_clk)) {
 +              ret = PTR_ERR(msm_host->ahb_clk);
 +              pr_err("%s: Unable to get mdss ahb clk. ret=%d\n",
 +                      __func__, ret);
 +              goto exit;
 +      }
 +
 +      msm_host->axi_clk = devm_clk_get(dev, "bus_clk");
 +      if (IS_ERR(msm_host->axi_clk)) {
 +              ret = PTR_ERR(msm_host->axi_clk);
 +              pr_err("%s: Unable to get axi bus clk. ret=%d\n",
 +                      __func__, ret);
 +              goto exit;
 +      }
 +
 +      msm_host->mmss_misc_ahb_clk = devm_clk_get(dev, "core_mmss_clk");
 +      if (IS_ERR(msm_host->mmss_misc_ahb_clk)) {
 +              ret = PTR_ERR(msm_host->mmss_misc_ahb_clk);
 +              pr_err("%s: Unable to get mmss misc ahb clk. ret=%d\n",
 +                      __func__, ret);
 +              goto exit;
 +      }
 +
 +      msm_host->byte_clk = devm_clk_get(dev, "byte_clk");
 +      if (IS_ERR(msm_host->byte_clk)) {
 +              ret = PTR_ERR(msm_host->byte_clk);
 +              pr_err("%s: can't find dsi_byte_clk. ret=%d\n",
 +                      __func__, ret);
 +              msm_host->byte_clk = NULL;
 +              goto exit;
 +      }
 +
 +      msm_host->pixel_clk = devm_clk_get(dev, "pixel_clk");
 +      if (IS_ERR(msm_host->pixel_clk)) {
 +              ret = PTR_ERR(msm_host->pixel_clk);
 +              pr_err("%s: can't find dsi_pixel_clk. ret=%d\n",
 +                      __func__, ret);
 +              msm_host->pixel_clk = NULL;
 +              goto exit;
 +      }
 +
 +      msm_host->esc_clk = devm_clk_get(dev, "core_clk");
 +      if (IS_ERR(msm_host->esc_clk)) {
 +              ret = PTR_ERR(msm_host->esc_clk);
 +              pr_err("%s: can't find dsi_esc_clk. ret=%d\n",
 +                      __func__, ret);
 +              msm_host->esc_clk = NULL;
 +              goto exit;
 +      }
 +
 +exit:
 +      return ret;
 +}
 +
 +static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host)
 +{
 +      int ret;
 +
 +      DBG("id=%d", msm_host->id);
 +
 +      ret = clk_prepare_enable(msm_host->mdp_core_clk);
 +      if (ret) {
 +              pr_err("%s: failed to enable mdp_core_clock, %d\n",
 +                                                       __func__, ret);
 +              goto core_clk_err;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->ahb_clk);
 +      if (ret) {
 +              pr_err("%s: failed to enable ahb clock, %d\n", __func__, ret);
 +              goto ahb_clk_err;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->axi_clk);
 +      if (ret) {
 +              pr_err("%s: failed to enable ahb clock, %d\n", __func__, ret);
 +              goto axi_clk_err;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->mmss_misc_ahb_clk);
 +      if (ret) {
 +              pr_err("%s: failed to enable mmss misc ahb clk, %d\n",
 +                      __func__, ret);
 +              goto misc_ahb_clk_err;
 +      }
 +
 +      return 0;
 +
 +misc_ahb_clk_err:
 +      clk_disable_unprepare(msm_host->axi_clk);
 +axi_clk_err:
 +      clk_disable_unprepare(msm_host->ahb_clk);
 +ahb_clk_err:
 +      clk_disable_unprepare(msm_host->mdp_core_clk);
 +core_clk_err:
 +      return ret;
 +}
 +
 +static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host)
 +{
 +      DBG("");
 +      clk_disable_unprepare(msm_host->mmss_misc_ahb_clk);
 +      clk_disable_unprepare(msm_host->axi_clk);
 +      clk_disable_unprepare(msm_host->ahb_clk);
 +      clk_disable_unprepare(msm_host->mdp_core_clk);
 +}
 +
 +static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
 +{
 +      int ret;
 +
 +      DBG("Set clk rates: pclk=%d, byteclk=%d",
 +              msm_host->mode->clock, msm_host->byte_clk_rate);
 +
 +      ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate);
 +      if (ret) {
 +              pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret);
 +              goto error;
 +      }
 +
 +      ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
 +      if (ret) {
 +              pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
 +              goto error;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->esc_clk);
 +      if (ret) {
 +              pr_err("%s: Failed to enable dsi esc clk\n", __func__);
 +              goto error;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->byte_clk);
 +      if (ret) {
 +              pr_err("%s: Failed to enable dsi byte clk\n", __func__);
 +              goto byte_clk_err;
 +      }
 +
 +      ret = clk_prepare_enable(msm_host->pixel_clk);
 +      if (ret) {
 +              pr_err("%s: Failed to enable dsi pixel clk\n", __func__);
 +              goto pixel_clk_err;
 +      }
 +
 +      return 0;
 +
 +pixel_clk_err:
 +      clk_disable_unprepare(msm_host->byte_clk);
 +byte_clk_err:
 +      clk_disable_unprepare(msm_host->esc_clk);
 +error:
 +      return ret;
 +}
 +
 +static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
 +{
 +      clk_disable_unprepare(msm_host->esc_clk);
 +      clk_disable_unprepare(msm_host->pixel_clk);
 +      clk_disable_unprepare(msm_host->byte_clk);
 +}
 +
 +static int dsi_clk_ctrl(struct msm_dsi_host *msm_host, bool enable)
 +{
 +      int ret = 0;
 +
 +      mutex_lock(&msm_host->clk_mutex);
 +      if (enable) {
 +              ret = dsi_bus_clk_enable(msm_host);
 +              if (ret) {
 +                      pr_err("%s: Can not enable bus clk, %d\n",
 +                              __func__, ret);
 +                      goto unlock_ret;
 +              }
 +              ret = dsi_link_clk_enable(msm_host);
 +              if (ret) {
 +                      pr_err("%s: Can not enable link clk, %d\n",
 +                              __func__, ret);
 +                      dsi_bus_clk_disable(msm_host);
 +                      goto unlock_ret;
 +              }
 +      } else {
 +              dsi_link_clk_disable(msm_host);
 +              dsi_bus_clk_disable(msm_host);
 +      }
 +
 +unlock_ret:
 +      mutex_unlock(&msm_host->clk_mutex);
 +      return ret;
 +}
 +
 +static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 +{
 +      struct drm_display_mode *mode = msm_host->mode;
 +      u8 lanes = msm_host->lanes;
 +      u32 bpp = dsi_get_bpp(msm_host->format);
 +      u32 pclk_rate;
 +
 +      if (!mode) {
 +              pr_err("%s: mode not set\n", __func__);
 +              return -EINVAL;
 +      }
 +
 +      pclk_rate = mode->clock * 1000;
 +      if (lanes > 0) {
 +              msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes);
 +      } else {
 +              pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
 +              msm_host->byte_clk_rate = (pclk_rate * bpp) / 8;
 +      }
 +
 +      DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate);
 +
 +      return 0;
 +}
 +
 +static void dsi_phy_sw_reset(struct msm_dsi_host *msm_host)
 +{
 +      DBG("");
 +      dsi_write(msm_host, REG_DSI_PHY_RESET, DSI_PHY_RESET_RESET);
 +      /* Make sure fully reset */
 +      wmb();
 +      udelay(1000);
 +      dsi_write(msm_host, REG_DSI_PHY_RESET, 0);
 +      udelay(100);
 +}
 +
 +static void dsi_intr_ctrl(struct msm_dsi_host *msm_host, u32 mask, int enable)
 +{
 +      u32 intr;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&msm_host->intr_lock, flags);
 +      intr = dsi_read(msm_host, REG_DSI_INTR_CTRL);
 +
 +      if (enable)
 +              intr |= mask;
 +      else
 +              intr &= ~mask;
 +
 +      DBG("intr=%x enable=%d", intr, enable);
 +
 +      dsi_write(msm_host, REG_DSI_INTR_CTRL, intr);
 +      spin_unlock_irqrestore(&msm_host->intr_lock, flags);
 +}
 +
 +static inline enum dsi_traffic_mode dsi_get_traffic_mode(const u32 mode_flags)
 +{
 +      if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
 +              return BURST_MODE;
 +      else if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
 +              return NON_BURST_SYNCH_PULSE;
 +
 +      return NON_BURST_SYNCH_EVENT;
 +}
 +
 +static inline enum dsi_vid_dst_format dsi_get_vid_fmt(
 +                              const enum mipi_dsi_pixel_format mipi_fmt)
 +{
 +      switch (mipi_fmt) {
 +      case MIPI_DSI_FMT_RGB888:       return VID_DST_FORMAT_RGB888;
 +      case MIPI_DSI_FMT_RGB666:       return VID_DST_FORMAT_RGB666_LOOSE;
 +      case MIPI_DSI_FMT_RGB666_PACKED:        return VID_DST_FORMAT_RGB666;
 +      case MIPI_DSI_FMT_RGB565:       return VID_DST_FORMAT_RGB565;
 +      default:                        return VID_DST_FORMAT_RGB888;
 +      }
 +}
 +
 +static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt(
 +                              const enum mipi_dsi_pixel_format mipi_fmt)
 +{
 +      switch (mipi_fmt) {
 +      case MIPI_DSI_FMT_RGB888:       return CMD_DST_FORMAT_RGB888;
 +      case MIPI_DSI_FMT_RGB666_PACKED:
 +      case MIPI_DSI_FMT_RGB666:       return VID_DST_FORMAT_RGB666;
 +      case MIPI_DSI_FMT_RGB565:       return CMD_DST_FORMAT_RGB565;
 +      default:                        return CMD_DST_FORMAT_RGB888;
 +      }
 +}
 +
 +static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
 +                              u32 clk_pre, u32 clk_post)
 +{
 +      u32 flags = msm_host->mode_flags;
 +      enum mipi_dsi_pixel_format mipi_fmt = msm_host->format;
 +      u32 data = 0;
 +
 +      if (!enable) {
 +              dsi_write(msm_host, REG_DSI_CTRL, 0);
 +              return;
 +      }
 +
 +      if (flags & MIPI_DSI_MODE_VIDEO) {
 +              if (flags & MIPI_DSI_MODE_VIDEO_HSE)
 +                      data |= DSI_VID_CFG0_PULSE_MODE_HSA_HE;
 +              if (flags & MIPI_DSI_MODE_VIDEO_HFP)
 +                      data |= DSI_VID_CFG0_HFP_POWER_STOP;
 +              if (flags & MIPI_DSI_MODE_VIDEO_HBP)
 +                      data |= DSI_VID_CFG0_HBP_POWER_STOP;
 +              if (flags & MIPI_DSI_MODE_VIDEO_HSA)
 +                      data |= DSI_VID_CFG0_HSA_POWER_STOP;
 +              /* Always set low power stop mode for BLLP
 +               * to let command engine send packets
 +               */
 +              data |= DSI_VID_CFG0_EOF_BLLP_POWER_STOP |
 +                      DSI_VID_CFG0_BLLP_POWER_STOP;
 +              data |= DSI_VID_CFG0_TRAFFIC_MODE(dsi_get_traffic_mode(flags));
 +              data |= DSI_VID_CFG0_DST_FORMAT(dsi_get_vid_fmt(mipi_fmt));
 +              data |= DSI_VID_CFG0_VIRT_CHANNEL(msm_host->channel);
 +              dsi_write(msm_host, REG_DSI_VID_CFG0, data);
 +
 +              /* Do not swap RGB colors */
 +              data = DSI_VID_CFG1_RGB_SWAP(SWAP_RGB);
 +              dsi_write(msm_host, REG_DSI_VID_CFG1, 0);
 +      } else {
 +              /* Do not swap RGB colors */
 +              data = DSI_CMD_CFG0_RGB_SWAP(SWAP_RGB);
 +              data |= DSI_CMD_CFG0_DST_FORMAT(dsi_get_cmd_fmt(mipi_fmt));
 +              dsi_write(msm_host, REG_DSI_CMD_CFG0, data);
 +
 +              data = DSI_CMD_CFG1_WR_MEM_START(MIPI_DCS_WRITE_MEMORY_START) |
 +                      DSI_CMD_CFG1_WR_MEM_CONTINUE(
 +                                      MIPI_DCS_WRITE_MEMORY_CONTINUE);
 +              /* Always insert DCS command */
 +              data |= DSI_CMD_CFG1_INSERT_DCS_COMMAND;
 +              dsi_write(msm_host, REG_DSI_CMD_CFG1, data);
 +      }
 +
 +      dsi_write(msm_host, REG_DSI_CMD_DMA_CTRL,
 +                      DSI_CMD_DMA_CTRL_FROM_FRAME_BUFFER |
 +                      DSI_CMD_DMA_CTRL_LOW_POWER);
 +
 +      data = 0;
 +      /* Always assume dedicated TE pin */
 +      data |= DSI_TRIG_CTRL_TE;
 +      data |= DSI_TRIG_CTRL_MDP_TRIGGER(TRIGGER_NONE);
 +      data |= DSI_TRIG_CTRL_DMA_TRIGGER(TRIGGER_SW);
 +      data |= DSI_TRIG_CTRL_STREAM(msm_host->channel);
 +      if ((msm_host->cfg->major == MSM_DSI_VER_MAJOR_6G) &&
 +              (msm_host->cfg->minor >= MSM_DSI_6G_VER_MINOR_V1_2))
 +              data |= DSI_TRIG_CTRL_BLOCK_DMA_WITHIN_FRAME;
 +      dsi_write(msm_host, REG_DSI_TRIG_CTRL, data);
 +
 +      data = DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(clk_post) |
 +              DSI_CLKOUT_TIMING_CTRL_T_CLK_PRE(clk_pre);
 +      dsi_write(msm_host, REG_DSI_CLKOUT_TIMING_CTRL, data);
 +
 +      data = 0;
 +      if (!(flags & MIPI_DSI_MODE_EOT_PACKET))
 +              data |= DSI_EOT_PACKET_CTRL_TX_EOT_APPEND;
 +      dsi_write(msm_host, REG_DSI_EOT_PACKET_CTRL, data);
 +
 +      /* allow only ack-err-status to generate interrupt */
 +      dsi_write(msm_host, REG_DSI_ERR_INT_MASK0, 0x13ff3fe0);
 +
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_ERROR, 1);
 +
 +      dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
 +
 +      data = DSI_CTRL_CLK_EN;
 +
 +      DBG("lane number=%d", msm_host->lanes);
 +      if (msm_host->lanes == 2) {
 +              data |= DSI_CTRL_LANE1 | DSI_CTRL_LANE2;
 +              /* swap lanes for 2-lane panel for better performance */
 +              dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
 +                      DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_1230));
 +      } else {
 +              /* Take 4 lanes as default */
 +              data |= DSI_CTRL_LANE0 | DSI_CTRL_LANE1 | DSI_CTRL_LANE2 |
 +                      DSI_CTRL_LANE3;
 +              /* Do not swap lanes for 4-lane panel */
 +              dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
 +                      DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
 +      }
 +      data |= DSI_CTRL_ENABLE;
 +
 +      dsi_write(msm_host, REG_DSI_CTRL, data);
 +}
 +
 +static void dsi_timing_setup(struct msm_dsi_host *msm_host)
 +{
 +      struct drm_display_mode *mode = msm_host->mode;
 +      u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */
 +      u32 h_total = mode->htotal;
 +      u32 v_total = mode->vtotal;
 +      u32 hs_end = mode->hsync_end - mode->hsync_start;
 +      u32 vs_end = mode->vsync_end - mode->vsync_start;
 +      u32 ha_start = h_total - mode->hsync_start;
 +      u32 ha_end = ha_start + mode->hdisplay;
 +      u32 va_start = v_total - mode->vsync_start;
 +      u32 va_end = va_start + mode->vdisplay;
 +      u32 wc;
 +
 +      DBG("");
 +
 +      if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
 +              dsi_write(msm_host, REG_DSI_ACTIVE_H,
 +                      DSI_ACTIVE_H_START(ha_start) |
 +                      DSI_ACTIVE_H_END(ha_end));
 +              dsi_write(msm_host, REG_DSI_ACTIVE_V,
 +                      DSI_ACTIVE_V_START(va_start) |
 +                      DSI_ACTIVE_V_END(va_end));
 +              dsi_write(msm_host, REG_DSI_TOTAL,
 +                      DSI_TOTAL_H_TOTAL(h_total - 1) |
 +                      DSI_TOTAL_V_TOTAL(v_total - 1));
 +
 +              dsi_write(msm_host, REG_DSI_ACTIVE_HSYNC,
 +                      DSI_ACTIVE_HSYNC_START(hs_start) |
 +                      DSI_ACTIVE_HSYNC_END(hs_end));
 +              dsi_write(msm_host, REG_DSI_ACTIVE_VSYNC_HPOS, 0);
 +              dsi_write(msm_host, REG_DSI_ACTIVE_VSYNC_VPOS,
 +                      DSI_ACTIVE_VSYNC_VPOS_START(vs_start) |
 +                      DSI_ACTIVE_VSYNC_VPOS_END(vs_end));
 +      } else {                /* command mode */
 +              /* image data and 1 byte write_memory_start cmd */
 +              wc = mode->hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
 +
 +              dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_CTRL,
 +                      DSI_CMD_MDP_STREAM_CTRL_WORD_COUNT(wc) |
 +                      DSI_CMD_MDP_STREAM_CTRL_VIRTUAL_CHANNEL(
 +                                      msm_host->channel) |
 +                      DSI_CMD_MDP_STREAM_CTRL_DATA_TYPE(
 +                                      MIPI_DSI_DCS_LONG_WRITE));
 +
 +              dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_TOTAL,
 +                      DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(mode->hdisplay) |
 +                      DSI_CMD_MDP_STREAM_TOTAL_V_TOTAL(mode->vdisplay));
 +      }
 +}
 +
 +static void dsi_sw_reset(struct msm_dsi_host *msm_host)
 +{
 +      dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
 +      wmb(); /* clocks need to be enabled before reset */
 +
 +      dsi_write(msm_host, REG_DSI_RESET, 1);
 +      wmb(); /* make sure reset happen */
 +      dsi_write(msm_host, REG_DSI_RESET, 0);
 +}
 +
 +static void dsi_op_mode_config(struct msm_dsi_host *msm_host,
 +                                      bool video_mode, bool enable)
 +{
 +      u32 dsi_ctrl;
 +
 +      dsi_ctrl = dsi_read(msm_host, REG_DSI_CTRL);
 +
 +      if (!enable) {
 +              dsi_ctrl &= ~(DSI_CTRL_ENABLE | DSI_CTRL_VID_MODE_EN |
 +                              DSI_CTRL_CMD_MODE_EN);
 +              dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_CMD_MDP_DONE |
 +                                      DSI_IRQ_MASK_VIDEO_DONE, 0);
 +      } else {
 +              if (video_mode) {
 +                      dsi_ctrl |= DSI_CTRL_VID_MODE_EN;
 +              } else {                /* command mode */
 +                      dsi_ctrl |= DSI_CTRL_CMD_MODE_EN;
 +                      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_CMD_MDP_DONE, 1);
 +              }
 +              dsi_ctrl |= DSI_CTRL_ENABLE;
 +      }
 +
 +      dsi_write(msm_host, REG_DSI_CTRL, dsi_ctrl);
 +}
 +
 +static void dsi_set_tx_power_mode(int mode, struct msm_dsi_host *msm_host)
 +{
 +      u32 data;
 +
 +      data = dsi_read(msm_host, REG_DSI_CMD_DMA_CTRL);
 +
 +      if (mode == 0)
 +              data &= ~DSI_CMD_DMA_CTRL_LOW_POWER;
 +      else
 +              data |= DSI_CMD_DMA_CTRL_LOW_POWER;
 +
 +      dsi_write(msm_host, REG_DSI_CMD_DMA_CTRL, data);
 +}
 +
 +static void dsi_wait4video_done(struct msm_dsi_host *msm_host)
 +{
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 1);
 +
 +      reinit_completion(&msm_host->video_comp);
 +
 +      wait_for_completion_timeout(&msm_host->video_comp,
 +                      msecs_to_jiffies(70));
 +
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 0);
 +}
 +
 +static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host)
 +{
 +      if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO))
 +              return;
 +
 +      if (msm_host->power_on) {
 +              dsi_wait4video_done(msm_host);
 +              /* delay 4 ms to skip BLLP */
 +              usleep_range(2000, 4000);
 +      }
 +}
 +
 +/* dsi_cmd */
 +static int dsi_tx_buf_alloc(struct msm_dsi_host *msm_host, int size)
 +{
 +      struct drm_device *dev = msm_host->dev;
 +      int ret;
 +      u32 iova;
 +
 +      mutex_lock(&dev->struct_mutex);
 +      msm_host->tx_gem_obj = msm_gem_new(dev, size, MSM_BO_UNCACHED);
 +      if (IS_ERR(msm_host->tx_gem_obj)) {
 +              ret = PTR_ERR(msm_host->tx_gem_obj);
 +              pr_err("%s: failed to allocate gem, %d\n", __func__, ret);
 +              msm_host->tx_gem_obj = NULL;
 +              mutex_unlock(&dev->struct_mutex);
 +              return ret;
 +      }
 +
 +      ret = msm_gem_get_iova_locked(msm_host->tx_gem_obj, 0, &iova);
 +      if (ret) {
 +              pr_err("%s: failed to get iova, %d\n", __func__, ret);
 +              return ret;
 +      }
 +      mutex_unlock(&dev->struct_mutex);
 +
 +      if (iova & 0x07) {
 +              pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +static void dsi_tx_buf_free(struct msm_dsi_host *msm_host)
 +{
 +      struct drm_device *dev = msm_host->dev;
 +
 +      if (msm_host->tx_gem_obj) {
 +              msm_gem_put_iova(msm_host->tx_gem_obj, 0);
 +              mutex_lock(&dev->struct_mutex);
 +              msm_gem_free_object(msm_host->tx_gem_obj);
 +              msm_host->tx_gem_obj = NULL;
 +              mutex_unlock(&dev->struct_mutex);
 +      }
 +}
 +
 +/*
 + * prepare cmd buffer to be txed
 + */
 +static int dsi_cmd_dma_add(struct drm_gem_object *tx_gem,
 +                      const struct mipi_dsi_msg *msg)
 +{
 +      struct mipi_dsi_packet packet;
 +      int len;
 +      int ret;
 +      u8 *data;
 +
 +      ret = mipi_dsi_create_packet(&packet, msg);
 +      if (ret) {
 +              pr_err("%s: create packet failed, %d\n", __func__, ret);
 +              return ret;
 +      }
 +      len = (packet.size + 3) & (~0x3);
 +
 +      if (len > tx_gem->size) {
 +              pr_err("%s: packet size is too big\n", __func__);
 +              return -EINVAL;
 +      }
 +
 +      data = msm_gem_vaddr(tx_gem);
 +
 +      if (IS_ERR(data)) {
 +              ret = PTR_ERR(data);
 +              pr_err("%s: get vaddr failed, %d\n", __func__, ret);
 +              return ret;
 +      }
 +
 +      /* MSM specific command format in memory */
 +      data[0] = packet.header[1];
 +      data[1] = packet.header[2];
 +      data[2] = packet.header[0];
 +      data[3] = BIT(7); /* Last packet */
 +      if (mipi_dsi_packet_format_is_long(msg->type))
 +              data[3] |= BIT(6);
 +      if (msg->rx_buf && msg->rx_len)
 +              data[3] |= BIT(5);
 +
 +      /* Long packet */
 +      if (packet.payload && packet.payload_length)
 +              memcpy(data + 4, packet.payload, packet.payload_length);
 +
 +      /* Append 0xff to the end */
 +      if (packet.size < len)
 +              memset(data + packet.size, 0xff, len - packet.size);
 +
 +      return len;
 +}
 +
 +/*
 + * dsi_short_read1_resp: 1 parameter
 + */
 +static int dsi_short_read1_resp(u8 *buf, const struct mipi_dsi_msg *msg)
 +{
 +      u8 *data = msg->rx_buf;
 +      if (data && (msg->rx_len >= 1)) {
 +              *data = buf[1]; /* strip out dcs type */
 +              return 1;
 +      } else {
 +              pr_err("%s: read data does not match with rx_buf len %d\n",
 +                      __func__, msg->rx_len);
 +              return -EINVAL;
 +      }
 +}
 +
 +/*
 + * dsi_short_read2_resp: 2 parameter
 + */
 +static int dsi_short_read2_resp(u8 *buf, const struct mipi_dsi_msg *msg)
 +{
 +      u8 *data = msg->rx_buf;
 +      if (data && (msg->rx_len >= 2)) {
 +              data[0] = buf[1]; /* strip out dcs type */
 +              data[1] = buf[2];
 +              return 2;
 +      } else {
 +              pr_err("%s: read data does not match with rx_buf len %d\n",
 +                      __func__, msg->rx_len);
 +              return -EINVAL;
 +      }
 +}
 +
 +static int dsi_long_read_resp(u8 *buf, const struct mipi_dsi_msg *msg)
 +{
 +      /* strip out 4 byte dcs header */
 +      if (msg->rx_buf && msg->rx_len)
 +              memcpy(msg->rx_buf, buf + 4, msg->rx_len);
 +
 +      return msg->rx_len;
 +}
 +
 +
 +static int dsi_cmd_dma_tx(struct msm_dsi_host *msm_host, int len)
 +{
 +      int ret;
 +      u32 iova;
 +      bool triggered;
 +
 +      ret = msm_gem_get_iova(msm_host->tx_gem_obj, 0, &iova);
 +      if (ret) {
 +              pr_err("%s: failed to get iova: %d\n", __func__, ret);
 +              return ret;
 +      }
 +
 +      reinit_completion(&msm_host->dma_comp);
 +
 +      dsi_wait4video_eng_busy(msm_host);
 +
 +      triggered = msm_dsi_manager_cmd_xfer_trigger(
 +                                              msm_host->id, iova, len);
 +      if (triggered) {
 +              ret = wait_for_completion_timeout(&msm_host->dma_comp,
 +                                      msecs_to_jiffies(200));
 +              DBG("ret=%d", ret);
 +              if (ret == 0)
 +                      ret = -ETIMEDOUT;
 +              else
 +                      ret = len;
 +      } else
 +              ret = len;
 +
 +      return ret;
 +}
 +
 +static int dsi_cmd_dma_rx(struct msm_dsi_host *msm_host,
 +                      u8 *buf, int rx_byte, int pkt_size)
 +{
 +      u32 *lp, *temp, data;
 +      int i, j = 0, cnt;
 +      bool ack_error = false;
 +      u32 read_cnt;
 +      u8 reg[16];
 +      int repeated_bytes = 0;
 +      int buf_offset = buf - msm_host->rx_buf;
 +
 +      lp = (u32 *)buf;
 +      temp = (u32 *)reg;
 +      cnt = (rx_byte + 3) >> 2;
 +      if (cnt > 4)
 +              cnt = 4; /* 4 x 32 bits registers only */
 +
 +      /* Calculate real read data count */
 +      read_cnt = dsi_read(msm_host, 0x1d4) >> 16;
 +
 +      ack_error = (rx_byte == 4) ?
 +              (read_cnt == 8) : /* short pkt + 4-byte error pkt */
 +              (read_cnt == (pkt_size + 6 + 4)); /* long pkt+4-byte error pkt*/
 +
 +      if (ack_error)
 +              read_cnt -= 4; /* Remove 4 byte error pkt */
 +
 +      /*
 +       * In case of multiple reads from the panel, after the first read, there
 +       * is possibility that there are some bytes in the payload repeating in
 +       * the RDBK_DATA registers. Since we read all the parameters from the
 +       * panel right from the first byte for every pass. We need to skip the
 +       * repeating bytes and then append the new parameters to the rx buffer.
 +       */
 +      if (read_cnt > 16) {
 +              int bytes_shifted;
 +              /* Any data more than 16 bytes will be shifted out.
 +               * The temp read buffer should already contain these bytes.
 +               * The remaining bytes in read buffer are the repeated bytes.
 +               */
 +              bytes_shifted = read_cnt - 16;
 +              repeated_bytes = buf_offset - bytes_shifted;
 +      }
 +
 +      for (i = cnt - 1; i >= 0; i--) {
 +              data = dsi_read(msm_host, REG_DSI_RDBK_DATA(i));
 +              *temp++ = ntohl(data); /* to host byte order */
 +              DBG("data = 0x%x and ntohl(data) = 0x%x", data, ntohl(data));
 +      }
 +
 +      for (i = repeated_bytes; i < 16; i++)
 +              buf[j++] = reg[i];
 +
 +      return j;
 +}
 +
 +static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host,
 +                              const struct mipi_dsi_msg *msg)
 +{
 +      int len, ret;
 +      int bllp_len = msm_host->mode->hdisplay *
 +                      dsi_get_bpp(msm_host->format) / 8;
 +
 +      len = dsi_cmd_dma_add(msm_host->tx_gem_obj, msg);
 +      if (!len) {
 +              pr_err("%s: failed to add cmd type = 0x%x\n",
 +                      __func__,  msg->type);
 +              return -EINVAL;
 +      }
 +
 +      /* for video mode, do not send cmds more than
 +      * one pixel line, since it only transmit it
 +      * during BLLP.
 +      */
 +      /* TODO: if the command is sent in LP mode, the bit rate is only
 +       * half of esc clk rate. In this case, if the video is already
 +       * actively streaming, we need to check more carefully if the
 +       * command can be fit into one BLLP.
 +       */
 +      if ((msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) && (len > bllp_len)) {
 +              pr_err("%s: cmd cannot fit into BLLP period, len=%d\n",
 +                      __func__, len);
 +              return -EINVAL;
 +      }
 +
 +      ret = dsi_cmd_dma_tx(msm_host, len);
 +      if (ret < len) {
 +              pr_err("%s: cmd dma tx failed, type=0x%x, data0=0x%x, len=%d\n",
 +                      __func__, msg->type, (*(u8 *)(msg->tx_buf)), len);
 +              return -ECOMM;
 +      }
 +
 +      return len;
 +}
 +
 +static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host)
 +{
 +      u32 data0, data1;
 +
 +      data0 = dsi_read(msm_host, REG_DSI_CTRL);
 +      data1 = data0;
 +      data1 &= ~DSI_CTRL_ENABLE;
 +      dsi_write(msm_host, REG_DSI_CTRL, data1);
 +      /*
 +       * dsi controller need to be disabled before
 +       * clocks turned on
 +       */
 +      wmb();
 +
 +      dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
 +      wmb();  /* make sure clocks enabled */
 +
 +      /* dsi controller can only be reset while clocks are running */
 +      dsi_write(msm_host, REG_DSI_RESET, 1);
 +      wmb();  /* make sure reset happen */
 +      dsi_write(msm_host, REG_DSI_RESET, 0);
 +      wmb();  /* controller out of reset */
 +      dsi_write(msm_host, REG_DSI_CTRL, data0);
 +      wmb();  /* make sure dsi controller enabled again */
 +}
 +
 +static void dsi_err_worker(struct work_struct *work)
 +{
 +      struct msm_dsi_host *msm_host =
 +              container_of(work, struct msm_dsi_host, err_work);
 +      u32 status = msm_host->err_work_state;
 +
 +      pr_err("%s: status=%x\n", __func__, status);
 +      if (status & DSI_ERR_STATE_MDP_FIFO_UNDERFLOW)
 +              dsi_sw_reset_restore(msm_host);
 +
 +      /* It is safe to clear here because error irq is disabled. */
 +      msm_host->err_work_state = 0;
 +
 +      /* enable dsi error interrupt */
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_ERROR, 1);
 +}
 +
 +static void dsi_ack_err_status(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_ACK_ERR_STATUS);
 +
 +      if (status) {
 +              dsi_write(msm_host, REG_DSI_ACK_ERR_STATUS, status);
 +              /* Writing of an extra 0 needed to clear error bits */
 +              dsi_write(msm_host, REG_DSI_ACK_ERR_STATUS, 0);
 +              msm_host->err_work_state |= DSI_ERR_STATE_ACK;
 +      }
 +}
 +
 +static void dsi_timeout_status(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_TIMEOUT_STATUS);
 +
 +      if (status) {
 +              dsi_write(msm_host, REG_DSI_TIMEOUT_STATUS, status);
 +              msm_host->err_work_state |= DSI_ERR_STATE_TIMEOUT;
 +      }
 +}
 +
 +static void dsi_dln0_phy_err(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_DLN0_PHY_ERR);
 +
 +      if (status) {
 +              dsi_write(msm_host, REG_DSI_DLN0_PHY_ERR, status);
 +              msm_host->err_work_state |= DSI_ERR_STATE_DLN0_PHY;
 +      }
 +}
 +
 +static void dsi_fifo_status(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_FIFO_STATUS);
 +
 +      /* fifo underflow, overflow */
 +      if (status) {
 +              dsi_write(msm_host, REG_DSI_FIFO_STATUS, status);
 +              msm_host->err_work_state |= DSI_ERR_STATE_FIFO;
 +              if (status & DSI_FIFO_STATUS_CMD_MDP_FIFO_UNDERFLOW)
 +                      msm_host->err_work_state |=
 +                                      DSI_ERR_STATE_MDP_FIFO_UNDERFLOW;
 +      }
 +}
 +
 +static void dsi_status(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_STATUS0);
 +
 +      if (status & DSI_STATUS0_INTERLEAVE_OP_CONTENTION) {
 +              dsi_write(msm_host, REG_DSI_STATUS0, status);
 +              msm_host->err_work_state |=
 +                      DSI_ERR_STATE_INTERLEAVE_OP_CONTENTION;
 +      }
 +}
 +
 +static void dsi_clk_status(struct msm_dsi_host *msm_host)
 +{
 +      u32 status;
 +
 +      status = dsi_read(msm_host, REG_DSI_CLK_STATUS);
 +
 +      if (status & DSI_CLK_STATUS_PLL_UNLOCKED) {
 +              dsi_write(msm_host, REG_DSI_CLK_STATUS, status);
 +              msm_host->err_work_state |= DSI_ERR_STATE_PLL_UNLOCKED;
 +      }
 +}
 +
 +static void dsi_error(struct msm_dsi_host *msm_host)
 +{
 +      /* disable dsi error interrupt */
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_ERROR, 0);
 +
 +      dsi_clk_status(msm_host);
 +      dsi_fifo_status(msm_host);
 +      dsi_ack_err_status(msm_host);
 +      dsi_timeout_status(msm_host);
 +      dsi_status(msm_host);
 +      dsi_dln0_phy_err(msm_host);
 +
 +      queue_work(msm_host->workqueue, &msm_host->err_work);
 +}
 +
 +static irqreturn_t dsi_host_irq(int irq, void *ptr)
 +{
 +      struct msm_dsi_host *msm_host = ptr;
 +      u32 isr;
 +      unsigned long flags;
 +
 +      if (!msm_host->ctrl_base)
 +              return IRQ_HANDLED;
 +
 +      spin_lock_irqsave(&msm_host->intr_lock, flags);
 +      isr = dsi_read(msm_host, REG_DSI_INTR_CTRL);
 +      dsi_write(msm_host, REG_DSI_INTR_CTRL, isr);
 +      spin_unlock_irqrestore(&msm_host->intr_lock, flags);
 +
 +      DBG("isr=0x%x, id=%d", isr, msm_host->id);
 +
 +      if (isr & DSI_IRQ_ERROR)
 +              dsi_error(msm_host);
 +
 +      if (isr & DSI_IRQ_VIDEO_DONE)
 +              complete(&msm_host->video_comp);
 +
 +      if (isr & DSI_IRQ_CMD_DMA_DONE)
 +              complete(&msm_host->dma_comp);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
 +                      struct device *panel_device)
 +{
 +      int ret;
 +
 +      msm_host->disp_en_gpio = devm_gpiod_get(panel_device,
 +                                              "disp-enable");
 +      if (IS_ERR(msm_host->disp_en_gpio)) {
 +              DBG("cannot get disp-enable-gpios %ld",
 +                              PTR_ERR(msm_host->disp_en_gpio));
 +              msm_host->disp_en_gpio = NULL;
 +      }
 +      if (msm_host->disp_en_gpio) {
 +              ret = gpiod_direction_output(msm_host->disp_en_gpio, 0);
 +              if (ret) {
 +                      pr_err("cannot set dir to disp-en-gpios %d\n", ret);
 +                      return ret;
 +              }
 +      }
 +
 +      msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te");
 +      if (IS_ERR(msm_host->te_gpio)) {
 +              DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
 +              msm_host->te_gpio = NULL;
 +      }
 +
 +      if (msm_host->te_gpio) {
 +              ret = gpiod_direction_input(msm_host->te_gpio);
 +              if (ret) {
 +                      pr_err("%s: cannot set dir to disp-te-gpios, %d\n",
 +                              __func__, ret);
 +                      return ret;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int dsi_host_attach(struct mipi_dsi_host *host,
 +                                      struct mipi_dsi_device *dsi)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      int ret;
 +
 +      msm_host->channel = dsi->channel;
 +      msm_host->lanes = dsi->lanes;
 +      msm_host->format = dsi->format;
 +      msm_host->mode_flags = dsi->mode_flags;
 +
 +      msm_host->panel_node = dsi->dev.of_node;
 +
 +      /* Some gpios defined in panel DT need to be controlled by host */
 +      ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
 +      if (ret)
 +              return ret;
 +
 +      DBG("id=%d", msm_host->id);
 +      if (msm_host->dev)
 +              drm_helper_hpd_irq_event(msm_host->dev);
 +
 +      return 0;
 +}
 +
 +static int dsi_host_detach(struct mipi_dsi_host *host,
 +                                      struct mipi_dsi_device *dsi)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      msm_host->panel_node = NULL;
 +
 +      DBG("id=%d", msm_host->id);
 +      if (msm_host->dev)
 +              drm_helper_hpd_irq_event(msm_host->dev);
 +
 +      return 0;
 +}
 +
 +static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
 +                                      const struct mipi_dsi_msg *msg)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      int ret;
 +
 +      if (!msg || !msm_host->power_on)
 +              return -EINVAL;
 +
 +      mutex_lock(&msm_host->cmd_mutex);
 +      ret = msm_dsi_manager_cmd_xfer(msm_host->id, msg);
 +      mutex_unlock(&msm_host->cmd_mutex);
 +
 +      return ret;
 +}
 +
 +static struct mipi_dsi_host_ops dsi_host_ops = {
 +      .attach = dsi_host_attach,
 +      .detach = dsi_host_detach,
 +      .transfer = dsi_host_transfer,
 +};
 +
 +int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 +{
 +      struct msm_dsi_host *msm_host = NULL;
 +      struct platform_device *pdev = msm_dsi->pdev;
 +      int ret;
 +
 +      msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL);
 +      if (!msm_host) {
 +              pr_err("%s: FAILED: cannot alloc dsi host\n",
 +                     __func__);
 +              ret = -ENOMEM;
 +              goto fail;
 +      }
 +
 +      ret = of_property_read_u32(pdev->dev.of_node,
 +                              "qcom,dsi-host-index", &msm_host->id);
 +      if (ret) {
 +              dev_err(&pdev->dev,
 +                      "%s: host index not specified, ret=%d\n",
 +                      __func__, ret);
 +              goto fail;
 +      }
 +      msm_host->pdev = pdev;
 +
 +      ret = dsi_clk_init(msm_host);
 +      if (ret) {
 +              pr_err("%s: unable to initialize dsi clks\n", __func__);
 +              goto fail;
 +      }
 +
 +      msm_host->ctrl_base = msm_ioremap(pdev, "dsi_ctrl", "DSI CTRL");
 +      if (IS_ERR(msm_host->ctrl_base)) {
 +              pr_err("%s: unable to map Dsi ctrl base\n", __func__);
 +              ret = PTR_ERR(msm_host->ctrl_base);
 +              goto fail;
 +      }
 +
 +      msm_host->cfg = dsi_get_config(msm_host);
 +      if (!msm_host->cfg) {
 +              ret = -EINVAL;
 +              pr_err("%s: get config failed\n", __func__);
 +              goto fail;
 +      }
 +
 +      ret = dsi_regulator_init(msm_host);
 +      if (ret) {
 +              pr_err("%s: regulator init failed\n", __func__);
 +              goto fail;
 +      }
 +
 +      msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL);
 +      if (!msm_host->rx_buf) {
 +              pr_err("%s: alloc rx temp buf failed\n", __func__);
 +              goto fail;
 +      }
 +
 +      init_completion(&msm_host->dma_comp);
 +      init_completion(&msm_host->video_comp);
 +      mutex_init(&msm_host->dev_mutex);
 +      mutex_init(&msm_host->cmd_mutex);
 +      mutex_init(&msm_host->clk_mutex);
 +      spin_lock_init(&msm_host->intr_lock);
 +
 +      /* setup workqueue */
 +      msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
 +      INIT_WORK(&msm_host->err_work, dsi_err_worker);
 +
 +      msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type,
 +                                      msm_host->id);
 +      if (!msm_dsi->phy) {
 +              ret = -EINVAL;
 +              pr_err("%s: phy init failed\n", __func__);
 +              goto fail;
 +      }
 +      msm_dsi->host = &msm_host->base;
 +      msm_dsi->id = msm_host->id;
 +
 +      DBG("Dsi Host %d initialized", msm_host->id);
 +      return 0;
 +
 +fail:
 +      return ret;
 +}
 +
 +void msm_dsi_host_destroy(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      DBG("");
 +      dsi_tx_buf_free(msm_host);
 +      if (msm_host->workqueue) {
 +              flush_workqueue(msm_host->workqueue);
 +              destroy_workqueue(msm_host->workqueue);
 +              msm_host->workqueue = NULL;
 +      }
 +
 +      mutex_destroy(&msm_host->clk_mutex);
 +      mutex_destroy(&msm_host->cmd_mutex);
 +      mutex_destroy(&msm_host->dev_mutex);
 +}
 +
 +int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 +                                      struct drm_device *dev)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      struct platform_device *pdev = msm_host->pdev;
 +      int ret;
 +
 +      msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
 +      if (msm_host->irq < 0) {
 +              ret = msm_host->irq;
 +              dev_err(dev->dev, "failed to get irq: %d\n", ret);
 +              return ret;
 +      }
 +
 +      ret = devm_request_irq(&pdev->dev, msm_host->irq,
 +                      dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 +                      "dsi_isr", msm_host);
 +      if (ret < 0) {
 +              dev_err(&pdev->dev, "failed to request IRQ%u: %d\n",
 +                              msm_host->irq, ret);
 +              return ret;
 +      }
 +
 +      msm_host->dev = dev;
 +      ret = dsi_tx_buf_alloc(msm_host, SZ_4K);
 +      if (ret) {
 +              pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret);
 +              return ret;
 +      }
 +
 +      return 0;
 +}
 +
 +int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      struct device_node *node;
 +      int ret;
 +
 +      /* Register mipi dsi host */
 +      if (!msm_host->registered) {
 +              host->dev = &msm_host->pdev->dev;
 +              host->ops = &dsi_host_ops;
 +              ret = mipi_dsi_host_register(host);
 +              if (ret)
 +                      return ret;
 +
 +              msm_host->registered = true;
 +
 +              /* If the panel driver has not been probed after host register,
 +               * we should defer the host's probe.
 +               * It makes sure panel is connected when fbcon detects
 +               * connector status and gets the proper display mode to
 +               * create framebuffer.
 +               */
 +              if (check_defer) {
 +                      node = of_get_child_by_name(msm_host->pdev->dev.of_node,
 +                                                      "panel");
 +                      if (node) {
 +                              if (!of_drm_find_panel(node))
 +                                      return -EPROBE_DEFER;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +void msm_dsi_host_unregister(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      if (msm_host->registered) {
 +              mipi_dsi_host_unregister(host);
 +              host->dev = NULL;
 +              host->ops = NULL;
 +              msm_host->registered = false;
 +      }
 +}
 +
 +int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host,
 +                              const struct mipi_dsi_msg *msg)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      /* TODO: make sure dsi_cmd_mdp is idle.
 +       * Since DSI6G v1.2.0, we can set DSI_TRIG_CTRL.BLOCK_DMA_WITHIN_FRAME
 +       * to ask H/W to wait until cmd mdp is idle. S/W wait is not needed.
 +       * How to handle the old versions? Wait for mdp cmd done?
 +       */
 +
 +      /*
 +       * mdss interrupt is generated in mdp core clock domain
 +       * mdp clock need to be enabled to receive dsi interrupt
 +       */
 +      dsi_clk_ctrl(msm_host, 1);
 +
 +      /* TODO: vote for bus bandwidth */
 +
 +      if (!(msg->flags & MIPI_DSI_MSG_USE_LPM))
 +              dsi_set_tx_power_mode(0, msm_host);
 +
 +      msm_host->dma_cmd_ctrl_restore = dsi_read(msm_host, REG_DSI_CTRL);
 +      dsi_write(msm_host, REG_DSI_CTRL,
 +              msm_host->dma_cmd_ctrl_restore |
 +              DSI_CTRL_CMD_MODE_EN |
 +              DSI_CTRL_ENABLE);
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_CMD_DMA_DONE, 1);
 +
 +      return 0;
 +}
 +
 +void msm_dsi_host_xfer_restore(struct mipi_dsi_host *host,
 +                              const struct mipi_dsi_msg *msg)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_CMD_DMA_DONE, 0);
 +      dsi_write(msm_host, REG_DSI_CTRL, msm_host->dma_cmd_ctrl_restore);
 +
 +      if (!(msg->flags & MIPI_DSI_MSG_USE_LPM))
 +              dsi_set_tx_power_mode(1, msm_host);
 +
 +      /* TODO: unvote for bus bandwidth */
 +
 +      dsi_clk_ctrl(msm_host, 0);
 +}
 +
 +int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host,
 +                              const struct mipi_dsi_msg *msg)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      return dsi_cmds2buf_tx(msm_host, msg);
 +}
 +
 +int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
 +                              const struct mipi_dsi_msg *msg)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      int data_byte, rx_byte, dlen, end;
 +      int short_response, diff, pkt_size, ret = 0;
 +      char cmd;
 +      int rlen = msg->rx_len;
 +      u8 *buf;
 +
 +      if (rlen <= 2) {
 +              short_response = 1;
 +              pkt_size = rlen;
 +              rx_byte = 4;
 +      } else {
 +              short_response = 0;
 +              data_byte = 10; /* first read */
 +              if (rlen < data_byte)
 +                      pkt_size = rlen;
 +              else
 +                      pkt_size = data_byte;
 +              rx_byte = data_byte + 6; /* 4 header + 2 crc */
 +      }
 +
 +      buf = msm_host->rx_buf;
 +      end = 0;
 +      while (!end) {
 +              u8 tx[2] = {pkt_size & 0xff, pkt_size >> 8};
 +              struct mipi_dsi_msg max_pkt_size_msg = {
 +                      .channel = msg->channel,
 +                      .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
 +                      .tx_len = 2,
 +                      .tx_buf = tx,
 +              };
 +
 +              DBG("rlen=%d pkt_size=%d rx_byte=%d",
 +                      rlen, pkt_size, rx_byte);
 +
 +              ret = dsi_cmds2buf_tx(msm_host, &max_pkt_size_msg);
 +              if (ret < 2) {
 +                      pr_err("%s: Set max pkt size failed, %d\n",
 +                              __func__, ret);
 +                      return -EINVAL;
 +              }
 +
 +              if ((msm_host->cfg->major == MSM_DSI_VER_MAJOR_6G) &&
 +                      (msm_host->cfg->minor >= MSM_DSI_6G_VER_MINOR_V1_1)) {
 +                      /* Clear the RDBK_DATA registers */
 +                      dsi_write(msm_host, REG_DSI_RDBK_DATA_CTRL,
 +                                      DSI_RDBK_DATA_CTRL_CLR);
 +                      wmb(); /* make sure the RDBK registers are cleared */
 +                      dsi_write(msm_host, REG_DSI_RDBK_DATA_CTRL, 0);
 +                      wmb(); /* release cleared status before transfer */
 +              }
 +
 +              ret = dsi_cmds2buf_tx(msm_host, msg);
 +              if (ret < msg->tx_len) {
 +                      pr_err("%s: Read cmd Tx failed, %d\n", __func__, ret);
 +                      return ret;
 +              }
 +
 +              /*
 +               * once cmd_dma_done interrupt received,
 +               * return data from client is ready and stored
 +               * at RDBK_DATA register already
 +               * since rx fifo is 16 bytes, dcs header is kept at first loop,
 +               * after that dcs header lost during shift into registers
 +               */
 +              dlen = dsi_cmd_dma_rx(msm_host, buf, rx_byte, pkt_size);
 +
 +              if (dlen <= 0)
 +                      return 0;
 +
 +              if (short_response)
 +                      break;
 +
 +              if (rlen <= data_byte) {
 +                      diff = data_byte - rlen;
 +                      end = 1;
 +              } else {
 +                      diff = 0;
 +                      rlen -= data_byte;
 +              }
 +
 +              if (!end) {
 +                      dlen -= 2; /* 2 crc */
 +                      dlen -= diff;
 +                      buf += dlen;    /* next start position */
 +                      data_byte = 14; /* NOT first read */
 +                      if (rlen < data_byte)
 +                              pkt_size += rlen;
 +                      else
 +                              pkt_size += data_byte;
 +                      DBG("buf=%p dlen=%d diff=%d", buf, dlen, diff);
 +              }
 +      }
 +
 +      /*
 +       * For single Long read, if the requested rlen < 10,
 +       * we need to shift the start position of rx
 +       * data buffer to skip the bytes which are not
 +       * updated.
 +       */
 +      if (pkt_size < 10 && !short_response)
 +              buf = msm_host->rx_buf + (10 - rlen);
 +      else
 +              buf = msm_host->rx_buf;
 +
 +      cmd = buf[0];
 +      switch (cmd) {
 +      case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
 +              pr_err("%s: rx ACK_ERR_PACLAGE\n", __func__);
 +              ret = 0;
 +      case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
 +      case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
 +              ret = dsi_short_read1_resp(buf, msg);
 +              break;
 +      case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
 +      case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
 +              ret = dsi_short_read2_resp(buf, msg);
 +              break;
 +      case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
 +      case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
 +              ret = dsi_long_read_resp(buf, msg);
 +              break;
 +      default:
 +              pr_warn("%s:Invalid response cmd\n", __func__);
 +              ret = 0;
 +      }
 +
 +      return ret;
 +}
 +
 +void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      dsi_write(msm_host, REG_DSI_DMA_BASE, iova);
 +      dsi_write(msm_host, REG_DSI_DMA_LEN, len);
 +      dsi_write(msm_host, REG_DSI_TRIG_DMA, 1);
 +
 +      /* Make sure trigger happens */
 +      wmb();
 +}
 +
 +int msm_dsi_host_enable(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      dsi_op_mode_config(msm_host,
 +              !!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO), true);
 +
 +      /* TODO: clock should be turned off for command mode,
 +       * and only turned on before MDP START.
 +       * This part of code should be enabled once mdp driver support it.
 +       */
 +      /* if (msm_panel->mode == MSM_DSI_CMD_MODE)
 +              dsi_clk_ctrl(msm_host, 0); */
 +
 +      return 0;
 +}
 +
 +int msm_dsi_host_disable(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      dsi_op_mode_config(msm_host,
 +              !!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO), false);
 +
 +      /* Since we have disabled INTF, the video engine won't stop so that
 +       * the cmd engine will be blocked.
 +       * Reset to disable video engine so that we can send off cmd.
 +       */
 +      dsi_sw_reset(msm_host);
 +
 +      return 0;
 +}
 +
 +int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      u32 clk_pre = 0, clk_post = 0;
 +      int ret = 0;
 +
 +      mutex_lock(&msm_host->dev_mutex);
 +      if (msm_host->power_on) {
 +              DBG("dsi host already on");
 +              goto unlock_ret;
 +      }
 +
 +      ret = dsi_calc_clk_rate(msm_host);
 +      if (ret) {
 +              pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
 +              goto unlock_ret;
 +      }
 +
 +      ret = dsi_host_regulator_enable(msm_host);
 +      if (ret) {
 +              pr_err("%s:Failed to enable vregs.ret=%d\n",
 +                      __func__, ret);
 +              goto unlock_ret;
 +      }
 +
 +      ret = dsi_bus_clk_enable(msm_host);
 +      if (ret) {
 +              pr_err("%s: failed to enable bus clocks, %d\n", __func__, ret);
 +              goto fail_disable_reg;
 +      }
 +
 +      dsi_phy_sw_reset(msm_host);
 +      ret = msm_dsi_manager_phy_enable(msm_host->id,
 +                                      msm_host->byte_clk_rate * 8,
 +                                      clk_get_rate(msm_host->esc_clk),
 +                                      &clk_pre, &clk_post);
 +      dsi_bus_clk_disable(msm_host);
 +      if (ret) {
 +              pr_err("%s: failed to enable phy, %d\n", __func__, ret);
 +              goto fail_disable_reg;
 +      }
 +
 +      ret = dsi_clk_ctrl(msm_host, 1);
 +      if (ret) {
 +              pr_err("%s: failed to enable clocks. ret=%d\n", __func__, ret);
 +              goto fail_disable_reg;
 +      }
 +
 +      dsi_timing_setup(msm_host);
 +      dsi_sw_reset(msm_host);
 +      dsi_ctrl_config(msm_host, true, clk_pre, clk_post);
 +
 +      if (msm_host->disp_en_gpio)
 +              gpiod_set_value(msm_host->disp_en_gpio, 1);
 +
 +      msm_host->power_on = true;
 +      mutex_unlock(&msm_host->dev_mutex);
 +
 +      return 0;
 +
 +fail_disable_reg:
 +      dsi_host_regulator_disable(msm_host);
 +unlock_ret:
 +      mutex_unlock(&msm_host->dev_mutex);
 +      return ret;
 +}
 +
 +int msm_dsi_host_power_off(struct mipi_dsi_host *host)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      mutex_lock(&msm_host->dev_mutex);
 +      if (!msm_host->power_on) {
 +              DBG("dsi host already off");
 +              goto unlock_ret;
 +      }
 +
 +      dsi_ctrl_config(msm_host, false, 0, 0);
 +
 +      if (msm_host->disp_en_gpio)
 +              gpiod_set_value(msm_host->disp_en_gpio, 0);
 +
 +      msm_dsi_manager_phy_disable(msm_host->id);
 +
 +      dsi_clk_ctrl(msm_host, 0);
 +
 +      dsi_host_regulator_disable(msm_host);
 +
 +      DBG("-");
 +
 +      msm_host->power_on = false;
 +
 +unlock_ret:
 +      mutex_unlock(&msm_host->dev_mutex);
 +      return 0;
 +}
 +
 +int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
 +                                      struct drm_display_mode *mode)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +
 +      if (msm_host->mode) {
 +              drm_mode_destroy(msm_host->dev, msm_host->mode);
 +              msm_host->mode = NULL;
 +      }
 +
 +      msm_host->mode = drm_mode_duplicate(msm_host->dev, mode);
 +      if (IS_ERR(msm_host->mode)) {
 +              pr_err("%s: cannot duplicate mode\n", __func__);
 +              return PTR_ERR(msm_host->mode);
 +      }
 +
 +      return 0;
 +}
 +
 +struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 +                              unsigned long *panel_flags)
 +{
 +      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 +      struct drm_panel *panel;
 +
 +      panel = of_drm_find_panel(msm_host->panel_node);
 +      if (panel_flags)
 +                      *panel_flags = msm_host->mode_flags;
 +
 +      return panel;
 +}
 +