Merge tag 'drm-intel-next-2018-12-04' of git://anongit.freedesktop.org/drm/drm-intel...
authorDave Airlie <airlied@redhat.com>
Wed, 5 Dec 2018 22:09:33 +0000 (08:09 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 5 Dec 2018 23:17:51 +0000 (09:17 +1000)
Final drm/i915 changes for v4.21:
- ICL DSI video mode enabling (Madhav, Vandita, Jani, Imre)
- eDP sink count fix (José)
- PSR fixes (José)
- DRM DP helper and i915 DSC enabling (Manasi, Gaurav, Anusha)
- DP FEC enabling (Anusha)
- SKL+ watermark/ddb programming improvements (Ville)
- Pixel format fixes (Ville)
- Selftest updates (Chris, Tvrtko)
- GT and engine workaround improvements (Tvrtko)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87va496uoe.fsf@intel.com
396 files changed:
CREDITS
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/security-bugs.rst
Documentation/core-api/xarray.rst
Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt
Documentation/devicetree/bindings/display/renesas,du.txt
Documentation/devicetree/bindings/net/can/holt_hi311x.txt
Documentation/devicetree/bindings/net/can/rcar_can.txt
Documentation/devicetree/bindings/net/dsa/dsa.txt
Documentation/gpu/drm-mm.rst
Documentation/gpu/todo.rst
Documentation/input/event-codes.rst
Documentation/media/uapi/v4l/dev-meta.rst
Documentation/media/uapi/v4l/vidioc-g-fmt.rst
Documentation/networking/rxrpc.txt
MAINTAINERS
Makefile
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cpufeature.c
arch/mips/configs/cavium_octeon_defconfig
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/loongson64/loongson-3/numa.c
arch/mips/sgi-ip27/ip27-memory.c
arch/riscv/Makefile
arch/riscv/boot/.gitignore [new file with mode: 0644]
arch/riscv/boot/Makefile [new file with mode: 0644]
arch/riscv/boot/install.sh [new file with mode: 0644]
arch/riscv/include/asm/module.h
arch/riscv/include/asm/uaccess.h
arch/riscv/include/asm/unistd.h
arch/riscv/include/uapi/asm/unistd.h [moved from arch/riscv/include/uapi/asm/syscalls.h with 53% similarity]
arch/riscv/kernel/cpu.c
arch/riscv/kernel/head.S
arch/riscv/kernel/vmlinux.lds.S
drivers/acpi/acpi_platform.c
drivers/cpufreq/ti-cpufreq.c
drivers/dma-buf/udmabuf.c
drivers/gnss/serial.c
drivers/gnss/sirf.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/sii902x.c
drivers/gpu/drm/bridge/tc358764.c
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fourcc.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/drm_info.c [deleted file]
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/imx/dw_hdmi-imx.c
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/imx-tve.c
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/meson/Kconfig
drivers/gpu/drm/meson/Makefile
drivers/gpu/drm/meson/meson_canvas.c
drivers/gpu/drm/meson/meson_canvas.h
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_drv.h
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_overlay.c [new file with mode: 0644]
drivers/gpu/drm/meson/meson_overlay.h [new file with mode: 0644]
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/meson/meson_registers.h
drivers/gpu/drm/meson/meson_vclk.c
drivers/gpu/drm/meson/meson_vclk.h
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/meson/meson_vpp.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_draw.c
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/qxl/qxl_object.h
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_lvds.c
drivers/gpu/drm/rockchip/cdn-dp-reg.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sti/sti_crtc.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_backend.h
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_frontend.h
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tinydrm/core/tinydrm-core.c
drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
drivers/gpu/drm/tinydrm/hx8357d.c
drivers/gpu/drm/tinydrm/ili9225.c
drivers/gpu/drm/tinydrm/ili9341.c
drivers/gpu/drm/tinydrm/mi0283qt.c
drivers/gpu/drm/tinydrm/mipi-dbi.c
drivers/gpu/drm/tinydrm/repaper.c
drivers/gpu/drm/tinydrm/st7586.c
drivers/gpu/drm/tinydrm/st7735r.c
drivers/gpu/drm/tve200/tve200_drv.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_gem.c
drivers/gpu/ipu-v3/ipu-cpmem.c
drivers/gpu/ipu-v3/ipu-ic.c
drivers/gpu/ipu-v3/ipu-image-convert.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/uhid.c
drivers/hv/hv_kvp.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/ipmmu-vmsa.c
drivers/media/cec/cec-adap.c
drivers/media/i2c/tc358743.c
drivers/media/pci/intel/ipu3/ipu3-cio2.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/vicodec/vicodec-core.c
drivers/media/platform/vim2m.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-event.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/misc/atmel-ssc.c
drivers/misc/sgi-gru/grukdump.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mtd/nand/raw/atmel/nand-controller.c
drivers/mtd/nand/raw/qcom_nandc.c
drivers/mtd/spi-nor/cadence-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/rcar/rcar_can.c
drivers/net/can/rx-offload.c
drivers/net/can/spi/hi311x.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/ucan.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb4/Makefile
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/cortina/gemini.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/lantiq_xrx200.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/alloc.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/qlogic/qed/qed_dcbx.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qlogic/qed/qed_rdma.h
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mscc.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/virtio_net.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/mediatek/mt76/Kconfig
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76x02.h
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/nvme/host/fc.c
drivers/nvmem/core.c
drivers/opp/ti-opp-supply.c
drivers/s390/net/ism_drv.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/ufs/ufs-hisi.c
drivers/scsi/ufs/ufs_quirks.h
drivers/scsi/ufs/ufshcd.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/slimbus/slimbus.h
drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
drivers/staging/media/sunxi/cedrus/cedrus.c
drivers/staging/vboxvideo/vbox_drv.c
drivers/uio/uio.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/pci.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/host/xhci-histb.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-tegra.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/appledisplay.c
fs/afs/rxrpc.c
fs/dax.c
fs/exec.c
fs/iomap.c
fs/nfs/callback_proc.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/flexfilelayout/flexfilelayout.h
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4state.c
fs/nilfs2/btnode.c
fs/read_write.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_file.c
fs/xfs/xfs_reflink.c
fs/xfs/xfs_trace.h
include/drm/drm_connector.h
include/drm/drm_drv.h
include/drm/drm_framebuffer.h
include/drm/drm_gem.h
include/drm/drm_gem_cma_helper.h
include/drm/drm_prime.h
include/drm/drm_syncobj.h
include/drm/tinydrm/tinydrm.h
include/linux/can/dev.h
include/linux/can/rx-offload.h
include/linux/dma-direct.h
include/linux/hid.h
include/linux/net_dim.h
include/linux/skbuff.h
include/linux/tcp.h
include/linux/usb/quirks.h
include/linux/xarray.h
include/media/v4l2-mem2mem.h
include/net/af_rxrpc.h
include/net/sctp/sctp.h
include/trace/events/rxrpc.h
include/uapi/drm/drm.h
include/uapi/drm/drm_fourcc.h
include/uapi/drm/v3d_drm.h
include/uapi/drm/virtgpu_drm.h
include/uapi/linux/input-event-codes.h
include/uapi/linux/v4l2-controls.h
include/uapi/linux/virtio_gpu.h
include/video/imx-ipu-v3.h
kernel/dma/swiotlb.c
lib/test_firmware.c
lib/test_xarray.c
lib/xarray.c
net/batman-adv/bat_v_elp.c
net/batman-adv/fragmentation.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/can/raw.c
net/ceph/messenger.c
net/core/dev.c
net/core/skbuff.c
net/ipv4/ip_tunnel_core.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/addrconf.c
net/ipv6/route.c
net/l2tp/l2tp_core.c
net/packet/af_packet.c
net/rxrpc/af_rxrpc.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/sch_fq.c
net/sctp/output.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_cdc.h
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ism.c
net/smc/smc_ism.h
net/smc/smc_wr.c
net/socket.c
net/tipc/discover.c
net/tipc/net.c
net/tipc/net.h
net/tipc/socket.c
scripts/coccinelle/api/drm-get-put.cocci [deleted file]
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_realtek.c
tools/power/cpupower/Makefile
tools/power/cpupower/bench/Makefile
tools/power/cpupower/debug/x86_64/Makefile
tools/power/cpupower/lib/cpufreq.c
tools/power/cpupower/lib/cpuidle.c
tools/power/cpupower/lib/cpupower.c
tools/power/cpupower/lib/cpupower_intern.h
tools/testing/selftests/tc-testing/tdc.py

diff --git a/CREDITS b/CREDITS
index 84cbec4c62115adc38b976504b04799bb6fb0469..c9273393fe14c12d1eb32f2ce65aba527a00c928 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2204,6 +2204,10 @@ S: Post Office Box 371
 S: North Little Rock, Arkansas 72115
 S: USA
 
+N: Christopher Li
+E: sparse@chrisli.org
+D: Sparse maintainer 2009 - 2018
+
 N: Stephan Linz
 E: linz@mazet.de
 E: Stephan.Linz@gmx.de
index 81d1d5a7472804e50a663480ef92dc67abc71ab5..19f4423e70d913ea2bf0801e4e14b57dc74e320f 100644 (file)
                                        prevent spurious wakeup);
                                n = USB_QUIRK_DELAY_CTRL_MSG (Device needs a
                                        pause after every control message);
+                               o = USB_QUIRK_HUB_SLOW_RESET (Hub needs extra
+                                       delay after resetting its port);
                        Example: quirks=0781:5580:bk,0a5c:5834:gij
 
        usbhid.mousepoll=
index 164bf71149fdf2e6ad099b45196cbd6d1d8347cc..30187d49dc2c7d38869c4073e60093d315c3fc4e 100644 (file)
@@ -32,16 +32,17 @@ Disclosure and embargoed information
 The security list is not a disclosure channel.  For that, see Coordination
 below.
 
-Once a robust fix has been developed, our preference is to release the
-fix in a timely fashion, treating it no differently than any of the other
-thousands of changes and fixes the Linux kernel project releases every
-month.
-
-However, at the request of the reporter, we will postpone releasing the
-fix for up to 5 business days after the date of the report or after the
-embargo has lifted; whichever comes first.  The only exception to that
-rule is if the bug is publicly known, in which case the preference is to
-release the fix as soon as it's available.
+Once a robust fix has been developed, the release process starts.  Fixes
+for publicly known bugs are released immediately.
+
+Although our preference is to release fixes for publicly undisclosed bugs
+as soon as they become available, this may be postponed at the request of
+the reporter or an affected party for up to 7 calendar days from the start
+of the release process, with an exceptional extension to 14 calendar days
+if it is agreed that the criticality of the bug requires more time.  The
+only valid reason for deferring the publication of a fix is to accommodate
+the logistics of QA and large scale rollouts which require release
+coordination.
 
 Whilst embargoed information may be shared with trusted individuals in
 order to develop a fix, such information will not be published alongside
index a4e705108f428e970b4c93be376ed3644dcb3649..dbe96cb5558ef5024fd9607a902c25ad430b4cb7 100644 (file)
@@ -74,7 +74,8 @@ using :c:func:`xa_load`.  xa_store will overwrite any entry with the
 new entry and return the previous entry stored at that index.  You can
 use :c:func:`xa_erase` instead of calling :c:func:`xa_store` with a
 ``NULL`` entry.  There is no difference between an entry that has never
-been stored to and one that has most recently had ``NULL`` stored to it.
+been stored to, one that has been erased and one that has most recently
+had ``NULL`` stored to it.
 
 You can conditionally replace an entry at an index by using
 :c:func:`xa_cmpxchg`.  Like :c:func:`cmpxchg`, it will only succeed if
@@ -105,23 +106,44 @@ may result in the entry being marked at some, but not all of the other
 indices.  Storing into one index may result in the entry retrieved by
 some, but not all of the other indices changing.
 
+Sometimes you need to ensure that a subsequent call to :c:func:`xa_store`
+will not need to allocate memory.  The :c:func:`xa_reserve` function
+will store a reserved entry at the indicated index.  Users of the normal
+API will see this entry as containing ``NULL``.  If you do not need to
+use the reserved entry, you can call :c:func:`xa_release` to remove the
+unused entry.  If another user has stored to the entry in the meantime,
+:c:func:`xa_release` will do nothing; if instead you want the entry to
+become ``NULL``, you should use :c:func:`xa_erase`.
+
+If all entries in the array are ``NULL``, the :c:func:`xa_empty` function
+will return ``true``.
+
 Finally, you can remove all entries from an XArray by calling
 :c:func:`xa_destroy`.  If the XArray entries are pointers, you may wish
 to free the entries first.  You can do this by iterating over all present
 entries in the XArray using the :c:func:`xa_for_each` iterator.
 
-ID assignment
--------------
+Allocating XArrays
+------------------
+
+If you use :c:func:`DEFINE_XARRAY_ALLOC` to define the XArray, or
+initialise it by passing ``XA_FLAGS_ALLOC`` to :c:func:`xa_init_flags`,
+the XArray changes to track whether entries are in use or not.
 
 You can call :c:func:`xa_alloc` to store the entry at any unused index
 in the XArray.  If you need to modify the array from interrupt context,
 you can use :c:func:`xa_alloc_bh` or :c:func:`xa_alloc_irq` to disable
-interrupts while allocating the ID.  Unlike :c:func:`xa_store`, allocating
-a ``NULL`` pointer does not delete an entry.  Instead it reserves an
-entry like :c:func:`xa_reserve` and you can release it using either
-:c:func:`xa_erase` or :c:func:`xa_release`.  To use ID assignment, the
-XArray must be defined with :c:func:`DEFINE_XARRAY_ALLOC`, or initialised
-by passing ``XA_FLAGS_ALLOC`` to :c:func:`xa_init_flags`,
+interrupts while allocating the ID.
+
+Using :c:func:`xa_store`, :c:func:`xa_cmpxchg` or :c:func:`xa_insert`
+will mark the entry as being allocated.  Unlike a normal XArray, storing
+``NULL`` will mark the entry as being in use, like :c:func:`xa_reserve`.
+To free an entry, use :c:func:`xa_erase` (or :c:func:`xa_release` if
+you only want to free the entry if it's ``NULL``).
+
+You cannot use ``XA_MARK_0`` with an allocating XArray as this mark
+is used to track whether an entry is free or not.  The other marks are
+available for your use.
 
 Memory allocation
 -----------------
@@ -158,6 +180,8 @@ Takes RCU read lock:
 
 Takes xa_lock internally:
  * :c:func:`xa_store`
+ * :c:func:`xa_store_bh`
+ * :c:func:`xa_store_irq`
  * :c:func:`xa_insert`
  * :c:func:`xa_erase`
  * :c:func:`xa_erase_bh`
@@ -167,6 +191,9 @@ Takes xa_lock internally:
  * :c:func:`xa_alloc`
  * :c:func:`xa_alloc_bh`
  * :c:func:`xa_alloc_irq`
+ * :c:func:`xa_reserve`
+ * :c:func:`xa_reserve_bh`
+ * :c:func:`xa_reserve_irq`
  * :c:func:`xa_destroy`
  * :c:func:`xa_set_mark`
  * :c:func:`xa_clear_mark`
@@ -177,6 +204,7 @@ Assumes xa_lock held on entry:
  * :c:func:`__xa_erase`
  * :c:func:`__xa_cmpxchg`
  * :c:func:`__xa_alloc`
+ * :c:func:`__xa_reserve`
  * :c:func:`__xa_set_mark`
  * :c:func:`__xa_clear_mark`
 
@@ -234,7 +262,8 @@ Sharing the XArray with interrupt context is also possible, either
 using :c:func:`xa_lock_irqsave` in both the interrupt handler and process
 context, or :c:func:`xa_lock_irq` in process context and :c:func:`xa_lock`
 in the interrupt handler.  Some of the more common patterns have helper
-functions such as :c:func:`xa_erase_bh` and :c:func:`xa_erase_irq`.
+functions such as :c:func:`xa_store_bh`, :c:func:`xa_store_irq`,
+:c:func:`xa_erase_bh` and :c:func:`xa_erase_irq`.
 
 Sometimes you need to protect access to the XArray with a mutex because
 that lock sits above another mutex in the locking hierarchy.  That does
@@ -322,7 +351,8 @@ to :c:func:`xas_retry`, and retry the operation if it returns ``true``.
      - :c:func:`xa_is_zero`
      - Zero entries appear as ``NULL`` through the Normal API, but occupy
        an entry in the XArray which can be used to reserve the index for
-       future use.
+       future use.  This is used by allocating XArrays for allocated entries
+       which are ``NULL``.
 
 Other internal entries may be added in the future.  As far as possible, they
 will be handled by :c:func:`xas_retry`.
index 057b81335775e7526805710324eb497fe7c04bcb..c65fd7a7467c09f1e7fa77ca3581de29f31653fd 100644 (file)
@@ -67,6 +67,8 @@ Required properties:
 Optional properties:
 - power-domains: Optional phandle to associated power domain as described in
        the file ../power/power_domain.txt
+- amlogic,canvas: phandle to canvas provider node as described in the file
+       ../soc/amlogic/amlogic,canvas.txt
 
 Required nodes:
 
index 3aeb0ec06fd02421bcb412fdfbca08747476b904..ba5469dd09f35393e339af8000d6ca776d1c2f31 100644 (file)
@@ -13,6 +13,7 @@ Required properties:
   - "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
   - "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
   - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
+  - "renesas,r8a77965-lvds" for R8A77965 (R-Car M3-N) compatible LVDS encoders
   - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
   - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
   - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
index f5e3c6f2095a502d420fec40af372c009e80e418..40f3d7c713bb13ccd4759bd2cef8f51c3b97253b 100644 (file)
@@ -1,47 +1,70 @@
 TPO TPG110 Panel
 ================
 
-This binding builds on the DPI bindings, adding a few properties
-as a superset of a DPI. See panel-dpi.txt for the required DPI
-bindings.
+This panel driver is a component that acts as an intermediary
+between an RGB output and a variety of panels. The panel
+driver is strapped up in electronics to the desired resolution
+and other properties, and has a control interface over 3WIRE
+SPI. By talking to the TPG110 over SPI, the strapped properties
+can be discovered and the hardware is therefore mostly
+self-describing.
+
+       +--------+
+SPI -> |  TPO   | -> physical display
+RGB -> | TPG110 |
+       +--------+
+
+If some electrical strap or alternate resolution is desired,
+this can be set up by taking software control of the display
+over the SPI interface. The interface can also adjust
+for properties of the display such as gamma correction and
+certain electrical driving levels.
+
+The TPG110 does not know the physical dimensions of the panel
+connected, so this needs to be specified in the device tree.
+
+It requires a GPIO line for control of its reset line.
+
+The serial protocol has line names that resemble I2C but the
+protocol is not I2C but 3WIRE SPI.
 
 Required properties:
-- compatible : "tpo,tpg110"
+- compatible : one of:
+  "ste,nomadik-nhk15-display", "tpo,tpg110"
+  "tpo,tpg110"
 - grestb-gpios : panel reset GPIO
-- scen-gpios : serial control enable GPIO
-- scl-gpios : serial control clock line GPIO
-- sda-gpios : serial control data line GPIO
+- width-mm : see display/panel/panel-common.txt
+- height-mm : see display/panel/panel-common.txt
+
+The device needs to be a child of an SPI bus, see
+spi/spi-bus.txt. The SPI child must set the following
+properties:
+- spi-3wire
+- spi-max-frequency = <3000000>;
+as these are characteristics of this device.
 
-Required nodes:
-- Video port for DPI input, see panel-dpi.txt
-- Panel timing for DPI setup, see panel-dpi.txt
+The device node can contain one 'port' child node with one child
+'endpoint' node, according to the bindings defined in
+media/video-interfaces.txt. This node should describe panel's video bus.
 
 Example
 -------
 
-panel {
-       compatible = "tpo,tpg110", "panel-dpi";
-       grestb-gpios = <&stmpe_gpio44 5 GPIO_ACTIVE_LOW>;
-       scen-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
-       scl-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
-       sda-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+panel: display@0 {
+       compatible = "tpo,tpg110";
+       reg = <0>;
+       spi-3wire;
+       /* 320 ns min period ~= 3 MHz */
+       spi-max-frequency = <3000000>;
+       /* Width and height from data sheet */
+       width-mm = <116>;
+       height-mm = <87>;
+       grestb-gpios = <&foo_gpio 5 GPIO_ACTIVE_LOW>;
        backlight = <&bl>;
 
        port {
                nomadik_clcd_panel: endpoint {
-                       remote-endpoint = <&nomadik_clcd_pads>;
+                       remote-endpoint = <&foo>;
                };
        };
-
-       panel-timing {
-               clock-frequency = <33200000>;
-               hactive = <800>;
-               hback-porch = <216>;
-               hfront-porch = <40>;
-               hsync-len = <1>;
-               vactive = <480>;
-               vback-porch = <35>;
-               vfront-porch = <10>;
-               vsync-len = <1>;
-       };
 };
index 9de67be632d1a7a42bbd765e5fa3cbd07b9a01f5..3c855d9f27193bcb03f365cc8c4a3a78a5d478a0 100644 (file)
@@ -4,7 +4,9 @@ Required Properties:
 
   - compatible: must be one of the following.
     - "renesas,du-r8a7743" for R8A7743 (RZ/G1M) compatible DU
+    - "renesas,du-r8a7744" for R8A7744 (RZ/G1N) compatible DU
     - "renesas,du-r8a7745" for R8A7745 (RZ/G1E) compatible DU
+    - "renesas,du-r8a77470" for R8A77470 (RZ/G1C) compatible DU
     - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
@@ -52,7 +54,9 @@ corresponding to each DU output.
                         Port0          Port1          Port2          Port3
 -----------------------------------------------------------------------------
  R8A7743 (RZ/G1M)       DPAD 0         LVDS 0         -              -
+ R8A7744 (RZ/G1N)       DPAD 0         LVDS 0         -              -
  R8A7745 (RZ/G1E)       DPAD 0         DPAD 1         -              -
+ R8A77470 (RZ/G1C)      DPAD 0         DPAD 1         LVDS 0         -
  R8A7779 (R-Car H1)     DPAD 0         DPAD 1         -              -
  R8A7790 (R-Car H2)     DPAD 0         LVDS 0         LVDS 1         -
  R8A7791 (R-Car M2-W)   DPAD 0         LVDS 0         -              -
index 903a78da65be288cf750af872584b60e9f42c06f..3a9926f99937039022d283817beac8e9bcbbc926 100644 (file)
@@ -17,7 +17,7 @@ Example:
                reg = <1>;
                clocks = <&clk32m>;
                interrupt-parent = <&gpio4>;
-               interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+               interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
                vdd-supply = <&reg5v0>;
                xceiver-supply = <&reg5v0>;
        };
index cc4372842bf37670284d9b676699b5eb00882de9..9936b9ee67c36672afeb050a5641aa44cebbb728 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
 - compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
              "renesas,can-r8a7744" if CAN controller is a part of R8A7744 SoC.
              "renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC.
+             "renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC.
              "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
              "renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
              "renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
@@ -14,26 +15,32 @@ Required properties:
              "renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC.
              "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
              "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
+             "renesas,can-r8a77965" if CAN controller is a part of R8A77965 SoC.
              "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
              "renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1
              compatible device.
-             "renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device.
+             "renesas,rcar-gen3-can" for a generic R-Car Gen3 or RZ/G2
+             compatible device.
              When compatible with the generic version, nodes must list the
              SoC-specific version corresponding to the platform first
              followed by the generic version.
 
 - reg: physical base address and size of the R-Car CAN register map.
 - interrupts: interrupt specifier for the sole interrupt.
-- clocks: phandles and clock specifiers for 3 CAN clock inputs.
-- clock-names: 3 clock input name strings: "clkp1", "clkp2", "can_clk".
+- clocks: phandles and clock specifiers for 2 CAN clock inputs for RZ/G2
+         devices.
+         phandles and clock specifiers for 3 CAN clock inputs for every other
+         SoC.
+- clock-names: 2 clock input name strings for RZ/G2: "clkp1", "can_clk".
+              3 clock input name strings for every other SoC: "clkp1", "clkp2",
+              "can_clk".
 - pinctrl-0: pin control group to be used for this controller.
 - pinctrl-names: must be "default".
 
-Required properties for "renesas,can-r8a7795" and "renesas,can-r8a7796"
-compatible:
-In R8A7795 and R8A7796 SoCs, "clkp2" can be CANFD clock. This is a div6 clock
-and can be used by both CAN and CAN FD controller at the same time. It needs to
-be scaled to maximum frequency if any of these controllers use it. This is done
+Required properties for R8A7795, R8A7796 and R8A77965:
+For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can
+be used by both CAN and CAN FD controller at the same time. It needs to be
+scaled to maximum frequency if any of these controllers use it. This is done
 using the below properties:
 
 - assigned-clocks: phandle of clkp2(CANFD) clock.
@@ -42,8 +49,9 @@ using the below properties:
 Optional properties:
 - renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are:
                            <0x0> (default) : Peripheral clock (clkp1)
-                           <0x1> : Peripheral clock (clkp2)
-                           <0x3> : Externally input clock
+                           <0x1> : Peripheral clock (clkp2) (not supported by
+                                   RZ/G2 devices)
+                           <0x3> : External input clock
 
 Example
 -------
index 3ceeb8de11963572cc1bd8ce324433e0dbf6bd03..35694c0c376b91c8b51982d1dce992682b983d92 100644 (file)
@@ -7,7 +7,7 @@ limitations.
 Current Binding
 ---------------
 
-Switches are true Linux devices and can be probes by any means. Once
+Switches are true Linux devices and can be probed by any means. Once
 probed, they register to the DSA framework, passing a node
 pointer. This node is expected to fulfil the following binding, and
 may contain additional properties as required by the device it is
index d0f3c6b032009d6a516cd409611e86b9d29dd4f5..54a696d961a7c923761c0765f985039d575e32e7 100644 (file)
@@ -79,9 +79,6 @@ count for the TTM, which will call your initialization function.
 
 See the radeon_ttm.c file for an example of usage.
 
-.. kernel-doc:: drivers/gpu/drm/drm_global.c
-   :export:
-
 
 The Graphics Execution Manager (GEM)
 ====================================
index 5c9d86c962af963d3a8bb688f9a304b847e9bfe3..ab347dec507960ae696d026fe2ce4a2cc88a0cc9 100644 (file)
@@ -28,22 +28,16 @@ them, but also all the virtual ones used by KVM, so everyone qualifies).
 
 Contact: Daniel Vetter, Thierry Reding, respective driver maintainers
 
-Switch from reference/unreference to get/put
---------------------------------------------
-
-For some reason DRM core uses ``reference``/``unreference`` suffixes for
-refcounting functions, but kernel uses ``get``/``put`` (e.g.
-``kref_get``/``put()``). It would be good to switch over for consistency, and
-it's shorter. Needs to be done in 3 steps for each pair of functions:
 
-* Create new ``get``/``put`` functions, define the old names as compatibility
-  wrappers
-* Switch over each file/driver using a cocci-generated spatch.
-* Once all users of the old names are gone, remove them.
+Remove custom dumb_map_offset implementations
+---------------------------------------------
 
-This way drivers/patches in the progress of getting merged won't break.
+All GEM based drivers should be using drm_gem_create_mmap_offset() instead.
+Audit each individual driver, make sure it'll work with the generic
+implementation (there's lots of outdated locking leftovers in various
+implementations), and then remove it.
 
-Contact: Daniel Vetter
+Contact: Daniel Vetter, respective driver maintainers
 
 Convert existing KMS drivers to atomic modesetting
 --------------------------------------------------
@@ -234,6 +228,19 @@ efficient.
 
 Contact: Daniel Vetter
 
+Defaults for .gem_prime_import and export
+-----------------------------------------
+
+Most drivers don't need to set drm_driver->gem_prime_import and
+->gem_prime_export now that drm_gem_prime_import() and drm_gem_prime_export()
+are the default.
+
+struct drm_gem_object_funcs
+---------------------------
+
+GEM objects can now have a function table instead of having the callbacks on the
+DRM driver struct. This is now the preferred way and drivers can be moved over.
+
 Core refactorings
 =================
 
index cef220c176a405b8f6839d846e074d295bd2b81e..a8c0873beb952e620db9bb2f2df823624ac90650 100644 (file)
@@ -190,16 +190,7 @@ A few EV_REL codes have special meanings:
 * REL_WHEEL, REL_HWHEEL:
 
   - These codes are used for vertical and horizontal scroll wheels,
-    respectively. The value is the number of "notches" moved on the wheel, the
-    physical size of which varies by device. For high-resolution wheels (which
-    report multiple events for each notch of movement, or do not have notches)
-    this may be an approximation based on the high-resolution scroll events.
-
-* REL_WHEEL_HI_RES:
-
-  - If a vertical scroll wheel supports high-resolution scrolling, this code
-    will be emitted in addition to REL_WHEEL. The value is the (approximate)
-    distance travelled by the user's finger, in microns.
+    respectively.
 
 EV_ABS
 ------
index f7ac8d0d3af14a1a6d951df74847972220711133..b65dc078abeb8ca4a1a9a045eddc2d1b8844c333 100644 (file)
@@ -40,7 +40,7 @@ To use the :ref:`format` ioctls applications set the ``type`` field of the
 the desired operation. Both drivers and applications must set the remainder of
 the :c:type:`v4l2_format` structure to 0.
 
-.. _v4l2-meta-format:
+.. c:type:: v4l2_meta_format
 
 .. tabularcolumns:: |p{1.4cm}|p{2.2cm}|p{13.9cm}|
 
index 3ead350e099f97a6146ff98bf0126a8388149883..9ea494a8facab2cca0b51745cda1af6f0f53fd4c 100644 (file)
@@ -132,6 +132,11 @@ The format as returned by :ref:`VIDIOC_TRY_FMT <VIDIOC_G_FMT>` must be identical
       - ``sdr``
       - Definition of a data format, see :ref:`pixfmt`, used by SDR
        capture and output devices.
+    * -
+      - struct :c:type:`v4l2_meta_format`
+      - ``meta``
+      - Definition of a metadata format, see :ref:`meta-formats`, used by
+       metadata capture devices.
     * -
       - __u8
       - ``raw_data``\ [200]
index 605e00cdd6beb1d024519ab8417464fc12064724..89f1302d593a5c0404ed8a434ba580e8440a9139 100644 (file)
@@ -1056,18 +1056,23 @@ The kernel interface functions are as follows:
 
        u32 rxrpc_kernel_check_life(struct socket *sock,
                                    struct rxrpc_call *call);
+       void rxrpc_kernel_probe_life(struct socket *sock,
+                                    struct rxrpc_call *call);
 
-     This returns a number that is updated when ACKs are received from the peer
-     (notably including PING RESPONSE ACKs which we can elicit by sending PING
-     ACKs to see if the call still exists on the server).  The caller should
-     compare the numbers of two calls to see if the call is still alive after
-     waiting for a suitable interval.
+     The first function returns a number that is updated when ACKs are received
+     from the peer (notably including PING RESPONSE ACKs which we can elicit by
+     sending PING ACKs to see if the call still exists on the server).  The
+     caller should compare the numbers of two calls to see if the call is still
+     alive after waiting for a suitable interval.
 
      This allows the caller to work out if the server is still contactable and
      if the call is still alive on the server whilst waiting for the server to
      process a client operation.
 
-     This function may transmit a PING ACK.
+     The second function causes a ping ACK to be transmitted to try to provoke
+     the peer into responding, which would then cause the value returned by the
+     first function to change.  Note that this must be called in TASK_RUNNING
+     state.
 
  (*) Get reply timestamp.
 
index 1026150ae90fc80e26687186adc7ef02e08e4f47..254b7b267731a90c1baea0a095be4f60fd2201f7 100644 (file)
@@ -180,6 +180,7 @@ F:  drivers/net/hamradio/6pack.c
 
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
 M:     Realtek linux nic maintainers <nic_swsd@realtek.com>
+M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/realtek/r8169.c
@@ -717,7 +718,7 @@ F:  include/linux/mfd/altera-a10sr.h
 F:     include/dt-bindings/reset/altr,rst-mgr-a10sr.h
 
 ALTERA TRIPLE SPEED ETHERNET DRIVER
-M:     Vince Bridgers <vbridger@opensource.altera.com>
+M:     Thor Thayer <thor.thayer@linux.intel.com>
 L:     netdev@vger.kernel.org
 L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
@@ -3276,6 +3277,12 @@ F:       include/uapi/linux/caif/
 F:     include/net/caif/
 F:     net/caif/
 
+CAKE QDISC
+M:     Toke Høiland-Jørgensen <toke@toke.dk>
+L:     cake@lists.bufferbloat.net (moderated for non-subscribers)
+S:     Maintained
+F:     net/sched/sch_cake.c
+
 CALGARY x86-64 IOMMU
 M:     Muli Ben-Yehuda <mulix@mulix.org>
 M:     Jon Mason <jdmason@kudzu.us>
@@ -5541,6 +5548,7 @@ F:        net/bridge/
 ETHERNET PHY LIBRARY
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/ABI/testing/sysfs-bus-mdio
@@ -6312,6 +6320,7 @@ F:        tools/testing/selftests/gpio/
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
+M:     Bartosz Golaszewski <bgolaszewski@baylibre.com>
 L:     linux-gpio@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
 S:     Maintained
@@ -7449,6 +7458,20 @@ S:       Maintained
 F:     Documentation/fb/intelfb.txt
 F:     drivers/video/fbdev/intelfb/
 
+INTEL GPIO DRIVERS
+M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+L:     linux-gpio@vger.kernel.org
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
+F:     drivers/gpio/gpio-ich.c
+F:     drivers/gpio/gpio-intel-mid.c
+F:     drivers/gpio/gpio-lynxpoint.c
+F:     drivers/gpio/gpio-merrifield.c
+F:     drivers/gpio/gpio-ml-ioh.c
+F:     drivers/gpio/gpio-pch.c
+F:     drivers/gpio/gpio-sch.c
+F:     drivers/gpio/gpio-sodaville.c
+
 INTEL GVT-g DRIVERS (Intel GPU Virtualization)
 M:     Zhenyu Wang <zhenyuw@linux.intel.com>
 M:     Zhi Wang <zhi.a.wang@intel.com>
@@ -7459,12 +7482,6 @@ T:       git https://github.com/intel/gvt-linux.git
 S:     Supported
 F:     drivers/gpu/drm/i915/gvt/
 
-INTEL PMIC GPIO DRIVER
-R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-S:     Maintained
-F:     drivers/gpio/gpio-*cove.c
-F:     drivers/gpio/gpio-msic.c
-
 INTEL HID EVENT DRIVER
 M:     Alex Hung <alex.hung@canonical.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -7552,12 +7569,6 @@ W:       https://01.org/linux-acpi
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
 
-INTEL MERRIFIELD GPIO DRIVER
-M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-L:     linux-gpio@vger.kernel.org
-S:     Maintained
-F:     drivers/gpio/gpio-merrifield.c
-
 INTEL MIC DRIVERS (mic)
 M:     Sudeep Dutt <sudeep.dutt@intel.com>
 M:     Ashutosh Dixit <ashutosh.dixit@intel.com>
@@ -7590,6 +7601,13 @@ F:       drivers/platform/x86/intel_punit_ipc.c
 F:     arch/x86/include/asm/intel_pmc_ipc.h
 F:     arch/x86/include/asm/intel_punit_ipc.h
 
+INTEL PMIC GPIO DRIVERS
+M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
+F:     drivers/gpio/gpio-*cove.c
+F:     drivers/gpio/gpio-msic.c
+
 INTEL MULTIFUNCTION PMIC DEVICE DRIVERS
 R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 S:     Maintained
@@ -13991,11 +14009,10 @@ F:    drivers/tty/serial/sunzilog.h
 F:     drivers/tty/vcc.c
 
 SPARSE CHECKER
-M:     "Christopher Li" <sparse@chrisli.org>
+M:     "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
 L:     linux-sparse@vger.kernel.org
 W:     https://sparse.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
-T:     git git://git.kernel.org/pub/scm/devel/sparse/chrisl/sparse.git
 S:     Maintained
 F:     include/linux/compiler.h
 
@@ -14092,6 +14109,7 @@ F:      Documentation/devicetree/bindings/iio/proximity/vl53l0x.txt
 
 STABLE BRANCH
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+M:     Sasha Levin <sashal@kernel.org>
 L:     stable@vger.kernel.org
 S:     Supported
 F:     Documentation/process/stable-kernel-rules.rst
index ddbf627cad8f5fd8a2d0d06a913294d88a0ff878..0ce4e29ee342fa191ecd0e3d3dc0e357eae7997c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 VERSION = 4
 PATCHLEVEL = 20
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
-NAME = "People's Front"
+EXTRAVERSION = -rc4
+NAME = Shy Crocodile
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 0c909c4a932ff3da741fbda7c16cf6a3780d6107..842fb9572661063bd0db34b27e14d4829093208d 100644 (file)
                         SCTLR_ELx_SA     | SCTLR_ELx_I    | SCTLR_ELx_WXN | \
                         SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0)
 
-#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffff
+#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffffUL
 #error "Inconsistent SCTLR_EL2 set/clear bits"
 #endif
 
                         SCTLR_EL1_UMA | SCTLR_ELx_WXN     | ENDIAN_CLEAR_EL1 |\
                         SCTLR_ELx_DSSBS | SCTLR_EL1_NTWI  | SCTLR_EL1_RES0)
 
-#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffff
+#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffffUL
 #error "Inconsistent SCTLR_EL1 set/clear bits"
 #endif
 
index af50064dea51ad23c7c47cbe4786839fbf8603fa..aec5ecb85737edbe274b4f1c8a9082ac4a6947e1 100644 (file)
@@ -1333,7 +1333,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .cpu_enable = cpu_enable_hw_dbm,
        },
 #endif
-#ifdef CONFIG_ARM64_SSBD
        {
                .desc = "CRC32 instructions",
                .capability = ARM64_HAS_CRC32,
@@ -1343,6 +1342,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .field_pos = ID_AA64ISAR0_CRC32_SHIFT,
                .min_field_value = 1,
        },
+#ifdef CONFIG_ARM64_SSBD
        {
                .desc = "Speculative Store Bypassing Safe (SSBS)",
                .capability = ARM64_SSBS,
index 490b12af103c1285043ecfec912b1839c5586f06..c52d0efacd1466f0320a025d3519ffb8ba212a09 100644 (file)
@@ -140,6 +140,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_STAGING=y
 CONFIG_OCTEON_ETHERNET=y
+CONFIG_OCTEON_USB=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_RAS=y
 CONFIG_EXT4_FS=y
index ea09ed6a80a9f2dc0aa625e2fcec0b34e2c6acea..8c6c48ed786a1527c22ba5b46bcdad70029e5865 100644 (file)
@@ -794,6 +794,7 @@ static void __init arch_mem_init(char **cmdline_p)
 
        /* call board setup routine */
        plat_mem_setup();
+       memblock_set_bottom_up(true);
 
        /*
         * Make sure all kernel memory is in the maps.  The "UP" and
index 0f852e1b589193d43f9125cfbfa303d6b47c6fed..15e103c6d799ebd90ad3f55a954c1d40329d5bac 100644 (file)
@@ -2260,10 +2260,8 @@ void __init trap_init(void)
                unsigned long size = 0x200 + VECTORSPACING*64;
                phys_addr_t ebase_pa;
 
-               memblock_set_bottom_up(true);
                ebase = (unsigned long)
                        memblock_alloc_from(size, 1 << fls(size), 0);
-               memblock_set_bottom_up(false);
 
                /*
                 * Try to ensure ebase resides in KSeg0 if possible.
@@ -2307,6 +2305,7 @@ void __init trap_init(void)
        if (board_ebase_setup)
                board_ebase_setup();
        per_cpu_trap_init(true);
+       memblock_set_bottom_up(false);
 
        /*
         * Copy the generic exception handlers to their final destination.
index 622761878cd11bd54e53affa43e5504c0aadc9c0..60bf0a1cb75719d731b60f8b2fe2954074dea77b 100644 (file)
@@ -231,6 +231,8 @@ static __init void prom_meminit(void)
                        cpumask_clear(&__node_data[(node)]->cpumask);
                }
        }
+       max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
+
        for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
                node = cpu / loongson_sysconf.cores_per_node;
                if (node >= num_online_nodes())
@@ -248,19 +250,9 @@ static __init void prom_meminit(void)
 
 void __init paging_init(void)
 {
-       unsigned node;
        unsigned long zones_size[MAX_NR_ZONES] = {0, };
 
        pagetable_init();
-
-       for_each_online_node(node) {
-               unsigned long  start_pfn, end_pfn;
-
-               get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
-
-               if (end_pfn > max_low_pfn)
-                       max_low_pfn = end_pfn;
-       }
 #ifdef CONFIG_ZONE_DMA32
        zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
 #endif
index d8b8444d679527e3843ea1de091be70926355f34..813d13f92957ed00715ac5914d62dc09bcba1861 100644 (file)
@@ -435,6 +435,7 @@ void __init prom_meminit(void)
 
        mlreset();
        szmem();
+       max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
 
        for (node = 0; node < MAX_COMPACT_NODES; node++) {
                if (node_online(node)) {
@@ -455,18 +456,8 @@ extern void setup_zero_pages(void);
 void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES] = {0, };
-       unsigned node;
 
        pagetable_init();
-
-       for_each_online_node(node) {
-               unsigned long start_pfn, end_pfn;
-
-               get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
-
-               if (end_pfn > max_low_pfn)
-                       max_low_pfn = end_pfn;
-       }
        zones_size[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(zones_size);
 }
index 4af153a182b071fcd4853a8853fb94fb1333312b..4b594f2e4f7ebd9eb791f6c2709f4023d3aa76c6 100644 (file)
@@ -71,6 +71,10 @@ KBUILD_CFLAGS += $(call cc-option,-mstrict-align)
 # arch specific predefines for sparse
 CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)
 
+# Default target when executing plain make
+boot           := arch/riscv/boot
+KBUILD_IMAGE   := $(boot)/Image.gz
+
 head-y := arch/riscv/kernel/head.o
 
 core-y += arch/riscv/kernel/ arch/riscv/mm/
@@ -81,4 +85,13 @@ PHONY += vdso_install
 vdso_install:
        $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
 
-all: vmlinux
+all: Image.gz
+
+Image: vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+Image.%: Image
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+zinstall install:
+       $(Q)$(MAKE) $(build)=$(boot) $@
diff --git a/arch/riscv/boot/.gitignore b/arch/riscv/boot/.gitignore
new file mode 100644 (file)
index 0000000..8dab0bb
--- /dev/null
@@ -0,0 +1,2 @@
+Image
+Image.gz
diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile
new file mode 100644 (file)
index 0000000..0990a9f
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# arch/riscv/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2018, Anup Patel.
+# Author: Anup Patel <anup@brainfault.org>
+#
+# Based on the ia64 and arm64 boot/Makefile.
+#
+
+OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+targets := Image
+
+$(obj)/Image: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/Image.gz: $(obj)/Image FORCE
+       $(call if_changed,gzip)
+
+install:
+       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+       $(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall:
+       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+       $(obj)/Image.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/riscv/boot/install.sh b/arch/riscv/boot/install.sh
new file mode 100644 (file)
index 0000000..18c3915
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# arch/riscv/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+#
+# "make install" script for the RISC-V Linux port
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+verify () {
+       if [ ! -f "$1" ]; then
+               echo ""                                                   1>&2
+               echo " *** Missing file: $1"                              1>&2
+               echo ' *** You need to run "make" before "make install".' 1>&2
+               echo ""                                                   1>&2
+               exit 1
+       fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+if [ "$(basename $2)" = "Image.gz" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  base=vmlinuz
+else
+# Normal install
+  echo "Installing normal kernel"
+  base=vmlinux
+fi
+
+if [ -f $4/$base-$1 ]; then
+  mv $4/$base-$1 $4/$base-$1.old
+fi
+cat $2 > $4/$base-$1
+
+# Install system map file
+if [ -f $4/System.map-$1 ]; then
+  mv $4/System.map-$1 $4/System.map-$1.old
+fi
+cp $3 $4/System.map-$1
index 349df33808c4231d155d2e6018e19cc4cb19cb4d..cd2af4b013e3826e3b43f44565a9b6c1c6ae7b70 100644 (file)
@@ -8,6 +8,7 @@
 
 #define MODULE_ARCH_VERMAGIC    "riscv"
 
+struct module;
 u64 module_emit_got_entry(struct module *mod, u64 val);
 u64 module_emit_plt_entry(struct module *mod, u64 val);
 
index 473cfc84e412f3827703caaadffa34a8983c978d..8c3e3e3c8be1204b67076985a9b54e80217707b1 100644 (file)
@@ -400,13 +400,13 @@ extern unsigned long __must_check __asm_copy_from_user(void *to,
 static inline unsigned long
 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-       return __asm_copy_to_user(to, from, n);
+       return __asm_copy_from_user(to, from, n);
 }
 
 static inline unsigned long
 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-       return __asm_copy_from_user(to, from, n);
+       return __asm_copy_to_user(to, from, n);
 }
 
 extern long strncpy_from_user(char *dest, const char __user *src, long count);
index eff7aa9aa1637851aadd871807644560bef5c412..fef96f117b4def3fe9a99ec9ca8b26d2278e087c 100644 (file)
 
 /*
  * There is explicitly no include guard here because this file is expected to
- * be included multiple times.  See uapi/asm/syscalls.h for more info.
+ * be included multiple times.
  */
 
-#define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SYS_CLONE
+
 #include <uapi/asm/unistd.h>
-#include <uapi/asm/syscalls.h>
similarity index 53%
rename from arch/riscv/include/uapi/asm/syscalls.h
rename to arch/riscv/include/uapi/asm/unistd.h
index 206dc4b0f6ea8423bf6446e2e13e679373a43ec5..1f3bd3ebbb0d27f8abcdd092d1c19fe04f2d6457 100644 (file)
@@ -1,13 +1,25 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
- * Copyright (C) 2017-2018 SiFive
+ * Copyright (C) 2018 David Abdurachmanov <david.abdurachmanov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/*
- * There is explicitly no include guard here because this file is expected to
- * be included multiple times in order to define the syscall macros via
- * __SYSCALL.
- */
+#ifdef __LP64__
+#define __ARCH_WANT_NEW_STAT
+#endif /* __LP64__ */
+
+#include <asm-generic/unistd.h>
 
 /*
  * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
index 3a5a2ee31547b2ca1f3ec0f0cf613ff3448e85e3..b4a7d4427fbb9430e02cdc1855729a9eba90c815 100644 (file)
@@ -64,7 +64,7 @@ int riscv_of_processor_hartid(struct device_node *node)
 
 static void print_isa(struct seq_file *f, const char *orig_isa)
 {
-       static const char *ext = "mafdc";
+       static const char *ext = "mafdcsu";
        const char *isa = orig_isa;
        const char *e;
 
@@ -88,11 +88,14 @@ static void print_isa(struct seq_file *f, const char *orig_isa)
        /*
         * Check the rest of the ISA string for valid extensions, printing those
         * we find.  RISC-V ISA strings define an order, so we only print the
-        * extension bits when they're in order.
+        * extension bits when they're in order. Hide the supervisor (S)
+        * extension from userspace as it's not accessible from there.
         */
        for (e = ext; *e != '\0'; ++e) {
                if (isa[0] == e[0]) {
-                       seq_write(f, isa, 1);
+                       if (isa[0] != 's')
+                               seq_write(f, isa, 1);
+
                        isa++;
                }
        }
index 711190d473d41f47dd52f9fc4720df720ebf57be..fe884cd69abd8f0d7b3fe3a9e20b781937a32502 100644 (file)
@@ -44,6 +44,16 @@ ENTRY(_start)
        amoadd.w a3, a2, (a3)
        bnez a3, .Lsecondary_start
 
+       /* Clear BSS for flat non-ELF images */
+       la a3, __bss_start
+       la a4, __bss_stop
+       ble a4, a3, clear_bss_done
+clear_bss:
+       REG_S zero, (a3)
+       add a3, a3, RISCV_SZPTR
+       blt a3, a4, clear_bss
+clear_bss_done:
+
        /* Save hart ID and DTB physical address */
        mv s0, a0
        mv s1, a1
index ece84991609ca56d2d3549d1a2dde2139a943028..65df1dfdc30385be7a9a149034a0ba66a5bbbd8e 100644 (file)
@@ -74,7 +74,7 @@ SECTIONS
                *(.sbss*)
        }
 
-       BSS_SECTION(0, 0, 0)
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
 
        EXCEPTION_TABLE(0x10)
        NOTES
index eaa60c94205a82f685190a5c0790d6ca91df69cb..1f32caa87686e2369b0f4841447d5ab5093b993d 100644 (file)
@@ -30,6 +30,7 @@ static const struct acpi_device_id forbidden_id_list[] = {
        {"PNP0200",  0},        /* AT DMA Controller */
        {"ACPI0009", 0},        /* IOxAPIC */
        {"ACPI000A", 0},        /* IOAPIC */
+       {"SMB0001",  0},        /* ACPI SMBUS virtual device */
        {"", 0},
 };
 
index 3f0e2a14895a03dc0c4bc1d01c032d0f50a4b4ae..22b53bf268179ad8c2e873dd9637af61adf2f54d 100644 (file)
@@ -201,19 +201,28 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
        {},
 };
 
+static const struct of_device_id *ti_cpufreq_match_node(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+
+       np = of_find_node_by_path("/");
+       match = of_match_node(ti_cpufreq_of_match, np);
+       of_node_put(np);
+
+       return match;
+}
+
 static int ti_cpufreq_probe(struct platform_device *pdev)
 {
        u32 version[VERSION_COUNT];
-       struct device_node *np;
        const struct of_device_id *match;
        struct opp_table *ti_opp_table;
        struct ti_cpufreq_data *opp_data;
        const char * const reg_names[] = {"vdd", "vbb"};
        int ret;
 
-       np = of_find_node_by_path("/");
-       match = of_match_node(ti_cpufreq_of_match, np);
-       of_node_put(np);
+       match = dev_get_platdata(&pdev->dev);
        if (!match)
                return -ENODEV;
 
@@ -290,7 +299,14 @@ fail_put_node:
 
 static int ti_cpufreq_init(void)
 {
-       platform_device_register_simple("ti-cpufreq", -1, NULL, 0);
+       const struct of_device_id *match;
+
+       /* Check to ensure we are on a compatible platform */
+       match = ti_cpufreq_match_node();
+       if (match)
+               platform_device_register_data(NULL, "ti-cpufreq", -1, match,
+                                             sizeof(*match));
+
        return 0;
 }
 module_init(ti_cpufreq_init);
index 5b44ef226904f9be2530b992c3d06ed338dca53c..fc359ca4503d127fda5f9f631f95d98c4a1d671a 100644 (file)
@@ -184,6 +184,7 @@ static long udmabuf_create(const struct udmabuf_create_list *head,
        exp_info.ops  = &udmabuf_ops;
        exp_info.size = ubuf->pagecount << PAGE_SHIFT;
        exp_info.priv = ubuf;
+       exp_info.flags = O_RDWR;
 
        buf = dma_buf_export(&exp_info);
        if (IS_ERR(buf)) {
index b01ba4438501a959de7796dc2eff67a6126d88e3..31e891f00175c635a9ee92c7e0f090eb135fc29b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/sched.h>
 #include <linux/serdev.h>
 #include <linux/slab.h>
 
@@ -63,7 +64,7 @@ static int gnss_serial_write_raw(struct gnss_device *gdev,
        int ret;
 
        /* write is only buffered synchronously */
-       ret = serdev_device_write(serdev, buf, count, 0);
+       ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);
        if (ret < 0)
                return ret;
 
index 79cb98950013bbb60f4ff4126cd562453441045a..71d014edd16760d6c37dad72836ed9e13cbfffba 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/sched.h>
 #include <linux/serdev.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
@@ -83,7 +84,7 @@ static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,
        int ret;
 
        /* write is only buffered synchronously */
-       ret = serdev_device_write(serdev, buf, count, 0);
+       ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);
        if (ret < 0)
                return ret;
 
index 8269cffc2967f772ba2da14e566fd136bb68da56..6a50f9f59c901b6d38069a67b5b9f7881e8a43b6 100644 (file)
@@ -35,8 +35,8 @@
 #define gpio_mockup_err(...)   pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__)
 
 enum {
-       GPIO_MOCKUP_DIR_OUT = 0,
-       GPIO_MOCKUP_DIR_IN = 1,
+       GPIO_MOCKUP_DIR_IN = 0,
+       GPIO_MOCKUP_DIR_OUT = 1,
 };
 
 /*
@@ -131,7 +131,7 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
-       return chip->lines[offset].dir;
+       return !chip->lines[offset].dir;
 }
 
 static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
index bfe4c5c9f41cef3a9c3a483e5283e015d840bc91..e9600b556f397babf8c472ceb2b012f2de97b42a 100644 (file)
@@ -268,8 +268,8 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 
        if (pxa_gpio_has_pinctrl()) {
                ret = pinctrl_gpio_direction_input(chip->base + offset);
-               if (!ret)
-                       return 0;
+               if (ret)
+                       return ret;
        }
 
        spin_lock_irqsave(&gpio_lock, flags);
index 230e41562462b27fdf5d11874b3de8c34c107707..a2cbb474901c224bebae335cd0789273a78955ae 100644 (file)
@@ -1295,7 +1295,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
        if (!gdev->descs) {
                status = -ENOMEM;
-               goto err_free_gdev;
+               goto err_free_ida;
        }
 
        if (chip->ngpio == 0) {
@@ -1427,8 +1427,9 @@ err_free_label:
        kfree_const(gdev->label);
 err_free_descs:
        kfree(gdev->descs);
-err_free_gdev:
+err_free_ida:
        ida_simple_remove(&gpio_ida, gdev->id);
+err_free_gdev:
        /* failures here can mean systems won't boot... */
        pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
               gdev->base, gdev->base + gdev->ngpio - 1,
index 65a643da48d7ab858e975a5a549773b59ec482c3..e490fe2687dbcd8987028f9f0a9ff898106ec49b 100644 (file)
@@ -10,7 +10,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
                drm_scatter.o drm_pci.o \
                drm_sysfs.o drm_hashtab.o drm_mm.o \
                drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
-               drm_info.o drm_encoder_slave.o \
+               drm_encoder_slave.o \
                drm_trace_points.o drm_prime.o \
                drm_rect.o drm_vma_manager.o drm_flip_work.o \
                drm_modeset_lock.o drm_atomic.o drm_bridge.o \
index 60f9a87e9c744c92a62f8f664cc6464b005615ac..bcf1666fb31d24befd3c5c86dd2a3242c4bef74c 100644 (file)
@@ -501,8 +501,11 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
 
-       amdgpu_dpm_switch_power_profile(adev,
-                                       PP_SMC_POWER_PROFILE_COMPUTE, !idle);
+       if (adev->powerplay.pp_funcs &&
+           adev->powerplay.pp_funcs->switch_power_profile)
+               amdgpu_dpm_switch_power_profile(adev,
+                                               PP_SMC_POWER_PROFILE_COMPUTE,
+                                               !idle);
 }
 
 bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
index 6748cd7fc129b0e7b83966da865f674c676c04e1..686a26de50f91e816471548bf3c1a0fc3f86db86 100644 (file)
@@ -626,6 +626,13 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
                                         "dither",
                                         amdgpu_dither_enum_list, sz);
 
+       if (amdgpu_device_has_dc_support(adev)) {
+               adev->mode_info.max_bpc_property =
+                       drm_property_create_range(adev->ddev, 0, "max bpc", 8, 16);
+               if (!adev->mode_info.max_bpc_property)
+                       return -ENOMEM;
+       }
+
        return 0;
 }
 
index 11723d8fffbd67fd77591ec03685a732271daa56..0dc2c5c57015947bc98204df4639be5be12b1f09 100644 (file)
@@ -338,6 +338,8 @@ struct amdgpu_mode_info {
        struct drm_property *audio_property;
        /* FMT dithering */
        struct drm_property *dither_property;
+       /* maximum number of bits per channel for monitor color */
+       struct drm_property *max_bpc_property;
        /* hardcoded DFP edid from BIOS */
        struct edid *bios_hardcoded_edid;
        int bios_hardcoded_edid_size;
index 2821d1d846e4aeb9cc40453c3e7a2a8bbbcaa7ae..9fc3296592fee928fda2ba4cbf960f8725a145fd 100644 (file)
@@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/tahiti_mc.bin");
 MODULE_FIRMWARE("amdgpu/pitcairn_mc.bin");
 MODULE_FIRMWARE("amdgpu/verde_mc.bin");
 MODULE_FIRMWARE("amdgpu/oland_mc.bin");
+MODULE_FIRMWARE("amdgpu/hainan_mc.bin");
 MODULE_FIRMWARE("amdgpu/si58_mc.bin");
 
 #define MC_SEQ_MISC0__MT__MASK   0xf0000000
index bf5e6a413dee6e9b5de53f62ad7547ecb5e5b23e..4cc0dcb1a1875bfc559affd1f55e268a25e6282e 100644 (file)
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL                                                             0x01ba
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX                                                    0
 
+/* for Vega20 register name change */
+#define mmHDP_MEM_POWER_CTRL   0x00d4
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK 0x00000001L
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK   0x00000002L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK  0x00010000L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK            0x00020000L
+#define mmHDP_MEM_POWER_CTRL_BASE_IDX  0
 /*
  * Indirect registers accessor
  */
@@ -870,15 +877,33 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable
 {
        uint32_t def, data;
 
-       def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+       if (adev->asic_type == CHIP_VEGA20) {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL));
 
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
-               data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
-       else
-               data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK;
+               else
+                       data &= ~(HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK);
 
-       if (def != data)
-               WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL), data);
+       } else {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               else
+                       data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+       }
 }
 
 static void soc15_update_drm_clock_gating(struct amdgpu_device *adev, bool enable)
index aa43bb253ea28c3177b610a9850fd3e3ac5a7fc5..d8d0b206a79cb5f39b40f40b25ac26a180c9ef89 100644 (file)
@@ -2422,8 +2422,15 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
 static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector)
 {
+       struct dm_connector_state *dm_conn_state =
+               to_dm_connector_state(connector->state);
        uint32_t bpc = connector->display_info.bpc;
 
+       /* TODO: Remove this when there's support for max_bpc in drm */
+       if (dm_conn_state && bpc > dm_conn_state->max_bpc)
+               /* Round down to nearest even number. */
+               bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1);
+
        switch (bpc) {
        case 0:
                /*
@@ -3007,6 +3014,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                dm_new_state->underscan_enable = val;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               dm_new_state->max_bpc = val;
+               ret = 0;
        }
 
        return ret;
@@ -3049,6 +3059,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                *val = dm_state->underscan_enable;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               *val = dm_state->max_bpc;
+               ret = 0;
        }
        return ret;
 }
@@ -3859,6 +3872,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        drm_object_attach_property(&aconnector->base.base,
                                adev->mode_info.underscan_vborder_property,
                                0);
+       drm_object_attach_property(&aconnector->base.base,
+                               adev->mode_info.max_bpc_property,
+                               0);
 
 }
 
index d6960644d71413c695a9e45f6f4cd19dd98a947f..607c3cdd7d0c25039232d644cfc97295ed49f56d 100644 (file)
@@ -252,6 +252,7 @@ struct dm_connector_state {
        enum amdgpu_rmx_type scaling;
        uint8_t underscan_vborder;
        uint8_t underscan_hborder;
+       uint8_t max_bpc;
        bool underscan_enable;
        bool freesync_enable;
        bool freesync_capable;
index ed35ec0341e671ab8f5cee4d89d2417283147bf3..88f6b35ea6fee9cb7bdf40df0eeef3b3d71ee233 100644 (file)
@@ -4525,12 +4525,12 @@ static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
        struct smu7_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.sclk_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -4567,12 +4567,12 @@ static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
        struct smu7_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mclk_table);
-       int value;
+        int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
-       value = (mclk_table->dpm_levels[mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 8c4db86bb4b770b345575564ad335d48e2681835..e2bc6e0c229f96dde7baf50d2f2189efce4c2c2e 100644 (file)
@@ -4522,15 +4522,13 @@ static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega10_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
-
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels
-                       [golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
                        [golden_sclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
@@ -4575,16 +4573,13 @@ static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega10_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index 74bc37308dc09cb8303cd42146c7d88af3a27c58..54364444ecd121dd611c30148f4e292a8ee18e1a 100644 (file)
@@ -2243,12 +2243,12 @@ static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega12_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -2264,16 +2264,13 @@ static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega12_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index f2daf00cc9119e15c61b7e084aeeda1b4895e4ef..2679d1240fa1e0c96736647f8b3c8749eea1e5bc 100644 (file)
@@ -75,7 +75,17 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
        data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
        data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
 
-       data->registry_data.disallowed_features = 0x0;
+       /*
+        * Disable the following features for now:
+        *   GFXCLK DS
+        *   SOCLK DS
+        *   LCLK DS
+        *   DCEFCLK DS
+        *   FCLK DS
+        *   MP1CLK DS
+        *   MP0CLK DS
+        */
+       data->registry_data.disallowed_features = 0xE0041C00;
        data->registry_data.od_state_in_dc_support = 0;
        data->registry_data.thermal_support = 1;
        data->registry_data.skip_baco_hardware = 0;
@@ -1313,12 +1323,13 @@ static int vega20_get_sclk_od(
                        &(data->dpm_table.gfx_table);
        struct vega20_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value -
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100,
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -1358,12 +1369,13 @@ static int vega20_get_mclk_od(
                        &(data->dpm_table.mem_table);
        struct vega20_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value -
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100,
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 2af847ebca3404d6a3e4adeb9c19d3e27cd066f4..206a76abf77133f0e56ac668041ada8b9ea9859b 100644 (file)
@@ -190,7 +190,7 @@ err_unload:
        arcpgu_unload(drm);
 
 err_unref:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return ret;
 }
@@ -201,7 +201,7 @@ static int arcpgu_remove(struct platform_device *pdev)
 
        drm_dev_unregister(drm);
        arcpgu_unload(drm);
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return 0;
 }
index 69dab82a37714853b5dfdb74dbe479f7d6c10fb1..bf589c53b908d66789679df6f4098c883150fa87 100644 (file)
@@ -60,8 +60,29 @@ static const struct pci_device_id pciidlist[] = {
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
+static void ast_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+       bool primary = false;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+       drm_fb_helper_remove_conflicting_framebuffers(ap, "astdrmfb", primary);
+       kfree(ap);
+}
+
 static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+       ast_kick_out_firmware_fb(pdev);
+
        return drm_get_pci_dev(pdev, ent, &driver);
 }
 
index 5e77d456d9bb9434040107a69536815a270c7865..7c6ac3cadb6b7fabcfe9a309d5fc201db6b75bf7 100644 (file)
@@ -568,6 +568,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
        }
        ast_bo_unreserve(bo);
 
+       ast_set_offset_reg(crtc);
        ast_set_start_address_crt1(crtc, (u32)gpu_addr);
 
        return 0;
@@ -1254,7 +1255,7 @@ static int ast_cursor_move(struct drm_crtc *crtc,
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));
 
        /* dummy write to fire HWC */
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xCB, 0xFF, 0x00);
+       ast_show_cursor(crtc);
 
        return 0;
 }
index 9eeb8ef0b1742227fda0e7386def9ab91d8887b0..2fee47b0d50b3af5bee4c3a4501707c81fe74f89 100644 (file)
@@ -95,6 +95,7 @@ config DRM_SII902X
        depends on OF
        select DRM_KMS_HELPER
        select REGMAP_I2C
+       select I2C_MUX
        ---help---
          Silicon Image sii902x bridge chip driver.
 
index e59a135423336bd187f0038956f06ac4574d94dc..bfa902013aa42e06f3eff686d25ba593cd9b2b89 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2018 Renesas Electronics
+ *
  * Copyright (C) 2016 Atmel
  *                   Bo Shen <voice.shen@atmel.com>
  *
@@ -21,6 +23,7 @@
  */
 
 #include <linux/gpio/consumer.h>
+#include <linux/i2c-mux.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
@@ -86,8 +89,49 @@ struct sii902x {
        struct drm_bridge bridge;
        struct drm_connector connector;
        struct gpio_desc *reset_gpio;
+       struct i2c_mux_core *i2cmux;
 };
 
+static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val)
+{
+       union i2c_smbus_data data;
+       int ret;
+
+       ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
+                              I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data);
+
+       if (ret < 0)
+               return ret;
+
+       *val = data.byte;
+       return 0;
+}
+
+static int sii902x_write_unlocked(struct i2c_client *i2c, u8 reg, u8 val)
+{
+       union i2c_smbus_data data;
+
+       data.byte = val;
+
+       return __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
+                               I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA,
+                               &data);
+}
+
+static int sii902x_update_bits_unlocked(struct i2c_client *i2c, u8 reg, u8 mask,
+                                       u8 val)
+{
+       int ret;
+       u8 status;
+
+       ret = sii902x_read_unlocked(i2c, reg, &status);
+       if (ret)
+               return ret;
+       status &= ~mask;
+       status |= val & mask;
+       return sii902x_write_unlocked(i2c, reg, status);
+}
+
 static inline struct sii902x *bridge_to_sii902x(struct drm_bridge *bridge)
 {
        return container_of(bridge, struct sii902x, bridge);
@@ -135,41 +179,11 @@ static const struct drm_connector_funcs sii902x_connector_funcs = {
 static int sii902x_get_modes(struct drm_connector *connector)
 {
        struct sii902x *sii902x = connector_to_sii902x(connector);
-       struct regmap *regmap = sii902x->regmap;
        u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-       struct device *dev = &sii902x->i2c->dev;
-       unsigned long timeout;
-       unsigned int retries;
-       unsigned int status;
        struct edid *edid;
-       int num = 0;
-       int ret;
-
-       ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
-                                SII902X_SYS_CTRL_DDC_BUS_REQ,
-                                SII902X_SYS_CTRL_DDC_BUS_REQ);
-       if (ret)
-               return ret;
-
-       timeout = jiffies +
-                 msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
-       do {
-               ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
-               if (ret)
-                       return ret;
-       } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
-                time_before(jiffies, timeout));
+       int num = 0, ret;
 
-       if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
-               dev_err(dev, "failed to acquire the i2c bus\n");
-               return -ETIMEDOUT;
-       }
-
-       ret = regmap_write(regmap, SII902X_SYS_CTRL_DATA, status);
-       if (ret)
-               return ret;
-
-       edid = drm_get_edid(connector, sii902x->i2c->adapter);
+       edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
        drm_connector_update_edid_property(connector, edid);
        if (edid) {
                num = drm_add_edid_modes(connector, edid);
@@ -181,42 +195,6 @@ static int sii902x_get_modes(struct drm_connector *connector)
        if (ret)
                return ret;
 
-       /*
-        * Sometimes the I2C bus can stall after failure to use the
-        * EDID channel. Retry a few times to see if things clear
-        * up, else continue anyway.
-        */
-       retries = 5;
-       do {
-               ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA,
-                                 &status);
-               retries--;
-       } while (ret && retries);
-       if (ret)
-               dev_err(dev, "failed to read status (%d)\n", ret);
-
-       ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
-                                SII902X_SYS_CTRL_DDC_BUS_REQ |
-                                SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
-       if (ret)
-               return ret;
-
-       timeout = jiffies +
-                 msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
-       do {
-               ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
-               if (ret)
-                       return ret;
-       } while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
-                          SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
-                time_before(jiffies, timeout));
-
-       if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
-                     SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
-               dev_err(dev, "failed to release the i2c bus\n");
-               return -ETIMEDOUT;
-       }
-
        return num;
 }
 
@@ -366,6 +344,121 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+/*
+ * The purpose of sii902x_i2c_bypass_select is to enable the pass through
+ * mode of the HDMI transmitter. Do not use regmap from within this function,
+ * only use sii902x_*_unlocked functions to read/modify/write registers.
+ * We are holding the parent adapter lock here, keep this in mind before
+ * adding more i2c transactions.
+ *
+ * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
+ * in this driver, we need to make sure that we only touch 0x1A[2:1] from
+ * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
+ * we leave the remaining bits as we have found them.
+ */
+static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
+{
+       struct sii902x *sii902x = i2c_mux_priv(mux);
+       struct device *dev = &sii902x->i2c->dev;
+       unsigned long timeout;
+       u8 status;
+       int ret;
+
+       ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                          SII902X_SYS_CTRL_DDC_BUS_REQ,
+                                          SII902X_SYS_CTRL_DDC_BUS_REQ);
+       if (ret)
+               return ret;
+
+       timeout = jiffies +
+                 msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
+       do {
+               ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                           &status);
+               if (ret)
+                       return ret;
+       } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
+                time_before(jiffies, timeout));
+
+       if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
+               dev_err(dev, "Failed to acquire the i2c bus\n");
+               return -ETIMEDOUT;
+       }
+
+       return sii902x_write_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                     status);
+}
+
+/*
+ * The purpose of sii902x_i2c_bypass_deselect is to disable the pass through
+ * mode of the HDMI transmitter. Do not use regmap from within this function,
+ * only use sii902x_*_unlocked functions to read/modify/write registers.
+ * We are holding the parent adapter lock here, keep this in mind before
+ * adding more i2c transactions.
+ *
+ * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
+ * in this driver, we need to make sure that we only touch 0x1A[2:1] from
+ * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
+ * we leave the remaining bits as we have found them.
+ */
+static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
+{
+       struct sii902x *sii902x = i2c_mux_priv(mux);
+       struct device *dev = &sii902x->i2c->dev;
+       unsigned long timeout;
+       unsigned int retries;
+       u8 status;
+       int ret;
+
+       /*
+        * When the HDMI transmitter is in pass through mode, we need an
+        * (undocumented) additional delay between STOP and START conditions
+        * to guarantee the bus won't get stuck.
+        */
+       udelay(30);
+
+       /*
+        * Sometimes the I2C bus can stall after failure to use the
+        * EDID channel. Retry a few times to see if things clear
+        * up, else continue anyway.
+        */
+       retries = 5;
+       do {
+               ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                           &status);
+               retries--;
+       } while (ret && retries);
+       if (ret) {
+               dev_err(dev, "failed to read status (%d)\n", ret);
+               return ret;
+       }
+
+       ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                          SII902X_SYS_CTRL_DDC_BUS_REQ |
+                                          SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
+       if (ret)
+               return ret;
+
+       timeout = jiffies +
+                 msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
+       do {
+               ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
+                                           &status);
+               if (ret)
+                       return ret;
+       } while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
+                          SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
+                time_before(jiffies, timeout));
+
+       if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
+                     SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
+               dev_err(dev, "failed to release the i2c bus\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int sii902x_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -375,6 +468,13 @@ static int sii902x_probe(struct i2c_client *client,
        u8 chipid[4];
        int ret;
 
+       ret = i2c_check_functionality(client->adapter,
+                                     I2C_FUNC_SMBUS_BYTE_DATA);
+       if (!ret) {
+               dev_err(dev, "I2C adapter not suitable\n");
+               return -EIO;
+       }
+
        sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL);
        if (!sii902x)
                return -ENOMEM;
@@ -433,7 +533,15 @@ static int sii902x_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, sii902x);
 
-       return 0;
+       sii902x->i2cmux = i2c_mux_alloc(client->adapter, dev,
+                                       1, 0, I2C_MUX_GATE,
+                                       sii902x_i2c_bypass_select,
+                                       sii902x_i2c_bypass_deselect);
+       if (!sii902x->i2cmux)
+               return -ENOMEM;
+
+       sii902x->i2cmux->priv = sii902x;
+       return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
 }
 
 static int sii902x_remove(struct i2c_client *client)
@@ -441,6 +549,7 @@ static int sii902x_remove(struct i2c_client *client)
 {
        struct sii902x *sii902x = i2c_get_clientdata(client);
 
+       i2c_mux_del_adapters(sii902x->i2cmux);
        drm_bridge_remove(&sii902x->bridge);
 
        return 0;
index ee6b98efa9c221015cd7cefb9cd3384dfa9efd16..afd491018bfc55817511ea1d7db9e6fc5f19a99b 100644 (file)
@@ -379,7 +379,7 @@ static void tc358764_detach(struct drm_bridge *bridge)
        drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector);
        drm_panel_detach(ctx->panel);
        ctx->panel = NULL;
-       drm_connector_unreference(&ctx->connector);
+       drm_connector_put(&ctx->connector);
 }
 
 static const struct drm_bridge_funcs tc358764_bridge_funcs = {
index 68ab1821e15bcc1787a9dd9800963971a4321117..4dd499c7d1ba13fc2cb49e91fc011ece76b07f16 100644 (file)
@@ -169,7 +169,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        struct drm_mode_fb_cmd2 mode_cmd;
        void *sysram;
        struct drm_gem_object *gobj = NULL;
-       struct cirrus_bo *bo = NULL;
        int size, ret;
 
        mode_cmd.width = sizes->surface_width;
@@ -185,8 +184,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
                return ret;
        }
 
-       bo = gem_to_cirrus_bo(gobj);
-
        sysram = vmalloc(size);
        if (!sysram)
                return -ENOMEM;
index 1706ed1100d5cd9bdf4aaa8a735eaf45bc76f353..9ac26437051b478b8d9a93da40c93edbaa87a912 100644 (file)
@@ -315,9 +315,11 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 
-static int drm_atomic_crtc_check(struct drm_crtc *crtc,
-               struct drm_crtc_state *state)
+static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state,
+                                const struct drm_crtc_state *new_crtc_state)
 {
+       struct drm_crtc *crtc = new_crtc_state->crtc;
+
        /* NOTE: we explicitly don't enforce constraints such as primary
         * layer covering entire screen, since that is something we want
         * to allow (on hw that supports it).  For hw that does not, it
@@ -326,7 +328,7 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         * TODO: Add generic modeset state checks once we support those.
         */
 
-       if (state->active && !state->enable) {
+       if (new_crtc_state->active && !new_crtc_state->enable) {
                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n",
                                 crtc->base.id, crtc->name);
                return -EINVAL;
@@ -336,14 +338,14 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         * as this is a kernel-internal detail that userspace should never
         * be able to trigger. */
        if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
-           WARN_ON(state->enable && !state->mode_blob)) {
+           WARN_ON(new_crtc_state->enable && !new_crtc_state->mode_blob)) {
                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n",
                                 crtc->base.id, crtc->name);
                return -EINVAL;
        }
 
        if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
-           WARN_ON(!state->enable && state->mode_blob)) {
+           WARN_ON(!new_crtc_state->enable && new_crtc_state->mode_blob)) {
                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n",
                                 crtc->base.id, crtc->name);
                return -EINVAL;
@@ -359,7 +361,8 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         * and legacy page_flip IOCTL which also reject service on a disabled
         * pipe.
         */
-       if (state->event && !state->active && !crtc->state->active) {
+       if (new_crtc_state->event &&
+           !new_crtc_state->active && !old_crtc_state->active) {
                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",
                                 crtc->base.id, crtc->name);
                return -EINVAL;
@@ -494,14 +497,13 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
 static bool
-plane_switching_crtc(struct drm_atomic_state *state,
-                    struct drm_plane *plane,
-                    struct drm_plane_state *plane_state)
+plane_switching_crtc(const struct drm_plane_state *old_plane_state,
+                    const struct drm_plane_state *new_plane_state)
 {
-       if (!plane->state->crtc || !plane_state->crtc)
+       if (!old_plane_state->crtc || !new_plane_state->crtc)
                return false;
 
-       if (plane->state->crtc == plane_state->crtc)
+       if (old_plane_state->crtc == new_plane_state->crtc)
                return false;
 
        /* This could be refined, but currently there's no helper or driver code
@@ -514,88 +516,95 @@ plane_switching_crtc(struct drm_atomic_state *state,
 
 /**
  * drm_atomic_plane_check - check plane state
- * @plane: plane to check
- * @state: plane state to check
+ * @old_plane_state: old plane state to check
+ * @new_plane_state: new plane state to check
  *
  * Provides core sanity checks for plane state.
  *
  * RETURNS:
  * Zero on success, error code on failure
  */
-static int drm_atomic_plane_check(struct drm_plane *plane,
-               struct drm_plane_state *state)
+static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
+                                 const struct drm_plane_state *new_plane_state)
 {
+       struct drm_plane *plane = new_plane_state->plane;
+       struct drm_crtc *crtc = new_plane_state->crtc;
+       const struct drm_framebuffer *fb = new_plane_state->fb;
        unsigned int fb_width, fb_height;
        int ret;
 
        /* either *both* CRTC and FB must be set, or neither */
-       if (state->crtc && !state->fb) {
+       if (crtc && !fb) {
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] CRTC set but no FB\n",
                                 plane->base.id, plane->name);
                return -EINVAL;
-       } else if (state->fb && !state->crtc) {
+       } else if (fb && !crtc) {
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] FB set but no CRTC\n",
                                 plane->base.id, plane->name);
                return -EINVAL;
        }
 
        /* if disabled, we don't care about the rest of the state: */
-       if (!state->crtc)
+       if (!crtc)
                return 0;
 
        /* Check whether this plane is usable on this CRTC */
-       if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {
+       if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
                DRM_DEBUG_ATOMIC("Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n",
-                                state->crtc->base.id, state->crtc->name,
+                                crtc->base.id, crtc->name,
                                 plane->base.id, plane->name);
                return -EINVAL;
        }
 
        /* Check whether this plane supports the fb pixel format. */
-       ret = drm_plane_check_pixel_format(plane, state->fb->format->format,
-                                          state->fb->modifier);
+       ret = drm_plane_check_pixel_format(plane, fb->format->format,
+                                          fb->modifier);
        if (ret) {
                struct drm_format_name_buf format_name;
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %s, modifier 0x%llx\n",
                                 plane->base.id, plane->name,
-                                drm_get_format_name(state->fb->format->format,
+                                drm_get_format_name(fb->format->format,
                                                     &format_name),
-                                state->fb->modifier);
+                                fb->modifier);
                return ret;
        }
 
        /* Give drivers some help against integer overflows */
-       if (state->crtc_w > INT_MAX ||
-           state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||
-           state->crtc_h > INT_MAX ||
-           state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {
+       if (new_plane_state->crtc_w > INT_MAX ||
+           new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w ||
+           new_plane_state->crtc_h > INT_MAX ||
+           new_plane_state->crtc_y > INT_MAX - (int32_t) new_plane_state->crtc_h) {
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n",
                                 plane->base.id, plane->name,
-                                state->crtc_w, state->crtc_h,
-                                state->crtc_x, state->crtc_y);
+                                new_plane_state->crtc_w, new_plane_state->crtc_h,
+                                new_plane_state->crtc_x, new_plane_state->crtc_y);
                return -ERANGE;
        }
 
-       fb_width = state->fb->width << 16;
-       fb_height = state->fb->height << 16;
+       fb_width = fb->width << 16;
+       fb_height = fb->height << 16;
 
        /* Make sure source coordinates are inside the fb. */
-       if (state->src_w > fb_width ||
-           state->src_x > fb_width - state->src_w ||
-           state->src_h > fb_height ||
-           state->src_y > fb_height - state->src_h) {
+       if (new_plane_state->src_w > fb_width ||
+           new_plane_state->src_x > fb_width - new_plane_state->src_w ||
+           new_plane_state->src_h > fb_height ||
+           new_plane_state->src_y > fb_height - new_plane_state->src_h) {
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid source coordinates "
                                 "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
                                 plane->base.id, plane->name,
-                                state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
-                                state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
-                                state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
-                                state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10,
-                                state->fb->width, state->fb->height);
+                                new_plane_state->src_w >> 16,
+                                ((new_plane_state->src_w & 0xffff) * 15625) >> 10,
+                                new_plane_state->src_h >> 16,
+                                ((new_plane_state->src_h & 0xffff) * 15625) >> 10,
+                                new_plane_state->src_x >> 16,
+                                ((new_plane_state->src_x & 0xffff) * 15625) >> 10,
+                                new_plane_state->src_y >> 16,
+                                ((new_plane_state->src_y & 0xffff) * 15625) >> 10,
+                                fb->width, fb->height);
                return -ENOSPC;
        }
 
-       if (plane_switching_crtc(state->state, plane, state)) {
+       if (plane_switching_crtc(old_plane_state, new_plane_state)) {
                DRM_DEBUG_ATOMIC("[PLANE:%d:%s] switching CRTC directly\n",
                                 plane->base.id, plane->name);
                return -EINVAL;
@@ -932,6 +941,8 @@ int
 drm_atomic_add_affected_planes(struct drm_atomic_state *state,
                               struct drm_crtc *crtc)
 {
+       const struct drm_crtc_state *old_crtc_state =
+               drm_atomic_get_old_crtc_state(state, crtc);
        struct drm_plane *plane;
 
        WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
@@ -939,7 +950,7 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
        DRM_DEBUG_ATOMIC("Adding all current planes for [CRTC:%d:%s] to %p\n",
                         crtc->base.id, crtc->name, state);
 
-       drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
+       drm_for_each_plane_mask(plane, state->dev, old_crtc_state->plane_mask) {
                struct drm_plane_state *plane_state =
                        drm_atomic_get_plane_state(state, plane);
 
@@ -966,17 +977,19 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        struct drm_device *dev = state->dev;
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *old_plane_state;
+       struct drm_plane_state *new_plane_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_connector *conn;
        struct drm_connector_state *conn_state;
        int i, ret = 0;
 
        DRM_DEBUG_ATOMIC("checking %p\n", state);
 
-       for_each_new_plane_in_state(state, plane, plane_state, i) {
-               ret = drm_atomic_plane_check(plane, plane_state);
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+               ret = drm_atomic_plane_check(old_plane_state, new_plane_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
                                         plane->base.id, plane->name);
@@ -984,8 +997,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
                }
        }
 
-       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-               ret = drm_atomic_crtc_check(crtc, crtc_state);
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               ret = drm_atomic_crtc_check(old_crtc_state, new_crtc_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
                                         crtc->base.id, crtc->name);
@@ -1013,8 +1026,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        }
 
        if (!state->allow_modeset) {
-               for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-                       if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+               for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+                       if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
                                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
                                                 crtc->base.id, crtc->name);
                                return -EINVAL;
index fa95f9974f6d071a8c1929b38be6ba70d8f7cd14..bc9fc9665614f0904f6184be66903d71f93ff9dc 100644 (file)
@@ -1460,6 +1460,9 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
                        DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
                                  crtc->base.id, crtc->name);
        }
+
+       if (old_state->fake_commit)
+               complete_all(&old_state->fake_commit->flip_done);
 }
 EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
 
@@ -2217,8 +2220,10 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
                spin_unlock(&crtc->commit_lock);
        }
 
-       if (old_state->fake_commit)
+       if (old_state->fake_commit) {
                complete_all(&old_state->fake_commit->cleanup_done);
+               WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done));
+       }
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done);
 
index fc03d26fcacc8057034bb22bf6c76b03f5f87b2f..9b2bd28dde0a61b3202adfa726c800231f022cd9 100644 (file)
@@ -81,8 +81,7 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
 {
        int ret;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
-           !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
+       if (!drm_core_check_feature(dev, DRIVER_MODESET) || !dev->driver->dumb_create)
                return -EOPNOTSUPP;
 
        if (funcs && !try_module_get(funcs->owner))
@@ -229,8 +228,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
 {
        struct drm_device *dev = buffer->client->dev;
 
-       if (buffer->vaddr && dev->driver->gem_prime_vunmap)
-               dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
+       drm_gem_vunmap(buffer->gem, buffer->vaddr);
 
        if (buffer->gem)
                drm_gem_object_put_unlocked(buffer->gem);
@@ -283,9 +281,9 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
         * fd_install step out of the driver backend hooks, to make that
         * final step optional for internal users.
         */
-       vaddr = dev->driver->gem_prime_vmap(obj);
-       if (!vaddr) {
-               ret = -ENOMEM;
+       vaddr = drm_gem_vmap(obj);
+       if (IS_ERR(vaddr)) {
+               ret = PTR_ERR(vaddr);
                goto err_delete;
        }
 
index 373bd4c2b698ba1ebcb3b4572cb6c84b3ce448fe..f8468eae05033f7c90242e2203eaacc306fe37ff 100644 (file)
@@ -32,6 +32,8 @@
 #include <drm/drm_debugfs.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_gem.h>
 #include <drm/drmP.h>
 
 #include "drm_internal.h"
  * Initialization, etc.
  **************************************************/
 
+static int drm_name_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_minor *minor = node->minor;
+       struct drm_device *dev = minor->dev;
+       struct drm_master *master;
+
+       mutex_lock(&dev->master_mutex);
+       master = dev->master;
+       seq_printf(m, "%s", dev->driver->name);
+       if (dev->dev)
+               seq_printf(m, " dev=%s", dev_name(dev->dev));
+       if (master && master->unique)
+               seq_printf(m, " master=%s", master->unique);
+       if (dev->unique)
+               seq_printf(m, " unique=%s", dev->unique);
+       seq_printf(m, "\n");
+       mutex_unlock(&dev->master_mutex);
+
+       return 0;
+}
+
+static int drm_clients_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_file *priv;
+       kuid_t uid;
+
+       seq_printf(m,
+                  "%20s %5s %3s master a %5s %10s\n",
+                  "command",
+                  "pid",
+                  "dev",
+                  "uid",
+                  "magic");
+
+       /* dev->filelist is sorted youngest first, but we want to present
+        * oldest first (i.e. kernel, servers, clients), so walk backwardss.
+        */
+       mutex_lock(&dev->filelist_mutex);
+       list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
+               struct task_struct *task;
+
+               rcu_read_lock(); /* locks pid_task()->comm */
+               task = pid_task(priv->pid, PIDTYPE_PID);
+               uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
+               seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n",
+                          task ? task->comm : "<unknown>",
+                          pid_vnr(priv->pid),
+                          priv->minor->index,
+                          drm_is_current_master(priv) ? 'y' : 'n',
+                          priv->authenticated ? 'y' : 'n',
+                          from_kuid_munged(seq_user_ns(m), uid),
+                          priv->magic);
+               rcu_read_unlock();
+       }
+       mutex_unlock(&dev->filelist_mutex);
+       return 0;
+}
+
+static int drm_gem_one_name_info(int id, void *ptr, void *data)
+{
+       struct drm_gem_object *obj = ptr;
+       struct seq_file *m = data;
+
+       seq_printf(m, "%6d %8zd %7d %8d\n",
+                  obj->name, obj->size,
+                  obj->handle_count,
+                  kref_read(&obj->refcount));
+       return 0;
+}
+
+static int drm_gem_name_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+
+       seq_printf(m, "  name     size handles refcount\n");
+
+       mutex_lock(&dev->object_name_lock);
+       idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
+       mutex_unlock(&dev->object_name_lock);
+
+       return 0;
+}
+
 static const struct drm_info_list drm_debugfs_list[] = {
        {"name", drm_name_info, 0},
        {"clients", drm_clients_info, 0},
index e2ffecd5e45379c80ed067c93b49215e78c25967..12e5e2be7890e39952947f85594675093f4e8eb9 100644 (file)
@@ -704,19 +704,6 @@ void drm_dev_put(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_dev_put);
 
-/**
- * drm_dev_unref - Drop reference of a DRM device
- * @dev: device to drop reference of or NULL
- *
- * This is a compatibility alias for drm_dev_put() and should not be used by new
- * code.
- */
-void drm_dev_unref(struct drm_device *dev)
-{
-       drm_dev_put(dev);
-}
-EXPORT_SYMBOL(drm_dev_unref);
-
 static int create_compat_control_link(struct drm_device *dev)
 {
        struct drm_minor *minor;
index 9a69ad7e9f3b8beb6769d7a92673cd7dd2840757..5e9ca6f9637929ff76a37db4c8e936eba82c5279 100644 (file)
@@ -219,6 +219,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
        mutex_lock(&fb_helper->lock);
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+                       continue;
+
                ret = __drm_fb_helper_add_one_connector(fb_helper, connector);
                if (ret)
                        goto fail;
index f523948c82b164977697518486f54c4d58e40430..d90ee03a84c607ed713ab1539e4a9b1b5cf4d936 100644 (file)
@@ -224,6 +224,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
                { .format = DRM_FORMAT_YVYU,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
                { .format = DRM_FORMAT_UYVY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
                { .format = DRM_FORMAT_VYUY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_XYUV8888,        .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
                { .format = DRM_FORMAT_AYUV,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
                { .format = DRM_FORMAT_Y0L0,            .depth = 0,  .num_planes = 1,
                  .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
index 512078ebd97b92f143d63f2af16fbe79ea6c7554..8b55ece97967f43d0861d6d5f6dfc043f00b9a39 100644 (file)
@@ -257,7 +257,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct drm_device *dev = obj->dev;
 
-       if (dev->driver->gem_close_object)
+       if (obj->funcs && obj->funcs->close)
+               obj->funcs->close(obj, file_priv);
+       else if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
 
        if (drm_core_check_feature(dev, DRIVER_PRIME))
@@ -410,7 +412,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
        if (ret)
                goto err_remove;
 
-       if (dev->driver->gem_open_object) {
+       if (obj->funcs && obj->funcs->open) {
+               ret = obj->funcs->open(obj, file_priv);
+               if (ret)
+                       goto err_revoke;
+       } else if (dev->driver->gem_open_object) {
                ret = dev->driver->gem_open_object(obj, file_priv);
                if (ret)
                        goto err_revoke;
@@ -835,7 +841,9 @@ drm_gem_object_free(struct kref *kref)
                container_of(kref, struct drm_gem_object, refcount);
        struct drm_device *dev = obj->dev;
 
-       if (dev->driver->gem_free_object_unlocked) {
+       if (obj->funcs) {
+               obj->funcs->free(obj);
+       } else if (dev->driver->gem_free_object_unlocked) {
                dev->driver->gem_free_object_unlocked(obj);
        } else if (dev->driver->gem_free_object) {
                WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -864,13 +872,13 @@ drm_gem_object_put_unlocked(struct drm_gem_object *obj)
 
        dev = obj->dev;
 
-       if (dev->driver->gem_free_object_unlocked) {
-               kref_put(&obj->refcount, drm_gem_object_free);
-       } else {
+       if (dev->driver->gem_free_object) {
                might_lock(&dev->struct_mutex);
                if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
                                &dev->struct_mutex))
                        mutex_unlock(&dev->struct_mutex);
+       } else {
+               kref_put(&obj->refcount, drm_gem_object_free);
        }
 }
 EXPORT_SYMBOL(drm_gem_object_put_unlocked);
@@ -960,11 +968,14 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
        if (obj_size < vma->vm_end - vma->vm_start)
                return -EINVAL;
 
-       if (!dev->driver->gem_vm_ops)
+       if (obj->funcs && obj->funcs->vm_ops)
+               vma->vm_ops = obj->funcs->vm_ops;
+       else if (dev->driver->gem_vm_ops)
+               vma->vm_ops = dev->driver->gem_vm_ops;
+       else
                return -EINVAL;
 
        vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
-       vma->vm_ops = dev->driver->gem_vm_ops;
        vma->vm_private_data = obj;
        vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
        vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
@@ -1066,6 +1077,86 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
        drm_printf_indent(p, indent, "imported=%s\n",
                          obj->import_attach ? "yes" : "no");
 
-       if (obj->dev->driver->gem_print_info)
+       if (obj->funcs && obj->funcs->print_info)
+               obj->funcs->print_info(p, indent, obj);
+       else if (obj->dev->driver->gem_print_info)
                obj->dev->driver->gem_print_info(p, indent, obj);
 }
+
+/**
+ * drm_gem_pin - Pin backing buffer in memory
+ * @obj: GEM object
+ *
+ * Make sure the backing buffer is pinned in memory.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_pin(struct drm_gem_object *obj)
+{
+       if (obj->funcs && obj->funcs->pin)
+               return obj->funcs->pin(obj);
+       else if (obj->dev->driver->gem_prime_pin)
+               return obj->dev->driver->gem_prime_pin(obj);
+       else
+               return 0;
+}
+EXPORT_SYMBOL(drm_gem_pin);
+
+/**
+ * drm_gem_unpin - Unpin backing buffer from memory
+ * @obj: GEM object
+ *
+ * Relax the requirement that the backing buffer is pinned in memory.
+ */
+void drm_gem_unpin(struct drm_gem_object *obj)
+{
+       if (obj->funcs && obj->funcs->unpin)
+               obj->funcs->unpin(obj);
+       else if (obj->dev->driver->gem_prime_unpin)
+               obj->dev->driver->gem_prime_unpin(obj);
+}
+EXPORT_SYMBOL(drm_gem_unpin);
+
+/**
+ * drm_gem_vmap - Map buffer into kernel virtual address space
+ * @obj: GEM object
+ *
+ * Returns:
+ * A virtual pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+void *drm_gem_vmap(struct drm_gem_object *obj)
+{
+       void *vaddr;
+
+       if (obj->funcs && obj->funcs->vmap)
+               vaddr = obj->funcs->vmap(obj);
+       else if (obj->dev->driver->gem_prime_vmap)
+               vaddr = obj->dev->driver->gem_prime_vmap(obj);
+       else
+               vaddr = ERR_PTR(-EOPNOTSUPP);
+
+       if (!vaddr)
+               vaddr = ERR_PTR(-ENOMEM);
+
+       return vaddr;
+}
+EXPORT_SYMBOL(drm_gem_vmap);
+
+/**
+ * drm_gem_vunmap - Remove buffer mapping from kernel virtual address space
+ * @obj: GEM object
+ * @vaddr: Virtual address (can be NULL)
+ */
+void drm_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+       if (!vaddr)
+               return;
+
+       if (obj->funcs && obj->funcs->vunmap)
+               obj->funcs->vunmap(obj, vaddr);
+       else if (obj->dev->driver->gem_prime_vunmap)
+               obj->dev->driver->gem_prime_vunmap(obj, vaddr);
+}
+EXPORT_SYMBOL(drm_gem_vunmap);
index 1d2ced882b6695d6723793e4d0e95577be2f07ec..cc26625b4b33b26f2d04d8884e977d56e5574cb4 100644 (file)
@@ -176,6 +176,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
  *
  * This function frees the backing memory of the CMA GEM object, cleans up the
  * GEM object state and frees the memory used to store the object itself.
+ * If the buffer is imported and the virtual address is set, it is released.
  * Drivers using the CMA helpers should set this as their
  * &drm_driver.gem_free_object_unlocked callback.
  */
@@ -189,6 +190,8 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
                dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
                            cma_obj->vaddr, cma_obj->paddr);
        } else if (gem_obj->import_attach) {
+               if (cma_obj->vaddr)
+                       dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
                drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
        }
 
@@ -575,3 +578,86 @@ void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
        /* Nothing to do */
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap);
+
+static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = {
+       .free = drm_gem_cma_free_object,
+       .print_info = drm_gem_cma_print_info,
+       .get_sg_table = drm_gem_cma_prime_get_sg_table,
+       .vmap = drm_gem_cma_prime_vmap,
+       .vm_ops = &drm_gem_cma_vm_ops,
+};
+
+/**
+ * drm_cma_gem_create_object_default_funcs - Create a CMA GEM object with a
+ *                                           default function table
+ * @dev: DRM device
+ * @size: Size of the object to allocate
+ *
+ * This sets the GEM object functions to the default CMA helper functions.
+ * This function can be used as the &drm_driver.gem_create_object callback.
+ *
+ * Returns:
+ * A pointer to a allocated GEM object or an error pointer on failure.
+ */
+struct drm_gem_object *
+drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size)
+{
+       struct drm_gem_cma_object *cma_obj;
+
+       cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+       if (!cma_obj)
+               return NULL;
+
+       cma_obj->base.funcs = &drm_cma_gem_default_funcs;
+
+       return &cma_obj->base;
+}
+EXPORT_SYMBOL(drm_cma_gem_create_object_default_funcs);
+
+/**
+ * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
+ *     scatter/gather table and get the virtual address of the buffer
+ * @dev: DRM device
+ * @attach: DMA-BUF attachment
+ * @sgt: Scatter/gather table of pinned pages
+ *
+ * This function imports a scatter/gather table using
+ * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
+ * virtual address. This ensures that a CMA GEM object always has its virtual
+ * address set. This address is released when the object is freed.
+ *
+ * This function can be used as the &drm_driver.gem_prime_import_sg_table
+ * callback. The DRM_GEM_CMA_VMAP_DRIVER_OPS() macro provides a shortcut to set
+ * the necessary DRM driver operations.
+ *
+ * Returns:
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_object *
+drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
+                                      struct dma_buf_attachment *attach,
+                                      struct sg_table *sgt)
+{
+       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_object *obj;
+       void *vaddr;
+
+       vaddr = dma_buf_vmap(attach->dmabuf);
+       if (!vaddr) {
+               DRM_ERROR("Failed to vmap PRIME buffer\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
+       if (IS_ERR(obj)) {
+               dma_buf_vunmap(attach->dmabuf, vaddr);
+               return obj;
+       }
+
+       cma_obj = to_drm_gem_cma_obj(obj);
+       cma_obj->vaddr = vaddr;
+
+       return obj;
+}
+EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
deleted file mode 100644 (file)
index 6b68e90..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * \file drm_info.c
- * DRM info file implementations
- *
- * \author Ben Gamari <bgamari@gmail.com>
- */
-
-/*
- * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * Copyright 2008 Ben Gamari <bgamari@gmail.com>
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/seq_file.h>
-#include <drm/drmP.h>
-#include <drm/drm_gem.h>
-
-#include "drm_internal.h"
-#include "drm_legacy.h"
-
-/**
- * Called when "/proc/dri/.../name" is read.
- *
- * Prints the device name together with the bus id if available.
- */
-int drm_name_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_minor *minor = node->minor;
-       struct drm_device *dev = minor->dev;
-       struct drm_master *master;
-
-       mutex_lock(&dev->master_mutex);
-       master = dev->master;
-       seq_printf(m, "%s", dev->driver->name);
-       if (dev->dev)
-               seq_printf(m, " dev=%s", dev_name(dev->dev));
-       if (master && master->unique)
-               seq_printf(m, " master=%s", master->unique);
-       if (dev->unique)
-               seq_printf(m, " unique=%s", dev->unique);
-       seq_printf(m, "\n");
-       mutex_unlock(&dev->master_mutex);
-
-       return 0;
-}
-
-/**
- * Called when "/proc/dri/.../clients" is read.
- *
- */
-int drm_clients_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-       struct drm_file *priv;
-       kuid_t uid;
-
-       seq_printf(m,
-                  "%20s %5s %3s master a %5s %10s\n",
-                  "command",
-                  "pid",
-                  "dev",
-                  "uid",
-                  "magic");
-
-       /* dev->filelist is sorted youngest first, but we want to present
-        * oldest first (i.e. kernel, servers, clients), so walk backwardss.
-        */
-       mutex_lock(&dev->filelist_mutex);
-       list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
-               struct task_struct *task;
-
-               rcu_read_lock(); /* locks pid_task()->comm */
-               task = pid_task(priv->pid, PIDTYPE_PID);
-               uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
-               seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n",
-                          task ? task->comm : "<unknown>",
-                          pid_vnr(priv->pid),
-                          priv->minor->index,
-                          drm_is_current_master(priv) ? 'y' : 'n',
-                          priv->authenticated ? 'y' : 'n',
-                          from_kuid_munged(seq_user_ns(m), uid),
-                          priv->magic);
-               rcu_read_unlock();
-       }
-       mutex_unlock(&dev->filelist_mutex);
-       return 0;
-}
-
-static int drm_gem_one_name_info(int id, void *ptr, void *data)
-{
-       struct drm_gem_object *obj = ptr;
-       struct seq_file *m = data;
-
-       seq_printf(m, "%6d %8zd %7d %8d\n",
-                  obj->name, obj->size,
-                  obj->handle_count,
-                  kref_read(&obj->refcount));
-       return 0;
-}
-
-int drm_gem_name_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-
-       seq_printf(m, "  name     size handles refcount\n");
-
-       mutex_lock(&dev->object_name_lock);
-       idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
-       mutex_unlock(&dev->object_name_lock);
-
-       return 0;
-}
index 0c4eb4a9ab31f79efff7d6902c542d9a6f69ddd9..c7a7d7ce5d1cbaf1531e329223c0ca2f759ff1cc 100644 (file)
@@ -56,11 +56,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
 void drm_minor_release(struct drm_minor *minor);
 
-/* drm_info.c */
-int drm_name_info(struct seq_file *m, void *data);
-int drm_clients_info(struct seq_file *m, void* data);
-int drm_gem_name_info(struct seq_file *m, void *data);
-
 /* drm_vblank.c */
 void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe);
 void drm_vblank_cleanup(struct drm_device *dev);
index ab4e70e63f6ecec47b2856215034269cebfeed53..52e445bb1aa581a4f012e03a166bb985a6aaf675 100644 (file)
@@ -63,7 +63,7 @@ static const struct drm_dmi_panel_orientation_data gpd_win2 = {
        .width = 720,
        .height = 1280,
        .bios_dates = (const char * const []){
-               "12/07/2017", "05/24/2018", NULL },
+               "12/07/2017", "05/24/2018", "06/29/2018", NULL },
        .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 };
 
index 8d54d51a6b6bffba2729c5a32d5dd55fd4d50c60..231e3f6d5f4162c243c19c04811b71727f7c50cb 100644 (file)
@@ -199,7 +199,6 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
 {
        struct drm_prime_attachment *prime_attach;
        struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
 
        prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
        if (!prime_attach)
@@ -208,10 +207,7 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
        prime_attach->dir = DMA_NONE;
        attach->priv = prime_attach;
 
-       if (!dev->driver->gem_prime_pin)
-               return 0;
-
-       return dev->driver->gem_prime_pin(obj);
+       return drm_gem_pin(obj);
 }
 EXPORT_SYMBOL(drm_gem_map_attach);
 
@@ -228,7 +224,6 @@ void drm_gem_map_detach(struct dma_buf *dma_buf,
 {
        struct drm_prime_attachment *prime_attach = attach->priv;
        struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
 
        if (prime_attach) {
                struct sg_table *sgt = prime_attach->sgt;
@@ -247,8 +242,7 @@ void drm_gem_map_detach(struct dma_buf *dma_buf,
                attach->priv = NULL;
        }
 
-       if (dev->driver->gem_prime_unpin)
-               dev->driver->gem_prime_unpin(obj);
+       drm_gem_unpin(obj);
 }
 EXPORT_SYMBOL(drm_gem_map_detach);
 
@@ -310,7 +304,10 @@ struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
        if (WARN_ON(prime_attach->dir != DMA_NONE))
                return ERR_PTR(-EBUSY);
 
-       sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
+       if (obj->funcs)
+               sgt = obj->funcs->get_sg_table(obj);
+       else
+               sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
 
        if (!IS_ERR(sgt)) {
                if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
@@ -406,12 +403,13 @@ EXPORT_SYMBOL(drm_gem_dmabuf_release);
 void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 {
        struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
+       void *vaddr;
 
-       if (dev->driver->gem_prime_vmap)
-               return dev->driver->gem_prime_vmap(obj);
-       else
-               return NULL;
+       vaddr = drm_gem_vmap(obj);
+       if (IS_ERR(vaddr))
+               vaddr = NULL;
+
+       return vaddr;
 }
 EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
 
@@ -426,10 +424,8 @@ EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
 void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 {
        struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
 
-       if (dev->driver->gem_prime_vunmap)
-               dev->driver->gem_prime_vunmap(obj, vaddr);
+       drm_gem_vunmap(obj, vaddr);
 }
 EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
 
@@ -529,7 +525,12 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev,
                return dmabuf;
        }
 
-       dmabuf = dev->driver->gem_prime_export(dev, obj, flags);
+       if (obj->funcs && obj->funcs->export)
+               dmabuf = obj->funcs->export(obj, flags);
+       else if (dev->driver->gem_prime_export)
+               dmabuf = dev->driver->gem_prime_export(dev, obj, flags);
+       else
+               dmabuf = drm_gem_prime_export(dev, obj, flags);
        if (IS_ERR(dmabuf)) {
                /* normally the created dma-buf takes ownership of the ref,
                 * but if that fails then drop the ref
@@ -648,6 +649,52 @@ out_unlock:
 }
 EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
 
+/**
+ * drm_gem_prime_mmap - PRIME mmap function for GEM drivers
+ * @obj: GEM object
+ * @vma: Virtual address range
+ *
+ * This function sets up a userspace mapping for PRIME exported buffers using
+ * the same codepath that is used for regular GEM buffer mapping on the DRM fd.
+ * The fake GEM offset is added to vma->vm_pgoff and &drm_driver->fops->mmap is
+ * called to set up the mapping.
+ *
+ * Drivers can use this as their &drm_driver.gem_prime_mmap callback.
+ */
+int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+       struct drm_file *priv;
+       struct file *fil;
+       int ret;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       fil = kzalloc(sizeof(*fil), GFP_KERNEL);
+       if (!priv || !fil) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* Used by drm_gem_mmap() to lookup the GEM object */
+       priv->minor = obj->dev->primary;
+       fil->private_data = priv;
+
+       ret = drm_vma_node_allow(&obj->vma_node, priv);
+       if (ret)
+               goto out;
+
+       vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
+
+       ret = obj->dev->driver->fops->mmap(fil, vma);
+
+       drm_vma_node_revoke(&obj->vma_node, priv);
+out:
+       kfree(priv);
+       kfree(fil);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_gem_prime_mmap);
+
 /**
  * drm_gem_prime_import_dev - core implementation of the import callback
  * @dev: drm_device to import into
@@ -762,7 +809,10 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
 
        /* never seen this one, need to import */
        mutex_lock(&dev->object_name_lock);
-       obj = dev->driver->gem_prime_import(dev, dma_buf);
+       if (dev->driver->gem_prime_import)
+               obj = dev->driver->gem_prime_import(dev, dma_buf);
+       else
+               obj = drm_gem_prime_import(dev, dma_buf);
        if (IS_ERR(obj)) {
                ret = PTR_ERR(obj);
                goto out_unlock;
index da8175d9c6ffcbaf4d7acb82f2d18da34f1acb6b..e2c5b3ca48240693fa5b23d95e9e039800ab663b 100644 (file)
@@ -56,9 +56,6 @@
 #include "drm_internal.h"
 #include <drm/drm_syncobj.h>
 
-/* merge normal syncobj to timeline syncobj, the point interval is 1 */
-#define DRM_SYNCOBJ_BINARY_POINT 1
-
 struct drm_syncobj_stub_fence {
        struct dma_fence base;
        spinlock_t lock;
@@ -74,29 +71,7 @@ static const struct dma_fence_ops drm_syncobj_stub_fence_ops = {
        .get_timeline_name = drm_syncobj_stub_fence_get_name,
 };
 
-struct drm_syncobj_signal_pt {
-       struct dma_fence_array *fence_array;
-       u64    value;
-       struct list_head list;
-};
-
-static DEFINE_SPINLOCK(signaled_fence_lock);
-static struct dma_fence signaled_fence;
 
-static struct dma_fence *drm_syncobj_get_stub_fence(void)
-{
-       spin_lock(&signaled_fence_lock);
-       if (!signaled_fence.ops) {
-               dma_fence_init(&signaled_fence,
-                              &drm_syncobj_stub_fence_ops,
-                              &signaled_fence_lock,
-                              0, 0);
-               dma_fence_signal_locked(&signaled_fence);
-       }
-       spin_unlock(&signaled_fence_lock);
-
-       return dma_fence_get(&signaled_fence);
-}
 /**
  * drm_syncobj_find - lookup and reference a sync object.
  * @file_private: drm file private pointer
@@ -123,27 +98,6 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
 }
 EXPORT_SYMBOL(drm_syncobj_find);
 
-static struct dma_fence *
-drm_syncobj_find_signal_pt_for_point(struct drm_syncobj *syncobj,
-                                    uint64_t point)
-{
-       struct drm_syncobj_signal_pt *signal_pt;
-
-       if ((syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) &&
-           (point <= syncobj->timeline))
-               return drm_syncobj_get_stub_fence();
-
-       list_for_each_entry(signal_pt, &syncobj->signal_pt_list, list) {
-               if (point > signal_pt->value)
-                       continue;
-               if ((syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) &&
-                   (point != signal_pt->value))
-                       continue;
-               return dma_fence_get(&signal_pt->fence_array->base);
-       }
-       return NULL;
-}
-
 static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj,
                                            struct drm_syncobj_cb *cb,
                                            drm_syncobj_func_t func)
@@ -152,158 +106,53 @@ static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj,
        list_add_tail(&cb->node, &syncobj->cb_list);
 }
 
-static void drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
-                                                 struct dma_fence **fence,
-                                                 struct drm_syncobj_cb *cb,
-                                                 drm_syncobj_func_t func)
+static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
+                                                struct dma_fence **fence,
+                                                struct drm_syncobj_cb *cb,
+                                                drm_syncobj_func_t func)
 {
-       u64 pt_value = 0;
-
-       WARN_ON(*fence);
-
-       if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) {
-               /*BINARY syncobj always wait on last pt */
-               pt_value = syncobj->signal_point;
+       int ret;
 
-               if (pt_value == 0)
-                       pt_value += DRM_SYNCOBJ_BINARY_POINT;
-       }
+       *fence = drm_syncobj_fence_get(syncobj);
+       if (*fence)
+               return 1;
 
-       mutex_lock(&syncobj->cb_mutex);
-       spin_lock(&syncobj->pt_lock);
-       *fence = drm_syncobj_find_signal_pt_for_point(syncobj, pt_value);
-       spin_unlock(&syncobj->pt_lock);
-       if (!*fence)
+       spin_lock(&syncobj->lock);
+       /* We've already tried once to get a fence and failed.  Now that we
+        * have the lock, try one more time just to be sure we don't add a
+        * callback when a fence has already been set.
+        */
+       if (syncobj->fence) {
+               *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
+                                                                lockdep_is_held(&syncobj->lock)));
+               ret = 1;
+       } else {
+               *fence = NULL;
                drm_syncobj_add_callback_locked(syncobj, cb, func);
-       mutex_unlock(&syncobj->cb_mutex);
-}
-
-static void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
-                                       struct drm_syncobj_cb *cb)
-{
-       mutex_lock(&syncobj->cb_mutex);
-       list_del_init(&cb->node);
-       mutex_unlock(&syncobj->cb_mutex);
-}
+               ret = 0;
+       }
+       spin_unlock(&syncobj->lock);
 
-static void drm_syncobj_init(struct drm_syncobj *syncobj)
-{
-       spin_lock(&syncobj->pt_lock);
-       syncobj->timeline_context = dma_fence_context_alloc(1);
-       syncobj->timeline = 0;
-       syncobj->signal_point = 0;
-       init_waitqueue_head(&syncobj->wq);
-
-       INIT_LIST_HEAD(&syncobj->signal_pt_list);
-       spin_unlock(&syncobj->pt_lock);
+       return ret;
 }
 
-static void drm_syncobj_fini(struct drm_syncobj *syncobj)
+void drm_syncobj_add_callback(struct drm_syncobj *syncobj,
+                             struct drm_syncobj_cb *cb,
+                             drm_syncobj_func_t func)
 {
-       struct drm_syncobj_signal_pt *signal_pt = NULL, *tmp;
-
-       spin_lock(&syncobj->pt_lock);
-       list_for_each_entry_safe(signal_pt, tmp,
-                                &syncobj->signal_pt_list, list) {
-               list_del(&signal_pt->list);
-               dma_fence_put(&signal_pt->fence_array->base);
-               kfree(signal_pt);
-       }
-       spin_unlock(&syncobj->pt_lock);
+       spin_lock(&syncobj->lock);
+       drm_syncobj_add_callback_locked(syncobj, cb, func);
+       spin_unlock(&syncobj->lock);
 }
 
-static int drm_syncobj_create_signal_pt(struct drm_syncobj *syncobj,
-                                       struct dma_fence *fence,
-                                       u64 point)
+void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
+                                struct drm_syncobj_cb *cb)
 {
-       struct drm_syncobj_signal_pt *signal_pt =
-               kzalloc(sizeof(struct drm_syncobj_signal_pt), GFP_KERNEL);
-       struct drm_syncobj_signal_pt *tail_pt;
-       struct dma_fence **fences;
-       int num_fences = 0;
-       int ret = 0, i;
-
-       if (!signal_pt)
-               return -ENOMEM;
-       if (!fence)
-               goto out;
-
-       fences = kmalloc_array(sizeof(void *), 2, GFP_KERNEL);
-       if (!fences) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       fences[num_fences++] = dma_fence_get(fence);
-       /* timeline syncobj must take this dependency */
-       if (syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) {
-               spin_lock(&syncobj->pt_lock);
-               if (!list_empty(&syncobj->signal_pt_list)) {
-                       tail_pt = list_last_entry(&syncobj->signal_pt_list,
-                                                 struct drm_syncobj_signal_pt, list);
-                       fences[num_fences++] =
-                               dma_fence_get(&tail_pt->fence_array->base);
-               }
-               spin_unlock(&syncobj->pt_lock);
-       }
-       signal_pt->fence_array = dma_fence_array_create(num_fences, fences,
-                                                       syncobj->timeline_context,
-                                                       point, false);
-       if (!signal_pt->fence_array) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       spin_lock(&syncobj->pt_lock);
-       if (syncobj->signal_point >= point) {
-               DRM_WARN("A later signal is ready!");
-               spin_unlock(&syncobj->pt_lock);
-               goto exist;
-       }
-       signal_pt->value = point;
-       list_add_tail(&signal_pt->list, &syncobj->signal_pt_list);
-       syncobj->signal_point = point;
-       spin_unlock(&syncobj->pt_lock);
-       wake_up_all(&syncobj->wq);
-
-       return 0;
-exist:
-       dma_fence_put(&signal_pt->fence_array->base);
-fail:
-       for (i = 0; i < num_fences; i++)
-               dma_fence_put(fences[i]);
-       kfree(fences);
-out:
-       kfree(signal_pt);
-       return ret;
+       spin_lock(&syncobj->lock);
+       list_del_init(&cb->node);
+       spin_unlock(&syncobj->lock);
 }
 
-static void drm_syncobj_garbage_collection(struct drm_syncobj *syncobj)
-{
-       struct drm_syncobj_signal_pt *signal_pt, *tmp, *tail_pt;
-
-       spin_lock(&syncobj->pt_lock);
-       tail_pt = list_last_entry(&syncobj->signal_pt_list,
-                                 struct drm_syncobj_signal_pt,
-                                 list);
-       list_for_each_entry_safe(signal_pt, tmp,
-                                &syncobj->signal_pt_list, list) {
-               if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY &&
-                   signal_pt == tail_pt)
-                       continue;
-               if (dma_fence_is_signaled(&signal_pt->fence_array->base)) {
-                       syncobj->timeline = signal_pt->value;
-                       list_del(&signal_pt->list);
-                       dma_fence_put(&signal_pt->fence_array->base);
-                       kfree(signal_pt);
-               } else {
-                       /*signal_pt is in order in list, from small to big, so
-                        * the later must not be signal either */
-                       break;
-               }
-       }
-
-       spin_unlock(&syncobj->pt_lock);
-}
 /**
  * drm_syncobj_replace_fence - replace fence in a sync object.
  * @syncobj: Sync object to replace fence in
@@ -316,30 +165,28 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
                               u64 point,
                               struct dma_fence *fence)
 {
-       u64 pt_value = point;
-
-       drm_syncobj_garbage_collection(syncobj);
-       if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) {
-               if (!fence) {
-                       drm_syncobj_fini(syncobj);
-                       drm_syncobj_init(syncobj);
-                       return;
-               }
-               pt_value = syncobj->signal_point +
-                       DRM_SYNCOBJ_BINARY_POINT;
-       }
-       drm_syncobj_create_signal_pt(syncobj, fence, pt_value);
-       if (fence) {
-               struct drm_syncobj_cb *cur, *tmp;
-               LIST_HEAD(cb_list);
+       struct dma_fence *old_fence;
+       struct drm_syncobj_cb *cur, *tmp;
+
+       if (fence)
+               dma_fence_get(fence);
+
+       spin_lock(&syncobj->lock);
 
-               mutex_lock(&syncobj->cb_mutex);
+       old_fence = rcu_dereference_protected(syncobj->fence,
+                                             lockdep_is_held(&syncobj->lock));
+       rcu_assign_pointer(syncobj->fence, fence);
+
+       if (fence != old_fence) {
                list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
                        list_del_init(&cur->node);
                        cur->func(syncobj, cur);
                }
-               mutex_unlock(&syncobj->cb_mutex);
        }
+
+       spin_unlock(&syncobj->lock);
+
+       dma_fence_put(old_fence);
 }
 EXPORT_SYMBOL(drm_syncobj_replace_fence);
 
@@ -362,64 +209,6 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
        return 0;
 }
 
-static int
-drm_syncobj_point_get(struct drm_syncobj *syncobj, u64 point, u64 flags,
-                     struct dma_fence **fence)
-{
-       int ret = 0;
-
-       if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
-               ret = wait_event_interruptible(syncobj->wq,
-                                              point <= syncobj->signal_point);
-               if (ret < 0)
-                       return ret;
-       }
-       spin_lock(&syncobj->pt_lock);
-       *fence = drm_syncobj_find_signal_pt_for_point(syncobj, point);
-       if (!*fence)
-               ret = -EINVAL;
-       spin_unlock(&syncobj->pt_lock);
-       return ret;
-}
-
-/**
- * drm_syncobj_search_fence - lookup and reference the fence in a sync object or
- * in a timeline point
- * @syncobj: sync object pointer
- * @point: timeline point
- * @flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or not
- * @fence: out parameter for the fence
- *
- * if flags is DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, the function will block
- * here until specific timeline points is reached.
- * if not, you need a submit thread and block in userspace until all future
- * timeline points have materialized, only then you can submit to the kernel,
- * otherwise, function will fail to return fence.
- *
- * Returns 0 on success or a negative error value on failure. On success @fence
- * contains a reference to the fence, which must be released by calling
- * dma_fence_put().
- */
-int drm_syncobj_search_fence(struct drm_syncobj *syncobj, u64 point,
-                            u64 flags, struct dma_fence **fence)
-{
-       u64 pt_value = point;
-
-       if (!syncobj)
-               return -ENOENT;
-
-       drm_syncobj_garbage_collection(syncobj);
-       if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) {
-               /*BINARY syncobj always wait on last pt */
-               pt_value = syncobj->signal_point;
-
-               if (pt_value == 0)
-                       pt_value += DRM_SYNCOBJ_BINARY_POINT;
-       }
-       return drm_syncobj_point_get(syncobj, pt_value, flags, fence);
-}
-EXPORT_SYMBOL(drm_syncobj_search_fence);
-
 /**
  * drm_syncobj_find_fence - lookup and reference the fence in a sync object
  * @file_private: drm file private pointer
@@ -429,7 +218,7 @@ EXPORT_SYMBOL(drm_syncobj_search_fence);
  * @fence: out parameter for the fence
  *
  * This is just a convenience function that combines drm_syncobj_find() and
- * drm_syncobj_lookup_fence().
+ * drm_syncobj_fence_get().
  *
  * Returns 0 on success or a negative error value on failure. On success @fence
  * contains a reference to the fence, which must be released by calling
@@ -440,11 +229,16 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
                           struct dma_fence **fence)
 {
        struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
-       int ret;
+       int ret = 0;
 
-       ret = drm_syncobj_search_fence(syncobj, point, flags, fence);
-       if (syncobj)
-               drm_syncobj_put(syncobj);
+       if (!syncobj)
+               return -ENOENT;
+
+       *fence = drm_syncobj_fence_get(syncobj);
+       if (!*fence) {
+               ret = -EINVAL;
+       }
+       drm_syncobj_put(syncobj);
        return ret;
 }
 EXPORT_SYMBOL(drm_syncobj_find_fence);
@@ -460,7 +254,7 @@ void drm_syncobj_free(struct kref *kref)
        struct drm_syncobj *syncobj = container_of(kref,
                                                   struct drm_syncobj,
                                                   refcount);
-       drm_syncobj_fini(syncobj);
+       drm_syncobj_replace_fence(syncobj, 0, NULL);
        kfree(syncobj);
 }
 EXPORT_SYMBOL(drm_syncobj_free);
@@ -489,13 +283,7 @@ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
 
        kref_init(&syncobj->refcount);
        INIT_LIST_HEAD(&syncobj->cb_list);
-       spin_lock_init(&syncobj->pt_lock);
-       mutex_init(&syncobj->cb_mutex);
-       if (flags & DRM_SYNCOBJ_CREATE_TYPE_TIMELINE)
-               syncobj->type = DRM_SYNCOBJ_TYPE_TIMELINE;
-       else
-               syncobj->type = DRM_SYNCOBJ_TYPE_BINARY;
-       drm_syncobj_init(syncobj);
+       spin_lock_init(&syncobj->lock);
 
        if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) {
                ret = drm_syncobj_assign_null_handle(syncobj);
@@ -778,8 +566,7 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data,
                return -EOPNOTSUPP;
 
        /* no valid flags yet */
-       if (args->flags & ~(DRM_SYNCOBJ_CREATE_SIGNALED |
-                           DRM_SYNCOBJ_CREATE_TYPE_TIMELINE))
+       if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED)
                return -EINVAL;
 
        return drm_syncobj_create_as_handle(file_private,
@@ -872,8 +659,9 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
        struct syncobj_wait_entry *wait =
                container_of(cb, struct syncobj_wait_entry, syncobj_cb);
 
-       drm_syncobj_search_fence(syncobj, 0, 0, &wait->fence);
-
+       /* This happens inside the syncobj lock */
+       wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
+                                                             lockdep_is_held(&syncobj->lock)));
        wake_up_process(wait->task);
 }
 
@@ -899,8 +687,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
        signaled_count = 0;
        for (i = 0; i < count; ++i) {
                entries[i].task = current;
-               drm_syncobj_search_fence(syncobjs[i], 0, 0,
-                                        &entries[i].fence);
+               entries[i].fence = drm_syncobj_fence_get(syncobjs[i]);
                if (!entries[i].fence) {
                        if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
                                continue;
@@ -931,9 +718,6 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 
        if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
                for (i = 0; i < count; ++i) {
-                       if (entries[i].fence)
-                               continue;
-
                        drm_syncobj_fence_get_or_add_callback(syncobjs[i],
                                                              &entries[i].fence,
                                                              &entries[i].syncobj_cb,
@@ -1165,13 +949,12 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < args->count_handles; i++) {
-               drm_syncobj_fini(syncobjs[i]);
-               drm_syncobj_init(syncobjs[i]);
-       }
+       for (i = 0; i < args->count_handles; i++)
+               drm_syncobj_replace_fence(syncobjs[i], 0, NULL);
+
        drm_syncobj_array_free(syncobjs, args->count_handles);
 
-       return ret;
+       return 0;
 }
 
 int
index 83c1f46670bfea9dcbe95e42da598c8665576b03..52802e6049e0adab5045b57cc09bd265708ae34d 100644 (file)
@@ -550,7 +550,7 @@ out_register:
 out_bind:
        kfree(priv);
 out_unref:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return ret;
 }
@@ -567,7 +567,7 @@ static void etnaviv_unbind(struct device *dev)
        drm->dev_private = NULL;
        kfree(priv);
 
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 }
 
 static const struct component_master_ops etnaviv_master_ops = {
index 7b3ae2333dbf4cea0cb95c3ead0d9d3e53b4dfa3..d4fac09095f862aed3131243957059de2df4f6b0 100644 (file)
@@ -2162,7 +2162,7 @@ await_fence_array(struct i915_execbuffer *eb,
                if (!(flags & I915_EXEC_FENCE_WAIT))
                        continue;
 
-               drm_syncobj_search_fence(syncobj, 0, 0, &fence);
+               fence = drm_syncobj_fence_get(syncobj);
                if (!fence)
                        return -EINVAL;
 
index fe6becdcc29edc8dc4fd105c932375a53c5e5865..77a26fd3a44ac18da443172883efaee8d66b7af7 100644 (file)
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  *
  * derived from imx-hdmi.c(renamed to bridge/dw_hdmi.c now)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 0e6942f21a4ea0879f10ba6f192035893cff0fa9..820c7e3878f0235d7ab9b4dd966a215ec7afa5b0 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Freescale i.MX drm driver
  *
  * Copyright (C) 2011 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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/component.h>
 #include <linux/device.h>
index 3bd0f8a18e748ca4be125d02a12bc50f7fe1bebc..2c5bbe3173537346e1ea0d5c0b0f0e011ea485e7 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i.MX drm driver - LVDS display bridge
  *
  * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index cffd3310240e5ddec86f13a2cce9b456d0c29d1f..293dd5752583bdad9148685f88c621d8f7840aa2 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i.MX drm driver - Television Encoder (TVEv2)
  *
  * Copyright (C) 2013 Philipp Zabel, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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>
@@ -442,7 +434,7 @@ static int clk_tve_di_set_rate(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
-static struct clk_ops clk_tve_di_ops = {
+static const struct clk_ops clk_tve_di_ops = {
        .round_rate = clk_tve_di_round_rate,
        .set_rate = clk_tve_di_set_rate,
        .recalc_rate = clk_tve_di_recalc_rate,
index 7d4b710b837ac40d90704484c4b2dc731df851bf..058b53c0aa7ecd5c308fa4b222146e57f3281db4 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i.MX IPUv3 Graphics driver
  *
  * Copyright (C) 2011 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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/component.h>
 #include <linux/module.h>
index 40605fdf0e338529fb040adaf15bfbde23e864f6..c390924de93d978d3acb4200c846fe6b53f753c8 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i.MX IPUv3 DP Overlay Planes
  *
  * Copyright (C) 2013 Philipp Zabel, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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 <drm/drmP.h>
@@ -236,9 +228,15 @@ static void ipu_plane_enable(struct ipu_plane *ipu_plane)
 
 void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
 {
+       int ret;
+
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
-       ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
+       ret = ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
+       if (ret == -ETIMEDOUT) {
+               DRM_ERROR("[PLANE:%d] IDMAC timeout\n",
+                         ipu_plane->base.base.id);
+       }
 
        if (ipu_plane->dp && disable_dp_channel)
                ipu_dp_disable_channel(ipu_plane->dp, false);
index aefd04e18f935037d3694a653b9cefb25540916c..f3ce51121dd62f967dbf011353097488bef47f7a 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i.MX drm driver - parallel display implementation
  *
  * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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/component.h>
index 3ce51d8dfe1c8964f178cf38943282712abcd10f..c28b69f485555ba4cef15a1af2c4b745530d1ea9 100644 (file)
@@ -7,6 +7,7 @@ config DRM_MESON
        select DRM_GEM_CMA_HELPER
        select VIDEOMODE_HELPERS
        select REGMAP_MMIO
+       select MESON_CANVAS
 
 config DRM_MESON_DW_HDMI
        tristate "HDMI Synopsys Controller support for Amlogic Meson Display"
index c5c4cc362f024b449ae76bb41bf625ed022264f5..7709f2fbb9f77eda97b2e8bd607e30412cb5c9da 100644 (file)
@@ -1,5 +1,5 @@
 meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
-meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
+meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o meson_overlay.o
 
 obj-$(CONFIG_DRM_MESON) += meson-drm.o
 obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
index 08f6073d967e04ce2e0f89650f656d08d953f9aa..5de11aa7c775ec8f191c7d3bc1b740f2b1ecfb28 100644 (file)
@@ -39,6 +39,7 @@
 #define CANVAS_WIDTH_HBIT       0
 #define CANVAS_HEIGHT_BIT       9
 #define CANVAS_BLKMODE_BIT      24
+#define CANVAS_ENDIAN_BIT      26
 #define DMC_CAV_LUT_ADDR       0x50 /* 0x14 offset in data sheet */
 #define CANVAS_LUT_WR_EN        (0x2 << 8)
 #define CANVAS_LUT_RD_EN        (0x1 << 8)
@@ -47,7 +48,8 @@ void meson_canvas_setup(struct meson_drm *priv,
                        uint32_t canvas_index, uint32_t addr,
                        uint32_t stride, uint32_t height,
                        unsigned int wrap,
-                       unsigned int blkmode)
+                       unsigned int blkmode,
+                       unsigned int endian)
 {
        unsigned int val;
 
@@ -60,7 +62,8 @@ void meson_canvas_setup(struct meson_drm *priv,
                                                CANVAS_WIDTH_HBIT) |
                (height << CANVAS_HEIGHT_BIT) |
                (wrap << 22) |
-               (blkmode << CANVAS_BLKMODE_BIT));
+               (blkmode << CANVAS_BLKMODE_BIT) |
+               (endian << CANVAS_ENDIAN_BIT));
 
        regmap_write(priv->dmc, DMC_CAV_LUT_ADDR,
                        CANVAS_LUT_WR_EN | canvas_index);
index af1759da4b275327377d73bdfe7d265bf40db497..85dbf26e2826a16fcbab87060b03c08a693e30f7 100644 (file)
@@ -23,6 +23,9 @@
 #define __MESON_CANVAS_H
 
 #define MESON_CANVAS_ID_OSD1   0x4e
+#define MESON_CANVAS_ID_VD1_0  0x60
+#define MESON_CANVAS_ID_VD1_1  0x61
+#define MESON_CANVAS_ID_VD1_2  0x62
 
 /* Canvas configuration. */
 #define MESON_CANVAS_WRAP_NONE 0x00
 #define        MESON_CANVAS_BLKMODE_32x32      0x01
 #define        MESON_CANVAS_BLKMODE_64x64      0x02
 
+#define MESON_CANVAS_ENDIAN_SWAP16     0x1
+#define MESON_CANVAS_ENDIAN_SWAP32     0x3
+#define MESON_CANVAS_ENDIAN_SWAP64     0x7
+#define MESON_CANVAS_ENDIAN_SWAP128    0xf
+
 void meson_canvas_setup(struct meson_drm *priv,
                        uint32_t canvas_index, uint32_t addr,
                        uint32_t stride, uint32_t height,
                        unsigned int wrap,
-                       unsigned int blkmode);
+                       unsigned int blkmode,
+                       unsigned int endian);
 
 #endif /* __MESON_CANVAS_H */
index 05520202c96778c1401dac07a9b9ff768ba97b91..d78168f979db3b46a3978eb9a7a3ff4dfb05334e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/bitfield.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -98,6 +99,10 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
        writel(crtc_state->mode.hdisplay,
               priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
 
+       /* VD1 Preblend vertical start/end */
+       writel(FIELD_PREP(GENMASK(11, 0), 2303),
+                       priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
+
        writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
                            priv->io_base + _REG(VPP_MISC));
 
@@ -110,11 +115,17 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct meson_drm *priv = meson_crtc->priv;
 
+       DRM_DEBUG_DRIVER("\n");
+
        priv->viu.osd1_enabled = false;
        priv->viu.osd1_commit = false;
 
+       priv->viu.vd1_enabled = false;
+       priv->viu.vd1_commit = false;
+
        /* Disable VPP Postblend */
-       writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+       writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
+                           VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
                            priv->io_base + _REG(VPP_MISC));
 
        if (crtc->state->event && !crtc->state->active) {
@@ -149,6 +160,7 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
        struct meson_drm *priv = meson_crtc->priv;
 
        priv->viu.osd1_commit = true;
+       priv->viu.vd1_commit = true;
 }
 
 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
@@ -177,26 +189,37 @@ void meson_crtc_irq(struct meson_drm *priv)
                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
                writel_relaxed(priv->viu.osd1_blk0_cfg[4],
                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
-
-               /* If output is interlace, make use of the Scaler */
-               if (priv->viu.osd1_interlace) {
-                       struct drm_plane *plane = priv->primary_plane;
-                       struct drm_plane_state *state = plane->state;
-                       struct drm_rect dest = {
-                               .x1 = state->crtc_x,
-                               .y1 = state->crtc_y,
-                               .x2 = state->crtc_x + state->crtc_w,
-                               .y2 = state->crtc_y + state->crtc_h,
-                       };
-
-                       meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
-               } else
-                       meson_vpp_disable_interlace_vscaler_osd1(priv);
-
-               meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
-                          priv->viu.osd1_addr, priv->viu.osd1_stride,
-                          priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE,
-                          MESON_CANVAS_BLKMODE_LINEAR);
+               writel_relaxed(priv->viu.osd_sc_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+               writel_relaxed(priv->viu.osd_sc_i_wh_m1,
+                               priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
+               writel_relaxed(priv->viu.osd_sc_o_h_start_end,
+                               priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
+               writel_relaxed(priv->viu.osd_sc_o_v_start_end,
+                               priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
+               writel_relaxed(priv->viu.osd_sc_v_ini_phase,
+                               priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
+               writel_relaxed(priv->viu.osd_sc_v_phase_step,
+                               priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
+               writel_relaxed(priv->viu.osd_sc_h_ini_phase,
+                               priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
+               writel_relaxed(priv->viu.osd_sc_h_phase_step,
+                               priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
+               writel_relaxed(priv->viu.osd_sc_h_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+               writel_relaxed(priv->viu.osd_sc_v_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+
+               if (priv->canvas)
+                       meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
+                               priv->viu.osd1_addr, priv->viu.osd1_stride,
+                               priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE,
+                               MESON_CANVAS_BLKMODE_LINEAR, 0);
+               else
+                       meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
+                               priv->viu.osd1_addr, priv->viu.osd1_stride,
+                               priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE,
+                               MESON_CANVAS_BLKMODE_LINEAR, 0);
 
                /* Enable OSD1 */
                writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
@@ -205,6 +228,206 @@ void meson_crtc_irq(struct meson_drm *priv)
                priv->viu.osd1_commit = false;
        }
 
+       /* Update the VD1 registers */
+       if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
+
+               switch (priv->viu.vd1_planes) {
+               case 3:
+                       if (priv->canvas)
+                               meson_canvas_config(priv->canvas,
+                                                   priv->canvas_id_vd1_2,
+                                                   priv->viu.vd1_addr2,
+                                                   priv->viu.vd1_stride2,
+                                                   priv->viu.vd1_height2,
+                                                   MESON_CANVAS_WRAP_NONE,
+                                                   MESON_CANVAS_BLKMODE_LINEAR,
+                                                   MESON_CANVAS_ENDIAN_SWAP64);
+                       else
+                               meson_canvas_setup(priv, MESON_CANVAS_ID_VD1_2,
+                                                  priv->viu.vd1_addr2,
+                                                  priv->viu.vd1_stride2,
+                                                  priv->viu.vd1_height2,
+                                                  MESON_CANVAS_WRAP_NONE,
+                                                  MESON_CANVAS_BLKMODE_LINEAR,
+                                                  MESON_CANVAS_ENDIAN_SWAP64);
+               /* fallthrough */
+               case 2:
+                       if (priv->canvas)
+                               meson_canvas_config(priv->canvas,
+                                                   priv->canvas_id_vd1_1,
+                                                   priv->viu.vd1_addr1,
+                                                   priv->viu.vd1_stride1,
+                                                   priv->viu.vd1_height1,
+                                                   MESON_CANVAS_WRAP_NONE,
+                                                   MESON_CANVAS_BLKMODE_LINEAR,
+                                                   MESON_CANVAS_ENDIAN_SWAP64);
+                       else
+                               meson_canvas_setup(priv, MESON_CANVAS_ID_VD1_1,
+                                                  priv->viu.vd1_addr2,
+                                                  priv->viu.vd1_stride2,
+                                                  priv->viu.vd1_height2,
+                                                  MESON_CANVAS_WRAP_NONE,
+                                                  MESON_CANVAS_BLKMODE_LINEAR,
+                                                  MESON_CANVAS_ENDIAN_SWAP64);
+               /* fallthrough */
+               case 1:
+                       if (priv->canvas)
+                               meson_canvas_config(priv->canvas,
+                                                   priv->canvas_id_vd1_0,
+                                                   priv->viu.vd1_addr0,
+                                                   priv->viu.vd1_stride0,
+                                                   priv->viu.vd1_height0,
+                                                   MESON_CANVAS_WRAP_NONE,
+                                                   MESON_CANVAS_BLKMODE_LINEAR,
+                                                   MESON_CANVAS_ENDIAN_SWAP64);
+                       else
+                               meson_canvas_setup(priv, MESON_CANVAS_ID_VD1_0,
+                                                  priv->viu.vd1_addr2,
+                                                  priv->viu.vd1_stride2,
+                                                  priv->viu.vd1_height2,
+                                                  MESON_CANVAS_WRAP_NONE,
+                                                  MESON_CANVAS_BLKMODE_LINEAR,
+                                                  MESON_CANVAS_ENDIAN_SWAP64);
+               };
+
+               writel_relaxed(priv->viu.vd1_if0_gen_reg,
+                               priv->io_base + _REG(VD1_IF0_GEN_REG));
+               writel_relaxed(priv->viu.vd1_if0_gen_reg,
+                               priv->io_base + _REG(VD2_IF0_GEN_REG));
+               writel_relaxed(priv->viu.vd1_if0_gen_reg2,
+                               priv->io_base + _REG(VD1_IF0_GEN_REG2));
+               writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
+                               priv->io_base + _REG(VIU_VD1_FMT_CTRL));
+               writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
+                               priv->io_base + _REG(VIU_VD2_FMT_CTRL));
+               writel_relaxed(priv->viu.viu_vd1_fmt_w,
+                               priv->io_base + _REG(VIU_VD1_FMT_W));
+               writel_relaxed(priv->viu.viu_vd1_fmt_w,
+                               priv->io_base + _REG(VIU_VD2_FMT_W));
+               writel_relaxed(priv->viu.vd1_if0_canvas0,
+                               priv->io_base + _REG(VD1_IF0_CANVAS0));
+               writel_relaxed(priv->viu.vd1_if0_canvas0,
+                               priv->io_base + _REG(VD1_IF0_CANVAS1));
+               writel_relaxed(priv->viu.vd1_if0_canvas0,
+                               priv->io_base + _REG(VD2_IF0_CANVAS0));
+               writel_relaxed(priv->viu.vd1_if0_canvas0,
+                               priv->io_base + _REG(VD2_IF0_CANVAS1));
+               writel_relaxed(priv->viu.vd1_if0_luma_x0,
+                               priv->io_base + _REG(VD1_IF0_LUMA_X0));
+               writel_relaxed(priv->viu.vd1_if0_luma_x0,
+                               priv->io_base + _REG(VD1_IF0_LUMA_X1));
+               writel_relaxed(priv->viu.vd1_if0_luma_x0,
+                               priv->io_base + _REG(VD2_IF0_LUMA_X0));
+               writel_relaxed(priv->viu.vd1_if0_luma_x0,
+                               priv->io_base + _REG(VD2_IF0_LUMA_X1));
+               writel_relaxed(priv->viu.vd1_if0_luma_y0,
+                               priv->io_base + _REG(VD1_IF0_LUMA_Y0));
+               writel_relaxed(priv->viu.vd1_if0_luma_y0,
+                               priv->io_base + _REG(VD1_IF0_LUMA_Y1));
+               writel_relaxed(priv->viu.vd1_if0_luma_y0,
+                               priv->io_base + _REG(VD2_IF0_LUMA_Y0));
+               writel_relaxed(priv->viu.vd1_if0_luma_y0,
+                               priv->io_base + _REG(VD2_IF0_LUMA_Y1));
+               writel_relaxed(priv->viu.vd1_if0_chroma_x0,
+                               priv->io_base + _REG(VD1_IF0_CHROMA_X0));
+               writel_relaxed(priv->viu.vd1_if0_chroma_x0,
+                               priv->io_base + _REG(VD1_IF0_CHROMA_X1));
+               writel_relaxed(priv->viu.vd1_if0_chroma_x0,
+                               priv->io_base + _REG(VD2_IF0_CHROMA_X0));
+               writel_relaxed(priv->viu.vd1_if0_chroma_x0,
+                               priv->io_base + _REG(VD2_IF0_CHROMA_X1));
+               writel_relaxed(priv->viu.vd1_if0_chroma_y0,
+                               priv->io_base + _REG(VD1_IF0_CHROMA_Y0));
+               writel_relaxed(priv->viu.vd1_if0_chroma_y0,
+                               priv->io_base + _REG(VD1_IF0_CHROMA_Y1));
+               writel_relaxed(priv->viu.vd1_if0_chroma_y0,
+                               priv->io_base + _REG(VD2_IF0_CHROMA_Y0));
+               writel_relaxed(priv->viu.vd1_if0_chroma_y0,
+                               priv->io_base + _REG(VD2_IF0_CHROMA_Y1));
+               writel_relaxed(priv->viu.vd1_if0_repeat_loop,
+                               priv->io_base + _REG(VD1_IF0_RPT_LOOP));
+               writel_relaxed(priv->viu.vd1_if0_repeat_loop,
+                               priv->io_base + _REG(VD2_IF0_RPT_LOOP));
+               writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
+                               priv->io_base + _REG(VD1_IF0_LUMA0_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
+                               priv->io_base + _REG(VD2_IF0_LUMA0_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
+                               priv->io_base + _REG(VD1_IF0_LUMA1_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
+                               priv->io_base + _REG(VD2_IF0_LUMA1_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
+                               priv->io_base + _REG(VD1_IF0_CHROMA0_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
+                               priv->io_base + _REG(VD2_IF0_CHROMA0_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
+                               priv->io_base + _REG(VD1_IF0_CHROMA1_RPT_PAT));
+               writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
+                               priv->io_base + _REG(VD2_IF0_CHROMA1_RPT_PAT));
+               writel_relaxed(0, priv->io_base + _REG(VD1_IF0_LUMA_PSEL));
+               writel_relaxed(0, priv->io_base + _REG(VD1_IF0_CHROMA_PSEL));
+               writel_relaxed(0, priv->io_base + _REG(VD2_IF0_LUMA_PSEL));
+               writel_relaxed(0, priv->io_base + _REG(VD2_IF0_CHROMA_PSEL));
+               writel_relaxed(priv->viu.vd1_range_map_y,
+                               priv->io_base + _REG(VD1_IF0_RANGE_MAP_Y));
+               writel_relaxed(priv->viu.vd1_range_map_cb,
+                               priv->io_base + _REG(VD1_IF0_RANGE_MAP_CB));
+               writel_relaxed(priv->viu.vd1_range_map_cr,
+                               priv->io_base + _REG(VD1_IF0_RANGE_MAP_CR));
+               writel_relaxed(0x78404,
+                               priv->io_base + _REG(VPP_SC_MISC));
+               writel_relaxed(priv->viu.vpp_pic_in_height,
+                               priv->io_base + _REG(VPP_PIC_IN_HEIGHT));
+               writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end,
+                       priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END));
+               writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end,
+                       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+               writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end,
+                       priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END));
+               writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end,
+                       priv->io_base + _REG(VPP_BLEND_VD2_V_START_END));
+               writel_relaxed(priv->viu.vpp_hsc_region12_startp,
+                               priv->io_base + _REG(VPP_HSC_REGION12_STARTP));
+               writel_relaxed(priv->viu.vpp_hsc_region34_startp,
+                               priv->io_base + _REG(VPP_HSC_REGION34_STARTP));
+               writel_relaxed(priv->viu.vpp_hsc_region4_endp,
+                               priv->io_base + _REG(VPP_HSC_REGION4_ENDP));
+               writel_relaxed(priv->viu.vpp_hsc_start_phase_step,
+                               priv->io_base + _REG(VPP_HSC_START_PHASE_STEP));
+               writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope,
+                       priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE));
+               writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope,
+                       priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE));
+               writel_relaxed(priv->viu.vpp_line_in_length,
+                               priv->io_base + _REG(VPP_LINE_IN_LENGTH));
+               writel_relaxed(priv->viu.vpp_preblend_h_size,
+                               priv->io_base + _REG(VPP_PREBLEND_H_SIZE));
+               writel_relaxed(priv->viu.vpp_vsc_region12_startp,
+                               priv->io_base + _REG(VPP_VSC_REGION12_STARTP));
+               writel_relaxed(priv->viu.vpp_vsc_region34_startp,
+                               priv->io_base + _REG(VPP_VSC_REGION34_STARTP));
+               writel_relaxed(priv->viu.vpp_vsc_region4_endp,
+                               priv->io_base + _REG(VPP_VSC_REGION4_ENDP));
+               writel_relaxed(priv->viu.vpp_vsc_start_phase_step,
+                               priv->io_base + _REG(VPP_VSC_START_PHASE_STEP));
+               writel_relaxed(priv->viu.vpp_vsc_ini_phase,
+                               priv->io_base + _REG(VPP_VSC_INI_PHASE));
+               writel_relaxed(priv->viu.vpp_vsc_phase_ctrl,
+                               priv->io_base + _REG(VPP_VSC_PHASE_CTRL));
+               writel_relaxed(priv->viu.vpp_hsc_phase_ctrl,
+                               priv->io_base + _REG(VPP_HSC_PHASE_CTRL));
+               writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
+
+               /* Enable VD1 */
+               writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
+                                   VPP_COLOR_MNG_ENABLE,
+                                   VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
+                                   VPP_COLOR_MNG_ENABLE,
+                                   priv->io_base + _REG(VPP_MISC));
+
+               priv->viu.vd1_commit = false;
+       }
+
        drm_crtc_handle_vblank(priv->crtc);
 
        spin_lock_irqsave(&priv->drm->event_lock, flags);
index 348b5a198b9d9bf92297b322990aa60e903f9e46..3ee4d4a4ecbae1e59c1fb5e0dfb873b24bf4497c 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "meson_drv.h"
 #include "meson_plane.h"
+#include "meson_overlay.h"
 #include "meson_crtc.h"
 #include "meson_venc_cvbs.h"
 
@@ -208,24 +209,51 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
                goto free_drm;
        }
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
-       if (!res) {
-               ret = -EINVAL;
-               goto free_drm;
-       }
-       /* Simply ioremap since it may be a shared register zone */
-       regs = devm_ioremap(dev, res->start, resource_size(res));
-       if (!regs) {
-               ret = -EADDRNOTAVAIL;
-               goto free_drm;
-       }
+       priv->canvas = meson_canvas_get(dev);
+       if (!IS_ERR(priv->canvas)) {
+               ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
+               if (ret)
+                       goto free_drm;
+               ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
+               if (ret) {
+                       meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+                       goto free_drm;
+               }
+               ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
+               if (ret) {
+                       meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+                       meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+                       goto free_drm;
+               }
+               ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
+               if (ret) {
+                       meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+                       meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+                       meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
+                       goto free_drm;
+               }
+       } else {
+               priv->canvas = NULL;
 
-       priv->dmc = devm_regmap_init_mmio(dev, regs,
-                                         &meson_regmap_config);
-       if (IS_ERR(priv->dmc)) {
-               dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
-               ret = PTR_ERR(priv->dmc);
-               goto free_drm;
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
+               if (!res) {
+                       ret = -EINVAL;
+                       goto free_drm;
+               }
+               /* Simply ioremap since it may be a shared register zone */
+               regs = devm_ioremap(dev, res->start, resource_size(res));
+               if (!regs) {
+                       ret = -EADDRNOTAVAIL;
+                       goto free_drm;
+               }
+
+               priv->dmc = devm_regmap_init_mmio(dev, regs,
+                                                 &meson_regmap_config);
+               if (IS_ERR(priv->dmc)) {
+                       dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
+                       ret = PTR_ERR(priv->dmc);
+                       goto free_drm;
+               }
        }
 
        priv->vsync_irq = platform_get_irq(pdev, 0);
@@ -264,6 +292,10 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
        if (ret)
                goto free_drm;
 
+       ret = meson_overlay_create(priv);
+       if (ret)
+               goto free_drm;
+
        ret = meson_crtc_create(priv);
        if (ret)
                goto free_drm;
@@ -300,6 +332,14 @@ static int meson_drv_bind(struct device *dev)
 static void meson_drv_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
+       struct meson_drm *priv = drm->dev_private;
+
+       if (priv->canvas) {
+               meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+               meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+               meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
+               meson_canvas_free(priv->canvas, priv->canvas_id_vd1_2);
+       }
 
        drm_dev_unregister(drm);
        drm_kms_helper_poll_fini(drm);
index aab96260da9f78145889399000d3fc51de5ac739..4dccf4cd042a58010c78c2f3f0db1195501f22ff 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
+#include <linux/soc/amlogic/meson-canvas.h>
 #include <drm/drmP.h>
 
 struct meson_drm {
@@ -31,9 +32,16 @@ struct meson_drm {
        struct regmap *dmc;
        int vsync_irq;
 
+       struct meson_canvas *canvas;
+       u8 canvas_id_osd1;
+       u8 canvas_id_vd1_0;
+       u8 canvas_id_vd1_1;
+       u8 canvas_id_vd1_2;
+
        struct drm_device *drm;
        struct drm_crtc *crtc;
        struct drm_plane *primary_plane;
+       struct drm_plane *overlay_plane;
 
        /* Components Data */
        struct {
@@ -45,6 +53,64 @@ struct meson_drm {
                uint32_t osd1_addr;
                uint32_t osd1_stride;
                uint32_t osd1_height;
+               uint32_t osd_sc_ctrl0;
+               uint32_t osd_sc_i_wh_m1;
+               uint32_t osd_sc_o_h_start_end;
+               uint32_t osd_sc_o_v_start_end;
+               uint32_t osd_sc_v_ini_phase;
+               uint32_t osd_sc_v_phase_step;
+               uint32_t osd_sc_h_ini_phase;
+               uint32_t osd_sc_h_phase_step;
+               uint32_t osd_sc_h_ctrl0;
+               uint32_t osd_sc_v_ctrl0;
+
+               bool vd1_enabled;
+               bool vd1_commit;
+               unsigned int vd1_planes;
+               uint32_t vd1_if0_gen_reg;
+               uint32_t vd1_if0_luma_x0;
+               uint32_t vd1_if0_luma_y0;
+               uint32_t vd1_if0_chroma_x0;
+               uint32_t vd1_if0_chroma_y0;
+               uint32_t vd1_if0_repeat_loop;
+               uint32_t vd1_if0_luma0_rpt_pat;
+               uint32_t vd1_if0_chroma0_rpt_pat;
+               uint32_t vd1_range_map_y;
+               uint32_t vd1_range_map_cb;
+               uint32_t vd1_range_map_cr;
+               uint32_t viu_vd1_fmt_w;
+               uint32_t vd1_if0_canvas0;
+               uint32_t vd1_if0_gen_reg2;
+               uint32_t viu_vd1_fmt_ctrl;
+               uint32_t vd1_addr0;
+               uint32_t vd1_addr1;
+               uint32_t vd1_addr2