Merge tag 'drm-misc-next-2019-08-08' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Fri, 9 Aug 2019 06:04:15 +0000 (16:04 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 9 Aug 2019 06:04:31 +0000 (16:04 +1000)
drm-misc-next for 5.4:

UAPI Changes:
 - HDCP: Add a Content protection type property

Cross-subsystem Changes:

Core Changes:
 - Continue to rework the include dependencies
 - fb: Remove the unused drm_gem_fbdev_fb_create function
 - drm-dp-helper: Make the link rate calculation more tolerant to
                  non-explicitly defined, yet supported, rates
 - fb-helper: Map DRM client buffer only when required, and instanciate a
              shadow buffer when the device has a dirty function or says so
 - connector: Add a helper to link the DDC adapter used by that connector to
              the userspace
 - vblank: Switch from DRM_WAIT_ON to wait_event_interruptible_timeout
 - dma-buf: Fix a stack corruption
 - ttm: Embed a drm_gem_object struct to make ttm_buffer_object a
        superclass of GEM, and convert drivers to use it.
 - hdcp: Improvements to report the content protection type to the
         userspace

Driver Changes:
 - Remove drm_gem_prime_import/export from being defined in the drivers
 - Drop DRM_AUTH usage from drivers
 - Continue to drop drmP.h
 - Convert drivers to the connector ddc helper

 - ingenic: Add support for more panel-related cases
 - komeda: Support for dual-link
 - lima: Reduce logging
 - mpag200: Fix the cursor support
 - panfrost: Export GPU features register to userspace through an ioctl
 - pl111: Remove the CLD pads wiring support from the DT
 - rockchip: Rework to use DRM PSR helpers, fix a bug in the VOP_WIN_GET
             macro
 - sun4i: Improve support for color encoding and range
 - tinydrm: Rework SPI support, improve MIPI-DBI support, move to drm/tiny
 - vkms: Rework of the CRC tracking

 - bridges:
   - sii902x: Add support for audio graph card
   - tc358767: Rework AUX data handling code
   - ti-sn65dsi86: Add Debugfs and proper DSI mode flags support

 - panels
   - Support for GiantPlus GPM940B0, Sharp LQ070Y3DG3B, Ortustech
     COM37H3M, Novatek NT39016, Sharp LS020B1DD01D, Raydium RM67191,
     Boe Himax8279d, Sharp LD-D5116Z01B
   - Conversion of the device tree bindings to the YAML description
   - jh057n00900: Rework the enable / disable path

 - fbdev:
   - ssd1307fb: Support more devices based on that controller

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190808121423.xzpedzkpyecvsiy4@flea
563 files changed:
Documentation/devicetree/bindings/display/arm,pl11x.txt
Documentation/devicetree/bindings/display/bridge/sii902x.txt
Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.txt [deleted file]
Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt
Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt [deleted file]
Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.txt [deleted file]
Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt [deleted file]
Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/edt,et-series.txt
Documentation/devicetree/bindings/display/panel/giantplus,gpm940b0.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.txt [deleted file]
Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/lvds.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.txt [deleted file]
Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.txt [deleted file]
Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/ortustech,com37h3m05dtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/ortustech,com37h3m99dtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/panel-common.txt [deleted file]
Documentation/devicetree/bindings/display/panel/panel-common.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/panel-lvds.txt [deleted file]
Documentation/devicetree/bindings/display/panel/panel.txt [deleted file]
Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.txt [deleted file]
Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.txt [deleted file]
Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.txt
Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.txt [deleted file]
Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/sharp,lq070y3dg3b.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/sharp,ls020b1dd01d.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/simple-panel.txt
Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.txt [deleted file]
Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt [deleted file]
Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt
Documentation/devicetree/bindings/display/ssd1307fb.txt
Documentation/gpu/drivers.rst
Documentation/gpu/drm-kms-helpers.rst
Documentation/gpu/drm-mm.rst
Documentation/gpu/introduction.rst
Documentation/gpu/tinydrm.rst [deleted file]
Documentation/gpu/todo.rst
Documentation/media/uapi/v4l/subdev-formats.rst
MAINTAINERS
drivers/dma-buf/dma-fence-chain.c
drivers/dma-buf/reservation.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.h
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
drivers/gpu/drm/arm/display/komeda/komeda_plane.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/arm/malidp_hw.c
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/armada/armada_gem.h
drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
drivers/gpu/drm/ast/Makefile
drivers/gpu/drm/ast/ast_dp501.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_fb.c [deleted file]
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_post.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/ati_pcigart.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/bochs/bochs.h
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/bochs/bochs_hw.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
drivers/gpu/drm/bridge/dumb-vga-dac.c
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
drivers/gpu/drm/bridge/nxp-ptn3460.c
drivers/gpu/drm/bridge/parade-ps8622.c
drivers/gpu/drm/bridge/sii902x.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/cirrus/cirrus.c
drivers/gpu/drm/drm_agpsupport.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_debugfs_crc.c
drivers/gpu/drm/drm_dma.c
drivers/gpu/drm/drm_dp_aux_dev.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_framebuffer_helper.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_hdcp.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_legacy_misc.c
drivers/gpu/drm/drm_lock.c
drivers/gpu/drm/drm_memory.c
drivers/gpu/drm/drm_mipi_dbi.c [new file with mode: 0644]
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_mode_object.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_scatter.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/drm_vblank.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_gem.h
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
drivers/gpu/drm/i2c/ch7006_priv.h
drivers/gpu/drm/i2c/sil164_drv.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i810/i810_drv.h
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_hdcp.h
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
drivers/gpu/drm/i915/gem/i915_gem_wait.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
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/ingenic/ingenic-drm.c
drivers/gpu/drm/lima/lima_device.c
drivers/gpu/drm/lima/lima_drv.c
drivers/gpu/drm/lima/lima_gem.c
drivers/gpu/drm/lima/lima_gem_prime.c
drivers/gpu/drm/lima/lima_object.c
drivers/gpu/drm/lima/lima_object.h
drivers/gpu/drm/lima/lima_vm.h
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/mediatek/mtk_disp_color.c
drivers/gpu/drm/mediatek/mtk_disp_ovl.c
drivers/gpu/drm/mediatek/mtk_disp_rdma.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_fb.c
drivers/gpu/drm/mediatek/mtk_drm_fb.h
drivers/gpu/drm/mediatek/mtk_drm_gem.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
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
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_venc.h
drivers/gpu/drm/meson/meson_venc_cvbs.c
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/meson/meson_vpp.c
drivers/gpu/drm/meson/meson_vpp.h
drivers/gpu/drm/mga/mga_dma.c
drivers/gpu/drm/mga/mga_drv.c
drivers/gpu/drm/mga/mga_drv.h
drivers/gpu/drm/mga/mga_ioc32.c
drivers/gpu/drm/mga/mga_irq.c
drivers/gpu/drm/mga/mga_state.c
drivers/gpu/drm/mga/mga_warp.c
drivers/gpu/drm/mgag200/Makefile
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_fb.c [deleted file]
drivers/gpu/drm/mgag200/mgag200_i2c.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/mxsfb/mxsfb_crtc.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/mxsfb/mxsfb_out.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_abi16.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_bo.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_gem.h
drivers/gpu/drm/nouveau/nouveau_prime.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_debugfs.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/omapdrm/omap_gem.h
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/Makefile
drivers/gpu/drm/panel/panel-lvds.c
drivers/gpu/drm/panel/panel-novatek-nt39016.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
drivers/gpu/drm/panel/panel-raydium-rm67191.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/panfrost/panfrost_devfreq.c
drivers/gpu/drm/panfrost/panfrost_device.h
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/panfrost/panfrost_gem.c
drivers/gpu/drm/panfrost/panfrost_gpu.c
drivers/gpu/drm/pl111/pl111_debugfs.c
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/pl111/pl111_drm.h
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/pl111/pl111_nomadik.h
drivers/gpu/drm/pl111/pl111_versatile.c
drivers/gpu/drm/pl111/pl111_versatile.h
drivers/gpu/drm/pl111/pl111_vexpress.c
drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_debugfs.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_draw.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_gem.c
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_irq.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/qxl/qxl_ttm.c
drivers/gpu/drm/r128/r128_ioc32.c
drivers/gpu/drm/r128/r128_irq.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_object.h
drivers/gpu/drm/radeon/radeon_prime.c
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/radeon_vm.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rockchip/Makefile
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/cdn-dp-core.h
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
drivers/gpu/drm/rockchip/rockchip_drm_gem.c
drivers/gpu/drm/rockchip/rockchip_drm_psr.c [deleted file]
drivers/gpu/drm/rockchip/rockchip_drm_psr.h [deleted file]
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/rockchip/rockchip_rgb.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/scheduler/sched_fence.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/selftests/test-drm_framebuffer.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/shmobile/shmob_drm_kms.c
drivers/gpu/drm/shmobile/shmob_drm_plane.c
drivers/gpu/drm/shmobile/shmob_drm_plane.h
drivers/gpu/drm/shmobile/shmob_drm_regs.h
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sti/sti_dvo.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_tvout.c
drivers/gpu/drm/stm/drv.c
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_crtc.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_framebuffer.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun4i_lvds.c
drivers/gpu/drm/sun4i/sun4i_rgb.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tv.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/sun4i/sun8i_csc.c
drivers/gpu/drm/sun4i/sun8i_csc.h
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_tcon_top.c
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tdfx/tdfx_drv.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/tegra/gem.h
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tilcdc/tilcdc_drv.h
drivers/gpu/drm/tilcdc/tilcdc_external.c
drivers/gpu/drm/tilcdc/tilcdc_external.h
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/gpu/drm/tilcdc/tilcdc_plane.c
drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
drivers/gpu/drm/tiny/Kconfig [new file with mode: 0644]
drivers/gpu/drm/tiny/Makefile [new file with mode: 0644]
drivers/gpu/drm/tiny/gm12u320.c [new file with mode: 0644]
drivers/gpu/drm/tiny/hx8357d.c [new file with mode: 0644]
drivers/gpu/drm/tiny/ili9225.c [new file with mode: 0644]
drivers/gpu/drm/tiny/ili9341.c [new file with mode: 0644]
drivers/gpu/drm/tiny/mi0283qt.c [new file with mode: 0644]
drivers/gpu/drm/tiny/repaper.c [new file with mode: 0644]
drivers/gpu/drm/tiny/st7586.c [new file with mode: 0644]
drivers/gpu/drm/tiny/st7735r.c [new file with mode: 0644]
drivers/gpu/drm/tinydrm/Kconfig [deleted file]
drivers/gpu/drm/tinydrm/Makefile [deleted file]
drivers/gpu/drm/tinydrm/core/Makefile [deleted file]
drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c [deleted file]
drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c [deleted file]
drivers/gpu/drm/tinydrm/hx8357d.c [deleted file]
drivers/gpu/drm/tinydrm/ili9225.c [deleted file]
drivers/gpu/drm/tinydrm/ili9341.c [deleted file]
drivers/gpu/drm/tinydrm/mi0283qt.c [deleted file]
drivers/gpu/drm/tinydrm/mipi-dbi.c [deleted file]
drivers/gpu/drm/tinydrm/repaper.c [deleted file]
drivers/gpu/drm/tinydrm/st7586.c [deleted file]
drivers/gpu/drm/tinydrm/st7735r.c [deleted file]
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/ttm/ttm_execbuf_util.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/tve200/tve200_display.c
drivers/gpu/drm/tve200/tve200_drm.h
drivers/gpu/drm/tve200/tve200_drv.c
drivers/gpu/drm/udl/udl_connector.c
drivers/gpu/drm/udl/udl_connector.h
drivers/gpu/drm/udl/udl_dmabuf.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_encoder.c
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/udl/udl_main.c
drivers/gpu/drm/udl/udl_modeset.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/v3d/v3d_debugfs.c
drivers/gpu/drm/v3d/v3d_drv.c
drivers/gpu/drm/v3d/v3d_drv.h
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_irq.c
drivers/gpu/drm/vboxvideo/Makefile
drivers/gpu/drm/vboxvideo/vbox_drv.c
drivers/gpu/drm/vboxvideo/vbox_drv.h
drivers/gpu/drm/vboxvideo/vbox_main.c
drivers/gpu/drm/vboxvideo/vbox_prime.c [deleted file]
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_debugfs.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_txp.c
drivers/gpu/drm/vc4/vc4_v3d.c
drivers/gpu/drm/vgem/vgem_drv.c
drivers/gpu/drm/vgem/vgem_drv.h
drivers/gpu/drm/vgem/vgem_fence.c
drivers/gpu/drm/via/via_dma.c
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/via/via_drv.h
drivers/gpu/drm/via/via_irq.c
drivers/gpu/drm/via/via_map.c
drivers/gpu/drm/via/via_mm.c
drivers/gpu/drm/via/via_verifier.c
drivers/gpu/drm/via/via_video.c
drivers/gpu/drm/virtio/virtgpu_debugfs.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_gem.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_prime.c
drivers/gpu/drm/virtio/virtgpu_ttm.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/Makefile
drivers/gpu/drm/vkms/vkms_composer.c [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_crc.c [deleted file]
drivers/gpu/drm/vkms/vkms_crtc.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_gem.c
drivers/gpu/drm/vkms/vkms_output.c
drivers/gpu/drm/vkms/vkms_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/drm/xen/xen_drm_front.c
drivers/gpu/drm/xen/xen_drm_front.h
drivers/gpu/drm/xen/xen_drm_front_cfg.c
drivers/gpu/drm/xen/xen_drm_front_conn.c
drivers/gpu/drm/xen/xen_drm_front_conn.h
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c
drivers/gpu/drm/xen/xen_drm_front_gem.c
drivers/gpu/drm/xen/xen_drm_front_gem.h
drivers/gpu/drm/xen/xen_drm_front_kms.c
drivers/gpu/drm/zte/zx_drm_drv.c
drivers/gpu/drm/zte/zx_hdmi.c
drivers/gpu/drm/zte/zx_plane.c
drivers/gpu/drm/zte/zx_tvenc.c
drivers/gpu/drm/zte/zx_vga.c
drivers/gpu/drm/zte/zx_vou.c
drivers/video/backlight/lcd.c
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/au1200fb.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/core/fbmon.c
drivers/video/fbdev/core/modedb.c
drivers/video/fbdev/mmp/fb/mmpfb.c
drivers/video/fbdev/nvidia/nv_backlight.c
drivers/video/fbdev/nvidia/nv_setup.c
drivers/video/fbdev/ssd1307fb.c
drivers/video/of_display_timing.c
include/drm/bridge/analogix_dp.h
include/drm/drm_agpsupport.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_dp_helper.h
include/drm/drm_dp_mst_helper.h
include/drm/drm_drv.h
include/drm/drm_gem.h
include/drm/drm_gem_framebuffer_helper.h
include/drm/drm_gem_vram_helper.h
include/drm/drm_hdcp.h
include/drm/drm_ioctl.h
include/drm/drm_mipi_dbi.h [new file with mode: 0644]
include/drm/drm_mode_config.h
include/drm/drm_panel.h
include/drm/drm_prime.h
include/drm/drm_sysfs.h
include/drm/drm_vblank.h
include/drm/drm_vram_mm_helper.h
include/drm/tinydrm/mipi-dbi.h [deleted file]
include/drm/tinydrm/tinydrm-helpers.h [deleted file]
include/drm/ttm/ttm_bo_api.h
include/drm/ttm/ttm_bo_driver.h
include/linux/fb.h
include/linux/lcd.h
include/linux/reservation.h
include/linux/soc/amlogic/meson-canvas.h
include/uapi/drm/drm_mode.h
include/uapi/drm/panfrost_drm.h
include/uapi/linux/media-bus-format.h

index 572fa27..3f977e7 100644 (file)
@@ -39,9 +39,11 @@ Required sub-nodes:
 
 - port: describes LCD panel signals, following the common binding
        for video transmitter interfaces; see
-       Documentation/devicetree/bindings/media/video-interfaces.txt;
-       when it is a TFT panel, the port's endpoint must define the
-       following property:
+       Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Deprecated properties:
+       The port's endbpoint subnode had this, now deprecated property
+       in the past. Drivers should be able to survive without it:
 
        - arm,pl11x,tft-r0g0b0-pads: an array of three 32-bit values,
                defining the way CLD pads are wired up; first value
@@ -80,7 +82,6 @@ Example:
                port {
                        clcd_pads: endpoint {
                                remote-endpoint = <&clcd_panel>;
-                               arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
                        };
                };
 
index 2df44b7..6e14e08 100644 (file)
@@ -26,9 +26,8 @@ Optional properties:
        - clocks: phandle and clock specifier for each clock listed in
            the clock-names property
        - clock-names: "mclk"
-          Describes SII902x MCLK input. MCLK is used to produce
-          HDMI audio CTS values. This property is required if
-          "#sound-dai-cells"-property is present. This property follows
+          Describes SII902x MCLK input. MCLK can be used to produce
+          HDMI audio CTS values. This property follows
           Documentation/devicetree/bindings/clock/clock-bindings.txt
           consumer binding.
 
diff --git a/Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.txt b/Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.txt
deleted file mode 100644 (file)
index 6812280..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
-
-This binding is compatible with the simple-panel binding, which is specified
-in simple-panel.txt in this directory.
-
-Required properties:
-- compatible: should be "ampire,am-480272h3tmqw-t01h"
-
-Optional properties:
-- power-supply: regulator to provide the supply voltage
-- enable-gpios: GPIO pin to enable or disable the panel
-- backlight: phandle of the backlight device attached to the panel
-
-Optional nodes:
-- Video port for RGB input.
-
-Example:
-       panel_rgb: panel-rgb {
-               compatible = "ampire,am-480272h3tmqw-t01h";
-               enable-gpios = <&gpioa 8 1>;
-               port {
-                       panel_in_rgb: endpoint {
-                               remote-endpoint = <&controller_out_rgb>;
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.yaml b/Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.yaml
new file mode 100644 (file)
index 0000000..c6e33e7
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/ampire,am-480272h3tmqw-t01h.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
+
+maintainers:
+  - Yannick Fertre <yannick.fertre@st.com>
+  - Thierry Reding <treding@nvidia.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: ampire,am-480272h3tmqw-t01h
+
+  power-supply: true
+  enable-gpios: true
+  backlight: true
+  port: true
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    panel_rgb: panel {
+      compatible = "ampire,am-480272h3tmqw-t01h";
+      enable-gpios = <&gpioa 8 1>;
+      port {
+        panel_in_rgb: endpoint {
+          remote-endpoint = <&controller_out_rgb>;
+        };
+      };
+    };
+
+...
index 248141c..0601a9e 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 - compatible: should be "arm,versatile-tft-panel"
 
 Required subnodes:
-- port: see display/panel/panel-common.txt, graph.txt
+- port: see display/panel/panel-common.yaml, graph.txt
 
 
 Example:
diff --git a/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt b/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt
deleted file mode 100644 (file)
index a30d63d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Armadeus ST0700 Adapt. A Santek ST0700I5Y-RBSLW 7.0" WVGA (800x480) TFT with
-an adapter board.
-
-Required properties:
-- compatible: "armadeus,st0700-adapt"
-- power-supply: see panel-common.txt
-
-Optional properties:
-- backlight: see panel-common.txt
diff --git a/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.yaml b/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.yaml
new file mode 100644 (file)
index 0000000..a6ade47
--- /dev/null
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/armadeus,st0700-adapt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Armadeus ST0700 Adapter
+
+description:
+  A Santek ST0700I5Y-RBSLW 7.0" WVGA (800x480) TFT with an adapter board.
+
+maintainers:
+  - '"Sébastien Szymanski" <sebastien.szymanski@armadeus.com>'
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: armadeus,st0700-adapt
+
+  power-supply: true
+  backlight: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - power-supply
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.txt b/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.txt
deleted file mode 100644 (file)
index 35bc0c8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Banana Pi 7" (S070WV20-CT16) TFT LCD Panel
-
-Required properties:
-- compatible: should be "bananapi,s070wv20-ct16"
-- power-supply: see ./panel-common.txt
-
-Optional properties:
-- enable-gpios: see ./simple-panel.txt
-- backlight: see ./simple-panel.txt
-
-This binding is compatible with the simple-panel binding, which is specified
-in ./simple-panel.txt.
diff --git a/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml b/Documentation/devicetree/bindings/display/panel/bananapi,s070wv20-ct16.yaml
new file mode 100644 (file)
index 0000000..bbf127f
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/bananapi,s070wv20-ct16.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Banana Pi 7" (S070WV20-CT16) TFT LCD Panel
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: bananapi,s070wv20-ct16
+
+  power-supply: true
+  backlight: true
+  enable-gpios: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - power-supply
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt b/Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt
new file mode 100644 (file)
index 0000000..3caea21
--- /dev/null
@@ -0,0 +1,24 @@
+Boe Himax8279d 1200x1920 TFT LCD panel
+
+Required properties:
+- compatible: should be "boe,himax8279d8p" and one of: "boe,himax8279d10p"
+- reg: DSI virtual channel of the peripheral
+- enable-gpios: panel enable gpio
+- pp33-gpios: a GPIO phandle for the 3.3v pin that provides the supply voltage
+- pp18-gpios: a GPIO phandle for the 1.8v pin that provides the supply voltage
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+       &mipi_dsi {
+               panel {
+                       compatible = "boe,himax8279d8p", "boe,himax8279d10p";
+                       reg = <0>;
+                       backlight = <&backlight>;
+                       enable-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>;
+                       pp33-gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+                       pp18-gpios = <&gpio 36 GPIO_ACTIVE_HIGH>;
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt
deleted file mode 100644 (file)
index bf06bb0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-DLC Display Co. DLC0700YZG-1 7.0" WSVGA TFT LCD panel
-
-Required properties:
-- compatible: should be "dlc,dlc0700yzg-1"
-- power-supply: See simple-panel.txt
-
-Optional properties:
-- reset-gpios: See panel-common.txt
-- enable-gpios: See simple-panel.txt
-- backlight: See simple-panel.txt
-
-This binding is compatible with the simple-panel binding, which is specified
-in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.yaml
new file mode 100644 (file)
index 0000000..287e2fe
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/dlc,dlc0700yzg-1.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DLC Display Co. DLC0700YZG-1 7.0" WSVGA TFT LCD panel
+
+maintainers:
+  - Philipp Zabel <p.zabel@pengutronix.de>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: dlc,dlc0700yzg-1
+
+  reset-gpios: true
+  enable-gpios: true
+  backlight: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - power-supply
+
+...
index be86843..b7ac1c7 100644 (file)
@@ -40,7 +40,7 @@ simple-panel.txt
 | Identifier      | compatbile          | description                         |
 +=================+=====================+=====================================+
 | ETM0700G0DH6    | edt,etm070080dh6    | WVGA TFT Display with capacitive    |
-|                 |                     | Touchscreen                         |
+|                 | edt,etm0700g0dh6    | Touchscreen                         |
 +-----------------+---------------------+-------------------------------------+
 | ETM0700G0BDH6   | edt,etm070080bdh6   | Same as ETM0700G0DH6 but with       |
 |                 |                     | inverted pixel clock.               |
diff --git a/Documentation/devicetree/bindings/display/panel/giantplus,gpm940b0.txt b/Documentation/devicetree/bindings/display/panel/giantplus,gpm940b0.txt
new file mode 100644 (file)
index 0000000..3dab52f
--- /dev/null
@@ -0,0 +1,12 @@
+GiantPlus 3.0" (320x240 pixels) 24-bit TFT LCD panel
+
+Required properties:
+- compatible: should be "giantplus,gpm940b0"
+- power-supply: as specified in the base binding
+
+Optional properties:
+- backlight: as specified in the base binding
+- enable-gpios: as specified in the base binding
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.txt b/Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.txt
deleted file mode 100644 (file)
index e5ca4cc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Innolux Corporation 10.1" EE101IA-01D WXGA (1280x800) LVDS panel
-
-Required properties:
-- compatible: should be "innolux,ee101ia-01d"
-
-This binding is compatible with the lvds-panel binding, which is specified
-in panel-lvds.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.yaml b/Documentation/devicetree/bindings/display/panel/innolux,ee101ia-01d.yaml
new file mode 100644 (file)
index 0000000..a69681e
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/innolux,ee101ia-01d.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Innolux Corporation 10.1" EE101IA-01D WXGA (1280x800) LVDS panel
+
+maintainers:
+  - Heiko Stuebner <heiko.stuebner@bq.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: lvds.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: innolux,ee101ia-01d
+      - {} # panel-lvds, but not listed here to avoid false select
+
+  backlight: true
+  enable-gpios: true
+  power-supply: true
+  width-mm: true
+  height-mm: true
+  panel-timing: true
+  port: true
+
+additionalProperties: false
+...
diff --git a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.txt b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd035g6-54nt.txt
new file mode 100644 (file)
index 0000000..fa95960
--- /dev/null
@@ -0,0 +1,42 @@
+King Display KD035G6-54NT 3.5" (320x240 pixels) 24-bit TFT LCD panel
+
+Required properties:
+- compatible: should be "kingdisplay,kd035g6-54nt"
+- power-supply: See panel-common.txt
+- reset-gpios: See panel-common.txt
+
+Optional properties:
+- backlight: see panel-common.txt
+
+The generic bindings for the SPI slaves documented in [1] also apply.
+
+The device node can contain one 'port' child node with one child
+'endpoint' node, according to the bindings defined in [2]. This
+node should describe panel's video bus.
+
+[1]: Documentation/devicetree/bindings/spi/spi-bus.txt
+[2]: Documentation/devicetree/bindings/graph.txt
+
+Example:
+
+&spi {
+       panel@0 {
+               compatible = "kingdisplay,kd035g6-54nt";
+               reg = <0>;
+
+               spi-max-frequency = <3125000>;
+               spi-3wire;
+               spi-cs-high;
+
+               reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
+
+               backlight = <&backlight>;
+               power-supply = <&ldo6>;
+
+               port {
+                       panel_input: endpoint {
+                               remote-endpoint = <&panel_output>;
+                       };
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/display/panel/lvds.yaml b/Documentation/devicetree/bindings/display/panel/lvds.yaml
new file mode 100644 (file)
index 0000000..d008330
--- /dev/null
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/lvds.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LVDS Display Panel
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |+
+  LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+  incompatible data link layers have been used over time to transmit image data
+  to LVDS panels. This bindings supports display panels compatible with the
+  following specifications.
+
+  [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+  1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+  [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+  Semiconductor
+  [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+  Electronics Standards Association (VESA)
+
+  Device compatible with those specifications have been marketed under the
+  FPD-Link and FlatLink brands.
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    contains:
+      const: panel-lvds
+    description:
+      Shall contain "panel-lvds" in addition to a mandatory panel-specific
+      compatible string defined in individual panel bindings. The "panel-lvds"
+      value shall never be used on its own.
+
+  data-mapping:
+    enum:
+      - jeida-18
+      - jeida-24
+      - vesa-24
+    description: |
+      The color signals mapping order.
+
+      LVDS data mappings are defined as follows.
+
+      - "jeida-18" - 18-bit data mapping compatible with the [JEIDA], [LDI] and
+        [VESA] specifications. Data are transferred as follows on 3 LVDS lanes.
+
+      Slot         0       1       2       3       4       5       6
+            ________________                         _________________
+      Clock                    \_______________________/
+              ______  ______  ______  ______  ______  ______  ______
+      DATA0    ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
+      DATA1    ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
+      DATA2    ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
+
+      - "jeida-24" - 24-bit data mapping compatible with the [DSIM] and [LDI]
+        specifications. Data are transferred as follows on 4 LVDS lanes.
+
+      Slot         0       1       2       3       4       5       6
+            ________________                         _________________
+      Clock                    \_______________________/
+              ______  ______  ______  ______  ______  ______  ______
+      DATA0    ><__G2__><__R7__><__R6__><__R5__><__R4__><__R3__><__R2__><
+      DATA1    ><__B3__><__B2__><__G7__><__G6__><__G5__><__G4__><__G3__><
+      DATA2    ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
+      DATA3    ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
+
+      - "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
+        Data are transferred as follows on 4 LVDS lanes.
+
+      Slot         0       1       2       3       4       5       6
+            ________________                         _________________
+      Clock                    \_______________________/
+              ______  ______  ______  ______  ______  ______  ______
+      DATA0    ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
+      DATA1    ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
+      DATA2    ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
+      DATA3    ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
+
+      Control signals are mapped as follows.
+
+      CTL0: HSync
+      CTL1: VSync
+      CTL2: Data Enable
+      CTL3: 0
+
+  data-mirror:
+    type: boolean
+    description:
+      If set, reverse the bit order described in the data mappings below on all
+      data lanes, transmitting bits for slots 6 to 0 instead of 0 to 6.
+
+required:
+  - compatible
+  - data-mapping
+  - width-mm
+  - height-mm
+  - panel-timing
+  - port
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.txt b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.txt
deleted file mode 100644 (file)
index ced0121..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Mitsubishi AA204XD12 LVDS Display Panel
-=======================================
-
-The AA104XD12 is a 10.4" XGA TFT-LCD display panel.
-
-These DT bindings follow the LVDS panel bindings defined in panel-lvds.txt
-with the following device-specific properties.
-
-
-Required properties:
-
-- compatible: Shall contain "mitsubishi,aa121td01" and "panel-lvds", in that
-  order.
-- vcc-supply: Reference to the regulator powering the panel VCC pins.
-
-
-Example
--------
-
-panel {
-       compatible = "mitsubishi,aa104xd12", "panel-lvds";
-       vcc-supply = <&vcc_3v3>;
-
-       width-mm = <210>;
-       height-mm = <158>;
-
-       data-mapping = "jeida-24";
-
-       panel-timing {
-               /* 1024x768 @65Hz */
-               clock-frequency = <65000000>;
-               hactive = <1024>;
-               vactive = <768>;
-               hsync-len = <136>;
-               hfront-porch = <20>;
-               hback-porch = <160>;
-               vfront-porch = <3>;
-               vback-porch = <29>;
-               vsync-len = <6>;
-       };
-
-       port {
-               panel_in: endpoint {
-                       remote-endpoint = <&lvds_encoder>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa104xd12.yaml
new file mode 100644 (file)
index 0000000..b5e7ee2
--- /dev/null
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/mitsubishi,aa104xd12.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mitsubishi AA104XD12 10.4" XGA LVDS Display Panel
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: lvds.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: mitsubishi,aa104xd12
+      - {} # panel-lvds, but not listed here to avoid false select
+
+  vcc-supply:
+    description: Reference to the regulator powering the panel VCC pins.
+
+  data-mapping:
+    const: jeida-24
+
+  width-mm:
+    const: 210
+
+  height-mm:
+    const: 158
+
+  panel-timing: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - vcc-supply
+
+examples:
+  - |+
+
+    panel {
+      compatible = "mitsubishi,aa104xd12", "panel-lvds";
+      vcc-supply = <&vcc_3v3>;
+
+      width-mm = <210>;
+      height-mm = <158>;
+
+      data-mapping = "jeida-24";
+
+      panel-timing {
+        /* 1024x768 @65Hz */
+        clock-frequency = <65000000>;
+        hactive = <1024>;
+        vactive = <768>;
+        hsync-len = <136>;
+        hfront-porch = <20>;
+        hback-porch = <160>;
+        vfront-porch = <3>;
+        vback-porch = <29>;
+        vsync-len = <6>;
+      };
+
+      port {
+        panel_in: endpoint {
+          remote-endpoint = <&lvds_encoder>;
+        };
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.txt b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.txt
deleted file mode 100644 (file)
index d6e1097..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Mitsubishi AA121TD01 LVDS Display Panel
-=======================================
-
-The AA121TD01 is a 12.1" WXGA TFT-LCD display panel.
-
-These DT bindings follow the LVDS panel bindings defined in panel-lvds.txt
-with the following device-specific properties.
-
-
-Required properties:
-
-- compatible: Shall contain "mitsubishi,aa121td01" and "panel-lvds", in that
-  order.
-- vcc-supply: Reference to the regulator powering the panel VCC pins.
-
-
-Example
--------
-
-panel {
-       compatible = "mitsubishi,aa121td01", "panel-lvds";
-       vcc-supply = <&vcc_3v3>;
-
-       width-mm = <261>;
-       height-mm = <163>;
-
-       data-mapping = "jeida-24";
-
-       panel-timing {
-               /* 1280x800 @60Hz */
-               clock-frequency = <71000000>;
-               hactive = <1280>;
-               vactive = <800>;
-               hsync-len = <70>;
-               hfront-porch = <20>;
-               hback-porch = <70>;
-               vsync-len = <5>;
-               vfront-porch = <3>;
-               vback-porch = <15>;
-       };
-
-       port {
-               panel_in: endpoint {
-                       remote-endpoint = <&lvds_encoder>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa121td01.yaml
new file mode 100644 (file)
index 0000000..977c50a
--- /dev/null
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/mitsubishi,aa121td01.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mitsubishi AA121TD01 12.1" WXGA LVDS Display Panel
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: lvds.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: mitsubishi,aa121td01
+      - {} # panel-lvds, but not listed here to avoid false select
+
+  vcc-supply:
+    description: Reference to the regulator powering the panel VCC pins.
+
+  data-mapping:
+    const: jeida-24
+
+  width-mm:
+    const: 261
+
+  height-mm:
+    const: 163
+
+  panel-timing: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - vcc-supply
+
+examples:
+  - |+
+    panel {
+      compatible = "mitsubishi,aa121td01", "panel-lvds";
+      vcc-supply = <&vcc_3v3>;
+
+      width-mm = <261>;
+      height-mm = <163>;
+
+      data-mapping = "jeida-24";
+
+      panel-timing {
+        /* 1280x800 @60Hz */
+        clock-frequency = <71000000>;
+        hactive = <1280>;
+        vactive = <800>;
+        hsync-len = <70>;
+        hfront-porch = <20>;
+        hback-porch = <70>;
+        vsync-len = <5>;
+        vfront-porch = <3>;
+        vback-porch = <15>;
+      };
+
+      port {
+        panel_in: endpoint {
+          remote-endpoint = <&lvds_encoder>;
+        };
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/ortustech,com37h3m05dtc.txt b/Documentation/devicetree/bindings/display/panel/ortustech,com37h3m05dtc.txt
new file mode 100644 (file)
index 0000000..c16907c
--- /dev/null
@@ -0,0 +1,12 @@
+OrtusTech COM37H3M05DTC Blanview 3.7" VGA portrait TFT-LCD panel
+
+Required properties:
+- compatible: should be "ortustech,com37h3m05dtc"
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/ortustech,com37h3m99dtc.txt b/Documentation/devicetree/bindings/display/panel/ortustech,com37h3m99dtc.txt
new file mode 100644 (file)
index 0000000..06a73c3
--- /dev/null
@@ -0,0 +1,12 @@
+OrtusTech COM37H3M99DTC Blanview 3.7" VGA portrait TFT-LCD panel
+
+Required properties:
+- compatible: should be "ortustech,com37h3m99dtc"
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
deleted file mode 100644 (file)
index 5d2519a..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-Common Properties for Display Panel
-===================================
-
-This document defines device tree properties common to several classes of
-display panels. It doesn't constitue a device tree binding specification by
-itself but is meant to be referenced by device tree bindings.
-
-When referenced from panel device tree bindings the properties defined in this
-document are defined as follows. The panel device tree bindings are
-responsible for defining whether each property is required or optional.
-
-
-Descriptive Properties
-----------------------
-
-- width-mm,
-- height-mm: The width-mm and height-mm specify the width and height of the
-  physical area where images are displayed. These properties are expressed in
-  millimeters and rounded to the closest unit.
-
-- label: The label property specifies a symbolic name for the panel as a
-  string suitable for use by humans. It typically contains a name inscribed on
-  the system (e.g. as an affixed label) or specified in the system's
-  documentation (e.g. in the user's manual).
-
-  If no such name exists, and unless the property is mandatory according to
-  device tree bindings, it shall rather be omitted than constructed of
-  non-descriptive information. For instance an LCD panel in a system that
-  contains a single panel shall not be labelled "LCD" if that name is not
-  inscribed on the system or used in a descriptive fashion in system
-  documentation.
-
-
-Display Timings
----------------
-
-- panel-timing: Most display panels are restricted to a single resolution and
-  require specific display timings. The panel-timing subnode expresses those
-  timings as specified in the timing subnode section of the display timing
-  bindings defined in
-  Documentation/devicetree/bindings/display/panel/display-timing.txt.
-
-
-Connectivity
-------------
-
-- ports: Panels receive video data through one or multiple connections. While
-  the nature of those connections is specific to the panel type, the
-  connectivity is expressed in a standard fashion using ports as specified in
-  the device graph bindings defined in
-  Documentation/devicetree/bindings/graph.txt.
-
-- ddc-i2c-bus: Some panels expose EDID information through an I2C-compatible
-  bus such as DDC2 or E-DDC. For such panels the ddc-i2c-bus contains a
-  phandle to the system I2C controller connected to that bus.
-
-
-Control I/Os
-------------
-
-Many display panels can be controlled through pins driven by GPIOs. The nature
-and timing of those control signals are device-specific and left for panel
-device tree bindings to specify. The following GPIO specifiers can however be
-used for panels that implement compatible control signals.
-
-- enable-gpios: Specifier for a GPIO connected to the panel enable control
-  signal. The enable signal is active high and enables operation of the panel.
-  This property can also be used for panels implementing an active low power
-  down signal, which is a negated version of the enable signal. Active low
-  enable signals (or active high power down signals) can be supported by
-  inverting the GPIO specifier polarity flag.
-
-  Note that the enable signal control panel operation only and must not be
-  confused with a backlight enable signal.
-
-- reset-gpios: Specifier for a GPIO coonnected to the panel reset control
-  signal. The reset signal is active low and resets the panel internal logic
-  while active. Active high reset signals can be supported by inverting the
-  GPIO specifier polarity flag.
-
-Power
------
-
-- power-supply: display panels require power to be supplied. While several
-  panels need more than one power supply with panel-specific constraints
-  governing the order and timings of the power supplies, in many cases a single
-  power supply is sufficient, either because the panel has a single power rail,
-  or because all its power rails can be driven by the same supply. In that case
-  the power-supply property specifies the supply powering the panel as a phandle
-  to a regulator.
-
-Backlight
----------
-
-Most display panels include a backlight. Some of them also include a backlight
-controller exposed through a control bus such as I2C or DSI. Others expose
-backlight control through GPIO, PWM or other signals connected to an external
-backlight controller.
-
-- backlight: For panels whose backlight is controlled by an external backlight
-  controller, this property contains a phandle that references the controller.
diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.yaml b/Documentation/devicetree/bindings/display/panel/panel-common.yaml
new file mode 100644 (file)
index 0000000..ef8d8cd
--- /dev/null
@@ -0,0 +1,149 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common Properties for Display Panels
+
+maintainers:
+  - Thierry Reding <thierry.reding@gmail.com>
+  - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+description: |
+  This document defines device tree properties common to several classes of
+  display panels. It doesn't constitue a device tree binding specification by
+  itself but is meant to be referenced by device tree bindings.
+
+  When referenced from panel device tree bindings the properties defined in this
+  document are defined as follows. The panel device tree bindings are
+  responsible for defining whether each property is required or optional.
+
+properties:
+  # Descriptive Properties
+  width-mm:
+    description:
+      Specifies the width of the physical area where images are displayed. This
+      property is expressed in millimeters and rounded to the closest unit.
+
+  height-mm:
+    description:
+      Specifies the height of the physical area where images are displayed. This
+      property is expressed in millimeters and rounded to the closest unit.
+
+  label:
+    description: |
+      The label property specifies a symbolic name for the panel as a
+      string suitable for use by humans. It typically contains a name inscribed
+      on the system (e.g. as an affixed label) or specified in the system's
+      documentation (e.g. in the user's manual).
+
+      If no such name exists, and unless the property is mandatory according to
+      device tree bindings, it shall rather be omitted than constructed of
+      non-descriptive information. For instance an LCD panel in a system that
+      contains a single panel shall not be labelled "LCD" if that name is not
+      inscribed on the system or used in a descriptive fashion in system
+      documentation.
+
+  rotation:
+    description:
+      Display rotation in degrees counter clockwise (0,90,180,270)
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [ 0, 90, 180, 270 ]
+
+  # Display Timings
+  panel-timing:
+    type: object
+    description:
+      Most display panels are restricted to a single resolution and
+      require specific display timings. The panel-timing subnode expresses those
+      timings as specified in the timing subnode section of the display timing
+      bindings defined in
+      Documentation/devicetree/bindings/display/panel/display-timing.txt.
+
+  # Connectivity
+  port:
+    type: object
+
+  ports:
+    type: object
+    description:
+      Panels receive video data through one or multiple connections. While
+      the nature of those connections is specific to the panel type, the
+      connectivity is expressed in a standard fashion using ports as specified
+      in the device graph bindings defined in
+      Documentation/devicetree/bindings/graph.txt.
+
+  ddc-i2c-bus:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Some panels expose EDID information through an I2C-compatible
+      bus such as DDC2 or E-DDC. For such panels the ddc-i2c-bus contains a
+      phandle to the system I2C controller connected to that bus.
+
+  no-hpd:
+    type: boolean
+    description:
+      This panel is supposed to communicate that it's ready via HPD
+      (hot plug detect) signal, but the signal isn't hooked up so we should
+      hardcode the max delay from the panel spec when powering up the panel.
+
+  # Control I/Os
+
+  # Many display panels can be controlled through pins driven by GPIOs. The nature
+  # and timing of those control signals are device-specific and left for panel
+  # device tree bindings to specify. The following GPIO specifiers can however be
+  # used for panels that implement compatible control signals.
+
+  enable-gpios:
+    maxItems: 1
+    description: |
+      Specifier for a GPIO connected to the panel enable control signal. The
+      enable signal is active high and enables operation of the panel. This
+      property can also be used for panels implementing an active low power down
+      signal, which is a negated version of the enable signal. Active low enable
+      signals (or active high power down signals) can be supported by inverting
+      the GPIO specifier polarity flag.
+
+      Note that the enable signal control panel operation only and must not be
+      confused with a backlight enable signal.
+
+  reset-gpios:
+    maxItems: 1
+    description:
+      Specifier for a GPIO connected to the panel reset control signal.
+      The reset signal is active low and resets the panel internal logic
+      while active. Active high reset signals can be supported by inverting the
+      GPIO specifier polarity flag.
+
+  # Power
+  power-supply:
+    description:
+      Display panels require power to be supplied. While several panels need
+      more than one power supply with panel-specific constraints governing the
+      order and timings of the power supplies, in many cases a single power
+      supply is sufficient, either because the panel has a single power rail, or
+      because all its power rails can be driven by the same supply. In that case
+      the power-supply property specifies the supply powering the panel as a
+      phandle to a regulator.
+
+  # Backlight
+
+  # Most display panels include a backlight. Some of them also include a backlight
+  # controller exposed through a control bus such as I2C or DSI. Others expose
+  # backlight control through GPIO, PWM or other signals connected to an external
+  # backlight controller.
+
+  backlight:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      For panels whose backlight is controlled by an external backlight
+      controller, this property contains a phandle that references the
+      controller.
+
+dependencies:
+  width-mm: [ height-mm ]
+  height-mm: [ width-mm ]
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
deleted file mode 100644 (file)
index 250850a..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-LVDS Display Panel
-==================
-
-LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
-incompatible data link layers have been used over time to transmit image data
-to LVDS panels. This bindings supports display panels compatible with the
-following specifications.
-
-[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
-1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
-[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
-Semiconductor
-[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
-Electronics Standards Association (VESA)
-
-Device compatible with those specifications have been marketed under the
-FPD-Link and FlatLink brands.
-
-
-Required properties:
-
-- compatible: Shall contain "panel-lvds" in addition to a mandatory
-  panel-specific compatible string defined in individual panel bindings. The
-  "panel-lvds" value shall never be used on its own.
-- width-mm: See panel-common.txt.
-- height-mm: See panel-common.txt.
-- data-mapping: The color signals mapping order, "jeida-18", "jeida-24"
-  or "vesa-24".
-
-Optional properties:
-
-- label: See panel-common.txt.
-- gpios: See panel-common.txt.
-- backlight: See panel-common.txt.
-- power-supply: See panel-common.txt.
-- data-mirror: If set, reverse the bit order described in the data mappings
-  below on all data lanes, transmitting bits for slots 6 to 0 instead of
-  0 to 6.
-
-Required nodes:
-
-- panel-timing: See panel-common.txt.
-- ports: See panel-common.txt. These bindings require a single port subnode
-  corresponding to the panel LVDS input.
-
-
-LVDS data mappings are defined as follows.
-
-- "jeida-18" - 18-bit data mapping compatible with the [JEIDA], [LDI] and
-  [VESA] specifications. Data are transferred as follows on 3 LVDS lanes.
-
-Slot       0       1       2       3       4       5       6
-       ________________                         _________________
-Clock                  \_______________________/
-         ______  ______  ______  ______  ______  ______  ______
-DATA0  ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
-DATA1  ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
-DATA2  ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
-
-- "jeida-24" - 24-bit data mapping compatible with the [DSIM] and [LDI]
-  specifications. Data are transferred as follows on 4 LVDS lanes.
-
-Slot       0       1       2       3       4       5       6
-       ________________                         _________________
-Clock                  \_______________________/
-         ______  ______  ______  ______  ______  ______  ______
-DATA0  ><__G2__><__R7__><__R6__><__R5__><__R4__><__R3__><__R2__><
-DATA1  ><__B3__><__B2__><__G7__><__G6__><__G5__><__G4__><__G3__><
-DATA2  ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
-DATA3  ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
-
-- "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
-  Data are transferred as follows on 4 LVDS lanes.
-
-Slot       0       1       2       3       4       5       6
-       ________________                         _________________
-Clock                  \_______________________/
-         ______  ______  ______  ______  ______  ______  ______
-DATA0  ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
-DATA1  ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
-DATA2  ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
-DATA3  ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
-
-Control signals are mapped as follows.
-
-CTL0: HSync
-CTL1: VSync
-CTL2: Data Enable
-CTL3: 0
-
-
-Example
--------
-
-panel {
-       compatible = "mitsubishi,aa121td01", "panel-lvds";
-
-       width-mm = <261>;
-       height-mm = <163>;
-
-       data-mapping = "jeida-24";
-
-       panel-timing {
-               /* 1280x800 @60Hz */
-               clock-frequency = <71000000>;
-               hactive = <1280>;
-               vactive = <800>;
-               hsync-len = <70>;
-               hfront-porch = <20>;
-               hback-porch = <70>;
-               vsync-len = <5>;
-               vfront-porch = <3>;
-               vback-porch = <15>;
-       };
-
-       port {
-               panel_in: endpoint {
-                       remote-endpoint = <&lvds_encoder>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/panel.txt b/Documentation/devicetree/bindings/display/panel/panel.txt
deleted file mode 100644 (file)
index e2e6867..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Common display properties
--------------------------
-
-- rotation:    Display rotation in degrees counter clockwise (0,90,180,270)
diff --git a/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.txt b/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.txt
deleted file mode 100644 (file)
index 1639fb1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-PDA 91-00156-A0 5.0" WVGA TFT LCD panel
-
-Required properties:
-- compatible: should be "pda,91-00156-a0"
-- power-supply: this panel requires a single power supply. A phandle to a
-regulator needs to be specified here. Compatible with panel-common binding which
-is specified in the panel-common.txt in this directory.
-- backlight: this panel's backlight is controlled by an external backlight
-controller. A phandle to this controller needs to be specified here.
-Compatible with panel-common binding which is specified in the panel-common.txt
-in this directory.
-
-This binding is compatible with the simple-panel binding, which is specified
-in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml b/Documentation/devicetree/bindings/display/panel/pda,91-00156-a0.yaml
new file mode 100644 (file)
index 0000000..ccd3623
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/pda,91-00156-a0.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PDA 91-00156-A0 5.0" WVGA TFT LCD panel
+
+maintainers:
+  - Cristian Birsan <cristian.birsan@microchip.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: pda,91-00156-a0
+
+  power-supply: true
+  backlight: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - power-supply
+  - backlight
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.txt b/Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.txt
deleted file mode 100644 (file)
index e9e19c0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-This binding covers the official 7" (800x480) Raspberry Pi touchscreen
-panel.
-
-This DSI panel contains:
-
-- TC358762 DSI->DPI bridge
-- Atmel microcontroller on I2C for power sequencing the DSI bridge and
-  controlling backlight
-- Touchscreen controller on I2C for touch input
-
-and this binding covers the DSI display parts but not its touch input.
-
-Required properties:
-- compatible:  Must be "raspberrypi,7inch-touchscreen-panel"
-- reg:         Must be "45"
-- port:                See panel-common.txt
-
-Example:
-
-dsi1: dsi@7e700000 {
-       #address-cells = <1>;
-       #size-cells = <0>;
-       <...>
-
-       port {
-               dsi_out_port: endpoint {
-                       remote-endpoint = <&panel_dsi_port>;
-               };
-       };
-};
-
-i2c_dsi: i2c {
-       compatible = "i2c-gpio";
-       #address-cells = <1>;
-       #size-cells = <0>;
-       gpios = <&gpio 28 0
-                &gpio 29 0>;
-
-       lcd@45 {
-               compatible = "raspberrypi,7inch-touchscreen-panel";
-               reg = <0x45>;
-
-               port {
-                       panel_dsi_port: endpoint {
-                               remote-endpoint = <&dsi_out_port>;
-                       };
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.yaml b/Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.yaml
new file mode 100644 (file)
index 0000000..22a083f
--- /dev/null
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/raspberrypi,7inch-touchscreen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: The official 7" (800x480) Raspberry Pi touchscreen
+
+maintainers:
+  - Eric Anholt <eric@anholt.net>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |+
+  This DSI panel contains:
+
+  - TC358762 DSI->DPI bridge
+  - Atmel microcontroller on I2C for power sequencing the DSI bridge and
+    controlling backlight
+  - Touchscreen controller on I2C for touch input
+
+  and this binding covers the DSI display parts but not its touch input.
+
+properties:
+  compatible:
+    const: raspberrypi,7inch-touchscreen-panel
+
+  reg:
+    const: 0x45
+
+  port: true
+
+required:
+  - compatible
+  - reg
+  - port
+
+additionalProperties: false
+
+examples:
+  - |+
+    dsi1: dsi {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      port {
+        dsi_out_port: endpoint {
+          remote-endpoint = <&panel_dsi_port>;
+        };
+      };
+    };
+
+    i2c_dsi: i2c {
+      compatible = "i2c-gpio";
+      #address-cells = <1>;
+      #size-cells = <0>;
+      scl-gpios = <&gpio 28 0>;
+      sda-gpios = <&gpio 29 0>;
+
+      lcd@45 {
+        compatible = "raspberrypi,7inch-touchscreen-panel";
+        reg = <0x45>;
+
+        port {
+          panel_dsi_port: endpoint {
+            remote-endpoint = <&dsi_out_port>;
+          };
+        };
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
new file mode 100644 (file)
index 0000000..1042469
--- /dev/null
@@ -0,0 +1,41 @@
+Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
+
+Required properties:
+- compatible:          "raydium,rm67191"
+- reg:                 virtual channel for MIPI-DSI protocol
+                       must be <0>
+- dsi-lanes:           number of DSI lanes to be used
+                       must be <3> or <4>
+- port:                input port node with endpoint definition as
+                       defined in Documentation/devicetree/bindings/graph.txt;
+                       the input port should be connected to a MIPI-DSI device
+                       driver
+
+Optional properties:
+- reset-gpios:         a GPIO spec for the RST_B GPIO pin
+- v3p3-supply:         phandle to 3.3V regulator that powers the VDD_3V3 pin
+- v1p8-supply:         phandle to 1.8V regulator that powers the VDD_1V8 pin
+- width-mm:            see panel-common.txt
+- height-mm:           see panel-common.txt
+- video-mode:          0 - burst-mode
+                       1 - non-burst with sync event
+                       2 - non-burst with sync pulse
+
+Example:
+
+       panel@0 {
+               compatible = "raydium,rm67191";
+               reg = <0>;
+               pinctrl-0 = <&pinctrl_mipi_dsi_0_1_en>;
+               pinctrl-names = "default";
+               reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+               dsi-lanes = <4>;
+               width-mm = <68>;
+               height-mm = <121>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&mipi_out>;
+                       };
+               };
+       };
index 1b57632..a372c5d 100644 (file)
@@ -5,6 +5,9 @@ Required properties:
 - reg: DSI virtual channel of the peripheral
 - reset-gpios: panel reset gpio
 - backlight: phandle of the backlight device attached to the panel
+- vcc-supply: phandle of the regulator that provides the vcc supply voltage.
+- iovcc-supply: phandle of the regulator that provides the iovcc supply
+  voltage.
 
 Example:
 
@@ -14,5 +17,7 @@ Example:
                        reg = <0>;
                        backlight = <&backlight>;
                        reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
+                       vcc-supply = <&reg_2v8_p>;
+                       iovcc-supply = <&reg_1v8_p>;
                };
        };
diff --git a/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.txt b/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.txt
deleted file mode 100644 (file)
index d06644b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-Solomon Goldentek Display GKTW70SDAE4SE LVDS Display Panel
-==========================================================
-
-The GKTW70SDAE4SE is a 7" WVGA TFT-LCD display panel.
-
-These DT bindings follow the LVDS panel bindings defined in panel-lvds.txt
-with the following device-specific properties.
-
-Required properties:
-
-- compatible: Shall contain "sgd,gktw70sdae4se" and "panel-lvds", in that order.
-
-Example
--------
-
-panel {
-       compatible = "sgd,gktw70sdae4se", "panel-lvds";
-
-       width-mm = <153>;
-       height-mm = <86>;
-
-       data-mapping = "jeida-18";
-
-       panel-timing {
-               clock-frequency = <32000000>;
-               hactive = <800>;
-               vactive = <480>;
-               hback-porch = <39>;
-               hfront-porch = <39>;
-               vback-porch = <29>;
-               vfront-porch = <13>;
-               hsync-len = <47>;
-               vsync-len = <2>;
-       };
-
-       port {
-               panel_in: endpoint {
-                       remote-endpoint = <&lvds_encoder>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml b/Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
new file mode 100644 (file)
index 0000000..e63a570
--- /dev/null
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/sgd,gktw70sdae4se.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Solomon Goldentek Display GKTW70SDAE4SE 7" WVGA LVDS Display Panel
+
+maintainers:
+  - Neil Armstrong <narmstrong@baylibre.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+allOf:
+  - $ref: lvds.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: sgd,gktw70sdae4se
+      - {} # panel-lvds, but not listed here to avoid false select
+
+  data-mapping:
+    const: jeida-18
+
+  width-mm:
+    const: 153
+
+  height-mm:
+    const: 86
+
+  panel-timing: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+
+examples:
+  - |+
+    panel {
+      compatible = "sgd,gktw70sdae4se", "panel-lvds";
+
+      width-mm = <153>;
+      height-mm = <86>;
+
+      data-mapping = "jeida-18";
+
+      panel-timing {
+        clock-frequency = <32000000>;
+        hactive = <800>;
+        vactive = <480>;
+        hback-porch = <39>;
+        hfront-porch = <39>;
+        vback-porch = <29>;
+        vfront-porch = <13>;
+        hsync-len = <47>;
+        vsync-len = <2>;
+      };
+
+      port {
+        panel_in: endpoint {
+          remote-endpoint = <&lvds_encoder>;
+        };
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.txt b/Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.txt
new file mode 100644 (file)
index 0000000..fd9cf39
--- /dev/null
@@ -0,0 +1,26 @@
+Sharp LD-D5116Z01B 12.3" WUXGA+ eDP panel
+
+Required properties:
+- compatible: should be "sharp,ld-d5116z01b"
+- power-supply: regulator to provide the VCC supply voltage (3.3 volts)
+
+This binding is compatible with the simple-panel binding.
+
+The device node can contain one 'port' child node with one child
+'endpoint' node, according to the bindings defined in [1]. This
+node should describe panel's video bus.
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+
+       panel: panel {
+               compatible = "sharp,ld-d5116z01b";
+               power-supply = <&vlcd_3v3>;
+
+               port {
+                       panel_ep: endpoint {
+                               remote-endpoint = <&bridge_out_ep>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,lq070y3dg3b.txt b/Documentation/devicetree/bindings/display/panel/sharp,lq070y3dg3b.txt
new file mode 100644 (file)
index 0000000..95534b5
--- /dev/null
@@ -0,0 +1,12 @@
+Sharp LQ070Y3DG3B 7.0" WVGA landscape TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,lq070y3dg3b"
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ls020b1dd01d.txt b/Documentation/devicetree/bindings/display/panel/sharp,ls020b1dd01d.txt
new file mode 100644 (file)
index 0000000..e45edbc
--- /dev/null
@@ -0,0 +1,12 @@
+Sharp 2.0" (240x160 pixels) 16-bit TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,ls020b1dd01d"
+- power-supply: as specified in the base binding
+
+Optional properties:
+- backlight: as specified in the base binding
+- enable-gpios: as specified in the base binding
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
index b2b872c..e11208f 100644 (file)
@@ -1,28 +1 @@
-Simple display panel
-====================
-
-panel node
-----------
-
-Required properties:
-- power-supply: See panel-common.txt
-
-Optional properties:
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-- enable-gpios: GPIO pin to enable or disable the panel
-- backlight: phandle of the backlight device attached to the panel
-- no-hpd: This panel is supposed to communicate that it's ready via HPD
-  (hot plug detect) signal, but the signal isn't hooked up so we should
-  hardcode the max delay from the panel spec when powering up the panel.
-
-Example:
-
-       panel: panel {
-               compatible = "cptt,claa101wb01";
-               ddc-i2c-bus = <&panelddc>;
-
-               power-supply = <&vdd_pnl_reg>;
-               enable-gpios = <&gpio 90 0>;
-
-               backlight = <&backlight>;
-       };
+See panel-common.yaml in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.txt b/Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.txt
deleted file mode 100644 (file)
index dfb572f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-TFC S9700RTWV43TR-01B 7" Three Five Corp 800x480 LCD panel with
-resistive touch
-
-The panel is found on TI AM335x-evm.
-
-Required properties:
-- compatible: should be "tfc,s9700rtwv43tr-01b"
-- power-supply: See panel-common.txt
-
-Optional properties:
-- enable-gpios: GPIO pin to enable or disable the panel, if there is one
-- backlight: phandle of the backlight device attached to the panel
-
-This binding is compatible with the simple-panel binding, which is specified
-in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.yaml b/Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.yaml
new file mode 100644 (file)
index 0000000..9e59944
--- /dev/null
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/tfc,s9700rtwv43tr-01b.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TFC S9700RTWV43TR-01B 7" Three Five Corp 800x480 LCD panel with resistive touch
+
+maintainers:
+  - Jyri Sarha <jsarha@ti.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |+
+  The panel is found on TI AM335x-evm.
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: tfc,s9700rtwv43tr-01b
+
+  enable-gpios: true
+  backlight: true
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - power-supply
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt
deleted file mode 100644 (file)
index 40f3d7c..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-TPO TPG110 Panel
-================
-
-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 : one of:
-  "ste,nomadik-nhk15-display", "tpo,tpg110"
-  "tpo,tpg110"
-- grestb-gpios : panel reset 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.
-
-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: 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 = <&foo>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
new file mode 100644 (file)
index 0000000..a51660b
--- /dev/null
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/tpo,tpg110.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TPO TPG110 Panel
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |+
+  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.
+
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - ste,nomadik-nhk15-display
+          - const: tpo,tpg110
+      - const: tpo,tpg110
+
+  reg: true
+
+  grestb-gpios:
+    maxItems: 1
+    description: panel reset GPIO
+
+  spi-3wire: true
+
+  spi-max-frequency:
+    const: 3000000
+
+required:
+  - compatible
+  - reg
+  - grestb-gpios
+  - width-mm
+  - height-mm
+  - spi-3wire
+  - spi-max-frequency
+  - port
+
+examples:
+  - |+
+    spi {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      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 1>;
+        backlight = <&bl>;
+
+        port {
+          nomadik_clcd_panel: endpoint {
+            remote-endpoint = <&foo>;
+          };
+        };
+      };
+    };
+
+...
index da6939e..7849ff0 100644 (file)
@@ -32,17 +32,6 @@ Their connections are modeled using the OF graph bindings specified in
 - video port 0 for the VOP input, the remote endpoint maybe vopb or vopl
 - video port 1 for either a panel or subsequent encoder
 
-the lvds panel described by
-       Documentation/devicetree/bindings/display/panel/simple-panel.txt
-
-Panel required properties:
-- ports for remote LVDS output
-
-Panel optional properties:
-- data-mapping: should be "vesa-24","jeida-24" or "jeida-18".
-This describes decribed by:
-       Documentation/devicetree/bindings/display/panel/panel-lvds.txt
-
 Example:
 
 lvds_panel: lvds-panel {
index b67f8ca..27333b9 100644 (file)
@@ -27,6 +27,15 @@ Optional properties:
   - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
                          This needs to be the higher, the higher the capacitance
                          of the OLED's pixels is
+  - solomon,dclk-div: Clock divisor 1 to 16
+  - solomon,dclk-frq: Clock frequency 0 to 15, higher value means higher
+                      frequency
+  - solomon,lookup-table: 8 bit value array of current drive pulse widths for
+                          BANK0, and colors A, B, and C. Each value in range
+                          of 31 to 63 for pulse widths of 32 to 64. Color D
+                          is always width 64.
+  - solomon,area-color-enable: Display uses color mode
+  - solomon,low-power. Display runs in low power mode
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -46,4 +55,5 @@ ssd1306: oled@3c {
         solomon,com-lrremap;
         solomon,com-invdir;
         solomon,com-offset = <32>;
+        solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;
 };
index 4bfb706..b4a0ed3 100644 (file)
@@ -11,7 +11,6 @@ GPU Driver Documentation
    meson
    pl111
    tegra
-   tinydrm
    tve200
    v3d
    vc4
index b327bbc..3868008 100644 (file)
@@ -263,6 +263,18 @@ the MST topology helpers easier to understand
                drm_dp_mst_topology_put_port
                drm_dp_mst_get_mstb_malloc drm_dp_mst_put_mstb_malloc
 
+MIPI DBI Helper Functions Reference
+===================================
+
+.. kernel-doc:: drivers/gpu/drm/drm_mipi_dbi.c
+   :doc: overview
+
+.. kernel-doc:: include/drm/drm_mipi_dbi.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_mipi_dbi.c
+   :export:
+
 MIPI DSI Helper Functions Reference
 ===================================
 
index c8ebd4f..b664f05 100644 (file)
@@ -433,43 +433,11 @@ PRIME is the cross device buffer sharing framework in drm, originally
 created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME
 buffers are dma-buf based file descriptors.
 
-Overview and Driver Interface
------------------------------
+Overview and Lifetime Rules
+---------------------------
 
-Similar to GEM global names, PRIME file descriptors are also used to
-share buffer objects across processes. They offer additional security:
-as file descriptors must be explicitly sent over UNIX domain sockets to
-be shared between applications, they can't be guessed like the globally
-unique GEM names.
-
-Drivers that support the PRIME API must set the DRIVER_PRIME bit in the
-struct :c:type:`struct drm_driver <drm_driver>`
-driver_features field, and implement the prime_handle_to_fd and
-prime_fd_to_handle operations.
-
-int (\*prime_handle_to_fd)(struct drm_device \*dev, struct drm_file
-\*file_priv, uint32_t handle, uint32_t flags, int \*prime_fd); int
-(\*prime_fd_to_handle)(struct drm_device \*dev, struct drm_file
-\*file_priv, int prime_fd, uint32_t \*handle); Those two operations
-convert a handle to a PRIME file descriptor and vice versa. Drivers must
-use the kernel dma-buf buffer sharing framework to manage the PRIME file
-descriptors. Similar to the mode setting API PRIME is agnostic to the
-underlying buffer object manager, as long as handles are 32bit unsigned
-integers.
-
-While non-GEM drivers must implement the operations themselves, GEM
-drivers must use the :c:func:`drm_gem_prime_handle_to_fd()` and
-:c:func:`drm_gem_prime_fd_to_handle()` helper functions. Those
-helpers rely on the driver gem_prime_export and gem_prime_import
-operations to create a dma-buf instance from a GEM object (dma-buf
-exporter role) and to create a GEM object from a dma-buf instance
-(dma-buf importer role).
-
-struct dma_buf \* (\*gem_prime_export)(struct drm_device \*dev,
-struct drm_gem_object \*obj, int flags); struct drm_gem_object \*
-(\*gem_prime_import)(struct drm_device \*dev, struct dma_buf
-\*dma_buf); These two operations are mandatory for GEM drivers that
-support PRIME.
+.. kernel-doc:: drivers/gpu/drm/drm_prime.c
+   :doc: overview and lifetime rules
 
 PRIME Helper Functions
 ----------------------
index fccbe37..25a56e9 100644 (file)
@@ -51,6 +51,22 @@ and "FIXME" where the interface could be cleaned up.
 
 Also read the :ref:`guidelines for the kernel documentation at large <doc_guide>`.
 
+Documentation Requirements for kAPI
+-----------------------------------
+
+All kernel APIs exported to other modules must be documented, including their
+datastructures and at least a short introductory section explaining the overall
+concepts. Documentation should be put into the code itself as kerneldoc comments
+as much as reasonable.
+
+Do not blindly document everything, but document only what's relevant for driver
+authors: Internal functions of drm.ko and definitely static functions should not
+have formal kerneldoc comments. Use normal C comments if you feel like a comment
+is warranted. You may use kerneldoc syntax in the comment, but it shall not
+start with a /** kerneldoc marker. Similar for data structures, annotate
+anything entirely private with ``/* private: */`` comments as per the
+documentation guide.
+
 Getting Started
 ===============
 
diff --git a/Documentation/gpu/tinydrm.rst b/Documentation/gpu/tinydrm.rst
deleted file mode 100644 (file)
index 33a4154..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-============================
-drm/tinydrm Tiny DRM drivers
-============================
-
-tinydrm is a collection of DRM drivers that are so small they can fit in a
-single source file.
-
-Helpers
-=======
-
-.. kernel-doc:: include/drm/tinydrm/tinydrm-helpers.h
-   :internal:
-
-.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
-   :export:
-
-.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
-   :export:
-
-MIPI DBI Compatible Controllers
-===============================
-
-.. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c
-   :doc: overview
-
-.. kernel-doc:: include/drm/tinydrm/mipi-dbi.h
-   :internal:
-
-.. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c
-   :export:
index 0a49c5a..32787ac 100644 (file)
@@ -162,7 +162,7 @@ Clean up mmap forwarding
 
 A lot of drivers forward gem mmap calls to dma-buf mmap for imported buffers.
 And also a lot of them forward dma-buf mmap to the gem mmap implementations.
-Would be great to refactor this all into a set of small common helpers.
+There's drm_gem_prime_mmap() for this now, but still needs to be rolled out.
 
 Contact: Daniel Vetter
 
@@ -196,15 +196,6 @@ Might be good to also have some igt testcases for this.
 
 Contact: Daniel Vetter, Noralf Tronnes
 
-Remove the ->gem_prime_res_obj callback
---------------------------------------------
-
-The ->gem_prime_res_obj callback can be removed from drivers by using the
-reservation_object in the drm_gem_object. It may also be possible to use the
-generic drm_gem_reservation_object_wait helper for waiting for a bo.
-
-Contact: Daniel Vetter
-
 idr_init_base()
 ---------------
 
@@ -215,22 +206,13 @@ 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.
 
-DRM_GEM_CMA_VMAP_DRIVER_OPS, DRM_GEM_SHMEM_DRIVER_OPS already support this, but
-DRM_GEM_VRAM_DRIVER_PRIME does not yet and needs to be aligned with the previous
-two. We also need a 2nd version of the CMA define that doesn't require the
+We also need a 2nd version of the CMA define that doesn't require the
 vmapping to be present (different hook for prime importing). Plus this needs to
 be rolled out to all drivers using their own implementations, too.
 
@@ -317,19 +299,6 @@ In the end no .c file should need to include ``drmP.h`` anymore.
 
 Contact: Daniel Vetter
 
-Add missing kerneldoc for exported functions
---------------------------------------------
-
-The DRM reference documentation is still lacking kerneldoc in a few areas. The
-task would be to clean up interfaces like moving functions around between
-files to better group them and improving the interfaces like dropping return
-values for functions that never fail. Then write kerneldoc for all exported
-functions and an overview section and integrate it all into the drm book.
-
-See https://dri.freedesktop.org/docs/drm/ for what's there already.
-
-Contact: Daniel Vetter
-
 Make panic handling work
 ------------------------
 
@@ -393,6 +362,9 @@ There's a bunch of issues with it:
   this (together with the drm_minor->drm_device move) would allow us to remove
   debugfs_init.
 
+- Drop the return code and error checking from all debugfs functions. Greg KH is
+  working on this already.
+
 Contact: Daniel Vetter
 
 KMS cleanups
@@ -440,39 +412,22 @@ fit the available time.
 
 Contact: Daniel Vetter
 
+Backlight Refactoring
+---------------------
+
+Backlight drivers have a triple enable/disable state, which is a bit overkill.
+Plan to fix this:
+
+1. Roll out backlight_enable() and backlight_disable() helpers everywhere. This
+   has started already.
+2. In all, only look at one of the three status bits set by the above helpers.
+3. Remove the other two status bits.
+
+Contact: Daniel Vetter
+
 Driver Specific
 ===============
 
-tinydrm
--------
-
-Tinydrm is the helper driver for really simple fb drivers. The goal is to make
-those drivers as simple as possible, so lots of room for refactoring:
-
-- backlight helpers, probably best to put them into a new drm_backlight.c.
-  This is because drivers/video is de-facto unmaintained. We could also
-  move drivers/video/backlight to drivers/gpu/backlight and take it all
-  over within drm-misc, but that's more work. Backlight helpers require a fair
-  bit of reworking and refactoring. A simple example is the enabling of a backlight.
-  Tinydrm has helpers for this. It would be good if other drivers can also use the
-  helper. However, there are various cases we need to consider i.e different
-  drivers seem to have different ways of enabling/disabling a backlight.
-  We also need to consider the backlight drivers (like gpio_backlight). The situation
-  is further complicated by the fact that the backlight is tied to fbdev
-  via fb_notifier_callback() which has complicated logic. For further details, refer
-  to the following discussion thread:
-  https://groups.google.com/forum/#!topic/outreachy-kernel/8rBe30lwtdA
-
-- spi helpers, probably best put into spi core/helper code. Thierry said
-  the spi maintainer is fast&reactive, so shouldn't be a big issue.
-
-- extract the mipi-dbi helper (well, the non-tinydrm specific parts at
-  least) into a separate helper, like we have for mipi-dsi already. Or follow
-  one of the ideas for having a shared dsi/dbi helper, abstracting away the
-  transport details more.
-
-Contact: Noralf Trønnes, Daniel Vetter
-
 AMD DC Display Driver
 ---------------------
 
index ab1a48a..f4f8de3 100644 (file)
@@ -1305,6 +1305,113 @@ The following tables list existing packed RGB formats.
       - g\ :sub:`6`
       - g\ :sub:`5`
       - g\ :sub:`4`
+    * .. _MEDIA-BUS-FMT-RGB888-3X8:
+
+      - MEDIA_BUS_FMT_RGB888_3X8
+      - 0x101c
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
     * .. _MEDIA-BUS-FMT-ARGB888-1X32:
 
       - MEDIA_BUS_FMT_ARGB888_1X32
index a2c343e..8573884 100644 (file)
@@ -5099,17 +5099,24 @@ S:      Maintained
 F:     drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
 F:     Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt
 
+DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS
+M:     Hans de Goede <hdegoede@redhat.com>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+S:     Maintained
+F:     drivers/gpu/drm/tiny/gm12u320.c
+
 DRM DRIVER FOR ILITEK ILI9225 PANELS
 M:     David Lechner <david@lechnology.com>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/ili9225.c
+F:     drivers/gpu/drm/tiny/ili9225.c
 F:     Documentation/devicetree/bindings/display/ilitek,ili9225.txt
 
 DRM DRIVER FOR HX8357D PANELS
 M:     Eric Anholt <eric@anholt.net>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/hx8357d.c
+F:     drivers/gpu/drm/tiny/hx8357d.c
 F:     Documentation/devicetree/bindings/display/himax,hx8357d.txt
 
 DRM DRIVER FOR INTEL I810 VIDEO CARDS
@@ -5129,8 +5136,9 @@ F:        drivers/gpu/drm/mgag200/
 
 DRM DRIVER FOR MI0283QT
 M:     Noralf Trønnes <noralf@tronnes.org>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/mi0283qt.c
+F:     drivers/gpu/drm/tiny/mi0283qt.c
 F:     Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
 
 DRM DRIVER FOR MSM ADRENO GPU
@@ -5162,8 +5170,9 @@ F:        Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino.txt
 
 DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS
 M:     Noralf Trønnes <noralf@tronnes.org>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/repaper.c
+F:     drivers/gpu/drm/tiny/repaper.c
 F:     Documentation/devicetree/bindings/display/repaper.txt
 
 DRM DRIVER FOR QEMU'S CIRRUS DEVICE
@@ -5185,6 +5194,12 @@ S:       Maintained
 F:     drivers/gpu/drm/qxl/
 F:     include/uapi/drm/qxl_drm.h
 
+DRM DRIVER FOR RAYDIUM RM67191 PANELS
+M:     Robert Chiras <robert.chiras@nxp.com>
+S:     Maintained
+F:     drivers/gpu/drm/panel/panel-raydium-rm67191.c
+F:     Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+
 DRM DRIVER FOR RAGE 128 VIDEO CARDS
 S:     Orphan / Obsolete
 F:     drivers/gpu/drm/r128/
@@ -5192,6 +5207,7 @@ F:        include/uapi/drm/r128_drm.h
 
 DRM DRIVER FOR ROCKTECH JH057N00900 PANELS
 M:     Guido Günther <agx@sigxcpu.org>
+R:     Purism Kernel Team <kernel@puri.sm>
 S:     Maintained
 F:     drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
 F:     Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.txt
@@ -5214,14 +5230,16 @@ F:      Documentation/devicetree/bindings/display/panel/sitronix,st7701.txt
 
 DRM DRIVER FOR SITRONIX ST7586 PANELS
 M:     David Lechner <david@lechnology.com>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/st7586.c
+F:     drivers/gpu/drm/tiny/st7586.c
 F:     Documentation/devicetree/bindings/display/sitronix,st7586.txt
 
 DRM DRIVER FOR SITRONIX ST7735R PANELS
 M:     David Lechner <david@lechnology.com>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/tinydrm/st7735r.c
+F:     drivers/gpu/drm/tiny/st7735r.c
 F:     Documentation/devicetree/bindings/display/sitronix,st7735r.txt
 
 DRM DRIVER FOR ST-ERICSSON MCDE
@@ -5240,7 +5258,7 @@ M:        Linus Walleij <linus.walleij@linaro.org>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/panel/panel-tpo-tpg110.c
-F:     Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt
+F:     Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
 
 DRM DRIVER FOR USB DISPLAYLINK VIDEO ADAPTERS
 M:     Dave Airlie <airlied@redhat.com>
@@ -5328,6 +5346,7 @@ F:        Documentation/gpu/meson.rst
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR ATMEL HLCDC
+M:     Sam Ravnborg <sam@ravnborg.org>
 M:     Boris Brezillon <bbrezillon@kernel.org>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
@@ -5337,7 +5356,10 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR BRIDGE CHIPS
 M:     Andrzej Hajda <a.hajda@samsung.com>
+M:     Neil Armstrong <narmstrong@baylibre.com>
 R:     Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
+R:     Jonas Karlman <jonas@kwiboo.se>
+R:     Jernej Skrabec <jernej.skrabec@siol.net>
 S:     Maintained
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     drivers/gpu/drm/bridge/
@@ -5525,14 +5547,6 @@ F:       drivers/gpu/drm/panel/
 F:     include/drm/drm_panel.h
 F:     Documentation/devicetree/bindings/display/panel/
 
-DRM TINYDRM DRIVERS
-M:     Noralf Trønnes <noralf@tronnes.org>
-W:     https://github.com/notro/tinydrm/wiki/Development
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-S:     Maintained
-F:     drivers/gpu/drm/tinydrm/
-F:     include/drm/tinydrm/
-
 DRM DRIVERS FOR XEN
 M:     Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
index b5089f6..44a7416 100644 (file)
@@ -178,8 +178,30 @@ static bool dma_fence_chain_signaled(struct dma_fence *fence)
 static void dma_fence_chain_release(struct dma_fence *fence)
 {
        struct dma_fence_chain *chain = to_dma_fence_chain(fence);
+       struct dma_fence *prev;
+
+       /* Manually unlink the chain as much as possible to avoid recursion
+        * and potential stack overflow.
+        */
+       while ((prev = rcu_dereference_protected(chain->prev, true))) {
+               struct dma_fence_chain *prev_chain;
+
+               if (kref_read(&prev->refcount) > 1)
+                      break;
+
+               prev_chain = to_dma_fence_chain(prev);
+               if (!prev_chain)
+                       break;
+
+               /* No need for atomic operations since we hold the last
+                * reference to prev_chain.
+                */
+               chain->prev = prev_chain->prev;
+               RCU_INIT_POINTER(prev_chain->prev, NULL);
+               dma_fence_put(prev);
+       }
+       dma_fence_put(prev);
 
-       dma_fence_put(rcu_dereference_protected(chain->prev, true));
        dma_fence_put(chain->fence);
        dma_fence_free(fence);
 }
index 4447e13..ad6775b 100644 (file)
@@ -55,6 +55,85 @@ EXPORT_SYMBOL(reservation_seqcount_class);
 const char reservation_seqcount_string[] = "reservation_seqcount";
 EXPORT_SYMBOL(reservation_seqcount_string);
 
+/**
+ * reservation_object_list_alloc - allocate fence list
+ * @shared_max: number of fences we need space for
+ *
+ * Allocate a new reservation_object_list and make sure to correctly initialize
+ * shared_max.
+ */
+static struct reservation_object_list *
+reservation_object_list_alloc(unsigned int shared_max)
+{
+       struct reservation_object_list *list;
+
+       list = kmalloc(offsetof(typeof(*list), shared[shared_max]), GFP_KERNEL);
+       if (!list)
+               return NULL;
+
+       list->shared_max = (ksize(list) - offsetof(typeof(*list), shared)) /
+               sizeof(*list->shared);
+
+       return list;
+}
+
+/**
+ * reservation_object_list_free - free fence list
+ * @list: list to free
+ *
+ * Free a reservation_object_list and make sure to drop all references.
+ */
+static void reservation_object_list_free(struct reservation_object_list *list)
+{
+       unsigned int i;
+
+       if (!list)
+               return;
+
+       for (i = 0; i < list->shared_count; ++i)
+               dma_fence_put(rcu_dereference_protected(list->shared[i], true));
+
+       kfree_rcu(list, rcu);
+}
+
+/**
+ * reservation_object_init - initialize a reservation object
+ * @obj: the reservation object
+ */
+void reservation_object_init(struct reservation_object *obj)
+{
+       ww_mutex_init(&obj->lock, &reservation_ww_class);
+
+       __seqcount_init(&obj->seq, reservation_seqcount_string,
+                       &reservation_seqcount_class);
+       RCU_INIT_POINTER(obj->fence, NULL);
+       RCU_INIT_POINTER(obj->fence_excl, NULL);
+}
+EXPORT_SYMBOL(reservation_object_init);
+
+/**
+ * reservation_object_fini - destroys a reservation object
+ * @obj: the reservation object
+ */
+void reservation_object_fini(struct reservation_object *obj)
+{
+       struct reservation_object_list *fobj;
+       struct dma_fence *excl;
+
+       /*
+        * This object should be dead and all references must have
+        * been released to it, so no need to be protected with rcu.
+        */
+       excl = rcu_dereference_protected(obj->fence_excl, 1);
+       if (excl)
+               dma_fence_put(excl);
+
+       fobj = rcu_dereference_protected(obj->fence, 1);
+       reservation_object_list_free(fobj);
+       ww_mutex_destroy(&obj->lock);
+}
+EXPORT_SYMBOL(reservation_object_fini);
+
 /**
  * reservation_object_reserve_shared - Reserve space to add shared fences to
  * a reservation_object.
@@ -87,7 +166,7 @@ int reservation_object_reserve_shared(struct reservation_object *obj,
                max = 4;
        }
 
-       new = kmalloc(offsetof(typeof(*new), shared[max]), GFP_KERNEL);
+       new = reservation_object_list_alloc(max);
        if (!new)
                return -ENOMEM;
 
@@ -108,23 +187,22 @@ int reservation_object_reserve_shared(struct reservation_object *obj,
                        RCU_INIT_POINTER(new->shared[j++], fence);
        }
        new->shared_count = j;
-       new->shared_max = max;
 
-       preempt_disable();
-       write_seqcount_begin(&obj->seq);
        /*
-        * RCU_INIT_POINTER can be used here,
-        * seqcount provides the necessary barriers
+        * We are not changing the effective set of fences here so can
+        * merely update the pointer to the new array; both existing
+        * readers and new readers will see exactly the same set of
+        * active (unsignaled) shared fences. Individual fences and the
+        * old array are protected by RCU and so will not vanish under
+        * the gaze of the rcu_read_lock() readers.
         */
-       RCU_INIT_POINTER(obj->fence, new);
-       write_seqcount_end(&obj->seq);
-       preempt_enable();
+       rcu_assign_pointer(obj->fence, new);
 
        if (!old)
                return 0;
 
        /* Drop the references to the signaled fences */
-       for (i = k; i < new->shared_max; ++i) {
+       for (i = k; i < max; ++i) {
                struct dma_fence *fence;
 
                fence = rcu_dereference_protected(new->shared[i],
@@ -149,6 +227,7 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
                                         struct dma_fence *fence)
 {
        struct reservation_object_list *fobj;
+       struct dma_fence *old;
        unsigned int i, count;
 
        dma_fence_get(fence);
@@ -162,18 +241,16 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
        write_seqcount_begin(&obj->seq);
 
        for (i = 0; i < count; ++i) {
-               struct dma_fence *old_fence;
 
-               old_fence = rcu_dereference_protected(fobj->shared[i],
-                                                     reservation_object_held(obj));
-               if (old_fence->context == fence->context ||
-                   dma_fence_is_signaled(old_fence)) {
-                       dma_fence_put(old_fence);
+               old = rcu_dereference_protected(fobj->shared[i],
+                                               reservation_object_held(obj));
+               if (old->context == fence->context ||
+                   dma_fence_is_signaled(old))
                        goto replace;
-               }
        }
 
        BUG_ON(fobj->shared_count >= fobj->shared_max);
+       old = NULL;
        count++;
 
 replace:
@@ -183,6 +260,7 @@ replace:
 
        write_seqcount_end(&obj->seq);
        preempt_enable();
+       dma_fence_put(old);
 }
 EXPORT_SYMBOL(reservation_object_add_shared_fence);
 
@@ -239,7 +317,6 @@ int reservation_object_copy_fences(struct reservation_object *dst,
 {
        struct reservation_object_list *src_list, *dst_list;
        struct dma_fence *old, *new;
-       size_t size;
        unsigned i;
 
        reservation_object_assert_held(dst);
@@ -251,10 +328,9 @@ retry:
        if (src_list) {
                unsigned shared_count = src_list->shared_count;
 
-               size = offsetof(typeof(*src_list), shared[shared_count]);
                rcu_read_unlock();
 
-               dst_list = kmalloc(size, GFP_KERNEL);
+               dst_list = reservation_object_list_alloc(shared_count);
                if (!dst_list)
                        return -ENOMEM;
 
@@ -266,7 +342,6 @@ retry:
                }
 
                dst_list->shared_count = 0;
-               dst_list->shared_max = shared_count;
                for (i = 0; i < src_list->shared_count; ++i) {
                        struct dma_fence *fence;
 
@@ -276,7 +351,7 @@ retry:
                                continue;
 
                        if (!dma_fence_get_rcu(fence)) {
-                               kfree(dst_list);
+                               reservation_object_list_free(dst_list);
                                src_list = rcu_dereference(src->fence);
                                goto retry;
                        }
@@ -306,8 +381,7 @@ retry:
        write_seqcount_end(&dst->seq);
        preempt_enable();
 
-       if (src_list)
-               kfree_rcu(src_list, rcu);
+       reservation_object_list_free(src_list);
        dma_fence_put(old);
 
        return 0;
@@ -385,13 +459,6 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
                                if (!dma_fence_get_rcu(shared[i]))
                                        break;
                        }
-
-                       if (!pfence_excl && fence_excl) {
-                               shared[i] = fence_excl;
-                               fence_excl = NULL;
-                               ++i;
-                               ++shared_count;
-                       }
                }
 
                if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
@@ -406,6 +473,11 @@ unlock:
                rcu_read_unlock();
        } while (ret);
 
+       if (pfence_excl)
+               *pfence_excl = fence_excl;
+       else if (fence_excl)
+               shared[++shared_count] = fence_excl;
+
        if (!shared_count) {
                kfree(shared);
                shared = NULL;
@@ -413,9 +485,6 @@ unlock:
 
        *pshared_count = shared_count;
        *pshared = shared;
-       if (pfence_excl)
-               *pfence_excl = fence_excl;
-
        return ret;
 }
 EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
index 3c88420..e67c194 100644 (file)
@@ -24,6 +24,10 @@ menuconfig DRM
          details.  You should also select and configure AGP
          (/dev/agpgart) support if it is available for your platform.
 
+config DRM_MIPI_DBI
+       tristate
+       depends on DRM
+
 config DRM_MIPI_DSI
        bool
        depends on DRM
@@ -336,7 +340,7 @@ source "drivers/gpu/drm/mxsfb/Kconfig"
 
 source "drivers/gpu/drm/meson/Kconfig"
 
-source "drivers/gpu/drm/tinydrm/Kconfig"
+source "drivers/gpu/drm/tiny/Kconfig"
 
 source "drivers/gpu/drm/pl111/Kconfig"
 
index 9f0d2ee..10f8329 100644 (file)
@@ -55,6 +55,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
 
 obj-$(CONFIG_DRM)      += drm.o
+obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
 obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
 obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
 obj-y                  += arm/
@@ -111,7 +112,7 @@ obj-$(CONFIG_DRM_ARCPGU)+= arc/
 obj-y                  += hisilicon/
 obj-$(CONFIG_DRM_ZTE)  += zte/
 obj-$(CONFIG_DRM_MXSFB)        += mxsfb/
-obj-$(CONFIG_DRM_TINYDRM) += tinydrm/
+obj-y                  += tiny/
 obj-$(CONFIG_DRM_PL111) += pl111/
 obj-$(CONFIG_DRM_TVE200) += tve200/
 obj-$(CONFIG_DRM_XEN) += xen/
index 6a5c96e..9410ffc 100644 (file)
@@ -218,7 +218,7 @@ void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo)
 static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
                                        struct amdgpu_amdkfd_fence *ef)
 {
-       struct reservation_object *resv = bo->tbo.resv;
+       struct reservation_object *resv = bo->tbo.base.resv;
        struct reservation_object_list *old, *new;
        unsigned int i, j, k;
 
@@ -812,7 +812,7 @@ static int process_sync_pds_resv(struct amdkfd_process_info *process_info,
                struct amdgpu_bo *pd = peer_vm->root.base.bo;
 
                ret = amdgpu_sync_resv(NULL,
-                                       sync, pd->tbo.resv,
+                                       sync, pd->tbo.base.resv,
                                        AMDGPU_FENCE_OWNER_KFD, false);
                if (ret)
                        return ret;
@@ -887,7 +887,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
                                  AMDGPU_FENCE_OWNER_KFD, false);
        if (ret)
                goto wait_pd_fail;
-       ret = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv, 1);
+       ret = reservation_object_reserve_shared(vm->root.base.bo->tbo.base.resv, 1);
        if (ret)
                goto reserve_shared_fail;
        amdgpu_bo_fence(vm->root.base.bo,
@@ -2133,7 +2133,7 @@ int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem
         * Add process eviction fence to bo so they can
         * evict each other.
         */
-       ret = reservation_object_reserve_shared(gws_bo->tbo.resv, 1);
+       ret = reservation_object_reserve_shared(gws_bo->tbo.base.resv, 1);
        if (ret)
                goto reserve_shared_fail;
        amdgpu_bo_fence(gws_bo, &process_info->eviction_fence->base, true);
index 73b2ede..ece55c8 100644 (file)
@@ -1505,6 +1505,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
        struct amdgpu_connector_atom_dig *amdgpu_dig_connector;
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
+       struct i2c_adapter *ddc = NULL;
        uint32_t subpixel_order = SubPixelNone;
        bool shared_ddc = false;
        bool is_dp_bridge = false;
@@ -1574,17 +1575,21 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                amdgpu_connector->con_priv = amdgpu_dig_connector;
                if (i2c_bus->valid) {
                        amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
-                       if (amdgpu_connector->ddc_bus)
+                       if (amdgpu_connector->ddc_bus) {
                                has_aux = true;
-                       else
+                               ddc = &amdgpu_connector->ddc_bus->adapter;
+                       } else {
                                DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                       }
                }
                switch (connector_type) {
                case DRM_MODE_CONNECTOR_VGA:
                case DRM_MODE_CONNECTOR_DVIA:
                default:
-                       drm_connector_init(dev, &amdgpu_connector->base,
-                                          &amdgpu_connector_dp_funcs, connector_type);
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_dp_funcs,
+                                                   connector_type,
+                                                   ddc);
                        drm_connector_helper_add(&amdgpu_connector->base,
                                                 &amdgpu_connector_dp_helper_funcs);
                        connector->interlace_allowed = true;
@@ -1602,8 +1607,10 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                case DRM_MODE_CONNECTOR_HDMIA:
                case DRM_MODE_CONNECTOR_HDMIB:
                case DRM_MODE_CONNECTOR_DisplayPort:
-                       drm_connector_init(dev, &amdgpu_connector->base,
-                                          &amdgpu_connector_dp_funcs, connector_type);
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_dp_funcs,
+                                                   connector_type,
+                                                   ddc);
                        drm_connector_helper_add(&amdgpu_connector->base,
                                                 &amdgpu_connector_dp_helper_funcs);
                        drm_object_attach_property(&amdgpu_connector->base.base,
@@ -1644,8 +1651,10 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        break;
                case DRM_MODE_CONNECTOR_LVDS:
                case DRM_MODE_CONNECTOR_eDP:
-                       drm_connector_init(dev, &amdgpu_connector->base,
-                                          &amdgpu_connector_edp_funcs, connector_type);
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_edp_funcs,
+                                                   connector_type,
+                                                   ddc);
                        drm_connector_helper_add(&amdgpu_connector->base,
                                                 &amdgpu_connector_dp_helper_funcs);
                        drm_object_attach_property(&amdgpu_connector->base.base,
@@ -1659,13 +1668,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
        } else {
                switch (connector_type) {
                case DRM_MODE_CONNECTOR_VGA:
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
                                if (!amdgpu_connector->ddc_bus)
                                        DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_vga_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
                        amdgpu_connector->dac_load_detect = true;
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      adev->mode_info.load_detect_property,
@@ -1679,13 +1693,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        connector->doublescan_allowed = true;
                        break;
                case DRM_MODE_CONNECTOR_DVIA:
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
                                if (!amdgpu_connector->ddc_bus)
                                        DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_vga_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
                        amdgpu_connector->dac_load_detect = true;
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      adev->mode_info.load_detect_property,
@@ -1704,13 +1723,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        if (!amdgpu_dig_connector)
                                goto failed;
                        amdgpu_connector->con_priv = amdgpu_dig_connector;
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
                                if (!amdgpu_connector->ddc_bus)
                                        DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_dvi_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
                        subpixel_order = SubPixelHorizontalRGB;
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      adev->mode_info.coherent_mode_property,
@@ -1754,13 +1778,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        if (!amdgpu_dig_connector)
                                goto failed;
                        amdgpu_connector->con_priv = amdgpu_dig_connector;
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
                                if (!amdgpu_connector->ddc_bus)
                                        DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_dvi_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      adev->mode_info.coherent_mode_property,
                                                      1);
@@ -1796,15 +1825,20 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        if (!amdgpu_dig_connector)
                                goto failed;
                        amdgpu_connector->con_priv = amdgpu_dig_connector;
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dp_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
-                               if (amdgpu_connector->ddc_bus)
+                               if (amdgpu_connector->ddc_bus) {
                                        has_aux = true;
-                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
+                               } else {
                                        DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               }
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_dp_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
                        subpixel_order = SubPixelHorizontalRGB;
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      adev->mode_info.coherent_mode_property,
@@ -1838,15 +1872,20 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        if (!amdgpu_dig_connector)
                                goto failed;
                        amdgpu_connector->con_priv = amdgpu_dig_connector;
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_edp_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
-                               if (amdgpu_connector->ddc_bus)
+                               if (amdgpu_connector->ddc_bus) {
                                        has_aux = true;
-                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
+                               } else {
                                        DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               }
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_edp_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      dev->mode_config.scaling_mode_property,
                                                      DRM_MODE_SCALE_FULLSCREEN);
@@ -1859,13 +1898,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        if (!amdgpu_dig_connector)
                                goto failed;
                        amdgpu_connector->con_priv = amdgpu_dig_connector;
-                       drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_lvds_funcs, connector_type);
-                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_lvds_helper_funcs);
                        if (i2c_bus->valid) {
                                amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
                                if (!amdgpu_connector->ddc_bus)
                                        DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
+                               else
+                                       ddc = &amdgpu_connector->ddc_bus->adapter;
                        }
+                       drm_connector_init_with_ddc(dev, &amdgpu_connector->base,
+                                                   &amdgpu_connector_lvds_funcs,
+                                                   connector_type,
+                                                   ddc);
+                       drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_lvds_helper_funcs);
                        drm_object_attach_property(&amdgpu_connector->base.base,
                                                      dev->mode_config.scaling_mode_property,
                                                      DRM_MODE_SCALE_FULLSCREEN);
index 4e4094f..9ccf32c 100644 (file)
@@ -402,7 +402,7 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
        struct ttm_operation_ctx ctx = {
                .interruptible = true,
                .no_wait_gpu = false,
-               .resv = bo->tbo.resv,
+               .resv = bo->tbo.base.resv,
                .flags = 0
        };
        uint32_t domain;
@@ -730,7 +730,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
 
        list_for_each_entry(e, &p->validated, tv.head) {
                struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
-               struct reservation_object *resv = bo->tbo.resv;
+               struct reservation_object *resv = bo->tbo.base.resv;
 
                r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp,
                                     amdgpu_bo_explicit_sync(bo));
@@ -1727,7 +1727,7 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
        *map = mapping;
 
        /* Double check that the BO is reserved by this CS */
-       if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket)
+       if (reservation_object_locking_ctx((*bo)->tbo.base.resv) != &parser->ticket)
                return -EINVAL;
 
        if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) {
index 5356509..b5d020e 100644 (file)
@@ -204,7 +204,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
                goto unpin;
        }
 
-       r = reservation_object_get_fences_rcu(new_abo->tbo.resv, &work->excl,
+       r = reservation_object_get_fences_rcu(new_abo->tbo.base.resv, &work->excl,
                                              &work->shared_count,
                                              &work->shared);
        if (unlikely(r != 0)) {
index 489041d..b88e27d 100644 (file)
@@ -216,7 +216,7 @@ static int amdgpu_dma_buf_map_attach(struct dma_buf *dma_buf,
                 * fences on the reservation object into a single exclusive
                 * fence.
                 */
-               r = __reservation_object_make_exclusive(bo->tbo.resv);
+               r = __reservation_object_make_exclusive(bo->tbo.base.resv);
                if (r)
                        goto error_unreserve;
        }
@@ -267,20 +267,6 @@ error:
        drm_gem_map_detach(dma_buf, attach);
 }
 
-/**
- * amdgpu_gem_prime_res_obj - &drm_driver.gem_prime_res_obj implementation
- * @obj: GEM BO
- *
- * Returns:
- * The BO's reservation object.
- */
-struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj)
-{
-       struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-
-       return bo->tbo.resv;
-}
-
 /**
  * amdgpu_dma_buf_begin_cpu_access - &dma_buf_ops.begin_cpu_access implementation
  * @dma_buf: Shared DMA buffer
@@ -339,14 +325,12 @@ const struct dma_buf_ops amdgpu_dmabuf_ops = {
  * @gobj: GEM BO
  * @flags: Flags such as DRM_CLOEXEC and DRM_RDWR.
  *
- * The main work is done by the &drm_gem_prime_export helper, which in turn
- * uses &amdgpu_gem_prime_res_obj.
+ * The main work is done by the &drm_gem_prime_export helper.
  *
  * Returns:
  * Shared DMA buffer representing the GEM BO from the given device.
  */
-struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
-                                       struct drm_gem_object *gobj,
+struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
                                        int flags)
 {
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
@@ -356,9 +340,9 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
            bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)
                return ERR_PTR(-EPERM);
 
-       buf = drm_gem_prime_export(dev, gobj, flags);
+       buf = drm_gem_prime_export(gobj, flags);
        if (!IS_ERR(buf)) {
-               buf->file->f_mapping = dev->anon_inode->i_mapping;
+               buf->file->f_mapping = gobj->dev->anon_inode->i_mapping;
                buf->ops = &amdgpu_dmabuf_ops;
        }
 
@@ -396,7 +380,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
        bp.flags = 0;
        bp.type = ttm_bo_type_sg;
        bp.resv = resv;
-       ww_mutex_lock(&resv->lock, NULL);
+       reservation_object_lock(resv, NULL);
        ret = amdgpu_bo_create(adev, &bp, &bo);
        if (ret)
                goto error;
@@ -408,11 +392,11 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
        if (attach->dmabuf->ops != &amdgpu_dmabuf_ops)
                bo->prime_shared_count = 1;
 
-       ww_mutex_unlock(&resv->lock);
-       return &bo->gem_base;
+       reservation_object_unlock(resv);
+       return &bo->tbo.base;
 
 error:
-       ww_mutex_unlock(&resv->lock);
+       reservation_object_unlock(resv);
        return ERR_PTR(ret);
 }
 
index c7056cb..5012e6a 100644 (file)
@@ -30,12 +30,10 @@ struct drm_gem_object *
 amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
                                 struct dma_buf_attachment *attach,
                                 struct sg_table *sg);
-struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
-                                       struct drm_gem_object *gobj,
+struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
                                        int flags);
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
                                            struct dma_buf *dma_buf);
-struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *);
 void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj);
 void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
index 5376328..6d24b42 100644 (file)
@@ -1373,7 +1373,7 @@ static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_ATOMIC |
            DRIVER_GEM |
-           DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
+           DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
        .load = amdgpu_driver_load_kms,
        .open = amdgpu_driver_open_kms,
        .postclose = amdgpu_driver_postclose_kms,
@@ -1397,7 +1397,6 @@ static struct drm_driver kms_driver = {
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = amdgpu_gem_prime_export,
        .gem_prime_import = amdgpu_gem_prime_import,
-       .gem_prime_res_obj = amdgpu_gem_prime_res_obj,
        .gem_prime_get_sg_table = amdgpu_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table,
        .gem_prime_vmap = amdgpu_gem_prime_vmap,
index 939f830..bff9173 100644 (file)
@@ -85,7 +85,7 @@ retry:
                }
                return r;
        }
-       *obj = &bo->gem_base;
+       *obj = &bo->tbo.base;
 
        return 0;
 }
@@ -134,7 +134,7 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
                return -EPERM;
 
        if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID &&
-           abo->tbo.resv != vm->root.base.bo->tbo.resv)
+           abo->tbo.base.resv != vm->root.base.bo->tbo.base.resv)
                return -EPERM;
 
        r = amdgpu_bo_reserve(abo, false);
@@ -252,7 +252,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
                if (r)
                        return r;
 
-               resv = vm->root.base.bo->tbo.resv;
+               resv = vm->root.base.bo->tbo.base.resv;
        }
 
        r = amdgpu_gem_object_create(adev, size, args->in.alignment,
@@ -433,7 +433,7 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
                return -ENOENT;
        }
        robj = gem_to_amdgpu_bo(gobj);
-       ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true,
+       ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true,
                                                  timeout);
 
        /* ret == 0 means not signaled,
@@ -689,7 +689,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
                struct drm_amdgpu_gem_create_in info;
                void __user *out = u64_to_user_ptr(args->value);
 
-               info.bo_size = robj->gem_base.size;
+               info.bo_size = robj->tbo.base.size;
                info.alignment = robj->tbo.mem.page_alignment << PAGE_SHIFT;
                info.domains = robj->preferred_domains;
                info.domain_flags = robj->flags;
@@ -819,8 +819,8 @@ static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data)
        if (pin_count)
                seq_printf(m, " pin count %d", pin_count);
 
-       dma_buf = READ_ONCE(bo->gem_base.dma_buf);
-       attachment = READ_ONCE(bo->gem_base.import_attach);
+       dma_buf = READ_ONCE(bo->tbo.base.dma_buf);
+       attachment = READ_ONCE(bo->tbo.base.import_attach);
 
        if (attachment)
                seq_printf(m, " imported from %p", dma_buf);
index b8ba6e2..2f17150 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #define AMDGPU_GEM_DOMAIN_MAX          0x3
-#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base)
+#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, tbo.base)
 
 void amdgpu_gem_object_free(struct drm_gem_object *obj);
 int amdgpu_gem_object_open(struct drm_gem_object *obj,
index 0cf7e86..252f71e 100644 (file)
@@ -1088,7 +1088,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
        amdgpu_vm_fini(adev, &fpriv->vm);
 
        if (pasid)
-               amdgpu_pasid_free_delayed(pd->tbo.resv, pasid);
+               amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
        amdgpu_bo_unref(&pd);
 
        idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
index 3971c20..50022ac 100644 (file)
@@ -179,7 +179,7 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
                if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
                        continue;
 
-               r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
+               r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv,
                        true, false, MAX_SCHEDULE_TIMEOUT);
                if (r <= 0)
                        DRM_ERROR("(%ld) failed to wait for user bo\n", r);
index bea6f29..8ae44d3 100644 (file)
@@ -85,9 +85,9 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
 
        amdgpu_bo_kunmap(bo);
 
-       if (bo->gem_base.import_attach)
-               drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg);
-       drm_gem_object_release(&bo->gem_base);
+       if (bo->tbo.base.import_attach)
+               drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg);
+       drm_gem_object_release(&bo->tbo.base);
        /* in case amdgpu_device_recover_vram got NULL of bo->parent */
        if (!list_empty(&bo->shadow_list)) {
                mutex_lock(&adev->shadow_list_lock);
@@ -454,7 +454,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
        bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
-       drm_gem_private_object_init(adev->ddev, &bo->gem_base, size);
+       drm_gem_private_object_init(adev->ddev, &bo->tbo.base, size);
        INIT_LIST_HEAD(&bo->shadow_list);
        bo->vm_bo = NULL;
        bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain :
@@ -521,7 +521,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
            bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
                struct dma_fence *fence;
 
-               r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
+               r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence);
                if (unlikely(r))
                        goto fail_unreserve;
 
@@ -544,7 +544,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
 
 fail_unreserve:
        if (!bp->resv)
-               ww_mutex_unlock(&bo->tbo.resv->lock);
+               reservation_object_unlock(bo->tbo.base.resv);
        amdgpu_bo_unref(&bo);
        return r;
 }
@@ -565,7 +565,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev,
        bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC |
                AMDGPU_GEM_CREATE_SHADOW;
        bp.type = ttm_bo_type_kernel;
-       bp.resv = bo->tbo.resv;
+       bp.resv = bo->tbo.base.resv;
 
        r = amdgpu_bo_do_create(adev, &bp, &bo->shadow);
        if (!r) {
@@ -606,13 +606,13 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
 
        if ((flags & AMDGPU_GEM_CREATE_SHADOW) && !(adev->flags & AMD_IS_APU)) {
                if (!bp->resv)
-                       WARN_ON(reservation_object_lock((*bo_ptr)->tbo.resv,
+                       WARN_ON(reservation_object_lock((*bo_ptr)->tbo.base.resv,
                                                        NULL));
 
                r = amdgpu_bo_create_shadow(adev, bp->size, *bo_ptr);
 
                if (!bp->resv)
-                       reservation_object_unlock((*bo_ptr)->tbo.resv);
+                       reservation_object_unlock((*bo_ptr)->tbo.base.resv);
 
                if (r)
                        amdgpu_bo_unref(bo_ptr);
@@ -709,7 +709,7 @@ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
                return 0;
        }
 
-       r = reservation_object_wait_timeout_rcu(bo->tbo.resv, false, false,
+       r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, false, false,
                                                MAX_SCHEDULE_TIMEOUT);
        if (r < 0)
                return r;
@@ -1087,7 +1087,7 @@ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)
  */
 void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
 {
-       lockdep_assert_held(&bo->tbo.resv->lock.base);
+       reservation_object_assert_held(bo->tbo.base.resv);
 
        if (tiling_flags)
                *tiling_flags = bo->tiling_flags;
@@ -1283,7 +1283,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
                     bool shared)
 {
-       struct reservation_object *resv = bo->tbo.resv;
+       struct reservation_object *resv = bo->tbo.base.resv;
 
        if (shared)
                reservation_object_add_shared_fence(resv, fence);
@@ -1308,7 +1308,7 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr)
        int r;
 
        amdgpu_sync_create(&sync);
-       amdgpu_sync_resv(adev, &sync, bo->tbo.resv, owner, false);
+       amdgpu_sync_resv(adev, &sync, bo->tbo.base.resv, owner, false);
        r = amdgpu_sync_wait(&sync, intr);
        amdgpu_sync_free(&sync);
 
@@ -1328,7 +1328,7 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr)
 u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
 {
        WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
-       WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
+       WARN_ON_ONCE(!reservation_object_is_locked(bo->tbo.base.resv) &&
                     !bo->pin_count && bo->tbo.type != ttm_bo_type_kernel);
        WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET);
        WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM &&
index d60593c..113fb2f 100644 (file)
@@ -94,7 +94,6 @@ struct amdgpu_bo {
        /* per VM structure for page tables and with virtual addresses */
        struct amdgpu_vm_bo_base        *vm_bo;
        /* Constant after initialization */
-       struct drm_gem_object           gem_base;
        struct amdgpu_bo                *parent;
        struct amdgpu_bo                *shadow;
 
@@ -192,7 +191,7 @@ static inline unsigned amdgpu_bo_gpu_page_alignment(struct amdgpu_bo *bo)
  */
 static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo)
 {
-       return drm_vma_node_offset_addr(&bo->tbo.vma_node);
+       return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
 /**
index e51b48a..63e7d1e 100644 (file)
@@ -227,7 +227,7 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 
        if (amdgpu_ttm_tt_get_usermm(bo->ttm))
                return -EPERM;
-       return drm_vma_node_verify_access(&abo->gem_base.vma_node,
+       return drm_vma_node_verify_access(&abo->tbo.base.vma_node,
                                          filp->private_data);
 }
 
@@ -440,7 +440,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
 
        r = amdgpu_ttm_copy_mem_to_mem(adev, &src, &dst,
                                       new_mem->num_pages << PAGE_SHIFT,
-                                      bo->resv, &fence);
+                                      bo->base.resv, &fence);
        if (r)
                goto error;
 
@@ -1478,18 +1478,18 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
         * cleanly handle page faults.
         */
        if (bo->type == ttm_bo_type_kernel &&
-           !reservation_object_test_signaled_rcu(bo->resv, true))
+           !reservation_object_test_signaled_rcu(bo->base.resv, true))
                return false;
 
        /* If bo is a KFD BO, check if the bo belongs to the current process.
         * If true, then return false as any KFD process needs all its BOs to
         * be resident to run successfully
         */
-       flist = reservation_object_get_list(bo->resv);
+       flist = reservation_object_get_list(bo->base.resv);
        if (flist) {
                for (i = 0; i < flist->shared_count; ++i) {
                        f = rcu_dereference_protected(flist->shared[i],
-                               reservation_object_held(bo->resv));
+                               reservation_object_held(bo->base.resv));
                        if (amdkfd_fence_check_mm(f, current->mm))
                                return false;
                }
index 5b2fea3..f858607 100644 (file)
@@ -1073,7 +1073,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
        ib->length_dw = 16;
 
        if (direct) {
-               r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
+               r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv,
                                                        true, false,
                                                        msecs_to_jiffies(10));
                if (r == 0)
@@ -1085,7 +1085,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
                if (r)
                        goto err_free;
        } else {
-               r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv,
+               r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.base.resv,
                                     AMDGPU_FENCE_OWNER_UNDEFINED, false);
                if (r)
                        goto err_free;
index 24c3c05..95eef0a 100644 (file)
@@ -302,7 +302,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
        base->next = bo->vm_bo;
        bo->vm_bo = base;
 
-       if (bo->tbo.resv != vm->root.base.bo->tbo.resv)
+       if (bo->tbo.base.resv != vm->root.base.bo->tbo.base.resv)
                return;
 
        vm->bulk_moveable = false;
@@ -583,7 +583,7 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo)
        for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) {
                struct amdgpu_vm *vm = bo_base->vm;
 
-               if (abo->tbo.resv == vm->root.base.bo->tbo.resv)
+               if (abo->tbo.base.resv == vm->root.base.bo->tbo.base.resv)
                        vm->bulk_moveable = false;
        }
 
@@ -834,7 +834,7 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                bp->flags |= AMDGPU_GEM_CREATE_SHADOW;
        bp->type = ttm_bo_type_kernel;
        if (vm->root.base.bo)
-               bp->resv = vm->root.base.bo->tbo.resv;
+               bp->resv = vm->root.base.bo->tbo.base.resv;
 }
 
 /**
@@ -1702,7 +1702,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
                        ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm);
                        pages_addr = ttm->dma_address;
                }
-               exclusive = reservation_object_get_excl(bo->tbo.resv);
+               exclusive = reservation_object_get_excl(bo->tbo.base.resv);
        }
 
        if (bo) {
@@ -1712,7 +1712,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
                flags = 0x0;
        }
 
-       if (clear || (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv))
+       if (clear || (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv))
                last_update = &vm->last_update;
        else
                last_update = &bo_va->last_pt_update;
@@ -1743,7 +1743,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
         * the evicted list so that it gets validated again on the
         * next command submission.
         */
-       if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) {
+       if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) {
                uint32_t mem_type = bo->tbo.mem.mem_type;
 
                if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(mem_type)))
@@ -1879,7 +1879,7 @@ static void amdgpu_vm_free_mapping(struct amdgpu_device *adev,
  */
 static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 {
-       struct reservation_object *resv = vm->root.base.bo->tbo.resv;
+       struct reservation_object *resv = vm->root.base.bo->tbo.base.resv;
        struct dma_fence *excl, **shared;
        unsigned i, shared_count;
        int r;
@@ -1993,7 +1993,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
        while (!list_empty(&vm->invalidated)) {
                bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
                                         base.vm_status);
-               resv = bo_va->base.bo->tbo.resv;
+               resv = bo_va->base.bo->tbo.base.resv;
                spin_unlock(&vm->invalidated_lock);
 
                /* Try to reserve the BO to avoid clearing its ptes */
@@ -2084,7 +2084,7 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
        if (mapping->flags & AMDGPU_PTE_PRT)
                amdgpu_vm_prt_get(adev);
 
-       if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv &&
+       if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv &&
            !bo_va->base.moved) {
                list_move(&bo_va->base.vm_status, &vm->moved);
        }
@@ -2416,7 +2416,8 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket)
                        struct amdgpu_bo *bo;
 
                        bo = mapping->bo_va->base.bo;
-                       if (READ_ONCE(bo->tbo.resv->lock.ctx) != ticket)
+                       if (reservation_object_locking_ctx(bo->tbo.base.resv) !=
+                           ticket)
                                continue;
                }
 
@@ -2443,7 +2444,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
        struct amdgpu_vm_bo_base **base;
 
        if (bo) {
-               if (bo->tbo.resv == vm->root.base.bo->tbo.resv)
+               if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv)
                        vm->bulk_moveable = false;
 
                for (base = &bo_va->base.bo->vm_bo; *base;
@@ -2507,7 +2508,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
        for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
                struct amdgpu_vm *vm = bo_base->vm;
 
-               if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) {
+               if (evicted && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) {
                        amdgpu_vm_bo_evicted(bo_base);
                        continue;
                }
@@ -2518,7 +2519,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
 
                if (bo->tbo.type == ttm_bo_type_kernel)
                        amdgpu_vm_bo_relocated(bo_base);
-               else if (bo->tbo.resv == vm->root.base.bo->tbo.resv)
+               else if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv)
                        amdgpu_vm_bo_moved(bo_base);
                else
                        amdgpu_vm_bo_invalidated(bo_base);
@@ -2648,7 +2649,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
  */
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
 {
-       return reservation_object_wait_timeout_rcu(vm->root.base.bo->tbo.resv,
+       return reservation_object_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv,
                                                   true, true, timeout);
 }
 
@@ -2723,7 +2724,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        if (r)
                goto error_free_root;
 
-       r = reservation_object_reserve_shared(root->tbo.resv, 1);
+       r = reservation_object_reserve_shared(root->tbo.base.resv, 1);
        if (r)
                goto error_unreserve;
 
index ddd181f..61fc584 100644 (file)
@@ -72,7 +72,7 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
        if (r)
                return r;
 
-       r = amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.resv,
+       r = amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.base.resv,
                             owner, false);
        if (r)
                return r;
index 4a29f72..381a534 100644 (file)
@@ -5693,7 +5693,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                 * deadlock during GPU reset when this fence will not signal
                 * but we hold reservation lock for the BO.
                 */
-               r = reservation_object_wait_timeout_rcu(abo->tbo.resv, true,
+               r = reservation_object_wait_timeout_rcu(abo->tbo.base.resv, true,
                                                        false,
                                                        msecs_to_jiffies(5000));
                if (unlikely(r <= 0))
index 6e205ee..16218a2 100644 (file)
@@ -156,6 +156,26 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
        kfree(amdgpu_dm_connector);
 }
 
+static int
+amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
+{
+       struct amdgpu_dm_connector *amdgpu_dm_connector =
+               to_amdgpu_dm_connector(connector);
+       struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+       return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
+{
+       struct amdgpu_dm_connector *amdgpu_dm_connector =
+               to_amdgpu_dm_connector(connector);
+       struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+       drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
        .detect = dm_dp_mst_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
@@ -164,7 +184,9 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
        .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
        .atomic_set_property = amdgpu_dm_connector_atomic_set_property,
-       .atomic_get_property = amdgpu_dm_connector_atomic_get_property
+       .atomic_get_property = amdgpu_dm_connector_atomic_get_property,
+       .late_register = amdgpu_dm_mst_connector_late_register,
+       .early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
@@ -388,7 +410,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
                                       struct amdgpu_dm_connector *aconnector)
 {
        aconnector->dm_dp_aux.aux.name = "dmdc";
-       aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+       aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev;
        aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
        aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
 
index af60c6d..6b7f791 100644 (file)
@@ -135,8 +135,7 @@ static int arcpgu_debugfs_init(struct drm_minor *minor)
 #endif
 
 static struct drm_driver arcpgu_drm_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .name = "arcpgu",
        .desc = "ARC PGU Controller",
        .date = "20160219",
@@ -150,8 +149,6 @@ static struct drm_driver arcpgu_drm_driver = {
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_print_info = drm_gem_cma_print_info,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 4073a45..55a8cc9 100644 (file)
@@ -4,8 +4,6 @@
  * Author: James.Qian.Wang <james.qian.wang@arm.com>
  *
  */
-
-#include <drm/drm_print.h>
 #include "d71_dev.h"
 #include "komeda_kms.h"
 #include "malidp_io.h"
@@ -804,7 +802,7 @@ static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,
                denominator = (mode->htotal - 1) * v_out -  2 * v_in;
        }
 
-       return aclk_rate * denominator >= mode->clock * 1000 * fraction ?
+       return aclk_rate * denominator >= mode->crtc_clock * 1000 * fraction ?
               0 : -EINVAL;
 }
 
@@ -1032,21 +1030,31 @@ static void d71_timing_ctrlr_update(struct komeda_component *c,
                                    struct komeda_component_state *state)
 {
        struct drm_crtc_state *crtc_st = state->crtc->state;
+       struct drm_display_mode *mode = &crtc_st->adjusted_mode;
        u32 __iomem *reg = c->reg;
-       struct videomode vm;
+       u32 hactive, hfront_porch, hback_porch, hsync_len;
+       u32 vactive, vfront_porch, vback_porch, vsync_len;
        u32 value;
 
-       drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
-
-       malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
-       malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
-                                                       vm.hback_porch));
-       malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
-                                                       vm.vback_porch));
-
-       value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
-       value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
-       value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
+       hactive = mode->crtc_hdisplay;
+       hfront_porch = mode->crtc_hsync_start - mode->crtc_hdisplay;
+       hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+       hback_porch = mode->crtc_htotal - mode->crtc_hsync_end;
+
+       vactive = mode->crtc_vdisplay;
+       vfront_porch = mode->crtc_vsync_start - mode->crtc_vdisplay;
+       vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+       vback_porch = mode->crtc_vtotal - mode->crtc_vsync_end;
+
+       malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(hactive, vactive));
+       malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(hfront_porch,
+                                                       hback_porch));
+       malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vfront_porch,
+                                                       vback_porch));
+
+       value = BS_SYNC_VSW(vsync_len) | BS_SYNC_HSW(hsync_len);
+       value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BS_SYNC_VSP : 0;
+       value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BS_SYNC_HSP : 0;
        malidp_write32(reg, BS_SYNC, value);
 
        malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
@@ -1054,6 +1062,10 @@ static void d71_timing_ctrlr_update(struct komeda_component *c,
 
        /* configure bs control register */
        value = BS_CTRL_EN | BS_CTRL_VM;
+       if (c->pipeline->dual_link) {
+               malidp_write32(reg, BS_DRIFT_TO, hfront_porch + 16);
+               value |= BS_CTRL_DL;
+       }
 
        malidp_write32(reg, BLK_CONTROL, value);
 }
index f440078..fa9a459 100644 (file)
@@ -27,8 +27,8 @@ static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st)
                return;
        }
 
-       pxlclk = kcrtc_st->base.adjusted_mode.clock * 1000;
-       aclk = komeda_calc_aclk(kcrtc_st);
+       pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000;
+       aclk = komeda_crtc_get_aclk(kcrtc_st);
 
        kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk);
 }
@@ -74,14 +74,6 @@ komeda_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
-unsigned long komeda_calc_aclk(struct komeda_crtc_state *kcrtc_st)
-{
-       struct komeda_dev *mdev = kcrtc_st->base.crtc->dev->dev_private;
-       unsigned long pxlclk = kcrtc_st->base.adjusted_mode.clock;
-
-       return clk_round_rate(mdev->aclk, pxlclk * 1000);
-}
-
 /* For active a crtc, mainly need two parts of preparation
  * 1. adjust display operation mode.
  * 2. enable needed clk
@@ -92,7 +84,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc)
        struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
        struct komeda_pipeline *master = kcrtc->master;
        struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state);
-       unsigned long pxlclk_rate = kcrtc_st->base.adjusted_mode.clock * 1000;
+       struct drm_display_mode *mode = &kcrtc_st->base.adjusted_mode;
        u32 new_mode;
        int err;
 
@@ -118,7 +110,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc)
         * to enable it again.
         */
        if (new_mode != KOMEDA_MODE_DUAL_DISP) {
-               err = clk_set_rate(mdev->aclk, komeda_calc_aclk(kcrtc_st));
+               err = clk_set_rate(mdev->aclk, komeda_crtc_get_aclk(kcrtc_st));
                if (err)
                        DRM_ERROR("failed to set aclk.\n");
                err = clk_prepare_enable(mdev->aclk);
@@ -126,7 +118,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc)
                        DRM_ERROR("failed to enable aclk.\n");
        }
 
-       err = clk_set_rate(master->pxlclk, pxlclk_rate);
+       err = clk_set_rate(master->pxlclk, mode->crtc_clock * 1000);
        if (err)
                DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id);
        err = clk_prepare_enable(master->pxlclk);
@@ -342,29 +334,58 @@ komeda_crtc_atomic_flush(struct drm_crtc *crtc,
        komeda_crtc_do_flush(crtc, old);
 }
 
+/* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */
+static unsigned long
+komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc,
+                         unsigned long pxlclk)
+{
+       /* Once dual-link one display pipeline drives two display outputs,
+        * the aclk needs run on the double rate of pxlclk
+        */
+       if (kcrtc->master->dual_link)
+               return pxlclk * 2;
+       else
+               return pxlclk;
+}
+
+/* Get current aclk rate that specified by state */
+unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st)
+{
+       struct drm_crtc *crtc = kcrtc_st->base.crtc;
+       struct komeda_dev *mdev = crtc->dev->dev_private;
+       unsigned long pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000;
+       unsigned long min_aclk;
+
+       min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), pxlclk);
+
+       return clk_round_rate(mdev->aclk, min_aclk);
+}
+
 static enum drm_mode_status
 komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m)
 {
        struct komeda_dev *mdev = crtc->dev->dev_private;
        struct komeda_crtc *kcrtc = to_kcrtc(crtc);
        struct komeda_pipeline *master = kcrtc->master;
-       long mode_clk, pxlclk;
+       unsigned long min_pxlclk, min_aclk;
 
        if (m->flags & DRM_MODE_FLAG_INTERLACE)
                return MODE_NO_INTERLACE;
 
-       mode_clk = m->clock * 1000;
-       pxlclk = clk_round_rate(master->pxlclk, mode_clk);
-       if (pxlclk != mode_clk) {
-               DRM_DEBUG_ATOMIC("pxlclk doesn't support %ld Hz\n", mode_clk);
+       min_pxlclk = m->clock * 1000;
+       if (master->dual_link)
+               min_pxlclk /= 2;
+
+       if (min_pxlclk != clk_round_rate(master->pxlclk, min_pxlclk)) {
+               DRM_DEBUG_ATOMIC("pxlclk doesn't support %lu Hz\n", min_pxlclk);
 
                return MODE_NOCLOCK;
        }
 
-       /* main engine clock must be faster than pxlclk*/
-       if (clk_round_rate(mdev->aclk, mode_clk) < pxlclk) {
-               DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %ld.\n",
-                                m->name, pxlclk);
+       min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), min_pxlclk);
+       if (clk_round_rate(mdev->aclk, min_aclk) < min_aclk) {
+               DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %lu.\n",
+                                m->name, min_pxlclk);
 
                return MODE_CLOCK_HIGH;
        }
@@ -377,10 +398,22 @@ static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc,
                                   struct drm_display_mode *adjusted_mode)
 {
        struct komeda_crtc *kcrtc = to_kcrtc(crtc);
-       struct komeda_pipeline *master = kcrtc->master;
-       long mode_clk = m->clock * 1000;
+       unsigned long clk_rate;
+
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
+       /* In dual link half the horizontal settings */
+       if (kcrtc->master->dual_link) {
+               adjusted_mode->crtc_clock /= 2;
+               adjusted_mode->crtc_hdisplay /= 2;
+               adjusted_mode->crtc_hsync_start /= 2;
+               adjusted_mode->crtc_hsync_end /= 2;
+               adjusted_mode->crtc_htotal /= 2;
+       }
 
-       adjusted_mode->clock = clk_round_rate(master->pxlclk, mode_clk) / 1000;
+       clk_rate = adjusted_mode->crtc_clock * 1000;
+       /* crtc_clock will be used as the komeda output pixel clock */
+       adjusted_mode->crtc_clock = clk_round_rate(kcrtc->master->pxlclk,
+                                                  clk_rate) / 1000;
 
        return true;
 }
@@ -488,10 +521,8 @@ int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
                else
                        sprintf(str, "None");
 
-               DRM_INFO("crtc%d: master(pipe-%d) slave(%s) output: %s.\n",
-                        kms->n_crtcs, master->id, str,
-                        master->of_output_dev ?
-                        master->of_output_dev->full_name : "None");
+               DRM_INFO("CRTC-%d: master(pipe-%d) slave(%s).\n",
+                        kms->n_crtcs, master->id, str);
 
                kms->n_crtcs++;
        }
index 5a11898..1ff7f4b 100644 (file)
@@ -121,11 +121,14 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np)
        pipe->pxlclk = clk;
 
        /* enum ports */
-       pipe->of_output_dev =
+       pipe->of_output_links[0] =
                of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 0);
+       pipe->of_output_links[1] =
+               of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 1);
        pipe->of_output_port =
                of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
 
+       pipe->dual_link = pipe->of_output_links[0] && pipe->of_output_links[1];
        pipe->of_node = np;
 
        return 0;
index cfa5068..69ace6f 100644 (file)
@@ -83,11 +83,12 @@ static int compare_of(struct device *dev, void *data)
 
 static void komeda_add_slave(struct device *master,
                             struct component_match **match,
-                            struct device_node *np, int port)
+                            struct device_node *np,
+                            u32 port, u32 endpoint)
 {
        struct device_node *remote;
 
-       remote = of_graph_get_remote_node(np, port, 0);
+       remote = of_graph_get_remote_node(np, port, endpoint);
        if (remote) {
                drm_of_component_match_add(master, match, compare_of, remote);
                of_node_put(remote);
@@ -108,7 +109,8 @@ static int komeda_platform_probe(struct platform_device *pdev)
                        continue;
 
                /* add connector */
-               komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT);
+               komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 0);
+               komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 1);
        }
 
        return component_master_add_with_match(dev, &komeda_master_ops, match);
index 419a8b0..89191a5 100644 (file)
@@ -55,16 +55,13 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 }
 
 static struct drm_driver komeda_kms_driver = {
-       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
-                          DRIVER_PRIME | DRIVER_HAVE_IRQ,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .lastclose                      = drm_fb_helper_lastclose,
        .gem_free_object_unlocked       = drm_gem_cma_free_object,
        .gem_vm_ops                     = &drm_gem_cma_vm_ops,
        .dumb_create                    = komeda_gem_cma_dumb_create,
        .prime_handle_to_fd             = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle             = drm_gem_prime_fd_to_handle,
-       .gem_prime_export               = drm_gem_prime_export,
-       .gem_prime_import               = drm_gem_prime_import,
        .gem_prime_get_sg_table         = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table      = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap                 = drm_gem_cma_prime_vmap,
index 8c89fc2..45c498e 100644 (file)
@@ -14,8 +14,6 @@
 #include <drm/drm_device.h>
 #include <drm/drm_writeback.h>
 #include <drm/drm_print.h>
-#include <video/videomode.h>
-#include <video/display_timing.h>
 
 /**
  * struct komeda_plane - komeda instance of drm_plane
@@ -168,7 +166,7 @@ static inline bool has_flip_h(u32 rot)
                return !!(rotation & DRM_MODE_REFLECT_X);
 }
 
-unsigned long komeda_calc_aclk(struct komeda_crtc_state *kcrtc_st);
+unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st);
 
 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
 
index 78e44d9..452e505 100644 (file)
@@ -54,7 +54,8 @@ void komeda_pipeline_destroy(struct komeda_dev *mdev,
 
        clk_put(pipe->pxlclk);
 
-       of_node_put(pipe->of_output_dev);
+       of_node_put(pipe->of_output_links[0]);
+       of_node_put(pipe->of_output_links[1]);
        of_node_put(pipe->of_output_port);
        of_node_put(pipe->of_node);
 
@@ -246,9 +247,15 @@ static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
        struct komeda_component *c;
        int id;
 
-       DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s\n",
+       DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
                 pipe->id, pipe->n_layers, pipe->n_scalers,
-                pipe->of_output_dev ? pipe->of_output_dev->full_name : "none");
+                pipe->dual_link ? "dual-link" : "single-link");
+       DRM_INFO("      output_link[0]: %s.\n",
+                pipe->of_output_links[0] ?
+                pipe->of_output_links[0]->full_name : "none");
+       DRM_INFO("      output_link[1]: %s.\n",
+                pipe->of_output_links[1] ?
+                pipe->of_output_links[1]->full_name : "none");
 
        dp_for_each_set_bit(id, pipe->avail_comps) {
                c = komeda_pipeline_get_component(pipe, id);
@@ -305,6 +312,12 @@ static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
 
                layer->right = komeda_get_layer_split_right_layer(pipe, layer);
        }
+
+       if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {
+               pipe->dual_link = false;
+               DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
+                        pipe->id);
+       }
 }
 
 /* if pipeline_A accept another pipeline_B's component as input, treat
index a90bcbb..a7a84e6 100644 (file)
@@ -416,8 +416,10 @@ struct komeda_pipeline {
        struct device_node *of_node;
        /** @of_output_port: pipeline output port */
        struct device_node *of_output_port;
-       /** @of_output_dev: output connector device node */
-       struct device_node *of_output_dev;
+       /** @of_output_links: output connector device nodes */
+       struct device_node *of_output_links[2];
+       /** @dual_link: true if of_output_links[0] and [1] are both valid */
+       bool dual_link;
 };
 
 /**
index 950235a..ea26bc9 100644 (file)
@@ -473,7 +473,7 @@ komeda_scaler_check_cfg(struct komeda_scaler *scaler,
 
                err = pipe->funcs->downscaling_clk_check(pipe,
                                        &kcrtc_st->base.adjusted_mode,
-                                       komeda_calc_aclk(kcrtc_st), dflow);
+                                       komeda_crtc_get_aclk(kcrtc_st), dflow);
                if (err) {
                        DRM_DEBUG_ATOMIC("aclk can't satisfy the clock requirement of the downscaling\n");
                        return err;
index c095af1..98e915e 100644 (file)
@@ -158,7 +158,7 @@ static void komeda_plane_reset(struct drm_plane *plane)
 static struct drm_plane_state *
 komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
 {
-       struct komeda_plane_state *new, *old;
+       struct komeda_plane_state *new;
 
        if (WARN_ON(!plane->state))
                return NULL;
@@ -169,8 +169,6 @@ komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
 
        __drm_atomic_helper_plane_duplicate_state(plane, &new->base);
 
-       old = to_kplane_st(plane->state);
-
        return &new->base;
 }
 
index 8fc0b88..27c46a2 100644 (file)
@@ -229,9 +229,7 @@ static int hdlcd_debugfs_init(struct drm_minor *minor)
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver hdlcd_driver = {
-       .driver_features = DRIVER_GEM |
-                          DRIVER_MODESET | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .irq_handler = hdlcd_irq,
        .irq_preinstall = hdlcd_irq_preinstall,
        .irq_postinstall = hdlcd_irq_postinstall,
@@ -242,8 +240,6 @@ static struct drm_driver hdlcd_driver = {
        .dumb_create = drm_gem_cma_dumb_create,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index f25ec43..c27ff45 100644 (file)
@@ -561,15 +561,12 @@ static int malidp_debugfs_init(struct drm_minor *minor)
 #endif //CONFIG_DEBUG_FS
 
 static struct drm_driver malidp_driver = {
-       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
-                          DRIVER_PRIME,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = malidp_dumb_create,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 50af399..380be66 100644 (file)
@@ -385,6 +385,7 @@ int malidp_format_get_bpp(u32 fmt)
                switch (fmt) {
                case DRM_FORMAT_VUY101010:
                        bpp = 30;
+                       break;
                case DRM_FORMAT_YUV420_10BIT:
                        bpp = 15;
                        break;
@@ -1309,7 +1310,7 @@ static irqreturn_t malidp_se_irq(int irq, void *arg)
                        break;
                case MW_RESTART:
                        drm_writeback_signal_completion(&malidp->mw_connector, 0);
-                       /* fall through to a new start */
+                       /* fall through to a new start */
                case MW_START:
                        /* writeback started, need to emulate one-shot mode */
                        hw->disable_memwrite(hwdev);
index 521464f..055c92b 100644 (file)
@@ -40,8 +40,7 @@ static struct drm_driver armada_drm_driver = {
        .name                   = "armada-drm",
        .desc                   = "Armada SoC DRM",
        .date                   = "20120730",
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET |
-                                 DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .ioctls                 = armada_ioctls,
        .fops                   = &armada_drm_fops,
 };
index 874b296..60c5097 100644 (file)
@@ -482,8 +482,7 @@ static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
 };
 
 struct dma_buf *
-armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
-       int flags)
+armada_gem_prime_export(struct drm_gem_object *obj, int flags)
 {
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
@@ -492,7 +491,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
        exp_info.flags = O_RDWR;
        exp_info.priv = obj;
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       return drm_gem_dmabuf_export(obj->dev, &exp_info);
 }
 
 struct drm_gem_object *
index 1dd8054..de04cc2 100644 (file)
@@ -32,8 +32,7 @@ struct armada_gem_object *armada_gem_alloc_private_object(struct drm_device *,
        size_t);
 int armada_gem_dumb_create(struct drm_file *, struct drm_device *,
        struct drm_mode_create_dumb *);
-struct dma_buf *armada_gem_prime_export(struct drm_device *dev,
-       struct drm_gem_object *obj, int flags);
+struct dma_buf *armada_gem_prime_export(struct drm_gem_object *obj, int flags);
 struct drm_gem_object *armada_gem_prime_import(struct drm_device *,
        struct dma_buf *);
 int armada_gem_map_import(struct armada_gem_object *);
index eeb22ec..ada2f6a 100644 (file)
@@ -194,8 +194,7 @@ static void aspeed_gfx_unload(struct drm_device *drm)
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver aspeed_gfx_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET |
-                               DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .gem_create_object      = drm_cma_gem_create_object_default_funcs,
        .dumb_create            = drm_gem_cma_dumb_create,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
index b086dae..561f7c4 100644 (file)
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-ast-y := ast_drv.o ast_main.o ast_mode.o ast_fb.o ast_ttm.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_main.o ast_mode.o ast_ttm.o ast_post.o ast_dp501.o
 
 obj-$(CONFIG_DRM_AST) := ast.o
index 4c7375b..98cd692 100644 (file)
@@ -1,8 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#include <linux/delay.h>
 #include <linux/firmware.h>
-#include <drm/drmP.h>
+#include <linux/module.h>
+
 #include "ast_drv.h"
+
 MODULE_FIRMWARE("ast_dp501_fw.bin");
 
 static int ast_load_dp501_microcode(struct drm_device *dev)
index 3811997..6ed6ff4 100644 (file)
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
-#include <linux/module.h>
+
 #include <linux/console.h>
+#include <linux/module.h>
+#include <linux/pci.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_pci.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vram_mm_helper.h>
 
 #include "ast_drv.h"
 
@@ -100,28 +105,21 @@ ast_pci_remove(struct pci_dev *pdev)
 static int ast_drm_freeze(struct drm_device *dev)
 {
        drm_kms_helper_poll_disable(dev);
-
        pci_save_state(dev->pdev);
+       drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true);
 
-       console_lock();
-       ast_fbdev_set_suspend(dev, 1);
-       console_unlock();
        return 0;
 }
 
 static int ast_drm_thaw(struct drm_device *dev)
 {
-       int error = 0;
-
        ast_post_gpu(dev);
 
        drm_mode_config_reset(dev);
        drm_helper_resume_force_mode(dev);
+       drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false);
 
-       console_lock();
-       ast_fbdev_set_suspend(dev, 0);
-       console_unlock();
-       return error;
+       return 0;
 }
 
 static int ast_drm_resume(struct drm_device *dev)
index 684e15e..244cc7c 100644 (file)
 #ifndef __AST_DRV_H__
 #define __AST_DRV_H__
 
-#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
-
-#include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
-
-#include <drm/drm_vram_mm_helper.h>
-
+#include <linux/types.h>
+#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_fb_helper.h>
+
 #define DRIVER_AUTHOR          "Dave Airlie"
 
 #define DRIVER_NAME            "ast"
@@ -81,8 +82,6 @@ enum ast_tx_chip {
 #define AST_DRAM_4Gx16   7
 #define AST_DRAM_8Gx16   8
 
-struct ast_fbdev;
-
 struct ast_private {
        struct drm_device *dev;
 
@@ -96,8 +95,6 @@ struct ast_private {
        uint32_t mclk;
        uint32_t vram_size;
 
-       struct ast_fbdev *fbdev;
-
        int fb_mtrr;
 
        struct drm_gem_object *cursor_cache;
@@ -239,24 +236,9 @@ struct ast_encoder {
        struct drm_encoder base;
 };
 
-struct ast_framebuffer {
-       struct drm_framebuffer base;
-       struct drm_gem_object *obj;
-};
-
-struct ast_fbdev {
-       struct drm_fb_helper helper; /* must be first */
-       struct ast_framebuffer afb;
-       void *sysram;
-       int size;
-       int x1, y1, x2, y2; /* dirty rect */
-       spinlock_t dirty_lock;
-};
-
 #define to_ast_crtc(x) container_of(x, struct ast_crtc, base)
 #define to_ast_connector(x) container_of(x, struct ast_connector, base)
 #define to_ast_encoder(x) container_of(x, struct ast_encoder, base)
-#define to_ast_framebuffer(x) container_of(x, struct ast_framebuffer, base)
 
 struct ast_vbios_stdtable {
        u8 misc;
@@ -296,16 +278,6 @@ struct ast_vbios_mode_info {
 extern int ast_mode_init(struct drm_device *dev);
 extern void ast_mode_fini(struct drm_device *dev);
 
-int ast_framebuffer_init(struct drm_device *dev,
-                        struct ast_framebuffer *ast_fb,
-                        const struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct drm_gem_object *obj);
-
-int ast_fbdev_init(struct drm_device *dev);
-void ast_fbdev_fini(struct drm_device *dev);
-void ast_fbdev_set_suspend(struct drm_device *dev, int state);
-void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr);
-
 #define AST_MM_ALIGN_SHIFT 4
 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
 
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
deleted file mode 100644 (file)
index 8200b25..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS 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.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- */
-/*
- * Authors: Dave Airlie <airlied@redhat.com>
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/sysrq.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_util.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "ast_drv.h"
-
-static void ast_dirty_update(struct ast_fbdev *afbdev,
-                            int x, int y, int width, int height)
-{
-       int i;
-       struct drm_gem_vram_object *gbo;
-       int src_offset, dst_offset;
-       int bpp = afbdev->afb.base.format->cpp[0];
-       int ret;
-       u8 *dst;
-       bool unmap = false;
-       bool store_for_later = false;
-       int x2, y2;
-       unsigned long flags;
-
-       gbo = drm_gem_vram_of_gem(afbdev->afb.obj);
-
-       if (drm_can_sleep()) {
-               /* We pin the BO so it won't be moved during the
-                * update. The actual location, video RAM or system
-                * memory, is not important.
-                */
-               ret = drm_gem_vram_pin(gbo, 0);
-               if (ret) {
-                       if (ret != -EBUSY)
-                               return;
-                       store_for_later = true;
-               }
-       } else {
-               store_for_later = true;
-       }
-
-       x2 = x + width - 1;
-       y2 = y + height - 1;
-       spin_lock_irqsave(&afbdev->dirty_lock, flags);
-
-       if (afbdev->y1 < y)
-               y = afbdev->y1;
-       if (afbdev->y2 > y2)
-               y2 = afbdev->y2;
-       if (afbdev->x1 < x)
-               x = afbdev->x1;
-       if (afbdev->x2 > x2)
-               x2 = afbdev->x2;
-
-       if (store_for_later) {
-               afbdev->x1 = x;
-               afbdev->x2 = x2;
-               afbdev->y1 = y;
-               afbdev->y2 = y2;
-               spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
-               return;
-       }
-
-       afbdev->x1 = afbdev->y1 = INT_MAX;
-       afbdev->x2 = afbdev->y2 = 0;
-       spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
-
-       dst = drm_gem_vram_kmap(gbo, false, NULL);
-       if (IS_ERR(dst)) {
-               DRM_ERROR("failed to kmap fb updates\n");
-               goto out;
-       } else if (!dst) {
-               dst = drm_gem_vram_kmap(gbo, true, NULL);
-               if (IS_ERR(dst)) {
-                       DRM_ERROR("failed to kmap fb updates\n");
-                       goto out;
-               }
-               unmap = true;
-       }
-
-       for (i = y; i <= y2; i++) {
-               /* assume equal stride for now */
-               src_offset = dst_offset =
-                       i * afbdev->afb.base.pitches[0] + (x * bpp);
-               memcpy_toio(dst + dst_offset, afbdev->sysram + src_offset,
-                           (x2 - x + 1) * bpp);
-       }
-
-       if (unmap)
-               drm_gem_vram_kunmap(gbo);
-
-out:
-       drm_gem_vram_unpin(gbo);
-}
-
-static void ast_fillrect(struct fb_info *info,
-                        const struct fb_fillrect *rect)
-{
-       struct ast_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_fillrect(info, rect);
-       ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
-                        rect->height);
-}
-
-static void ast_copyarea(struct fb_info *info,
-                        const struct fb_copyarea *area)
-{
-       struct ast_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_copyarea(info, area);
-       ast_dirty_update(afbdev, area->dx, area->dy, area->width,
-                        area->height);
-}
-
-static void ast_imageblit(struct fb_info *info,
-                         const struct fb_image *image)
-{
-       struct ast_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_imageblit(info, image);
-       ast_dirty_update(afbdev, image->dx, image->dy, image->width,
-                        image->height);
-}
-
-static struct fb_ops astfb_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = ast_fillrect,
-       .fb_copyarea = ast_copyarea,
-       .fb_imageblit = ast_imageblit,
-       .fb_pan_display = drm_fb_helper_pan_display,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcmap = drm_fb_helper_setcmap,
-};
-
-static int astfb_create_object(struct ast_fbdev *afbdev,
-                              const struct drm_mode_fb_cmd2 *mode_cmd,
-                              struct drm_gem_object **gobj_p)
-{
-       struct drm_device *dev = afbdev->helper.dev;
-       u32 size;
-       struct drm_gem_object *gobj;
-       int ret = 0;
-
-       size = mode_cmd->pitches[0] * mode_cmd->height;
-       ret = ast_gem_create(dev, size, true, &gobj);
-       if (ret)
-               return ret;
-
-       *gobj_p = gobj;
-       return ret;
-}
-
-static int astfb_create(struct drm_fb_helper *helper,
-                       struct drm_fb_helper_surface_size *sizes)
-{
-       struct ast_fbdev *afbdev =
-               container_of(helper, struct ast_fbdev, helper);
-       struct drm_device *dev = afbdev->helper.dev;
-       struct drm_mode_fb_cmd2 mode_cmd;
-       struct drm_framebuffer *fb;
-       struct fb_info *info;
-       int size, ret;
-       void *sysram;
-       struct drm_gem_object *gobj = NULL;
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7)/8);
-
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
-
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-
-       ret = astfb_create_object(afbdev, &mode_cmd, &gobj);
-       if (ret) {
-               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
-               return ret;
-       }
-
-       sysram = vmalloc(size);
-       if (!sysram)
-               return -ENOMEM;
-
-       info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info)) {
-               ret = PTR_ERR(info);
-               goto out;
-       }
-       ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj);
-       if (ret)
-               goto out;
-
-       afbdev->sysram = sysram;
-       afbdev->size = size;
-
-       fb = &afbdev->afb.base;
-       afbdev->helper.fb = fb;
-
-       info->fbops = &astfb_ops;
-
-       info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
-       info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
-
-       drm_fb_helper_fill_info(info, &afbdev->helper, sizes);
-
-       info->screen_base = sysram;
-       info->screen_size = size;
-
-       info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-       DRM_DEBUG_KMS("allocated %dx%d\n",
-                     fb->width, fb->height);
-
-       return 0;
-
-out:
-       vfree(sysram);
-       return ret;
-}
-
-static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
-       .fb_probe = astfb_create,
-};
-
-static void ast_fbdev_destroy(struct drm_device *dev,
-                             struct ast_fbdev *afbdev)
-{
-       struct ast_framebuffer *afb = &afbdev->afb;
-
-       drm_helper_force_disable_all(dev);
-       drm_fb_helper_unregister_fbi(&afbdev->helper);
-
-       if (afb->obj) {
-               drm_gem_object_put_unlocked(afb->obj);
-               afb->obj = NULL;
-       }
-       drm_fb_helper_fini(&afbdev->helper);
-
-       vfree(afbdev->sysram);
-       drm_framebuffer_unregister_private(&afb->base);
-       drm_framebuffer_cleanup(&afb->base);
-}
-
-int ast_fbdev_init(struct drm_device *dev)
-{
-       struct ast_private *ast = dev->dev_private;
-       struct ast_fbdev *afbdev;
-       int ret;
-
-       afbdev = kzalloc(sizeof(struct ast_fbdev), GFP_KERNEL);
-       if (!afbdev)
-               return -ENOMEM;
-
-       ast->fbdev = afbdev;
-       spin_lock_init(&afbdev->dirty_lock);
-
-       drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
-
-       ret = drm_fb_helper_init(dev, &afbdev->helper, 1);
-       if (ret)
-               goto free;
-
-       ret = drm_fb_helper_single_add_all_connectors(&afbdev->helper);
-       if (ret)
-               goto fini;
-
-       /* disable all the possible outputs/crtcs before entering KMS mode */
-       drm_helper_disable_unused_functions(dev);
-
-       ret = drm_fb_helper_initial_config(&afbdev->helper, 32);
-       if (ret)
-               goto fini;
-
-       return 0;
-
-fini:
-       drm_fb_helper_fini(&afbdev->helper);
-free:
-       kfree(afbdev);
-       return ret;
-}
-
-void ast_fbdev_fini(struct drm_device *dev)
-{
-       struct ast_private *ast = dev->dev_private;
-
-       if (!ast->fbdev)
-               return;
-
-       ast_fbdev_destroy(dev, ast->fbdev);
-       kfree(ast->fbdev);
-       ast->fbdev = NULL;
-}
-
-void ast_fbdev_set_suspend(struct drm_device *dev, int state)
-{
-       struct ast_private *ast = dev->dev_private;
-
-       if (!ast->fbdev)
-               return;
-
-       drm_fb_helper_set_suspend(&ast->fbdev->helper, state);
-}
-
-void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr)
-{
-       ast->fbdev->helper.fbdev->fix.smem_start =
-               ast->fbdev->helper.fbdev->apertures->ranges[0].base + gpu_addr;
-       ast->fbdev->helper.fbdev->fix.smem_len = ast->vram_size - gpu_addr;
-}
index 4c7e31c..dab77b2 100644 (file)
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
-#include <drm/drmP.h>
-#include "ast_drv.h"
 
+#include <linux/pci.h>
 
-#include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_vram_mm_helper.h>
+
+#include "ast_drv.h"
 
 void ast_set_index_reg_mask(struct ast_private *ast,
                            uint32_t base, uint8_t index,
@@ -383,67 +388,8 @@ static int ast_get_dram_info(struct drm_device *dev)
        return 0;
 }
 
-static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
-
-       drm_gem_object_put_unlocked(ast_fb->obj);
-       drm_framebuffer_cleanup(fb);
-       kfree(ast_fb);
-}
-
-static const struct drm_framebuffer_funcs ast_fb_funcs = {
-       .destroy = ast_user_framebuffer_destroy,
-};
-
-
-int ast_framebuffer_init(struct drm_device *dev,
-                        struct ast_framebuffer *ast_fb,
-                        const struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct drm_gem_object *obj)
-{
-       int ret;
-
-       drm_helper_mode_fill_fb_struct(dev, &ast_fb->base, mode_cmd);
-       ast_fb->obj = obj;
-       ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs);
-       if (ret) {
-               DRM_ERROR("framebuffer init failed %d\n", ret);
-               return ret;
-       }
-       return 0;
-}
-
-static struct drm_framebuffer *
-ast_user_framebuffer_create(struct drm_device *dev,
-              struct drm_file *filp,
-              const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       struct drm_gem_object *obj;
-       struct ast_framebuffer *ast_fb;
-       int ret;
-
-       obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
-       if (obj == NULL)
-               return ERR_PTR(-ENOENT);
-
-       ast_fb = kzalloc(sizeof(*ast_fb), GFP_KERNEL);
-       if (!ast_fb) {
-               drm_gem_object_put_unlocked(obj);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       ret = ast_framebuffer_init(dev, ast_fb, mode_cmd, obj);
-       if (ret) {
-               drm_gem_object_put_unlocked(obj);
-               kfree(ast_fb);
-               return ERR_PTR(ret);
-       }
-       return &ast_fb->base;
-}
-
 static const struct drm_mode_config_funcs ast_mode_funcs = {
-       .fb_create = ast_user_framebuffer_create,
+       .fb_create = drm_gem_fb_create
 };
 
 static u32 ast_get_vram_info(struct drm_device *dev)
@@ -561,7 +507,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto out_free;
 
-       ret = ast_fbdev_init(dev);
+       ret = drm_fbdev_generic_setup(dev, 32);
        if (ret)
                goto out_free;
 
@@ -579,7 +525,6 @@ void ast_driver_unload(struct drm_device *dev)
        ast_release_firmware(dev);
        kfree(ast->dp501_fw_addr);
        ast_mode_fini(dev);
-       ast_fbdev_fini(dev);
        drm_mode_config_cleanup(dev);
 
        ast_mm_fini(ast);
@@ -609,6 +554,6 @@ int ast_gem_create(struct drm_device *dev,
                        DRM_ERROR("failed to allocate GEM object\n");
                return ret;
        }
-       *obj = &gbo->gem;
+       *obj = &gbo->bo.base;
        return 0;
 }
index ffccbef..1c899a6 100644 (file)
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
+
 #include <linux/export.h>
-#include <drm/drmP.h>
+#include <linux/pci.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include "ast_drv.h"
 
+#include "ast_drv.h"
 #include "ast_tables.h"
 
 static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
@@ -525,28 +529,16 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                int x, int y, int atomic)
 {
-       struct ast_private *ast = crtc->dev->dev_private;
-       struct drm_gem_object *obj;
-       struct ast_framebuffer *ast_fb;
        struct drm_gem_vram_object *gbo;
        int ret;
        s64 gpu_addr;
-       void *base;
 
        if (!atomic && fb) {
-               ast_fb = to_ast_framebuffer(fb);
-               obj = ast_fb->obj;
-               gbo = drm_gem_vram_of_gem(obj);
-
-               /* unmap if console */
-               if (&ast->fbdev->afb == ast_fb)
-                       drm_gem_vram_kunmap(gbo);
+               gbo = drm_gem_vram_of_gem(fb->obj[0]);
                drm_gem_vram_unpin(gbo);
        }
 
-       ast_fb = to_ast_framebuffer(crtc->primary->fb);
-       obj = ast_fb->obj;
-       gbo = drm_gem_vram_of_gem(obj);
+       gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]);
 
        ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
        if (ret)
@@ -557,17 +549,6 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
                goto err_drm_gem_vram_unpin;
        }
 
-       if (&ast->fbdev->afb == ast_fb) {
-               /* if pushing console in kmap it */
-               base = drm_gem_vram_kmap(gbo, true, NULL);
-               if (IS_ERR(base)) {
-                       ret = PTR_ERR(base);
-                       DRM_ERROR("failed to kmap fbcon\n");
-               } else {
-                       ast_fbdev_set_base(ast, gpu_addr);
-               }
-       }
-
        ast_set_offset_reg(crtc);
        ast_set_start_address_crt1(crtc, (u32)gpu_addr);
 
@@ -624,14 +605,10 @@ static void ast_crtc_disable(struct drm_crtc *crtc)
        DRM_DEBUG_KMS("\n");
        ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
        if (crtc->primary->fb) {
-               struct ast_private *ast = crtc->dev->dev_private;
-               struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb);
-               struct drm_gem_object *obj = ast_fb->obj;
-               struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj);
-
-               /* unmap if console */
-               if (&ast->fbdev->afb == ast_fb)
-                       drm_gem_vram_kunmap(gbo);
+               struct drm_framebuffer *fb = crtc->primary->fb;
+               struct drm_gem_vram_object *gbo =
+                       drm_gem_vram_of_gem(fb->obj[0]);
+
                drm_gem_vram_unpin(gbo);
        }
        crtc->primary->fb = NULL;
@@ -890,7 +867,14 @@ static int ast_connector_init(struct drm_device *dev)
                return -ENOMEM;
 
        connector = &ast_connector->base;
-       drm_connector_init(dev, connector, &ast_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+       ast_connector->i2c = ast_i2c_create(dev);
+       if (!ast_connector->i2c)
+               DRM_ERROR("failed to add ddc bus for connector\n");
+
+       drm_connector_init_with_ddc(dev, connector,
+                                   &ast_connector_funcs,
+                                   DRM_MODE_CONNECTOR_VGA,
+                                   &ast_connector->i2c->adapter);
 
        drm_connector_helper_add(connector, &ast_connector_helper_funcs);
 
@@ -904,10 +888,6 @@ static int ast_connector_init(struct drm_device *dev)
        encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
        drm_connector_attach_encoder(connector, encoder);
 
-       ast_connector->i2c = ast_i2c_create(dev);
-       if (!ast_connector->i2c)
-               DRM_ERROR("failed to add ddc bus for connector\n");
-
        return 0;
 }
 
index f7d4213..e1d9cdf 100644 (file)
  * Authors: Dave Airlie <airlied@redhat.com>
  */
 
-#include <drm/drmP.h>
-#include "ast_drv.h"
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <drm/drm_print.h>
 
 #include "ast_dram_tables.h"
+#include "ast_drv.h"
 
 static void ast_post_chip_2300(struct drm_device *dev);
 static void ast_post_chip_2500(struct drm_device *dev);
index 779c53e..c52d922 100644 (file)
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
-#include <drm/drmP.h>
+
+#include <linux/pci.h>
+
+#include <drm/drm_print.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_vram_mm_helper.h>
 
 #include "ast_drv.h"
 
index 2a413e2..580aa26 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <drm/ati_pcigart.h>
 #include <drm/drm_device.h>
-#include <drm/drm_os_linux.h>
 #include <drm/drm_pci.h>
 #include <drm/drm_print.h>
 
@@ -169,6 +168,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                page_base = (u32) entry->busaddr[i];
 
                for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+                       u32 offset;
                        u32 val;
 
                        switch(gart_info->gart_reg_if) {
@@ -184,10 +184,12 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                                break;
                        }
                        if (gart_info->gart_table_location ==
-                           DRM_ATI_GART_MAIN)
+                           DRM_ATI_GART_MAIN) {
                                pci_gart[gart_idx] = cpu_to_le32(val);
-                       else
-                               DRM_WRITE32(map, gart_idx * sizeof(u32), val);
+                       } else {
+                               offset = gart_idx * sizeof(u32);
+                               writel(val, (void __iomem *)map->handle + offset);
+                       }
                        gart_idx++;
                        page_base += ATI_PCIGART_PAGE_SIZE;
                }
index 6c6c7cf..f2e73e6 100644 (file)
@@ -8,15 +8,19 @@
  */
 
 #include <linux/clk.h>
+#include <linux/mfd/atmel-hlcdc.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
-#include <linux/pinctrl/consumer.h>
 
+#include <video/videomode.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
-
-#include <video/videomode.h>
+#include <drm/drm_vblank.h>
 
 #include "atmel_hlcdc_dc.h"
 
index 9bab6e5..9264029 100644 (file)
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
+#include <linux/mfd/atmel-hlcdc.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "atmel_hlcdc_dc.h"
 
@@ -823,9 +835,7 @@ static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver atmel_hlcdc_dc_driver = {
-       .driver_features = DRIVER_GEM |
-                          DRIVER_MODESET | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .irq_handler = atmel_hlcdc_dc_irq_handler,
        .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
        .irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
@@ -834,8 +844,6 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_import = drm_gem_prime_import,
-       .gem_prime_export = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 7300e3f..469d450 100644 (file)
 #ifndef DRM_ATMEL_HLCDC_H
 #define DRM_ATMEL_HLCDC_H
 
-#include <linux/clk.h>
-#include <linux/dmapool.h>
-#include <linux/irqdomain.h>
-#include <linux/mfd/atmel-hlcdc.h>
-#include <linux/pwm.h>
-
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
+#include <linux/regmap.h>
+
+#include <drm/drm_plane.h>
 
 #define ATMEL_HLCDC_LAYER_CHER                 0x0
 #define ATMEL_HLCDC_LAYER_CHDR                 0x4
index 7e08318..375fa84 100644 (file)
@@ -8,9 +8,10 @@
  * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
  */
 
+#include <linux/media-bus-format.h>
 #include <linux/of_graph.h>
 
-#include <drm/drmP.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_of.h>
 #include <drm/drm_bridge.h>
 
index 4127aca..89f5a75 100644 (file)
@@ -6,6 +6,16 @@
  * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
  */
 
+#include <linux/dmapool.h>
+#include <linux/mfd/atmel-hlcdc.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
 #include "atmel_hlcdc_dc.h"
 
 /**
@@ -361,7 +371,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
        atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG,
                                    cfg);
 
-       cfg = ATMEL_HLCDC_LAYER_DMA;
+       cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP;
 
        if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
                cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
index 2a65434..68483a2 100644 (file)
@@ -1,17 +1,15 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+
 #include <linux/io.h>
 #include <linux/console.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
-
+#include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vram_mm_helper.h>
 
 /* ---------------------------------------------------------------------- */
index 8f3a5bd..770e162 100644 (file)
@@ -2,11 +2,10 @@
 /*
  */
 
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_probe_helper.h>
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
 #include <drm/drm_atomic_helper.h>
 
 #include "bochs.h"
@@ -65,8 +64,7 @@ static const struct file_operations bochs_fops = {
 };
 
 static struct drm_driver bochs_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
-                                 DRIVER_PRIME,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &bochs_fops,
        .name                   = "bochs-drm",
        .desc                   = "bochs dispi vga interface (qemu stdvga)",
@@ -74,7 +72,6 @@ static struct drm_driver bochs_driver = {
        .major                  = 1,
        .minor                  = 0,
        DRM_GEM_VRAM_DRIVER,
-       DRM_GEM_VRAM_DRIVER_PRIME,
 };
 
 /* ---------------------------------------------------------------------- */
@@ -83,16 +80,14 @@ static struct drm_driver bochs_driver = {
 #ifdef CONFIG_PM_SLEEP
 static int bochs_pm_suspend(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
 
        return drm_mode_config_helper_suspend(drm_dev);
 }
 
 static int bochs_pm_resume(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
 
        return drm_mode_config_helper_resume(drm_dev);
 }
index ebfea87..e567bdf 100644 (file)
@@ -2,6 +2,10 @@
 /*
  */
 
+#include <linux/pci.h>
+
+#include <drm/drm_fourcc.h>
+
 #include "bochs.h"
 
 /* ---------------------------------------------------------------------- */
index 359030d..02a9c1e 100644 (file)
@@ -2,12 +2,14 @@
 /*
  */
 
-#include "bochs.h"
+#include <linux/moduleparam.h>
+
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "bochs.h"
 
 static int defx = 1024;
 static int defy = 768;
index e4e22bb..1cc9f50 100644 (file)
@@ -21,7 +21,7 @@ config DRM_ANALOGIX_ANX78XX
        select DRM_KMS_HELPER
        select REGMAP_I2C
        ---help---
-         ANX78XX is an ultra-low Full-HD SlimPort transmitter
+         ANX78XX is an ultra-low power Full-HD SlimPort transmitter
          designed for portable devices. The ANX78XX transforms
          the HDMI output of an application processor to MyDP
          or DisplayPort.
index f6d2681..98bccac 100644 (file)
@@ -874,9 +874,6 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge)
                                 &adv7511_connector_helper_funcs);
        drm_connector_attach_encoder(&adv->connector, bridge->encoder);
 
-       if (adv->type == ADV7533)
-               ret = adv7533_attach_dsi(adv);
-
        if (adv->i2c_main->irq)
                regmap_write(adv->regmap, ADV7511_REG_INT_ENABLE(0),
                             ADV7511_INT0_HPD);
@@ -1222,8 +1219,17 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
        drm_bridge_add(&adv7511->bridge);
 
        adv7511_audio_init(dev, adv7511);
+
+       if (adv7511->type == ADV7533) {
+               ret = adv7533_attach_dsi(adv7511);
+               if (ret)
+                       goto err_remove_bridge;
+       }
+
        return 0;
 
+err_remove_bridge:
+       drm_bridge_remove(&adv7511->bridge);
 err_unregister_cec:
        i2c_unregister_device(adv7511->i2c_cec);
        if (adv7511->cec_clk)
index 3f7f488..f2f7f69 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/bridge/analogix_dp.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
@@ -101,63 +102,7 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
        return 0;
 }
 
-int analogix_dp_psr_enabled(struct analogix_dp_device *dp)
-{
-
-       return dp->psr_enable;
-}
-EXPORT_SYMBOL_GPL(analogix_dp_psr_enabled);
-
-int analogix_dp_enable_psr(struct analogix_dp_device *dp)
-{
-       struct dp_sdp psr_vsc;
-
-       if (!dp->psr_enable)
-               return 0;
-
-       /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
-       memset(&psr_vsc, 0, sizeof(psr_vsc));
-       psr_vsc.sdp_header.HB0 = 0;
-       psr_vsc.sdp_header.HB1 = 0x7;
-       psr_vsc.sdp_header.HB2 = 0x2;
-       psr_vsc.sdp_header.HB3 = 0x8;
-
-       psr_vsc.db[0] = 0;
-       psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
-
-       return analogix_dp_send_psr_spd(dp, &psr_vsc, true);
-}
-EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
-
-int analogix_dp_disable_psr(struct analogix_dp_device *dp)
-{
-       struct dp_sdp psr_vsc;
-       int ret;
-
-       if (!dp->psr_enable)
-               return 0;
-
-       /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
-       memset(&psr_vsc, 0, sizeof(psr_vsc));
-       psr_vsc.sdp_header.HB0 = 0;
-       psr_vsc.sdp_header.HB1 = 0x7;
-       psr_vsc.sdp_header.HB2 = 0x2;
-       psr_vsc.sdp_header.HB3 = 0x8;
-
-       psr_vsc.db[0] = 0;
-       psr_vsc.db[1] = 0;
-
-       ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
-       if (ret != 1) {
-               dev_err(dp->dev, "Failed to set DP Power0 %d\n", ret);
-               return ret;
-       }
-
-       return analogix_dp_send_psr_spd(dp, &psr_vsc, false);
-}
-EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
-
-static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
 {
        unsigned char psr_version;
        int ret;
@@ -165,14 +110,11 @@ static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
        ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_SUPPORT, &psr_version);
        if (ret != 1) {
                dev_err(dp->dev, "failed to get PSR version, disable it\n");
-               return ret;
+               return false;
        }
 
        dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
-
-       dp->psr_enable = (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
-
-       return 0;
+       return psr_version & DP_PSR_IS_SUPPORTED;
 }
 
 static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
@@ -195,7 +137,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
        }
 
        /* Main-Link transmitter remains active during PSR active states */
-       psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+       psr_en = DP_PSR_CRC_VERIFICATION;
        ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en);
        if (ret != 1) {
                dev_err(dp->dev, "failed to set panel psr\n");
@@ -203,8 +145,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
        }
 
        /* Enable psr function */
-       psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
-                DP_PSR_CRC_VERIFICATION;
+       psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION;
        ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en);
        if (ret != 1) {
                dev_err(dp->dev, "failed to set panel psr\n");
@@ -213,10 +154,11 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
 
        analogix_dp_enable_psr_crc(dp);
 
+       dp->psr_supported = true;
+
        return 0;
 end:
        dev_err(dp->dev, "enable psr fail, force to disable psr\n");
-       dp->psr_enable = false;
 
        return ret;
 }
@@ -1031,24 +973,90 @@ static int analogix_dp_commit(struct analogix_dp_device *dp)
                }
        }
 
-       ret = analogix_dp_detect_sink_psr(dp);
+       /* Check whether panel supports fast training */
+       ret = analogix_dp_fast_link_train_detection(dp);
        if (ret)
                return ret;
 
-       if (dp->psr_enable) {
+       if (analogix_dp_detect_sink_psr(dp)) {
                ret = analogix_dp_enable_sink_psr(dp);
                if (ret)
                        return ret;
        }
 
-       /* Check whether panel supports fast training */
-       ret =  analogix_dp_fast_link_train_detection(dp);
-       if (ret)
-               dp->psr_enable = false;
+       return ret;
+}
+
+static int analogix_dp_enable_psr(struct analogix_dp_device *dp)
+{
+       struct dp_sdp psr_vsc;
+       int ret;
+       u8 sink;
+
+       ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink);
+       if (ret != 1)
+               DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret);
+       else if (sink == DP_PSR_SINK_ACTIVE_RFB)
+               return 0;
+
+       /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+       memset(&psr_vsc, 0, sizeof(psr_vsc));
+       psr_vsc.sdp_header.HB0 = 0;
+       psr_vsc.sdp_header.HB1 = 0x7;
+       psr_vsc.sdp_header.HB2 = 0x2;
+       psr_vsc.sdp_header.HB3 = 0x8;
+       psr_vsc.db[0] = 0;
+       psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+       ret = analogix_dp_send_psr_spd(dp, &psr_vsc, true);
+       if (!ret)
+               analogix_dp_set_analog_power_down(dp, POWER_ALL, true);
 
        return ret;
 }
 
+static int analogix_dp_disable_psr(struct analogix_dp_device *dp)
+{
+       struct dp_sdp psr_vsc;
+       int ret;
+       u8 sink;
+
+       analogix_dp_set_analog_power_down(dp, POWER_ALL, false);
+
+       ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
+       if (ret != 1) {
+               DRM_DEV_ERROR(dp->dev, "Failed to set DP Power0 %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink);
+       if (ret != 1) {
+               DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret);
+               return ret;
+       } else if (sink == DP_PSR_SINK_INACTIVE) {
+               DRM_DEV_ERROR(dp->dev, "sink inactive, skip disable psr");
+               return 0;
+       }
+
+       ret = analogix_dp_train_link(dp);
+       if (ret) {
+               DRM_DEV_ERROR(dp->dev, "Failed to train the link %d\n", ret);
+               return ret;
+       }
+
+       /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+       memset(&psr_vsc, 0, sizeof(psr_vsc));
+       psr_vsc.sdp_header.HB0 = 0;
+       psr_vsc.sdp_header.HB1 = 0x7;
+       psr_vsc.sdp_header.HB2 = 0x2;
+       psr_vsc.sdp_header.HB3 = 0x8;
+
+       psr_vsc.db[0] = 0;
+       psr_vsc.db[1] = 0;
+
+       return analogix_dp_send_psr_spd(dp, &psr_vsc, true);
+}
+
 /*
  * This function is a bit of a catch-all for panel preparation, hopefully
  * simplifying the logic of functions that need to prepare/unprepare the panel
@@ -1139,9 +1147,37 @@ analogix_dp_best_encoder(struct drm_connector *connector)
        return dp->encoder;
 }
 
+
+static int analogix_dp_atomic_check(struct drm_connector *connector,
+                                   struct drm_atomic_state *state)
+{
+       struct analogix_dp_device *dp = to_dp(connector);
+       struct drm_connector_state *conn_state;
+       struct drm_crtc_state *crtc_state;
+
+       conn_state = drm_atomic_get_new_connector_state(state, connector);
+       if (WARN_ON(!conn_state))
+               return -ENODEV;
+
+       conn_state->self_refresh_aware = true;
+
+       if (!conn_state->crtc)
+               return 0;
+
+       crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+       if (!crtc_state)
+               return 0;
+
+       if (crtc_state->self_refresh_active && !dp->psr_supported)
+               return -EINVAL;
+
+       return 0;
+}
+
 static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = {
        .get_modes = analogix_dp_get_modes,
        .best_encoder = analogix_dp_best_encoder,
+       .atomic_check = analogix_dp_atomic_check,
 };
 
 static enum drm_connector_status
@@ -1233,11 +1269,42 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
        return 0;
 }
 
-static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge)
+static
+struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
+                                         struct drm_atomic_state *state)
+{
+       struct drm_encoder *encoder = dp->encoder;
+       struct drm_connector *connector;
+       struct drm_connector_state *conn_state;
+
+       connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+       if (!connector)
+               return NULL;
+
+       conn_state = drm_atomic_get_new_connector_state(state, connector);
+       if (!conn_state)
+               return NULL;
+
+       return conn_state->crtc;
+}
+
+static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+                                                struct drm_atomic_state *state)
 {
        struct analogix_dp_device *dp = bridge->driver_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state;
        int ret;
 
+       crtc = analogix_dp_get_new_crtc(dp, state);
+       if (!crtc)
+               return;
+
+       old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+       /* Don't touch the panel if we're coming back from PSR */
+       if (old_crtc_state && old_crtc_state->self_refresh_active)
+               return;
+
        ret = analogix_dp_prepare_panel(dp, true, true);
        if (ret)
                DRM_ERROR("failed to setup the panel ret = %d\n", ret);
@@ -1298,10 +1365,27 @@ out_dp_clk_pre:
        return ret;
 }
 
-static void analogix_dp_bridge_enable(struct drm_bridge *bridge)
+static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
+                                            struct drm_atomic_state *state)
 {
        struct analogix_dp_device *dp = bridge->driver_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state;
        int timeout_loop = 0;
+       int ret;
+
+       crtc = analogix_dp_get_new_crtc(dp, state);
+       if (!crtc)
+               return;
+
+       old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+       /* Not a full enable, just disable PSR and continue */
+       if (old_crtc_state && old_crtc_state->self_refresh_active) {
+               ret = analogix_dp_disable_psr(dp);
+               if (ret)
+                       DRM_ERROR("Failed to disable psr %d\n", ret);
+               return;
+       }
 
        if (dp->dpms_mode == DRM_MODE_DPMS_ON)
                return;
@@ -1350,11 +1434,56 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
        if (ret)
                DRM_ERROR("failed to setup the panel ret = %d\n", ret);
 
-       dp->psr_enable = false;
        dp->fast_train_enable = false;
+       dp->psr_supported = false;
        dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }
 
+static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
+                                             struct drm_atomic_state *state)
+{
+       struct analogix_dp_device *dp = bridge->driver_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *new_crtc_state = NULL;
+
+       crtc = analogix_dp_get_new_crtc(dp, state);
+       if (!crtc)
+               goto out;
+
+       new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+       if (!new_crtc_state)
+               goto out;
+
+       /* Don't do a full disable on PSR transitions */
+       if (new_crtc_state->self_refresh_active)
+               return;
+
+out:
+       analogix_dp_bridge_disable(bridge);
+}
+
+static
+void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
+                                           struct drm_atomic_state *state)
+{
+       struct analogix_dp_device *dp = bridge->driver_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *new_crtc_state;
+       int ret;
+
+       crtc = analogix_dp_get_new_crtc(dp, state);
+       if (!crtc)
+               return;
+
+       new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+       if (!new_crtc_state || !new_crtc_state->self_refresh_active)
+               return;
+
+       ret = analogix_dp_enable_psr(dp);
+       if (ret)
+               DRM_ERROR("Failed to enable psr (%d)\n", ret);
+}
+
 static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
                                const struct drm_display_mode *orig_mode,
                                const struct drm_display_mode *mode)
@@ -1432,16 +1561,11 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
                video->interlaced = true;
 }
 
-static void analogix_dp_bridge_nop(struct drm_bridge *bridge)
-{
-       /* do nothing */
-}
-
 static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
-       .pre_enable = analogix_dp_bridge_pre_enable,
-       .enable = analogix_dp_bridge_enable,
-       .disable = analogix_dp_bridge_disable,
-       .post_disable = analogix_dp_bridge_nop,
+       .atomic_pre_enable = analogix_dp_bridge_atomic_pre_enable,
+       .atomic_enable = analogix_dp_bridge_atomic_enable,
+       .atomic_disable = analogix_dp_bridge_atomic_disable,
+       .atomic_post_disable = analogix_dp_bridge_atomic_post_disable,
        .mode_set = analogix_dp_bridge_mode_set,
        .attach = analogix_dp_bridge_attach,
 };
index da05825..c051502 100644 (file)
@@ -171,8 +171,8 @@ struct analogix_dp_device {
        int                     dpms_mode;
        struct gpio_desc        *hpd_gpiod;
        bool                    force_hpd;
-       bool                    psr_enable;
        bool                    fast_train_enable;
+       bool                    psr_supported;
 
        struct mutex            panel_lock;
        bool                    panel_is_modeset;
index d32885b..8ef6539 100644 (file)
@@ -111,8 +111,10 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
 
        drm_connector_helper_add(&vga->connector,
                                 &dumb_vga_con_helper_funcs);
-       ret = drm_connector_init(bridge->dev, &vga->connector,
-                                &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
+       ret = drm_connector_init_with_ddc(bridge->dev, &vga->connector,
+                                         &dumb_vga_con_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         vga->ddc);
        if (ret) {
                DRM_ERROR("Failed to initialize connector\n");
                return ret;
index 79311f8..6e81e5d 100644 (file)
@@ -19,7 +19,6 @@
  *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
  */
 
-#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/of.h>
index 98bc650..d4a1cc5 100644 (file)
@@ -6,13 +6,10 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
-
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
index 2d88146..93c68e2 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
index dd7aa46..38f75ac 100644 (file)
 
 #define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS 500
 
+#define SII902X_AUDIO_PORT_INDEX               3
+
 struct sii902x {
        struct i2c_client *i2c;
        struct regmap *regmap;
@@ -568,13 +570,14 @@ static int sii902x_audio_hw_params(struct device *dev, void *data,
                return ret;
        }
 
-       mclk_rate = clk_get_rate(sii902x->audio.mclk);
-
-       ret = sii902x_select_mclk_div(&i2s_config_reg, params->sample_rate,
-                                     mclk_rate);
-       if (mclk_rate != ret * params->sample_rate)
-               dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n",
-                       mclk_rate, ret, params->sample_rate);
+       if (sii902x->audio.mclk) {
+               mclk_rate = clk_get_rate(sii902x->audio.mclk);
+               ret = sii902x_select_mclk_div(&i2s_config_reg,
+                                             params->sample_rate, mclk_rate);
+               if (mclk_rate != ret * params->sample_rate)
+                       dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n",
+                               mclk_rate, ret, params->sample_rate);
+       }
 
        mutex_lock(&sii902x->mutex);
 
@@ -662,7 +665,8 @@ static void sii902x_audio_shutdown(struct device *dev, void *data)
        clk_disable_unprepare(sii902x->audio.mclk);
 }
 
-int sii902x_audio_digital_mute(struct device *dev, void *data, bool enable)
+static int sii902x_audio_digital_mute(struct device *dev,
+                                     void *data, bool enable)
 {
        struct sii902x *sii902x = dev_get_drvdata(dev);
 
@@ -690,11 +694,32 @@ static int sii902x_audio_get_eld(struct device *dev, void *data,
        return 0;
 }
 
+static int sii902x_audio_get_dai_id(struct snd_soc_component *component,
+                                   struct device_node *endpoint)
+{
+       struct of_endpoint of_ep;
+       int ret;
+
+       ret = of_graph_parse_endpoint(endpoint, &of_ep);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * HDMI sound should be located at reg = <3>
+        * Return expected DAI index 0.
+        */
+       if (of_ep.port == SII902X_AUDIO_PORT_INDEX)
+               return 0;
+
+       return -EINVAL;
+}
+
 static const struct hdmi_codec_ops sii902x_audio_codec_ops = {
        .hw_params = sii902x_audio_hw_params,
        .audio_shutdown = sii902x_audio_shutdown,
        .digital_mute = sii902x_audio_digital_mute,
        .get_eld = sii902x_audio_get_eld,
+       .get_dai_id = sii902x_audio_get_dai_id,
 };
 
 static int sii902x_audio_codec_init(struct sii902x *sii902x,
@@ -750,10 +775,11 @@ static int sii902x_audio_codec_init(struct sii902x *sii902x,
                sii902x->audio.i2s_fifo_sequence[i] |= audio_fifo_id[i] |
                        i2s_lane_id[lanes[i]] | SII902X_TPI_I2S_FIFO_ENABLE;
 
+       sii902x->audio.mclk = devm_clk_get_optional(dev, "mclk");
        if (IS_ERR(sii902x->audio.mclk)) {
                dev_err(dev, "%s: No clock (audio mclk) found: %ld\n",
                        __func__, PTR_ERR(sii902x->audio.mclk));
-               return 0;
+               return PTR_ERR(sii902x->audio.mclk);
        }
 
        sii902x->audio.pdev = platform_device_register_data(
index c649094..83b94b6 100644 (file)
@@ -508,8 +508,14 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
        /* nshift factor = 0 */
        hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 
-       hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
-                   HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+       /* Use automatic CTS generation mode when CTS is not set */
+       if (cts)
+               hdmi_writeb(hdmi, ((cts >> 16) &
+                                  HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+                                 HDMI_AUD_CTS3_CTS_MANUAL,
+                           HDMI_AUD_CTS3);
+       else
+               hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3);
        hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
        hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 
@@ -579,24 +585,33 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 {
        unsigned long ftdms = pixel_clk;
        unsigned int n, cts;
+       u8 config3;
        u64 tmp;
 
        n = hdmi_compute_n(sample_rate, pixel_clk);
 
-       /*
-        * Compute the CTS value from the N value.  Note that CTS and N
-        * can be up to 20 bits in total, so we need 64-bit math.  Also
-        * note that our TDMS clock is not fully accurate; it is accurate
-        * to kHz.  This can introduce an unnecessary remainder in the
-        * calculation below, so we don't try to warn about that.
-        */
-       tmp = (u64)ftdms * n;
-       do_div(tmp, 128 * sample_rate);
-       cts = tmp;
+       config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
 
-       dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
-               __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
-               n, cts);
+       /* Only compute CTS when using internal AHB audio */
+       if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
+               /*
+                * Compute the CTS value from the N value.  Note that CTS and N
+                * can be up to 20 bits in total, so we need 64-bit math.  Also
+                * note that our TDMS clock is not fully accurate; it is
+                * accurate to kHz.  This can introduce an unnecessary remainder
+                * in the calculation below, so we don't try to warn about that.
+                */
+               tmp = (u64)ftdms * n;
+               do_div(tmp, 128 * sample_rate);
+               cts = tmp;
+
+               dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
+                       __func__, sample_rate,
+                       ftdms / 1000000, (ftdms / 1000) % 1000,
+                       n, cts);
+       } else {
+               cts = 0;
+       }
 
        spin_lock_irq(&hdmi->audio_lock);
        hdmi->audio_n = n;
@@ -2185,8 +2200,10 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
 
        drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
 
-       drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_HDMIA);
+       drm_connector_init_with_ddc(bridge->dev, connector,
+                                   &dw_hdmi_connector_funcs,
+                                   DRM_MODE_CONNECTOR_HDMIA,
+                                   hdmi->ddc);
 
        drm_connector_attach_encoder(connector, encoder);
 
index 281c58b..675442b 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/debugfs.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -89,6 +90,8 @@
 #define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS    0x1
 #define VID_MODE_TYPE_BURST                    0x2
 #define VID_MODE_TYPE_MASK                     0x3
+#define VID_MODE_VPG_ENABLE            BIT(16)
+#define VID_MODE_VPG_HORIZONTAL                BIT(24)
 
 #define DSI_VID_PKT_SIZE               0x3c
 #define VID_PKT_SIZE(p)                        ((p) & 0x3fff)
@@ -233,6 +236,13 @@ struct dw_mipi_dsi {
        u32 format;
        unsigned long mode_flags;
 
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs;
+
+       bool vpg;
+       bool vpg_horizontal;
+#endif /* CONFIG_DEBUG_FS */
+
        struct dw_mipi_dsi *master; /* dual-dsi master ptr */
        struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */
 
@@ -518,6 +528,13 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
        else
                val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS;
 
+#ifdef CONFIG_DEBUG_FS
+       if (dsi->vpg) {
+               val |= VID_MODE_VPG_ENABLE;
+               val |= dsi->vpg_horizontal ? VID_MODE_VPG_HORIZONTAL : 0;
+       }
+#endif /* CONFIG_DEBUG_FS */
+
        dsi_write(dsi, DSI_VID_MODE_CFG, val);
 }
 
@@ -930,6 +947,33 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
        .attach       = dw_mipi_dsi_bridge_attach,
 };
 
+#ifdef CONFIG_DEBUG_FS
+
+static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi)
+{
+       dsi->debugfs = debugfs_create_dir(dev_name(dsi->dev), NULL);
+       if (IS_ERR(dsi->debugfs)) {
+               dev_err(dsi->dev, "failed to create debugfs root\n");
+               return;
+       }
+
+       debugfs_create_bool("vpg", 0660, dsi->debugfs, &dsi->vpg);
+       debugfs_create_bool("vpg_horizontal", 0660, dsi->debugfs,
+                           &dsi->vpg_horizontal);
+}
+
+static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi)
+{
+       debugfs_remove_recursive(dsi->debugfs);
+}
+
+#else
+
+static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) { }
+static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { }
+
+#endif /* CONFIG_DEBUG_FS */
+
 static struct dw_mipi_dsi *
 __dw_mipi_dsi_probe(struct platform_device *pdev,
                    const struct dw_mipi_dsi_plat_data *plat_data)
@@ -1000,6 +1044,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
                clk_disable_unprepare(dsi->pclk);
        }
 
+       dw_mipi_dsi_debugfs_init(dsi);
        pm_runtime_enable(dev);
 
        dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
@@ -1007,6 +1052,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
        ret = mipi_dsi_host_register(&dsi->dsi_host);
        if (ret) {
                dev_err(dev, "Failed to register MIPI host: %d\n", ret);
+               dw_mipi_dsi_debugfs_remove(dsi);
                return ERR_PTR(ret);
        }
 
@@ -1024,6 +1070,7 @@ static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi)
        mipi_dsi_host_unregister(&dsi->dsi_host);
 
        pm_runtime_disable(dsi->dev);
+       dw_mipi_dsi_debugfs_remove(dsi);
 }
 
 void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave)
index 13ade28..42f03a9 100644 (file)
@@ -15,6 +15,7 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
@@ -47,6 +48,7 @@
 
 /* Video Path */
 #define VPCTRL0                        0x0450
+#define VSDELAY                        GENMASK(31, 20)
 #define OPXLFMT_RGB666                 (0 << 8)
 #define OPXLFMT_RGB888                 (1 << 8)
 #define FRMSYNC_DISABLED               (0 << 4) /* Video Timing Gen Disabled */
 #define MSF_DISABLED                   (0 << 0) /* Magic Square FRC disabled */
 #define MSF_ENABLED                    (1 << 0) /* Magic Square FRC enabled */
 #define HTIM01                 0x0454
+#define HPW                    GENMASK(8, 0)
+#define HBPR                   GENMASK(24, 16)
 #define HTIM02                 0x0458
+#define HDISPR                 GENMASK(10, 0)
+#define HFPR                   GENMASK(24, 16)
 #define VTIM01                 0x045c
+#define VSPR                   GENMASK(7, 0)
+#define VBPR                   GENMASK(23, 16)
 #define VTIM02                 0x0460
+#define VFPR                   GENMASK(23, 16)
+#define VDISPR                 GENMASK(10, 0)
 #define VFUEN0                 0x0464
 #define VFUEN                          BIT(0)   /* Video Frame Timing Upload */
 
 #define DP0_VIDSRC_DSI_RX              (1 << 0)
 #define DP0_VIDSRC_DPI_RX              (2 << 0)
 #define DP0_VIDSRC_COLOR_BAR           (3 << 0)
+#define SYSRSTENB              0x050c
+#define ENBI2C                         (1 << 0)
+#define ENBLCD0                                (1 << 2)
+#define ENBBM                          (1 << 3)
+#define ENBDSIRX                       (1 << 4)
+#define ENBREG                         (1 << 5)
+#define ENBHDCP                                (1 << 8)
 #define GPIOM                  0x0540
 #define GPIOC                  0x0544
 #define GPIOO                  0x0548
 /* Main Channel */
 #define DP0_SECSAMPLE          0x0640
 #define DP0_VIDSYNCDELAY       0x0644
+#define VID_SYNC_DLY           GENMASK(15, 0)
+#define THRESH_DLY             GENMASK(31, 16)
+
 #define DP0_TOTALVAL           0x0648
+#define H_TOTAL                        GENMASK(15, 0)
+#define V_TOTAL                        GENMASK(31, 16)
 #define DP0_STARTVAL           0x064c
+#define H_START                        GENMASK(15, 0)
+#define V_START                        GENMASK(31, 16)
 #define DP0_ACTIVEVAL          0x0650
+#define H_ACT                  GENMASK(15, 0)
+#define V_ACT                  GENMASK(31, 16)
+
 #define DP0_SYNCVAL            0x0654
+#define VS_WIDTH               GENMASK(30, 16)
+#define HS_WIDTH               GENMASK(14, 0)
 #define SYNCVAL_HS_POL_ACTIVE_LOW      (1 << 15)
 #define SYNCVAL_VS_POL_ACTIVE_LOW      (1 << 31)
 #define DP0_MISC               0x0658
 #define TU_SIZE_RECOMMENDED            (63) /* LSCLK cycles per TU */
+#define MAX_TU_SYMBOL          GENMASK(28, 23)
+#define TU_SIZE                        GENMASK(21, 16)
 #define BPC_6                          (0 << 5)
 #define BPC_8                          (1 << 5)
 
 /* AUX channel */
 #define DP0_AUXCFG0            0x0660
+#define DP0_AUXCFG0_BSIZE      GENMASK(11, 8)
+#define DP0_AUXCFG0_ADDR_ONLY  BIT(4)
 #define DP0_AUXCFG1            0x0664
 #define AUX_RX_FILTER_EN               BIT(16)
 
 #define DP0_AUXWDATA(i)                (0x066c + (i) * 4)
 #define DP0_AUXRDATA(i)                (0x067c + (i) * 4)
 #define DP0_AUXSTATUS          0x068c
-#define AUX_STATUS_MASK                        0xf0
-#define AUX_STATUS_SHIFT               4
-#define AUX_TIMEOUT                    BIT(1)
-#define AUX_BUSY                       BIT(0)
+#define AUX_BYTES              GENMASK(15, 8)
+#define AUX_STATUS             GENMASK(7, 4)
+#define AUX_TIMEOUT            BIT(1)
+#define AUX_BUSY               BIT(0)
 #define DP0_AUXI2CADR          0x0698
 
 /* Link Training */
 
 /* Test & Debug */
 #define TSTCTL                 0x0a00
+#define COLOR_R                        GENMASK(31, 24)
+#define COLOR_G                        GENMASK(23, 16)
+#define COLOR_B                        GENMASK(15, 8)
+#define ENI2CFILTER            BIT(4)
+#define COLOR_BAR_MODE         GENMASK(1, 0)
+#define COLOR_BAR_MODE_BARS    2
 #define PLL_DBG                        0x0a04
 
 static bool tc_test_pattern;
@@ -241,137 +280,131 @@ static inline struct tc_data *connector_to_tc(struct drm_connector *c)
        return container_of(c, struct tc_data, connector);
 }
 
-/* Simple macros to avoid repeated error checks */
-#define tc_write(reg, var)                                     \
-       do {                                                    \
-               ret = regmap_write(tc->regmap, reg, var);       \
-               if (ret)                                        \
-                       goto err;                               \
-       } while (0)
-#define tc_read(reg, var)                                      \
-       do {                                                    \
-               ret = regmap_read(tc->regmap, reg, var);        \
-               if (ret)                                        \
-                       goto err;                               \
-       } while (0)
-
-static inline int tc_poll_timeout(struct regmap *map, unsigned int addr,
+static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr,
                                  unsigned int cond_mask,
                                  unsigned int cond_value,
                                  unsigned long sleep_us, u64 timeout_us)
 {
-       ktime_t timeout = ktime_add_us(ktime_get(), timeout_us);
        unsigned int val;
-       int ret;
 
-       for (;;) {
-               ret = regmap_read(map, addr, &val);
-               if (ret)
-                       break;
-               if ((val & cond_mask) == cond_value)
-                       break;
-               if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) {
-                       ret = regmap_read(map, addr, &val);
-                       break;
-               }
-               if (sleep_us)
-                       usleep_range((sleep_us >> 2) + 1, sleep_us);
-       }
-       return ret ?: (((val & cond_mask) == cond_value) ? 0 : -ETIMEDOUT);
+       return regmap_read_poll_timeout(tc->regmap, addr, val,
+                                       (val & cond_mask) == cond_value,
+                                       sleep_us, timeout_us);
 }
 
-static int tc_aux_wait_busy(struct tc_data *tc, unsigned int timeout_ms)
+static int tc_aux_wait_busy(struct tc_data *tc)
 {
-       return tc_poll_timeout(tc->regmap, DP0_AUXSTATUS, AUX_BUSY, 0,
-                              1000, 1000 * timeout_ms);
+       return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 1000, 100000);
 }
 
-static int tc_aux_get_status(struct tc_data *tc, u8 *reply)
+static int tc_aux_write_data(struct tc_data *tc, const void *data,
+                            size_t size)
 {
-       int ret;
-       u32 value;
+       u32 auxwdata[DP_AUX_MAX_PAYLOAD_BYTES / sizeof(u32)] = { 0 };
+       int ret, count = ALIGN(size, sizeof(u32));
 
-       ret = regmap_read(tc->regmap, DP0_AUXSTATUS, &value);
-       if (ret < 0)
+       memcpy(auxwdata, data, size);
+
+       ret = regmap_raw_write(tc->regmap, DP0_AUXWDATA(0), auxwdata, count);
+       if (ret)
                return ret;
 
-       if (value & AUX_BUSY) {
-               dev_err(tc->dev, "aux busy!\n");
-               return -EBUSY;
-       }
+       return size;
+}
 
-       if (value & AUX_TIMEOUT) {
-               dev_err(tc->dev, "aux access timeout!\n");
-               return -ETIMEDOUT;
-       }
+static int tc_aux_read_data(struct tc_data *tc, void *data, size_t size)
+{
+       u32 auxrdata[DP_AUX_MAX_PAYLOAD_BYTES / sizeof(u32)];
+       int ret, count = ALIGN(size, sizeof(u32));
 
-       *reply = (value & AUX_STATUS_MASK) >> AUX_STATUS_SHIFT;
-       return 0;
+       ret = regmap_raw_read(tc->regmap, DP0_AUXRDATA(0), auxrdata, count);
+       if (ret)
+               return ret;
+
+       memcpy(data, auxrdata, size);
+
+       return size;
+}
+
+static u32 tc_auxcfg0(struct drm_dp_aux_msg *msg, size_t size)
+{
+       u32 auxcfg0 = msg->request;
+
+       if (size)
+               auxcfg0 |= FIELD_PREP(DP0_AUXCFG0_BSIZE, size - 1);
+       else
+               auxcfg0 |= DP0_AUXCFG0_ADDR_ONLY;
+
+       return auxcfg0;
 }
 
 static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
                               struct drm_dp_aux_msg *msg)
 {
        struct tc_data *tc = aux_to_tc(aux);
-       size_t size = min_t(size_t, 8, msg->size);
+       size_t size = min_t(size_t, DP_AUX_MAX_PAYLOAD_BYTES - 1, msg->size);
        u8 request = msg->request & ~DP_AUX_I2C_MOT;
-       u8 *buf = msg->buffer;
-       u32 tmp = 0;
-       int i = 0;
+       u32 auxstatus;
        int ret;
 
-       if (size == 0)
-               return 0;
-
-       ret = tc_aux_wait_busy(tc, 100);
+       ret = tc_aux_wait_busy(tc);
        if (ret)
-               goto err;
+               return ret;
 
-       if (request == DP_AUX_I2C_WRITE || request == DP_AUX_NATIVE_WRITE) {
-               /* Store data */
-               while (i < size) {
-                       if (request == DP_AUX_NATIVE_WRITE)
-                               tmp = tmp | (buf[i] << (8 * (i & 0x3)));
-                       else
-                               tmp = (tmp << 8) | buf[i];
-                       i++;
-                       if (((i % 4) == 0) || (i == size)) {
-                               tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp);
-                               tmp = 0;
-                       }
+       switch (request) {
+       case DP_AUX_NATIVE_READ:
+       case DP_AUX_I2C_READ:
+               break;
+       case DP_AUX_NATIVE_WRITE:
+       case DP_AUX_I2C_WRITE:
+               if (size) {
+                       ret = tc_aux_write_data(tc, msg->buffer, size);
+                       if (ret < 0)
+                               return ret;
                }
-       } else if (request != DP_AUX_I2C_READ &&
-                  request != DP_AUX_NATIVE_READ) {
+               break;
+       default:
                return -EINVAL;
        }
 
        /* Store address */
-       tc_write(DP0_AUXADDR, msg->address);
+       ret = regmap_write(tc->regmap, DP0_AUXADDR, msg->address);
+       if (ret)
+               return ret;
        /* Start transfer */
-       tc_write(DP0_AUXCFG0, ((size - 1) << 8) | request);
+       ret = regmap_write(tc->regmap, DP0_AUXCFG0, tc_auxcfg0(msg, size));
+       if (ret)
+               return ret;
 
-       ret = tc_aux_wait_busy(tc, 100);
+       ret = tc_aux_wait_busy(tc);
        if (ret)
-               goto err;
+               return ret;
 
-       ret = tc_aux_get_status(tc, &msg->reply);
+       ret = regmap_read(tc->regmap, DP0_AUXSTATUS, &auxstatus);
        if (ret)
-               goto err;
+               return ret;
 
-       if (request == DP_AUX_I2C_READ || request == DP_AUX_NATIVE_READ) {
-               /* Read data */
-               while (i < size) {
-                       if ((i % 4) == 0)
-                               tc_read(DP0_AUXRDATA(i >> 2), &tmp);
-                       buf[i] = tmp & 0xff;
-                       tmp = tmp >> 8;
-                       i++;
-               }
+       if (auxstatus & AUX_TIMEOUT)
+               return -ETIMEDOUT;
+       /*
+        * For some reason address-only DP_AUX_I2C_WRITE (MOT), still
+        * reports 1 byte transferred in its status. To deal we that
+        * we ignore aux_bytes field if we know that this was an
+        * address-only transfer
+        */
+       if (size)
+               size = FIELD_GET(AUX_BYTES, auxstatus);
+       msg->reply = FIELD_GET(AUX_STATUS, auxstatus);
+
+       switch (request) {
+       case DP_AUX_NATIVE_READ:
+       case DP_AUX_I2C_READ:
+               if (size)
+                       return tc_aux_read_data(tc, msg->buffer, size);
+               break;
        }
 
        return size;
-err:
-       return ret;
 }
 
 static const char * const training_pattern1_errors[] = {
@@ -411,10 +444,18 @@ static u32 tc_srcctrl(struct tc_data *tc)
        return reg;
 }
 
-static void tc_wait_pll_lock(struct tc_data *tc)
+static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl)
 {
+       int ret;
+
+       ret = regmap_write(tc->regmap, pllctrl, PLLUPDATE | PLLEN);
+       if (ret)
+               return ret;
+
        /* Wait for PLL to lock: up to 2.09 ms, depending on refclk */
        usleep_range(3000, 6000);
+
+       return 0;
 }
 
 static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
@@ -428,6 +469,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
        int ext_div[] = {1, 2, 3, 5, 7};
        int best_pixelclock = 0;
        int vco_hi = 0;
+       u32 pxl_pllparam;
 
        dev_dbg(tc->dev, "PLL: requested %d pixelclock, ref %d\n", pixelclock,
                refclk);
@@ -497,24 +539,23 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
                best_mul = 0;
 
        /* Power up PLL and switch to bypass */
-       tc_write(PXL_PLLCTRL, PLLBYP | PLLEN);
-
-       tc_write(PXL_PLLPARAM,
-                (vco_hi << 24) |               /* For PLL VCO >= 300 MHz = 1 */
-                (ext_div[best_pre] << 20) |    /* External Pre-divider */
-                (ext_div[best_post] << 16) |   /* External Post-divider */
-                IN_SEL_REFCLK |                /* Use RefClk as PLL input */
-                (best_div << 8) |              /* Divider for PLL RefClk */
-                (best_mul << 0));              /* Multiplier for PLL */
+       ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN);
+       if (ret)
+               return ret;
 
-       /* Force PLL parameter update and disable bypass */
-       tc_write(PXL_PLLCTRL, PLLUPDATE | PLLEN);
+       pxl_pllparam  = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */
+       pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */
+       pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */
+       pxl_pllparam |= IN_SEL_REFCLK; /* Use RefClk as PLL input */
+       pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */
+       pxl_pllparam |= best_mul; /* Multiplier for PLL */
 
-       tc_wait_pll_lock(tc);
+       ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam);
+       if (ret)
+               return ret;
 
-       return 0;
-err:
-       return ret;
+       /* Force PLL parameter update and disable bypass */
+       return tc_pllupdate(tc, PXL_PLLCTRL);
 }
 
 static int tc_pxl_pll_dis(struct tc_data *tc)
@@ -525,7 +566,6 @@ static int tc_pxl_pll_dis(struct tc_data *tc)
 
 static int tc_stream_clock_calc(struct tc_data *tc)
 {
-       int ret;
        /*
         * If the Stream clock and Link Symbol clock are
         * asynchronous with each other, the value of M changes over
@@ -541,56 +581,63 @@ static int tc_stream_clock_calc(struct tc_data *tc)
         * M/N = f_STRMCLK / f_LSCLK
         *
         */
-       tc_write(DP0_VIDMNGEN1, 32768);
-
-       return 0;
-err:
-       return ret;
+       return regmap_write(tc->regmap, DP0_VIDMNGEN1, 32768);
 }
 
-static int tc_aux_link_setup(struct tc_data *tc)
+static int tc_set_syspllparam(struct tc_data *tc)
 {
        unsigned long rate;
-       u32 value;
-       int ret;
+       u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
 
        rate = clk_get_rate(tc->refclk);
        switch (rate) {
        case 38400000:
-               value = REF_FREQ_38M4;
+               pllparam |= REF_FREQ_38M4;
                break;
        case 26000000:
-               value = REF_FREQ_26M;
+               pllparam |= REF_FREQ_26M;
                break;
        case 19200000:
-               value = REF_FREQ_19M2;
+               pllparam |= REF_FREQ_19M2;
                break;
        case 13000000:
-               value = REF_FREQ_13M;
+               pllparam |= REF_FREQ_13M;
                break;
        default:
                dev_err(tc->dev, "Invalid refclk rate: %lu Hz\n", rate);
                return -EINVAL;
        }
 
-       /* Setup DP-PHY / PLL */
-       value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
-       tc_write(SYS_PLLPARAM, value);
+       return regmap_write(tc->regmap, SYS_PLLPARAM, pllparam);
+}
+
+static int tc_aux_link_setup(struct tc_data *tc)
+{
+       int ret;
+       u32 dp0_auxcfg1;
 
-       tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | PHY_A0_EN);
+       /* Setup DP-PHY / PLL */
+       ret = tc_set_syspllparam(tc);
+       if (ret)
+               goto err;
 
+       ret = regmap_write(tc->regmap, DP_PHY_CTRL,
+                          BGREN | PWR_SW_EN | PHY_A0_EN);
+       if (ret)
+               goto err;
        /*
         * Initially PLLs are in bypass. Force PLL parameter update,
         * disable PLL bypass, enable PLL
         */
-       tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN);
-       tc_wait_pll_lock(tc);
+       ret = tc_pllupdate(tc, DP0_PLLCTRL);
+       if (ret)
+               goto err;
 
-       tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN);
-       tc_wait_pll_lock(tc);
+       ret = tc_pllupdate(tc, DP1_PLLCTRL);
+       if (ret)
+               goto err;
 
-       ret = tc_poll_timeout(tc->regmap, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1,
-                             1000);
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
        if (ret == -ETIMEDOUT) {
                dev_err(tc->dev, "Timeout waiting for PHY to become ready");
                return ret;
@@ -599,9 +646,13 @@ static int tc_aux_link_setup(struct tc_data *tc)
        }
 
        /* Setup AUX link */
-       tc_write(DP0_AUXCFG1, AUX_RX_FILTER_EN |
-                (0x06 << 8) |  /* Aux Bit Period Calculator Threshold */
-                (0x3f << 0));  /* Aux Response Timeout Timer */
+       dp0_auxcfg1  = AUX_RX_FILTER_EN;
+       dp0_auxcfg1 |= 0x06 << 8; /* Aux Bit Period Calculator Threshold */
+       dp0_auxcfg1 |= 0x3f << 0; /* Aux Response Timeout Timer */
+
+       ret = regmap_write(tc->regmap, DP0_AUXCFG1, dp0_auxcfg1);
+       if (ret)
+               goto err;
 
        return 0;
 err:
@@ -612,8 +663,7 @@ err:
 static int tc_get_display_props(struct tc_data *tc)
 {
        int ret;
-       /* temp buffer */
-       u8 tmp[8];
+       u8 reg;
 
        /* Read DP Rx Link Capability */
        ret = drm_dp_link_probe(&tc->aux, &tc->link.base);
@@ -629,21 +679,21 @@ static int tc_get_display_props(struct tc_data *tc)
                tc->link.base.num_lanes = 2;
        }
 
-       ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
+       ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, &reg);
        if (ret < 0)
                goto err_dpcd_read;
-       tc->link.spread = tmp[0] & DP_MAX_DOWNSPREAD_0_5;
+       tc->link.spread = reg & DP_MAX_DOWNSPREAD_0_5;
 
-       ret = drm_dp_dpcd_readb(&tc->aux, DP_MAIN_LINK_CHANNEL_CODING, tmp);
+       ret = drm_dp_dpcd_readb(&tc->aux, DP_MAIN_LINK_CHANNEL_CODING, &reg);
        if (ret < 0)
                goto err_dpcd_read;
 
        tc->link.scrambler_dis = false;
        /* read assr */
-       ret = drm_dp_dpcd_readb(&tc->aux, DP_EDP_CONFIGURATION_SET, tmp);
+       ret = drm_dp_dpcd_readb(&tc->aux, DP_EDP_CONFIGURATION_SET, &reg);
        if (ret < 0)
                goto err_dpcd_read;
-       tc->link.assr = tmp[0] & DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;
+       tc->link.assr = reg & DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;
 
        dev_dbg(tc->dev, "DPCD rev: %d.%d, rate: %s, lanes: %d, framing: %s\n",
                tc->link.base.revision >> 4, tc->link.base.revision & 0x0f,
@@ -677,6 +727,7 @@ static int tc_set_video_mode(struct tc_data *tc,
        int upper_margin = mode->vtotal - mode->vsync_end;
        int lower_margin = mode->vsync_start - mode->vdisplay;
        int vsync_len = mode->vsync_end - mode->vsync_start;
+       u32 dp0_syncval;
 
        /*
         * Recommended maximum number of symbols transferred in a transfer unit:
@@ -701,156 +752,193 @@ static int tc_set_video_mode(struct tc_data *tc,
         * assume we do not need any delay when DPI is a source of
         * sync signals
         */
-       tc_write(VPCTRL0, (0 << 20) /* VSDELAY */ |
-                OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
-       tc_write(HTIM01, (ALIGN(left_margin, 2) << 16) | /* H back porch */
-                        (ALIGN(hsync_len, 2) << 0));    /* Hsync */
-       tc_write(HTIM02, (ALIGN(right_margin, 2) << 16) |  /* H front porch */
-                        (ALIGN(mode->hdisplay, 2) << 0)); /* width */
-       tc_write(VTIM01, (upper_margin << 16) |         /* V back porch */
-                        (vsync_len << 0));             /* Vsync */
-       tc_write(VTIM02, (lower_margin << 16) |         /* V front porch */
-                        (mode->vdisplay << 0));        /* height */
-       tc_write(VFUEN0, VFUEN);                /* update settings */
+       ret = regmap_write(tc->regmap, VPCTRL0,
+                          FIELD_PREP(VSDELAY, 0) |
+                          OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, HTIM01,
+                          FIELD_PREP(HBPR, ALIGN(left_margin, 2)) |
+                          FIELD_PREP(HPW, ALIGN(hsync_len, 2)));
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, HTIM02,
+                          FIELD_PREP(HDISPR, ALIGN(mode->hdisplay, 2)) |
+                          FIELD_PREP(HFPR, ALIGN(right_margin, 2)));
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, VTIM01,
+                          FIELD_PREP(VBPR, upper_margin) |
+                          FIELD_PREP(VSPR, vsync_len));
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, VTIM02,
+                          FIELD_PREP(VFPR, lower_margin) |
+                          FIELD_PREP(VDISPR, mode->vdisplay));
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, VFUEN0, VFUEN); /* update settings */
+       if (ret)
+               return ret;
 
        /* Test pattern settings */
-       tc_write(TSTCTL,
-                (120 << 24) |  /* Red Color component value */
-                (20 << 16) |   /* Green Color component value */
-                (99 << 8) |    /* Blue Color component value */
-                (1 << 4) |     /* Enable I2C Filter */
-                (2 << 0) |     /* Color bar Mode */
-                0);
+       ret = regmap_write(tc->regmap, TSTCTL,
+                          FIELD_PREP(COLOR_R, 120) |
+                          FIELD_PREP(COLOR_G, 20) |
+                          FIELD_PREP(COLOR_B, 99) |
+                          ENI2CFILTER |
+                          FIELD_PREP(COLOR_BAR_MODE, COLOR_BAR_MODE_BARS));
+       if (ret)
+               return ret;
 
        /* DP Main Stream Attributes */
        vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
-       tc_write(DP0_VIDSYNCDELAY,
-                (max_tu_symbol << 16) |        /* thresh_dly */
-                (vid_sync_dly << 0));
+       ret = regmap_write(tc->regmap, DP0_VIDSYNCDELAY,
+                FIELD_PREP(THRESH_DLY, max_tu_symbol) |
+                FIELD_PREP(VID_SYNC_DLY, vid_sync_dly));
+
+       ret = regmap_write(tc->regmap, DP0_TOTALVAL,
+                          FIELD_PREP(H_TOTAL, mode->htotal) |
+                          FIELD_PREP(V_TOTAL, mode->vtotal));
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, DP0_STARTVAL,
+                          FIELD_PREP(H_START, left_margin + hsync_len) |
+                          FIELD_PREP(V_START, upper_margin + vsync_len));
+       if (ret)
+               return ret;
 
-       tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal));
+       ret = regmap_write(tc->regmap, DP0_ACTIVEVAL,
+                          FIELD_PREP(V_ACT, mode->vdisplay) |
+                          FIELD_PREP(H_ACT, mode->hdisplay));
+       if (ret)
+               return ret;
 
-       tc_write(DP0_STARTVAL,
-                ((upper_margin + vsync_len) << 16) |
-                ((left_margin + hsync_len) << 0));
+       dp0_syncval = FIELD_PREP(VS_WIDTH, vsync_len) |
+                     FIELD_PREP(HS_WIDTH, hsync_len);
 
-       tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               dp0_syncval |= SYNCVAL_VS_POL_ACTIVE_LOW;
 
-       tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
-                ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
-                ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               dp0_syncval |= SYNCVAL_HS_POL_ACTIVE_LOW;
 
-       tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
-                DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
+       ret = regmap_write(tc->regmap, DP0_SYNCVAL, dp0_syncval);
+       if (ret)
+               return ret;
 
-       tc_write(DP0_MISC, (max_tu_symbol << 23) | (TU_SIZE_RECOMMENDED << 16) |
+       ret = regmap_write(tc->regmap, DPIPXLFMT,
+                          VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
+                          DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 |
+                          DPI_BPP_RGB888);
+       if (ret)
+               return ret;
+
+       ret = regmap_write(tc->regmap, DP0_MISC,
+                          FIELD_PREP(MAX_TU_SYMBOL, max_tu_symbol) |
+                          FIELD_PREP(TU_SIZE, TU_SIZE_RECOMMENDED) |
                           BPC_8);
+       if (ret)
+               return ret;
 
        return 0;
-err:
-       return ret;
 }
 
 static int tc_wait_link_training(struct tc_data *tc)
 {
-       u32 timeout = 1000;
        u32 value;
        int ret;
 
-       do {
-               udelay(1);
-               tc_read(DP0_LTSTAT, &value);
-       } while ((!(value & LT_LOOPDONE)) && (--timeout));
-
-       if (timeout == 0) {
+       ret = tc_poll_timeout(tc, DP0_LTSTAT, LT_LOOPDONE,
+                             LT_LOOPDONE, 1, 1000);
+       if (ret) {
                dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n");
-               return -ETIMEDOUT;
+               return ret;
        }
 
-       return (value >> 8) & 0x7;
+       ret = regmap_read(tc->regmap, DP0_LTSTAT, &value);
+       if (ret)
+               return ret;
 
-err:
-       return ret;
+       return (value >> 8) & 0x7;
 }
 
 static int tc_main_link_enable(struct tc_data *tc)
 {
        struct drm_dp_aux *aux = &tc->aux;
        struct device *dev = tc->dev;
-       unsigned int rate;
        u32 dp_phy_ctrl;
-       int timeout;
        u32 value;
        int ret;
-       u8 tmp[8];
+       u8 tmp[DP_LINK_STATUS_SIZE];
 
        dev_dbg(tc->dev, "link enable\n");
 
-       tc_read(DP0CTL, &value);
-       if (WARN_ON(value & DP_EN))
-               tc_write(DP0CTL, 0);
+       ret = regmap_read(tc->regmap, DP0CTL, &value);
+       if (ret)
+               return ret;
+
+       if (WARN_ON(value & DP_EN)) {
+               ret = regmap_write(tc->regmap, DP0CTL, 0);
+               if (ret)
+                       return ret;
+       }
 
-       tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
+       ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc));
+       if (ret)
+               return ret;
        /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
-       tc_write(DP1_SRCCTRL,
+       ret = regmap_write(tc->regmap, DP1_SRCCTRL,
                 (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
                 ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
+       if (ret)
+               return ret;
 
-       rate = clk_get_rate(tc->refclk);
-       switch (rate) {
-       case 38400000:
-               value = REF_FREQ_38M4;
-               break;
-       case 26000000:
-               value = REF_FREQ_26M;
-               break;
-       case 19200000:
-               value = REF_FREQ_19M2;
-               break;
-       case 13000000:
-               value = REF_FREQ_13M;
-               break;
-       default:
-               return -EINVAL;
-       }
-       value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
-       tc_write(SYS_PLLPARAM, value);
+       ret = tc_set_syspllparam(tc);
+       if (ret)
+               return ret;
 
        /* Setup Main Link */
        dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
        if (tc->link.base.num_lanes == 2)
                dp_phy_ctrl |= PHY_2LANE;
-       tc_write(DP_PHY_CTRL, dp_phy_ctrl);
+
+       ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
+       if (ret)
+               return ret;
 
        /* PLL setup */
-       tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN);
-       tc_wait_pll_lock(tc);
+       ret = tc_pllupdate(tc, DP0_PLLCTRL);
+       if (ret)
+               return ret;
 
-       tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN);
-       tc_wait_pll_lock(tc);
+       ret = tc_pllupdate(tc, DP1_PLLCTRL);
+       if (ret)
+               return ret;
 
        /* Reset/Enable Main Links */
        dp_phy_ctrl |= DP_PHY_RST | PHY_M1_RST | PHY_M0_RST;
-       tc_write(DP_PHY_CTRL, dp_phy_ctrl);
+       ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
        usleep_range(100, 200);
        dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST);
-       tc_write(DP_PHY_CTRL, dp_phy_ctrl);
-
-       timeout = 1000;
-       do {
-               tc_read(DP_PHY_CTRL, &value);
-               udelay(1);
-       } while ((!(value & PHY_RDY)) && (--timeout));
+       ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
 
-       if (timeout == 0) {
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+       if (ret) {
                dev_err(dev, "timeout waiting for phy become ready");
-               return -ETIMEDOUT;
+               return ret;
        }
 
        /* Set misc: 8 bits per color */
        ret = regmap_update_bits(tc->regmap, DP0_MISC, BPC_8, BPC_8);
        if (ret)
-               goto err;
+               return ret;
 
        /*
         * ASSR mode
@@ -903,53 +991,71 @@ static int tc_main_link_enable(struct tc_data *tc)
        /* Clock-Recovery */
 
        /* Set DPCD 0x102 for Training Pattern 1 */
-       tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE |
-                DP_TRAINING_PATTERN_1);
+       ret = regmap_write(tc->regmap, DP0_SNKLTCTRL,
+                          DP_LINK_SCRAMBLING_DISABLE |
+                          DP_TRAINING_PATTERN_1);
+       if (ret)
+               return ret;
 
-       tc_write(DP0_LTLOOPCTRL,
-                (15 << 28) |   /* Defer Iteration Count */
-                (15 << 24) |   /* Loop Iteration Count */
-                (0xd << 0));   /* Loop Timer Delay */
+       ret = regmap_write(tc->regmap, DP0_LTLOOPCTRL,
+                          (15 << 28) | /* Defer Iteration Count */
+                          (15 << 24) | /* Loop Iteration Count */
+                          (0xd << 0)); /* Loop Timer Delay */
+       if (ret)
+               return ret;
 
-       tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
-                DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP1);
+       ret = regmap_write(tc->regmap, DP0_SRCCTRL,
+                          tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
+                          DP0_SRCCTRL_AUTOCORRECT |
+                          DP0_SRCCTRL_TP1);
+       if (ret)
+               return ret;
 
        /* Enable DP0 to start Link Training */
-       tc_write(DP0CTL,
-                ((tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) |
-                DP_EN);
+       ret = regmap_write(tc->regmap, DP0CTL,
+                          ((tc->link.base.capabilities &
+                            DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) |
+                          DP_EN);
+       if (ret)
+               return ret;
 
        /* wait */
+
        ret = tc_wait_link_training(tc);
        if (ret < 0)
-               goto err;
+               return ret;
 
        if (ret) {
                dev_err(tc->dev, "Link training phase 1 failed: %s\n",
                        training_pattern1_errors[ret]);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
 
        /* Channel Equalization */
 
        /* Set DPCD 0x102 for Training Pattern 2 */
-       tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE |
-                DP_TRAINING_PATTERN_2);
+       ret = regmap_write(tc->regmap, DP0_SNKLTCTRL,
+                          DP_LINK_SCRAMBLING_DISABLE |
+                          DP_TRAINING_PATTERN_2);
+       if (ret)
+               return ret;
 
-       tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
-                DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP2);
+       ret = regmap_write(tc->regmap, DP0_SRCCTRL,
+                          tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
+                          DP0_SRCCTRL_AUTOCORRECT |
+                          DP0_SRCCTRL_TP2);
+       if (ret)
+               return ret;
 
        /* wait */
        ret = tc_wait_link_training(tc);
        if (ret < 0)
-               goto err;
+               return ret;
 
        if (ret) {
                dev_err(tc->dev, "Link training phase 2 failed: %s\n",
                        training_pattern2_errors[ret]);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
 
        /*
@@ -962,7 +1068,10 @@ static int tc_main_link_enable(struct tc_data *tc)
         */
 
        /* Clear Training Pattern, set AutoCorrect Mode = 1 */
-       tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_AUTOCORRECT);
+       ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc) |
+                          DP0_SRCCTRL_AUTOCORRECT);
+       if (ret)
+               return ret;
 
        /* Clear DPCD 0x102 */
        /* Note: Can Not use DP0_SNKLTCTRL (0x06E4) short cut */
@@ -1006,7 +1115,7 @@ static int tc_main_link_enable(struct tc_data *tc)
                dev_err(dev, "0x0205 SINK_STATUS:               0x%02x\n", tmp[3]);
                dev_err(dev, "0x0206 ADJUST_REQUEST_LANE0_1:    0x%02x\n", tmp[4]);
                dev_err(dev, "0x0207 ADJUST_REQUEST_LANE2_3:    0x%02x\n", tmp[5]);
-               goto err;
+               return ret;
        }
 
        return 0;
@@ -1015,7 +1124,6 @@ err_dpcd_read:
        return ret;
 err_dpcd_write:
        dev_err(tc->dev, "Failed to write DPCD: %d\n", ret);
-err:
        return ret;
 }
 
@@ -1025,12 +1133,11 @@ static int tc_main_link_disable(struct tc_data *tc)
 
        dev_dbg(tc->dev, "link disable\n");
 
-       tc_write(DP0_SRCCTRL, 0);
-       tc_write(DP0CTL, 0);
+       ret = regmap_write(tc->regmap, DP0_SRCCTRL, 0);
+       if (ret)
+               return ret;
 
-       return 0;
-err:
-       return ret;
+       return regmap_write(tc->regmap, DP0CTL, 0);
 }
 
 static int tc_stream_enable(struct tc_data *tc)
@@ -1045,7 +1152,7 @@ static int tc_stream_enable(struct tc_data *tc)
                ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk),
                                    1000 * tc->mode.clock);
                if (ret)
-                       goto err;
+                       return ret;
        }
 
        ret = tc_set_video_mode(tc, &tc->mode);
@@ -1060,7 +1167,9 @@ static int tc_stream_enable(struct tc_data *tc)
        value = VID_MN_GEN | DP_EN;
        if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
                value |= EF_EN;
-       tc_write(DP0CTL, value);
+       ret = regmap_write(tc->regmap, DP0CTL, value);
+       if (ret)
+               return ret;
        /*
         * VID_EN assertion should be delayed by at least N * LSCLK
         * cycles from the time VID_MN_GEN is enabled in order to
@@ -1070,36 +1179,35 @@ static int tc_stream_enable(struct tc_data *tc)
         */
        usleep_range(500, 1000);
        value |= VID_EN;
-       tc_write(DP0CTL, value);
+       ret = regmap_write(tc->regmap, DP0CTL, value);
+       if (ret)
+               return ret;
        /* Set input interface */
        value = DP0_AUDSRC_NO_INPUT;
        if (tc_test_pattern)
                value |= DP0_VIDSRC_COLOR_BAR;
        else
                value |= DP0_VIDSRC_DPI_RX;
-       tc_write(SYSCTRL, value);
+       ret = regmap_write(tc->regmap, SYSCTRL, value);
+       if (ret)
+               return ret;
 
        return 0;
-err:
-       return ret;
 }
 
 static int tc_stream_disable(struct tc_data *tc)
 {
        int ret;
-       u32 val;
 
        dev_dbg(tc->dev, "disable video stream\n");
 
-       tc_read(DP0CTL, &val);
-       val &= ~VID_EN;
-       tc_write(DP0CTL, val);
+       ret = regmap_update_bits(tc->regmap, DP0CTL, VID_EN, 0);
+       if (ret)
+               return ret;
 
        tc_pxl_pll_dis(tc);
 
        return 0;
-err:
-       return ret;
 }
 
 static void tc_bridge_pre_enable(struct drm_bridge *bridge)
@@ -1251,7 +1359,9 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne
                        return connector_status_unknown;
        }
 
-       tc_read(GPIOI, &val);
+       ret = regmap_read(tc->regmap, GPIOI, &val);
+       if (ret)
+               return connector_status_unknown;
 
        conn = val & BIT(tc->hpd_pin);
 
@@ -1259,9 +1369,6 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne
                return connector_status_connected;
        else
                return connector_status_disconnected;
-
-err:
-       return connector_status_unknown;
 }
 
 static const struct drm_connector_funcs tc_connector_funcs = {
@@ -1497,6 +1604,22 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        tc->assr = (tc->rev == 0x6601); /* Enable ASSR for eDP panels */
 
+       if (!tc->reset_gpio) {
+               /*
+                * If the reset pin isn't present, do a software reset. It isn't
+                * as thorough as the hardware reset, as we can't reset the I2C
+                * communication block for obvious reasons, but it's getting the
+                * chip into a defined state.
+                */
+               regmap_update_bits(tc->regmap, SYSRSTENB,
+                               ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP,
+                               0);
+               regmap_update_bits(tc->regmap, SYSRSTENB,
+                               ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP,
+                               ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP);
+               usleep_range(5000, 10000);
+       }
+
        if (tc->hpd_pin >= 0) {
                u32 lcnt_reg = tc->hpd_pin == 0 ? INT_GP0_LCNT : INT_GP1_LCNT;
                u32 h_lc = INT_GPIO_H(tc->hpd_pin) | INT_GPIO_LC(tc->hpd_pin);
index b77a52d..0a58095 100644 (file)
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * datasheet: http://www.ti.com/lit/ds/symlink/sn65dsi86.pdf
  */
 
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/iopoll.h>
@@ -90,6 +92,7 @@ struct ti_sn_bridge {
        struct drm_dp_aux               aux;
        struct drm_bridge               bridge;
        struct drm_connector            connector;
+       struct dentry                   *debugfs;
        struct device_node              *host_node;
        struct mipi_dsi_device          *dsi;
        struct clk                      *refclk;
@@ -155,6 +158,42 @@ static const struct dev_pm_ops ti_sn_bridge_pm_ops = {
        SET_RUNTIME_PM_OPS(ti_sn_bridge_suspend, ti_sn_bridge_resume, NULL)
 };
 
+static int status_show(struct seq_file *s, void *data)
+{
+       struct ti_sn_bridge *pdata = s->private;
+       unsigned int reg, val;
+
+       seq_puts(s, "STATUS REGISTERS:\n");
+
+       pm_runtime_get_sync(pdata->dev);
+
+       /* IRQ Status Registers, see Table 31 in datasheet */
+       for (reg = 0xf0; reg <= 0xf8; reg++) {
+               regmap_read(pdata->regmap, reg, &val);
+               seq_printf(s, "[0x%02x] = 0x%08x\n", reg, val);
+       }
+
+       pm_runtime_put(pdata->dev);
+
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(status);
+
+static void ti_sn_debugfs_init(struct ti_sn_bridge *pdata)
+{
+       pdata->debugfs = debugfs_create_dir(dev_name(pdata->dev), NULL);
+
+       debugfs_create_file("status", 0600, pdata->debugfs, pdata,
+                       &status_fops);
+}
+
+static void ti_sn_debugfs_remove(struct ti_sn_bridge *pdata)
+{
+       debugfs_remove_recursive(pdata->debugfs);
+       pdata->debugfs = NULL;
+}
+
 /* Connector funcs */
 static struct ti_sn_bridge *
 connector_to_ti_sn_bridge(struct drm_connector *connector)
@@ -275,8 +314,7 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge)
        /* TODO: setting to 4 lanes always for now */
        dsi->lanes = 4;
        dsi->format = MIPI_DSI_FMT_RGB888;
-       dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
-                         MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+       dsi->mode_flags = MIPI_DSI_MODE_VIDEO;
 
        /* check if continuous dsi clock is required or not */
        pm_runtime_get_sync(pdata->dev);
@@ -731,6 +769,8 @@ static int ti_sn_bridge_probe(struct i2c_client *client,
 
        drm_bridge_add(&pdata->bridge);
 
+       ti_sn_debugfs_init(pdata);
+
        return 0;
 }
 
@@ -741,6 +781,8 @@ static int ti_sn_bridge_remove(struct i2c_client *client)
        if (!pdata)
                return -EINVAL;
 
+       ti_sn_debugfs_remove(pdata);
+
        of_node_put(pdata->host_node);
 
        pm_runtime_disable(pdata->dev);
index dbf35c7..61cc235 100644 (file)
@@ -134,8 +134,10 @@ static int tfp410_attach(struct drm_bridge *bridge)
 
        drm_connector_helper_add(&dvi->connector,
                                 &tfp410_con_helper_funcs);
-       ret = drm_connector_init(bridge->dev, &dvi->connector,
-                                &tfp410_con_funcs, dvi->connector_type);
+       ret = drm_connector_init_with_ddc(bridge->dev, &dvi->connector,
+                                         &tfp410_con_funcs,
+                                         dvi->connector_type,
+                                         dvi->ddc);
        if (ret) {
                dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
                return ret;
index be4ea37..36a69ae 100644 (file)
@@ -513,7 +513,7 @@ static void cirrus_mode_config_init(struct cirrus_device *cirrus)
 DEFINE_DRM_GEM_SHMEM_FOPS(cirrus_fops);
 
 static struct drm_driver cirrus_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_PRIME,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 
        .name            = DRIVER_NAME,
        .desc            = DRIVER_DESC,
index 117b8ee..6e09f27 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_agpsupport.c
  * DRM support for AGP/GART backend
  *
@@ -465,46 +465,3 @@ void drm_legacy_agp_clear(struct drm_device *dev)
        dev->agp->acquired = 0;
        dev->agp->enabled = 0;
 }
-
-/**
- * Binds a collection of pages into AGP memory at the given offset, returning
- * the AGP memory structure containing them.
- *
- * No reference is held on the pages during this time -- it is up to the
- * caller to handle that.
- */
-struct agp_memory *
-drm_agp_bind_pages(struct drm_device *dev,
-                  struct page **pages,
-                  unsigned long num_pages,
-                  uint32_t gtt_offset,
-                  u32 type)
-{
-       struct agp_memory *mem;
-       int ret, i;
-
-       DRM_DEBUG("\n");
-
-       mem = agp_allocate_memory(dev->agp->bridge, num_pages,
-                                     type);
-       if (mem == NULL) {
-               DRM_ERROR("Failed to allocate memory for %ld pages\n",
-                         num_pages);
-               return NULL;
-       }
-
-       for (i = 0; i < num_pages; i++)
-               mem->pages[i] = pages[i];
-       mem->page_count = num_pages;
-
-       mem->is_flushed = true;
-       ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
-       if (ret != 0) {
-               DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
-               agp_free_memory(mem);
-               return NULL;
-       }
-
-       return mem;
-}
-EXPORT_SYMBOL(drm_agp_bind_pages);
index abe38bd..19ae119 100644 (file)
@@ -747,6 +747,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
                        return -EINVAL;
                }
                state->content_protection = val;
+       } else if (property == config->hdcp_content_type_property) {
+               state->hdcp_content_type = val;
        } else if (property == connector->colorspace_property) {
                state->colorspace = val;
        } else if (property == config->writeback_fb_id_property) {
@@ -831,6 +833,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
                        state->hdr_output_metadata->base.id : 0;
        } else if (property == config->content_protection_property) {
                *val = state->content_protection;
+       } else if (property == config->hdcp_content_type_property) {
+               *val = state->hdcp_content_type;
        } else if (property == config->writeback_fb_id_property) {
                /* Writeback framebuffer is one-shot, write and forget */
                *val = 0;
index e1dafb0..d9a2e36 100644 (file)
@@ -59,7 +59,6 @@ static void drm_client_close(struct drm_client_dev *client)
 
        drm_file_free(client->file);
 }
-EXPORT_SYMBOL(drm_client_close);
 
 /**
  * drm_client_init - Initialise a DRM client
index b3f2cf7..354798b 100644 (file)
@@ -92,6 +92,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
        { DRM_MODE_CONNECTOR_DSI, "DSI" },
        { DRM_MODE_CONNECTOR_DPI, "DPI" },
        { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" },
+       { DRM_MODE_CONNECTOR_SPI, "SPI" },
 };
 
 void drm_connector_ida_init(void)
@@ -140,8 +141,7 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
        }
 
        DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
-                     connector->name,
-                     mode->name,
+                     connector->name, mode->name,
                      mode->xres, mode->yres,
                      mode->refresh_specified ? mode->refresh : 60,
                      mode->rb ? " reduced blanking" : "",
@@ -297,6 +297,41 @@ out_put:
 }
 EXPORT_SYMBOL(drm_connector_init);
 
+/**
+ * drm_connector_init_with_ddc - Init a preallocated connector
+ * @dev: DRM device
+ * @connector: the connector to init
+ * @funcs: callbacks for this connector
+ * @connector_type: user visible type of the connector
+ * @ddc: pointer to the associated ddc adapter
+ *
+ * Initialises a preallocated connector. Connectors should be
+ * subclassed as part of driver connector objects.
+ *
+ * Ensures that the ddc field of the connector is correctly set.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_init_with_ddc(struct drm_device *dev,
+                               struct drm_connector *connector,
+                               const struct drm_connector_funcs *funcs,
+                               int connector_type,
+                               struct i2c_adapter *ddc)
+{
+       int ret;
+
+       ret = drm_connector_init(dev, connector, funcs, connector_type);
+       if (ret)
+               return ret;
+
+       /* provide ddc symlink in sysfs */
+       connector->ddc = ddc;
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_connector_init_with_ddc);
+
 /**
  * drm_connector_attach_edid_property - attach edid property.
  * @connector: the connector
@@ -948,10 +983,70 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = {
  *     - If the state is DESIRED, kernel should attempt to re-authenticate the
  *       link whenever possible. This includes across disable/enable, dpms,
  *       hotplug, downstream device changes, link status failures, etc..
- *     - Userspace is responsible for polling the property to determine when
- *       the value transitions from ENABLED to DESIRED. This signifies the link
- *       is no longer protected and userspace should take appropriate action
- *       (whatever that might be).
+ *     - Kernel sends uevent with the connector id and property id through
+ *       @drm_hdcp_update_content_protection, upon below kernel triggered
+ *       scenarios:
+ *             DESIRED -> ENABLED      (authentication success)
+ *             ENABLED -> DESIRED      (termination of authentication)
+ *     - Please note no uevents for userspace triggered property state changes,
+ *       which can't fail such as
+ *             DESIRED/ENABLED -> UNDESIRED
+ *             UNDESIRED -> DESIRED
+ *     - Userspace is responsible for polling the property or listen to uevents
+ *       to determine when the value transitions from ENABLED to DESIRED.
+ *       This signifies the link is no longer protected and userspace should
+ *       take appropriate action (whatever that might be).
+ *
+ * HDCP Content Type:
+ *     This Enum property is used by the userspace to declare the content type
+ *     of the display stream, to kernel. Here display stream stands for any
+ *     display content that userspace intended to display through HDCP
+ *     encryption.
+ *
+ *     Content Type of a stream is decided by the owner of the stream, as
+ *     "HDCP Type0" or "HDCP Type1".
+ *
+ *     The value of the property can be one of the below:
+ *       - "HDCP Type0": DRM_MODE_HDCP_CONTENT_TYPE0 = 0
+ *       - "HDCP Type1": DRM_MODE_HDCP_CONTENT_TYPE1 = 1
+ *
+ *     When kernel starts the HDCP authentication (see "Content Protection"
+ *     for details), it uses the content type in "HDCP Content Type"
+ *     for performing the HDCP authentication with the display sink.
+ *
+ *     Please note in HDCP spec versions, a link can be authenticated with
+ *     HDCP 2.2 for Content Type 0/Content Type 1. Where as a link can be
+ *     authenticated with HDCP1.4 only for Content Type 0(though it is implicit
+ *     in nature. As there is no reference for Content Type in HDCP1.4).
+ *
+ *     HDCP2.2 authentication protocol itself takes the "Content Type" as a
+ *     parameter, which is a input for the DP HDCP2.2 encryption algo.
+ *
+ *     In case of Type 0 content protection request, kernel driver can choose
+ *     either of HDCP spec versions 1.4 and 2.2. When HDCP2.2 is used for
+ *     "HDCP Type 0", a HDCP 2.2 capable repeater in the downstream can send
+ *     that content to a HDCP 1.4 authenticated HDCP sink (Type0 link).
+ *     But if the content is classified as "HDCP Type 1", above mentioned
+ *     HDCP 2.2 repeater wont send the content to the HDCP sink as it can't
+ *     authenticate the HDCP1.4 capable sink for "HDCP Type 1".
+ *
+ *     Please note userspace can be ignorant of the HDCP versions used by the
+ *     kernel driver to achieve the "HDCP Content Type".
+ *
+ *     At current scenario, classifying a content as Type 1 ensures that the
+ *     content will be displayed only through the HDCP2.2 encrypted link.
+ *
+ *     Note that the HDCP Content Type property is introduced at HDCP 2.2, and
+ *     defaults to type 0. It is only exposed by drivers supporting HDCP 2.2
+ *     (hence supporting Type 0 and Type 1). Based on how next versions of
+ *     HDCP specs are defined content Type could be used for higher versions
+ *     too.
+ *
+ *     If content type is changed when "Content Protection" is not UNDESIRED,
+ *     then kernel will disable the HDCP and re-enable with new type in the
+ *     same atomic commit. And when "Content Protection" is ENABLED, it means
+ *     that link is HDCP authenticated and encrypted, for the transmission of
+ *     the Type of stream mentioned at "HDCP Content Type".
  *
  * HDR_OUTPUT_METADATA:
  *     Connector property to enable userspace to send HDR Metadata to
index 7ca486d..be1b7ba 100644 (file)
  * the reported CRCs of frames that should have the same contents.
  *
  * On the driver side the implementation effort is minimal, drivers only need to
- * implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically
- * set up if that vfunc is set. CRC samples need to be captured in the driver by
- * calling drm_crtc_add_crc_entry().
+ * implement &drm_crtc_funcs.set_crc_source and &drm_crtc_funcs.verify_crc_source.
+ * The debugfs files are automatically set up if those vfuncs are set. CRC samples
+ * need to be captured in the driver by calling drm_crtc_add_crc_entry().
+ * Depending on the driver and HW requirements, &drm_crtc_funcs.set_crc_source
+ * may result in a commit (even a full modeset).
+ *
+ * CRC results must be reliable across non-full-modeset atomic commits, so if a
+ * commit via DRM_IOCTL_MODE_ATOMIC would disable or otherwise interfere with
+ * CRC generation, then the driver must mark that commit as a full modeset
+ * (drm_atomic_crtc_needs_modeset() should return true). As a result, to ensure
+ * consistent results, generic userspace must re-setup CRC generation after a
+ * legacy SETCRTC or an atomic commit with DRM_MODE_ATOMIC_ALLOW_MODESET.
  */
 
 static int crc_control_show(struct seq_file *m, void *data)
index 5ef0227..e45b078 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_dma.c
  * DMA IOCTL and function support
  *
index 5be28e3..0cfb386 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_print.h>
 
 #include "drm_crtc_helper_internal.h"
@@ -82,8 +83,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux)
        kref_init(&aux_dev->refcount);
 
        mutex_lock(&aux_idr_mutex);
-       index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-                                GFP_KERNEL);
+       index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
        mutex_unlock(&aux_idr_mutex);
        if (index < 0) {
                kfree(aux_dev);
@@ -163,7 +163,12 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
                        break;
                }
 
-               res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+               if (aux_dev->aux->is_remote)
+                       res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf,
+                                                  todo);
+               else
+                       res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
                if (res <= 0)
                        break;
 
@@ -210,7 +215,12 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
                        break;
                }
 
-               res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+               if (aux_dev->aux->is_remote)
+                       res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf,
+                                                   todo);
+               else
+                       res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
                if (res <= 0)
                        break;
 
index 0b994d0..ffc68d3 100644 (file)
@@ -152,38 +152,15 @@ EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate)
 {
-       switch (link_rate) {
-       default:
-               WARN(1, "unknown DP link rate %d, using %x\n", link_rate,
-                    DP_LINK_BW_1_62);
-               /* fall through */
-       case 162000:
-               return DP_LINK_BW_1_62;
-       case 270000:
-               return DP_LINK_BW_2_7;
-       case 540000:
-               return DP_LINK_BW_5_4;
-       case 810000:
-               return DP_LINK_BW_8_1;
-       }
+       /* Spec says link_bw = link_rate / 0.27Gbps */
+       return link_rate / 27000;
 }
 EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
 
 int drm_dp_bw_code_to_link_rate(u8 link_bw)
 {
-       switch (link_bw) {
-       default:
-               WARN(1, "unknown DP link BW code %x, using 162000\n", link_bw);
-               /* fall through */
-       case DP_LINK_BW_1_62:
-               return 162000;
-       case DP_LINK_BW_2_7:
-               return 270000;
-       case DP_LINK_BW_5_4:
-               return 540000;
-       case DP_LINK_BW_8_1:
-               return 810000;
-       }
+       /* Spec says link_rate = link_bw * 0.27Gbps */
+       return link_bw * 27000;
 }
 EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
 
index 0984b9a..82add73 100644 (file)
@@ -36,6 +36,8 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp mst helper
  *
@@ -53,6 +55,9 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
                                     int id,
                                     struct drm_dp_payload *payload);
 
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+                                struct drm_dp_mst_port *port,
+                                int offset, int size, u8 *bytes);
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_dp_mst_port *port,
                                  int offset, int size, u8 *bytes);
@@ -1483,6 +1488,52 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
        return send_link;
 }
 
+/**
+ * drm_dp_mst_dpcd_read() - read a series of bytes from the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the (first) register to read
+ * @buffer: buffer to store the register values
+ * @size: number of bytes in @buffer
+ *
+ * Performs the same functionality for remote devices via
+ * sideband messaging as drm_dp_dpcd_read() does for local
+ * devices via actual AUX CH.
+ *
+ * Return: Number of bytes read, or negative error code on failure.
+ */
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+                            unsigned int offset, void *buffer, size_t size)
+{
+       struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port,
+                                                   aux);
+
+       return drm_dp_send_dpcd_read(port->mgr, port,
+                                    offset, size, buffer);
+}
+
+/**
+ * drm_dp_mst_dpcd_write() - write a series of bytes to the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the (first) register to write
+ * @buffer: buffer containing the values to write
+ * @size: number of bytes in @buffer
+ *
+ * Performs the same functionality for remote devices via
+ * sideband messaging as drm_dp_dpcd_write() does for local
+ * devices via actual AUX CH.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
+                             unsigned int offset, void *buffer, size_t size)
+{
+       struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port,
+                                                   aux);
+
+       return drm_dp_send_dpcd_write(port->mgr, port,
+                                     offset, size, buffer);
+}
+
 static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
 {
        int ret;
@@ -1526,6 +1577,46 @@ static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
        strlcat(proppath, temp, proppath_size);
 }
 
+/**
+ * drm_dp_mst_connector_late_register() - Late MST connector registration
+ * @connector: The MST connector
+ * @port: The MST port for this connector
+ *
+ * Helper to register the remote aux device for this MST port. Drivers should
+ * call this from their mst connector's late_register hook to enable MST aux
+ * devices.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int drm_dp_mst_connector_late_register(struct drm_connector *connector,
+                                      struct drm_dp_mst_port *port)
+{
+       DRM_DEBUG_KMS("registering %s remote bus for %s\n",
+                     port->aux.name, connector->kdev->kobj.name);
+
+       port->aux.dev = connector->kdev;
+       return drm_dp_aux_register_devnode(&port->aux);
+}
+EXPORT_SYMBOL(drm_dp_mst_connector_late_register);
+
+/**
+ * drm_dp_mst_connector_early_unregister() - Early MST connector unregistration
+ * @connector: The MST connector
+ * @port: The MST port for this connector
+ *
+ * Helper to unregister the remote aux device for this MST port, registered by
+ * drm_dp_mst_connector_late_register(). Drivers should call this from their mst
+ * connector's early_unregister hook.
+ */
+void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
+                                          struct drm_dp_mst_port *port)
+{
+       DRM_DEBUG_KMS("unregistering %s remote bus for %s\n",
+                     port->aux.name, connector->kdev->kobj.name);
+       drm_dp_aux_unregister_devnode(&port->aux);
+}
+EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister);
+
 static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                            struct drm_device *dev,
                            struct drm_dp_link_addr_reply_port *port_msg)
@@ -1548,6 +1639,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                port->mgr = mstb->mgr;
                port->aux.name = "DPMST";
                port->aux.dev = dev->dev;
+               port->aux.is_remote = true;
 
                /*
                 * Make sure the memory allocation for our parent branch stays
@@ -1816,7 +1908,6 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
        return false;
 }
 
-#if 0
 static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
 {
        struct drm_dp_sideband_msg_req_body req;
@@ -1829,7 +1920,6 @@ static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32
 
        return 0;
 }
-#endif
 
 static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
                                    bool up, u8 *msg, int len)
@@ -2441,26 +2531,58 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
 }
 EXPORT_SYMBOL(drm_dp_update_payload_part2);
 
-#if 0 /* unused as of yet */
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
                                 struct drm_dp_mst_port *port,
-                                int offset, int size)
+                                int offset, int size, u8 *bytes)
 {
        int len;
+       int ret = 0;
        struct drm_dp_sideband_msg_tx *txmsg;
+       struct drm_dp_mst_branch *mstb;
+
+       mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
+       if (!mstb)
+               return -EINVAL;
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
-       if (!txmsg)
-               return -ENOMEM;
+       if (!txmsg) {
+               ret = -ENOMEM;
+               goto fail_put;
+       }
 
-       len = build_dpcd_read(txmsg, port->port_num, 0, 8);
+       len = build_dpcd_read(txmsg, port->port_num, offset, size);
        txmsg->dst = port->parent;
 
        drm_dp_queue_down_tx(mgr, txmsg);
 
-       return 0;
+       ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+       if (ret < 0)
+               goto fail_free;
+
+       /* DPCD read should never be NACKed */
+       if (txmsg->reply.reply_type == 1) {
+               DRM_ERROR("mstb %p port %d: DPCD read on addr 0x%x for %d bytes NAKed\n",
+                         mstb, port->port_num, offset, size);
+               ret = -EIO;
+               goto fail_free;
+       }
+
+       if (txmsg->reply.u.remote_dpcd_read_ack.num_bytes != size) {
+               ret = -EPROTO;
+               goto fail_free;
+       }
+
+       ret = min_t(size_t, txmsg->reply.u.remote_dpcd_read_ack.num_bytes,
+                   size);
+       memcpy(bytes, txmsg->reply.u.remote_dpcd_read_ack.bytes, ret);
+
+fail_free:
+       kfree(txmsg);
+fail_put:
+       drm_dp_mst_topology_put_mstb(mstb);
+
+       return ret;
 }
-#endif
 
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_dp_mst_port *port,
@@ -2489,7 +2611,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
        if (ret > 0) {
                if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
-                       ret = -EINVAL;
+                       ret = -EIO;
                else
                        ret = 0;
        }
index 9d00947..e652305 100644 (file)
@@ -978,14 +978,14 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto err_minors;
 
-       dev->registered = true;
-
        if (dev->driver->load) {
                ret = dev->driver->load(dev, flags);
                if (ret)
                        goto err_minors;
        }
 
+       dev->registered = true;
+
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                drm_modeset_register_all(dev);
 
index 754af25..ea34bc9 100644 (file)
@@ -147,8 +147,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
        if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
                drm_syncobj_open(file);
 
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_init_file_private(&file->prime);
+       drm_prime_init_file_private(&file->prime);
 
        if (dev->driver->open) {
                ret = dev->driver->open(dev, file);
@@ -159,8 +158,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
        return file;
 
 out_prime_destroy:
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_destroy_file_private(&file->prime);
+       drm_prime_destroy_file_private(&file->prime);
        if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
                drm_syncobj_release(file);
        if (drm_core_check_feature(dev, DRIVER_GEM))
@@ -253,8 +251,7 @@ void drm_file_free(struct drm_file *file)
        if (dev->driver->postclose)
                dev->driver->postclose(dev, file);
 
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_destroy_file_private(&file->prime);
+       drm_prime_destroy_file_private(&file->prime);
 
        WARN_ON(!list_empty(&file->event_list));
 
index a8c4468..afc38ce 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/mem_encrypt.h>
 #include <linux/pagevec.h>
 
+#include <drm/drm.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_file.h>
@@ -254,8 +255,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        else if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
 
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_gem_remove_prime_handles(obj, file_priv);
+       drm_gem_remove_prime_handles(obj, file_priv);
        drm_vma_node_revoke(&obj->vma_node, file_priv);
 
        drm_gem_object_handle_put_unlocked(obj);
@@ -1288,8 +1288,8 @@ retry:
        if (contended != -1) {
                struct drm_gem_object *obj = objs[contended];
 
-               ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock,
-                                                      acquire_ctx);
+               ret = reservation_object_lock_slow_interruptible(obj->resv,
+                                                                acquire_ctx);
                if (ret) {
                        ww_acquire_done(acquire_ctx);
                        return ret;
@@ -1300,16 +1300,16 @@ retry:
                if (i == contended)
                        continue;
 
-               ret = ww_mutex_lock_interruptible(&objs[i]->resv->lock,
-                                                 acquire_ctx);
+               ret = reservation_object_lock_interruptible(objs[i]->resv,
+                                                           acquire_ctx);
                if (ret) {
                        int j;
 
                        for (j = 0; j < i; j++)
-                               ww_mutex_unlock(&objs[j]->resv->lock);
+                               reservation_object_unlock(objs[j]->resv);
 
                        if (contended != -1 && contended >= i)
-                               ww_mutex_unlock(&objs[contended]->resv->lock);
+                               reservation_object_unlock(objs[contended]->resv);
 
                        if (ret == -EDEADLK) {
                                contended = i;
@@ -1334,7 +1334,7 @@ drm_gem_unlock_reservations(struct drm_gem_object **objs, int count,
        int i;
 
        for (i = 0; i < count; i++)
-               ww_mutex_unlock(&objs[i]->resv->lock);
+               reservation_object_unlock(objs[i]->resv);
 
        ww_acquire_fini(acquire_ctx);
 }
index 8fcbabf..f613040 100644 (file)
@@ -271,11 +271,11 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
  * @plane: Plane
  * @state: Plane state the fence will be attached to
  *
- * This function prepares a GEM backed framebuffer for scanout by checking if
- * the plane framebuffer has a DMA-BUF attached. If it does, it extracts the
- * exclusive fence and attaches it to the plane state for the atomic helper to
- * wait on. This function can be used as the &drm_plane_helper_funcs.prepare_fb
- * callback.
+ * This function extracts the exclusive fence from &drm_gem_object.resv and
+ * attaches it to plane state for the atomic helper to wait on. This is
+ * necessary to correctly implement implicit synchronization for any buffers
+ * shared as a struct &dma_buf. This function can be used as the
+ * &drm_plane_helper_funcs.prepare_fb callback.
  *
  * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple
  * gem based framebuffer drivers which have their buffers always pinned in
@@ -287,17 +287,15 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
 int drm_gem_fb_prepare_fb(struct drm_plane *plane,
                          struct drm_plane_state *state)
 {
-       struct dma_buf *dma_buf;
+       struct drm_gem_object *obj;
        struct dma_fence *fence;
 
        if (!state->fb)
                return 0;
 
-       dma_buf = drm_gem_fb_get_obj(state->fb, 0)->dma_buf;
-       if (dma_buf) {
-               fence = reservation_object_get_excl_rcu(dma_buf->resv);
-               drm_atomic_set_fence_for_plane(state, fence);
-       }
+       obj = drm_gem_fb_get_obj(state->fb, 0);
+       fence = reservation_object_get_excl_rcu(obj->resv);
+       drm_atomic_set_fence_for_plane(state, fence);
 
        return 0;
 }
@@ -309,10 +307,11 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb);
  * @pipe: Simple display pipe
  * @plane_state: Plane state
  *
- * This function uses drm_gem_fb_prepare_fb() to check if the plane FB has a
- * &dma_buf attached, extracts the exclusive fence and attaches it to plane
- * state for the atomic helper to wait on. Drivers can use this as their
- * &drm_simple_display_pipe_funcs.prepare_fb callback.
+ * This function uses drm_gem_fb_prepare_fb() to extract the exclusive fence
+ * from &drm_gem_object.resv and attaches it to plane state for the atomic
+ * helper to wait on. This is necessary to correctly implement implicit
+ * synchronization for any buffers shared as a struct &dma_buf. Drivers can use
+ * this as their &drm_simple_display_pipe_funcs.prepare_fb callback.
  *
  * See drm_atomic_set_fence_for_plane() for a discussion of implicit and
  * explicit fencing in atomic modeset updates.
@@ -323,46 +322,3 @@ int drm_gem_fb_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pi
        return drm_gem_fb_prepare_fb(&pipe->plane, plane_state);
 }
 EXPORT_SYMBOL(drm_gem_fb_simple_display_pipe_prepare_fb);
-
-/**
- * drm_gem_fbdev_fb_create - Create a GEM backed &drm_framebuffer for fbdev
- *                           emulation
- * @dev: DRM device
- * @sizes: fbdev size description
- * @pitch_align: Optional pitch alignment
- * @obj: GEM object backing the framebuffer
- * @funcs: Optional vtable to be used for the new framebuffer object when the
- *         dirty callback is needed.
- *
- * This function creates a framebuffer from a &drm_fb_helper_surface_size
- * description for use in the &drm_fb_helper_funcs.fb_probe callback.
- *
- * Returns:
- * Pointer to a &drm_framebuffer on success or an error pointer on failure.
- */
-struct drm_framebuffer *
-drm_gem_fbdev_fb_create(struct drm_device *dev,
-                       struct drm_fb_helper_surface_size *sizes,
-                       unsigned int pitch_align, struct drm_gem_object *obj,
-                       const struct drm_framebuffer_funcs *funcs)
-{
-       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = sizes->surface_width *
-                             DIV_ROUND_UP(sizes->surface_bpp, 8);
-       if (pitch_align)
-               mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0],
-                                             pitch_align);
-       mode_cmd.pixel_format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp,
-                                                           sizes->surface_depth);
-       if (obj->size < mode_cmd.pitches[0] * mode_cmd.height)
-               return ERR_PTR(-EINVAL);
-
-       if (!funcs)
-               funcs = &drm_gem_fb_funcs;
-
-       return drm_gem_fb_alloc(dev, &mode_cmd, &obj, 1, funcs);
-}
-EXPORT_SYMBOL(drm_gem_fbdev_fb_create);
index 472ea5d..2f64667 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
+#include <drm/drm.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_gem_shmem_helper.h>
index 4de782c..fd75107 100644 (file)
@@ -7,6 +7,8 @@
 #include <drm/drm_vram_mm_helper.h>
 #include <drm/ttm/ttm_page_alloc.h>
 
+static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
+
 /**
  * DOC: overview
  *
@@ -24,7 +26,7 @@ static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
         * TTM buffer object in 'bo' has already been cleaned
         * up; only release the GEM object.
         */
-       drm_gem_object_release(&gbo->gem);
+       drm_gem_object_release(&gbo->bo.base);
 }
 
 static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo)
@@ -80,7 +82,10 @@ static int drm_gem_vram_init(struct drm_device *dev,
        int ret;
        size_t acc_size;
 
-       ret = drm_gem_object_init(dev, &gbo->gem, size);
+       if (!gbo->bo.base.funcs)
+               gbo->bo.base.funcs = &drm_gem_vram_object_funcs;
+
+       ret = drm_gem_object_init(dev, &gbo->bo.base, size);
        if (ret)
                return ret;
 
@@ -98,7 +103,7 @@ static int drm_gem_vram_init(struct drm_device *dev,
        return 0;
 
 err_drm_gem_object_release:
-       drm_gem_object_release(&gbo->gem);
+       drm_gem_object_release(&gbo->bo.base);
        return ret;
 }
 
@@ -163,7 +168,7 @@ EXPORT_SYMBOL(drm_gem_vram_put);
  */
 u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo)
 {
-       return drm_vma_node_offset_addr(&gbo->bo.vma_node);
+       return drm_vma_node_offset_addr(&gbo->bo.base.vma_node);
 }
 EXPORT_SYMBOL(drm_gem_vram_mmap_offset);
 
@@ -378,11 +383,11 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
        if (IS_ERR(gbo))
                return PTR_ERR(gbo);
 
-       ret = drm_gem_handle_create(file, &gbo->gem, &handle);
+       ret = drm_gem_handle_create(file, &gbo->bo.base, &handle);
        if (ret)
                goto err_drm_gem_object_put_unlocked;
 
-       drm_gem_object_put_unlocked(&gbo->gem);
+       drm_gem_object_put_unlocked(&gbo->bo.base);
 
        args->pitch = pitch;
        args->size = size;
@@ -391,7 +396,7 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
        return 0;
 
 err_drm_gem_object_put_unlocked:
-       drm_gem_object_put_unlocked(&gbo->gem);
+       drm_gem_object_put_unlocked(&gbo->bo.base);
        return ret;
 }
 EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
@@ -441,7 +446,7 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
 
-       return drm_vma_node_verify_access(&gbo->gem.vma_node,
+       return drm_vma_node_verify_access(&gbo->bo.base.vma_node,
                                          filp->private_data);
 }
 EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access);
@@ -460,21 +465,24 @@ const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = {
 EXPORT_SYMBOL(drm_gem_vram_mm_funcs);
 
 /*
- * Helpers for struct drm_driver
+ * Helpers for struct drm_gem_object_funcs
  */
 
 /**
- * drm_gem_vram_driver_gem_free_object_unlocked() - \
-       Implements &struct drm_driver.gem_free_object_unlocked
- * @gem:       GEM object. Refers to &struct drm_gem_vram_object.gem
+ * drm_gem_vram_object_free() - \
+       Implements &struct drm_gem_object_funcs.free
+ * @gem:       GEM object. Refers to &struct drm_gem_vram_object.gem
  */
-void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem)
+static void drm_gem_vram_object_free(struct drm_gem_object *gem)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
        drm_gem_vram_put(gbo);
 }
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked);
+
+/*
+ * Helpers for dump buffers
+ */
 
 /**
  * drm_gem_vram_driver_create_dumb() - \
@@ -536,19 +544,19 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
 EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset);
 
 /*
- * PRIME helpers for struct drm_driver
+ * PRIME helpers
  */
 
 /**
- * drm_gem_vram_driver_gem_prime_pin() - \
-       Implements &struct drm_driver.gem_prime_pin
+ * drm_gem_vram_object_pin() - \
+       Implements &struct drm_gem_object_funcs.pin
  * @gem:       The GEM object to pin
  *
  * Returns:
  * 0 on success, or
  * a negative errno code otherwise.
  */
-int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem)
+static int drm_gem_vram_object_pin(struct drm_gem_object *gem)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
@@ -562,31 +570,29 @@ int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem)
         */
        return drm_gem_vram_pin(gbo, 0);
 }
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_pin);
 
 /**
- * drm_gem_vram_driver_gem_prime_unpin() - \
-       Implements &struct drm_driver.gem_prime_unpin
+ * drm_gem_vram_object_unpin() - \
+       Implements &struct drm_gem_object_funcs.unpin
  * @gem:       The GEM object to unpin
  */
-void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *gem)
+static void drm_gem_vram_object_unpin(struct drm_gem_object *gem)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
        drm_gem_vram_unpin(gbo);
 }
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_unpin);
 
 /**
- * drm_gem_vram_driver_gem_prime_vmap() - \
-       Implements &struct drm_driver.gem_prime_vmap
+ * drm_gem_vram_object_vmap() - \
+       Implements &struct drm_gem_object_funcs.vmap
  * @gem:       The GEM object to map
  *
  * Returns:
  * The buffers virtual address on success, or
  * NULL otherwise.
  */
-void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem)
+static void *drm_gem_vram_object_vmap(struct drm_gem_object *gem)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
        int ret;
@@ -602,40 +608,30 @@ void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem)
        }
        return base;
 }
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vmap);
 
 /**
- * drm_gem_vram_driver_gem_prime_vunmap() - \
-       Implements &struct drm_driver.gem_prime_vunmap
+ * drm_gem_vram_object_vunmap() - \
+       Implements &struct drm_gem_object_funcs.vunmap
  * @gem:       The GEM object to unmap
  * @vaddr:     The mapping's base address
  */
-void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *gem,
-                                         void *vaddr)
+static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem,
+                                      void *vaddr)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
        drm_gem_vram_kunmap(gbo);
        drm_gem_vram_unpin(gbo);
 }
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vunmap);
 
-/**
- * drm_gem_vram_driver_gem_prime_mmap() - \
-       Implements &struct drm_driver.gem_prime_mmap
- * @gem:       The GEM object to map
- * @vma:       The VMA describing the mapping
- *
- * Returns:
- * 0 on success, or
- * a negative errno code otherwise.
+/*
+ * GEM object funcs
  */
-int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *gem,
-                                      struct vm_area_struct *vma)
-{
-       struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
-       gbo->gem.vma_node.vm_node.start = gbo->bo.vma_node.vm_node.start;
-       return drm_gem_prime_mmap(gem, vma);
-}
-EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_mmap);
+static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = {
+       .free   = drm_gem_vram_object_free,
+       .pin    = drm_gem_vram_object_pin,
+       .unpin  = drm_gem_vram_object_unpin,
+       .vmap   = drm_gem_vram_object_vmap,
+       .vunmap = drm_gem_vram_object_vunmap
+};
index cd837bd..9191633 100644 (file)
@@ -271,6 +271,13 @@ exit:
  *
  * SRM should be presented in the name of "display_hdcp_srm.bin".
  *
+ * Format of the SRM table, that userspace needs to write into the binary file,
+ * is defined at:
+ * 1. Renewability chapter on 55th page of HDCP 1.4 specification
+ * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf
+ * 2. Renewability chapter on 63rd page of HDCP 2.2 specification
+ * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf
+ *
  * Returns:
  * TRUE on any of the KSV is revoked, else FALSE.
  */
@@ -344,23 +351,45 @@ static struct drm_prop_enum_list drm_cp_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
 
+static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = {
+       { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" },
+       { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" },
+};
+DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name,
+                drm_hdcp_content_type_enum_list)
+
 /**
  * drm_connector_attach_content_protection_property - attach content protection
  * property
  *
  * @connector: connector to attach CP property on.
+ * @hdcp_content_type: is HDCP Content Type property needed for connector
  *
  * This is used to add support for content protection on select connectors.
  * Content Protection is intentionally vague to allow for different underlying
  * technologies, however it is most implemented by HDCP.
  *
+ * When hdcp_content_type is true enum property called HDCP Content Type is
+ * created (if it is not already) and attached to the connector.
+ *
+ * This property is used for sending the protected content's stream type
+ * from userspace to kernel on selected connectors. Protected content provider
+ * will decide their type of their content and declare the same to kernel.
+ *
+ * Content type will be used during the HDCP 2.2 authentication.
+ * Content type will be set to &drm_connector_state.hdcp_content_type.
+ *
  * The content protection will be set to &drm_connector_state.content_protection
  *
+ * When kernel triggered content protection state change like DESIRED->ENABLED
+ * and ENABLED->DESIRED, will use drm_hdcp_update_content_protection() to update
+ * the content protection state of a connector.
+ *
  * Returns:
  * Zero on success, negative errno on failure.
  */
 int drm_connector_attach_content_protection_property(
-               struct drm_connector *connector)
+               struct drm_connector *connector, bool hdcp_content_type)
 {
        struct drm_device *dev = connector->dev;
        struct drm_property *prop =
@@ -377,6 +406,52 @@ int drm_connector_attach_content_protection_property(
                                   DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
        dev->mode_config.content_protection_property = prop;
 
+       if (!hdcp_content_type)
+               return 0;
+
+       prop = dev->mode_config.hdcp_content_type_property;
+       if (!prop)
+               prop = drm_property_create_enum(dev, 0, "HDCP Content Type",
+                                       drm_hdcp_content_type_enum_list,
+                                       ARRAY_SIZE(
+                                       drm_hdcp_content_type_enum_list));
+       if (!prop)
+               return -ENOMEM;
+
+       drm_object_attach_property(&connector->base, prop,
+                                  DRM_MODE_HDCP_CONTENT_TYPE0);
+       dev->mode_config.hdcp_content_type_property = prop;
+
        return 0;
 }
 EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
+
+/**
+ * drm_hdcp_update_content_protection - Updates the content protection state
+ * of a connector
+ *
+ * @connector: drm_connector on which content protection state needs an update
+ * @val: New state of the content protection property
+ *
+ * This function can be used by display drivers, to update the kernel triggered
+ * content protection state changes of a drm_connector such as DESIRED->ENABLED
+ * and ENABLED->DESIRED. No uevent for DESIRED->UNDESIRED or ENABLED->UNDESIRED,
+ * as userspace is triggering such state change and kernel performs it without
+ * fail.This function update the new state of the property into the connector's
+ * state and generate an uevent to notify the userspace.
+ */
+void drm_hdcp_update_content_protection(struct drm_connector *connector,
+                                       u64 val)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_connector_state *state = connector->state;
+
+       WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+       if (state->content_protection == val)
+               return;
+
+       state->content_protection = val;
+       drm_sysfs_connector_status_event(connector,
+                                dev->mode_config.content_protection_property);
+}
+EXPORT_SYMBOL(drm_hdcp_update_content_protection);
index a16b6dc..22c7fd7 100644 (file)
@@ -108,7 +108,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
                .desc = compat_ptr(v32.desc),
        };
        err = drm_ioctl_kernel(file, drm_version, &v,
-                              DRM_UNLOCKED|DRM_RENDER_ALLOW);
+                              DRM_RENDER_ALLOW);
        if (err)
                return err;
 
@@ -142,7 +142,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
                .unique = compat_ptr(uq32.unique),
        };
 
-       err = drm_ioctl_kernel(file, drm_getunique, &uq, DRM_UNLOCKED);
+       err = drm_ioctl_kernel(file, drm_getunique, &uq, 0);
        if (err)
                return err;
 
@@ -181,7 +181,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
                return -EFAULT;
 
        map.offset = m32.offset;
-       err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, DRM_UNLOCKED);
+       err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0);
        if (err)
                return err;
 
@@ -267,7 +267,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
 
        client.idx = c32.idx;
 
-       err = drm_ioctl_kernel(file, drm_getclient, &client, DRM_UNLOCKED);
+       err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
        if (err)
                return err;
 
@@ -297,7 +297,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
        drm_stats32_t __user *argp = (void __user *)arg;
        int err;
 
-       err = drm_ioctl_kernel(file, drm_noop, NULL, DRM_UNLOCKED);
+       err = drm_ioctl_kernel(file, drm_noop, NULL, 0);
        if (err)
                return err;
 
@@ -895,8 +895,7 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
                           sizeof(req64.modifier)))
                return -EFAULT;
 
-       err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64,
-                              DRM_UNLOCKED);
+       err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0);
        if (err)
                return err;
 
index bd81045..f675a3b 100644 (file)
@@ -570,24 +570,23 @@ EXPORT_SYMBOL(drm_ioctl_permit);
 
 /* Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
 
-       DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, DRM_UNLOCKED),
+       DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0),
 
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_UNLOCKED | DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
 
        DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_UNLOCKED|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_MASTER),
 
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH),
@@ -595,8 +594,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH),
 
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_UNLOCKED|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_UNLOCKED|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
 
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -642,74 +641,74 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 
        DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-       DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_UNLOCKED),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, 0),
 
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_CREATE, drm_syncobj_create_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_DESTROY, drm_syncobj_destroy_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, drm_syncobj_handle_to_fd_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TRANSFER, drm_syncobj_transfer_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
+                     DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl,
-                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_UNLOCKED),
+                     DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER),
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
@@ -777,7 +776,7 @@ long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata,
                return retcode;
 
        /* Enforce sane locking for modern driver ioctls. */
-       if (!drm_core_check_feature(dev, DRIVER_LEGACY) ||
+       if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) ||
            (flags & DRM_UNLOCKED))
                retcode = func(dev, kdata, file_priv);
        else {
index 4d3a11c..8f54e6a 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_legacy_misc.c
  * Misc legacy support functions.
  *
index 68b18b0..2e8ce99 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_lock.c
  * IOCTLs for locking
  *
index b634e16..0bec6db 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_memory.c
  * Memory management wrappers for DRM
  *
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
new file mode 100644 (file)
index 0000000..1961f71
--- /dev/null
@@ -0,0 +1,1330 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MIPI Display Bus Interface (DBI) LCD controller support
+ *
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
+#include <video/mipi_display.h>
+
+#define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */
+
+#define DCS_POWER_MODE_DISPLAY                 BIT(2)
+#define DCS_POWER_MODE_DISPLAY_NORMAL_MODE     BIT(3)
+#define DCS_POWER_MODE_SLEEP_MODE              BIT(4)
+#define DCS_POWER_MODE_PARTIAL_MODE            BIT(5)
+#define DCS_POWER_MODE_IDLE_MODE               BIT(6)
+#define DCS_POWER_MODE_RESERVED_MASK           (BIT(0) | BIT(1) | BIT(7))
+
+/**
+ * DOC: overview
+ *
+ * This library provides helpers for MIPI Display Bus Interface (DBI)
+ * compatible display controllers.
+ *
+ * Many controllers for tiny lcd displays are MIPI compliant and can use this
+ * library. If a controller uses registers 0x2A and 0x2B to set the area to
+ * update and uses register 0x2C to write to frame memory, it is most likely
+ * MIPI compliant.
+ *
+ * Only MIPI Type 1 displays are supported since a full frame memory is needed.
+ *
+ * There are 3 MIPI DBI implementation types:
+ *
+ * A. Motorola 6800 type parallel bus
+ *
+ * B. Intel 8080 type parallel bus
+ *
+ * C. SPI type with 3 options:
+ *
+ *    1. 9-bit with the Data/Command signal as the ninth bit
+ *    2. Same as above except it's sent as 16 bits
+ *    3. 8-bit with the Data/Command signal as a separate D/CX pin
+ *
+ * Currently mipi_dbi only supports Type C options 1 and 3 with
+ * mipi_dbi_spi_init().
+ */
+
+#define MIPI_DBI_DEBUG_COMMAND(cmd, data, len) \
+({ \
+       if (!len) \
+               DRM_DEBUG_DRIVER("cmd=%02x\n", cmd); \
+       else if (len <= 32) \
+               DRM_DEBUG_DRIVER("cmd=%02x, par=%*ph\n", cmd, (int)len, data);\
+       else \
+               DRM_DEBUG_DRIVER("cmd=%02x, len=%zu\n", cmd, len); \
+})
+
+static const u8 mipi_dbi_dcs_read_commands[] = {
+       MIPI_DCS_GET_DISPLAY_ID,
+       MIPI_DCS_GET_RED_CHANNEL,
+       MIPI_DCS_GET_GREEN_CHANNEL,
+       MIPI_DCS_GET_BLUE_CHANNEL,
+       MIPI_DCS_GET_DISPLAY_STATUS,
+       MIPI_DCS_GET_POWER_MODE,
+       MIPI_DCS_GET_ADDRESS_MODE,
+       MIPI_DCS_GET_PIXEL_FORMAT,
+       MIPI_DCS_GET_DISPLAY_MODE,
+       MIPI_DCS_GET_SIGNAL_MODE,
+       MIPI_DCS_GET_DIAGNOSTIC_RESULT,
+       MIPI_DCS_READ_MEMORY_START,
+       MIPI_DCS_READ_MEMORY_CONTINUE,
+       MIPI_DCS_GET_SCANLINE,
+       MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
+       MIPI_DCS_GET_CONTROL_DISPLAY,
+       MIPI_DCS_GET_POWER_SAVE,
+       MIPI_DCS_GET_CABC_MIN_BRIGHTNESS,
+       MIPI_DCS_READ_DDB_START,
+       MIPI_DCS_READ_DDB_CONTINUE,
+       0, /* sentinel */
+};
+
+static bool mipi_dbi_command_is_read(struct mipi_dbi *dbi, u8 cmd)
+{
+       unsigned int i;
+
+       if (!dbi->read_commands)
+               return false;
+
+       for (i = 0; i < 0xff; i++) {
+               if (!dbi->read_commands[i])
+                       return false;
+               if (cmd == dbi->read_commands[i])
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * mipi_dbi_command_read - MIPI DCS read command
+ * @dbi: MIPI DBI structure
+ * @cmd: Command
+ * @val: Value read
+ *
+ * Send MIPI DCS read command to the controller.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val)
+{
+       if (!dbi->read_commands)
+               return -EACCES;
+
+       if (!mipi_dbi_command_is_read(dbi, cmd))
+               return -EINVAL;
+
+       return mipi_dbi_command_buf(dbi, cmd, val, 1);
+}
+EXPORT_SYMBOL(mipi_dbi_command_read);
+
+/**
+ * mipi_dbi_command_buf - MIPI DCS command with parameter(s) in an array
+ * @dbi: MIPI DBI structure
+ * @cmd: Command
+ * @data: Parameter buffer
+ * @len: Buffer length
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len)
+{
+       u8 *cmdbuf;
+       int ret;
+
+       /* SPI requires dma-safe buffers */
+       cmdbuf = kmemdup(&cmd, 1, GFP_KERNEL);
+       if (!cmdbuf)
+               return -ENOMEM;
+
+       mutex_lock(&dbi->cmdlock);
+       ret = dbi->command(dbi, cmdbuf, data, len);
+       mutex_unlock(&dbi->cmdlock);
+
+       kfree(cmdbuf);
+
+       return ret;
+}
+EXPORT_SYMBOL(mipi_dbi_command_buf);
+
+/* This should only be used by mipi_dbi_command() */
+int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len)
+{
+       u8 *buf;
+       int ret;
+
+       buf = kmemdup(data, len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = mipi_dbi_command_buf(dbi, cmd, buf, len);
+
+       kfree(buf);
+
+       return ret;
+}
+EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
+
+/**
+ * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary
+ * @dst: The destination buffer
+ * @fb: The source framebuffer
+ * @clip: Clipping rectangle of the area to be copied
+ * @swap: When true, swap MSB/LSB of 16-bit values
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
+                     struct drm_rect *clip, bool swap)
+{
+       struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem);
+       struct dma_buf_attachment *import_attach = gem->import_attach;
+       struct drm_format_name_buf format_name;
+       void *src = cma_obj->vaddr;
+       int ret = 0;
+
+       if (import_attach) {
+               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
+                                              DMA_FROM_DEVICE);
+               if (ret)
+                       return ret;
+       }
+
+       switch (fb->format->format) {
+       case DRM_FORMAT_RGB565:
+               if (swap)
+                       drm_fb_swab16(dst, src, fb, clip);
+               else
+                       drm_fb_memcpy(dst, src, fb, clip);
+               break;
+       case DRM_FORMAT_XRGB8888:
+               drm_fb_xrgb8888_to_rgb565(dst, src, fb, clip, swap);
+               break;
+       default:
+               dev_err_once(fb->dev->dev, "Format is not supported: %s\n",
+                            drm_get_format_name(fb->format->format,
+                                                &format_name));
+               return -EINVAL;
+       }
+
+       if (import_attach)
+               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
+                                            DMA_FROM_DEVICE);
+       return ret;
+}
+EXPORT_SYMBOL(mipi_dbi_buf_copy);
+
+static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+{
+       struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem);
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
+       unsigned int height = rect->y2 - rect->y1;
+       unsigned int width = rect->x2 - rect->x1;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       bool swap = dbi->swap_bytes;
+       int idx, ret = 0;
+       bool full;
+       void *tr;
+
+       if (!dbidev->enabled)
+               return;
+
+       if (!drm_dev_enter(fb->dev, &idx))
+               return;
+
+       full = width == fb->width && height == fb->height;
+
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
+
+       if (!dbi->dc || !full || swap ||
+           fb->format->format == DRM_FORMAT_XRGB8888) {
+               tr = dbidev->tx_buf;
+               ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap);
+               if (ret)
+                       goto err_msg;
+       } else {
+               tr = cma_obj->vaddr;
+       }
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS,
+                        (rect->x1 >> 8) & 0xff, rect->x1 & 0xff,
+                        ((rect->x2 - 1) >> 8) & 0xff, (rect->x2 - 1) & 0xff);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS,
+                        (rect->y1 >> 8) & 0xff, rect->y1 & 0xff,
+                        ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff);
+
+       ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr,
+                                  width * height * 2);
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
+
+       drm_dev_exit(idx);
+}
+
+/**
+ * mipi_dbi_pipe_update - Display pipe update helper
+ * @pipe: Simple display pipe
+ * @old_state: Old plane state
+ *
+ * This function handles framebuffer flushing and vblank events. Drivers can use
+ * this as their &drm_simple_display_pipe_funcs->update callback.
+ */
+void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
+                         struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               mipi_dbi_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+EXPORT_SYMBOL(mipi_dbi_pipe_update);
+
+/**
+ * mipi_dbi_enable_flush - MIPI DBI enable helper
+ * @dbidev: MIPI DBI device structure
+ * @crtc_state: CRTC state
+ * @plane_state: Plane state
+ *
+ * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and
+ * enables the backlight. Drivers can use this in their
+ * &drm_simple_display_pipe_funcs->enable callback.
+ *
+ * Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom
+ * framebuffer flushing, can't use this function since they both use the same
+ * flushing code.
+ */
+void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
+                          struct drm_crtc_state *crtc_state,
+                          struct drm_plane_state *plane_state)
+{
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
+       int idx;
+
+       if (!drm_dev_enter(&dbidev->drm, &idx))
+               return;
+
+       dbidev->enabled = true;
+       mipi_dbi_fb_dirty(fb, &rect);
+       backlight_enable(dbidev->backlight);
+
+       drm_dev_exit(idx);
+}
+EXPORT_SYMBOL(mipi_dbi_enable_flush);
+
+static void mipi_dbi_blank(struct mipi_dbi_dev *dbidev)
+{
+       struct drm_device *drm = &dbidev->drm;
+       u16 height = drm->mode_config.min_height;
+       u16 width = drm->mode_config.min_width;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       size_t len = width * height * 2;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       memset(dbidev->tx_buf, 0, len);
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0,
+                        (width >> 8) & 0xFF, (width - 1) & 0xFF);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0,
+                        (height >> 8) & 0xFF, (height - 1) & 0xFF);
+       mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START,
+                            (u8 *)dbidev->tx_buf, len);
+
+       drm_dev_exit(idx);
+}
+
+/**
+ * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper
+ * @pipe: Display pipe
+ *
+ * This function disables backlight if present, if not the display memory is
+ * blanked. The regulator is disabled if in use. Drivers can use this as their
+ * &drm_simple_display_pipe_funcs->disable callback.
+ */
+void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+
+       if (!dbidev->enabled)
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       dbidev->enabled = false;
+
+       if (dbidev->backlight)
+               backlight_disable(dbidev->backlight);
+       else
+               mipi_dbi_blank(dbidev);
+
+       if (dbidev->regulator)
+               regulator_disable(dbidev->regulator);
+}
+EXPORT_SYMBOL(mipi_dbi_pipe_disable);
+
+static int mipi_dbi_connector_get_modes(struct drm_connector *connector)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, &dbidev->mode);
+       if (!mode) {
+               DRM_ERROR("Failed to duplicate mode\n");
+               return 0;
+       }
+
+       if (mode->name[0] == '\0')
+               drm_mode_set_name(mode);
+
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+       drm_mode_probed_add(connector, mode);
+
+       if (mode->width_mm) {
+               connector->display_info.width_mm = mode->width_mm;
+               connector->display_info.height_mm = mode->height_mm;
+       }
+
+       return 1;
+}
+
+static const struct drm_connector_helper_funcs mipi_dbi_connector_hfuncs = {
+       .get_modes = mipi_dbi_connector_get_modes,
+};
+
+static const struct drm_connector_funcs mipi_dbi_connector_funcs = {
+       .reset = drm_atomic_helper_connector_reset,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int mipi_dbi_rotate_mode(struct drm_display_mode *mode,
+                               unsigned int rotation)
+{
+       if (rotation == 0 || rotation == 180) {
+               return 0;
+       } else if (rotation == 90 || rotation == 270) {
+               swap(mode->hdisplay, mode->vdisplay);
+               swap(mode->hsync_start, mode->vsync_start);
+               swap(mode->hsync_end, mode->vsync_end);
+               swap(mode->htotal, mode->vtotal);
+               swap(mode->width_mm, mode->height_mm);
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+}
+
+static const struct drm_mode_config_funcs mipi_dbi_mode_config_funcs = {
+       .fb_create = drm_gem_fb_create_with_dirty,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+};
+
+static const uint32_t mipi_dbi_formats[] = {
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_XRGB8888,
+};
+
+/**
+ * mipi_dbi_dev_init_with_formats - MIPI DBI device initialization with custom formats
+ * @dbidev: MIPI DBI device structure to initialize
+ * @funcs: Display pipe functions
+ * @formats: Array of supported formats (DRM_FORMAT\_\*).
+ * @format_count: Number of elements in @formats
+ * @mode: Display mode
+ * @rotation: Initial rotation in degrees Counter Clock Wise
+ * @tx_buf_size: Allocate a transmit buffer of this size.
+ *
+ * This function sets up a &drm_simple_display_pipe with a &drm_connector that
+ * has one fixed &drm_display_mode which is rotated according to @rotation.
+ * This mode is used to set the mode config min/max width/height properties.
+ *
+ * Use mipi_dbi_dev_init() if you don't need custom formats.
+ *
+ * Note:
+ * Some of the helper functions expects RGB565 to be the default format and the
+ * transmit buffer sized to fit that.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
+                                  const struct drm_simple_display_pipe_funcs *funcs,
+                                  const uint32_t *formats, unsigned int format_count,
+                                  const struct drm_display_mode *mode,
+                                  unsigned int rotation, size_t tx_buf_size)
+{
+       static const uint64_t modifiers[] = {
+               DRM_FORMAT_MOD_LINEAR,
+               DRM_FORMAT_MOD_INVALID
+       };
+       struct drm_device *drm = &dbidev->drm;
+       int ret;
+
+       if (!dbidev->dbi.command)
+               return -EINVAL;
+
+       dbidev->tx_buf = devm_kmalloc(drm->dev, tx_buf_size, GFP_KERNEL);
+       if (!dbidev->tx_buf)
+               return -ENOMEM;
+
+       drm_mode_copy(&dbidev->mode, mode);
+       ret = mipi_dbi_rotate_mode(&dbidev->mode, rotation);
+       if (ret) {
+               DRM_ERROR("Illegal rotation value %u\n", rotation);
+               return -EINVAL;
+       }
+
+       drm_connector_helper_add(&dbidev->connector, &mipi_dbi_connector_hfuncs);
+       ret = drm_connector_init(drm, &dbidev->connector, &mipi_dbi_connector_funcs,
+                                DRM_MODE_CONNECTOR_SPI);
+       if (ret)
+               return ret;
+
+       ret = drm_simple_display_pipe_init(drm, &dbidev->pipe, funcs, formats, format_count,
+                                          modifiers, &dbidev->connector);
+       if (ret)
+               return ret;
+
+       drm_plane_enable_fb_damage_clips(&dbidev->pipe.plane);
+
+       drm->mode_config.funcs = &mipi_dbi_mode_config_funcs;
+       drm->mode_config.min_width = dbidev->mode.hdisplay;
+       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       drm->mode_config.min_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       dbidev->rotation = rotation;
+
+       DRM_DEBUG_KMS("rotation = %u\n", rotation);
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_dev_init_with_formats);
+
+/**
+ * mipi_dbi_dev_init - MIPI DBI device initialization
+ * @dbidev: MIPI DBI device structure to initialize
+ * @funcs: Display pipe functions
+ * @mode: Display mode
+ * @rotation: Initial rotation in degrees Counter Clock Wise
+ *
+ * This function sets up a &drm_simple_display_pipe with a &drm_connector that
+ * has one fixed &drm_display_mode which is rotated according to @rotation.
+ * This mode is used to set the mode config min/max width/height properties.
+ * Additionally &mipi_dbi.tx_buf is allocated.
+ *
+ * Supported formats: Native RGB565 and emulated XRGB8888.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev,
+                     const struct drm_simple_display_pipe_funcs *funcs,
+                     const struct drm_display_mode *mode, unsigned int rotation)
+{
+       size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16);
+
+       dbidev->drm.mode_config.preferred_depth = 16;
+
+       return mipi_dbi_dev_init_with_formats(dbidev, funcs, mipi_dbi_formats,
+                                             ARRAY_SIZE(mipi_dbi_formats), mode,
+                                             rotation, bufsize);
+}
+EXPORT_SYMBOL(mipi_dbi_dev_init);
+
+/**
+ * mipi_dbi_release - DRM driver release helper
+ * @drm: DRM device
+ *
+ * This function finalizes and frees &mipi_dbi.
+ *
+ * Drivers can use this as their &drm_driver->release callback.
+ */
+void mipi_dbi_release(struct drm_device *drm)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(drm);
+
+       DRM_DEBUG_DRIVER("\n");
+
+       drm_mode_config_cleanup(drm);
+       drm_dev_fini(drm);
+       kfree(dbidev);
+}
+EXPORT_SYMBOL(mipi_dbi_release);
+
+/**
+ * mipi_dbi_hw_reset - Hardware reset of controller
+ * @dbi: MIPI DBI structure
+ *
+ * Reset controller if the &mipi_dbi->reset gpio is set.
+ */
+void mipi_dbi_hw_reset(struct mipi_dbi *dbi)
+{
+       if (!dbi->reset)
+               return;
+
+       gpiod_set_value_cansleep(dbi->reset, 0);
+       usleep_range(20, 1000);
+       gpiod_set_value_cansleep(dbi->reset, 1);
+       msleep(120);
+}
+EXPORT_SYMBOL(mipi_dbi_hw_reset);
+
+/**
+ * mipi_dbi_display_is_on - Check if display is on
+ * @dbi: MIPI DBI structure
+ *
+ * This function checks the Power Mode register (if readable) to see if
+ * display output is turned on. This can be used to see if the bootloader
+ * has already turned on the display avoiding flicker when the pipeline is
+ * enabled.
+ *
+ * Returns:
+ * true if the display can be verified to be on, false otherwise.
+ */
+bool mipi_dbi_display_is_on(struct mipi_dbi *dbi)
+{
+       u8 val;
+
+       if (mipi_dbi_command_read(dbi, MIPI_DCS_GET_POWER_MODE, &val))
+               return false;
+
+       val &= ~DCS_POWER_MODE_RESERVED_MASK;
+
+       /* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
+       if (val != (DCS_POWER_MODE_DISPLAY |
+           DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
+               return false;
+
+       DRM_DEBUG_DRIVER("Display is ON\n");
+
+       return true;
+}
+EXPORT_SYMBOL(mipi_dbi_display_is_on);
+
+static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi_dev *dbidev, bool cond)
+{
+       struct device *dev = dbidev->drm.dev;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       int ret;
+
+       if (dbidev->regulator) {
+               ret = regulator_enable(dbidev->regulator);
+               if (ret) {
+                       DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
+                       return ret;
+               }
+       }
+
+       if (cond && mipi_dbi_display_is_on(dbi))
+               return 1;
+
+       mipi_dbi_hw_reset(dbi);
+       ret = mipi_dbi_command(dbi, MIPI_DCS_SOFT_RESET);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
+               if (dbidev->regulator)
+                       regulator_disable(dbidev->regulator);
+               return ret;
+       }
+
+       /*
+        * If we did a hw reset, we know the controller is in Sleep mode and
+        * per MIPI DSC spec should wait 5ms after soft reset. If we didn't,
+        * we assume worst case and wait 120ms.
+        */
+       if (dbi->reset)
+               usleep_range(5000, 20000);
+       else
+               msleep(120);
+
+       return 0;
+}
+
+/**
+ * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
+ * @dbidev: MIPI DBI device structure
+ *
+ * This function enables the regulator if used and does a hardware and software
+ * reset.
+ *
+ * Returns:
+ * Zero on success, or a negative error code.
+ */
+int mipi_dbi_poweron_reset(struct mipi_dbi_dev *dbidev)
+{
+       return mipi_dbi_poweron_reset_conditional(dbidev, false);
+}
+EXPORT_SYMBOL(mipi_dbi_poweron_reset);
+
+/**
+ * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
+ * @dbidev: MIPI DBI device structure
+ *
+ * This function enables the regulator if used and if the display is off, it
+ * does a hardware and software reset. If mipi_dbi_display_is_on() determines
+ * that the display is on, no reset is performed.
+ *
+ * Returns:
+ * Zero if the controller was reset, 1 if the display was already on, or a
+ * negative error code.
+ */
+int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev)
+{
+       return mipi_dbi_poweron_reset_conditional(dbidev, true);
+}
+EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
+
+#if IS_ENABLED(CONFIG_SPI)
+
+/**
+ * mipi_dbi_spi_cmd_max_speed - get the maximum SPI bus speed
+ * @spi: SPI device
+ * @len: The transfer buffer length.
+ *
+ * Many controllers have a max speed of 10MHz, but can be pushed way beyond
+ * that. Increase reliability by running pixel data at max speed and the rest
+ * at 10MHz, preventing transfer glitches from messing up the init settings.
+ */
+u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len)
+{
+       if (len > 64)
+               return 0; /* use default */
+
+       return min_t(u32, 10000000, spi->max_speed_hz);
+}
+EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
+
+static bool mipi_dbi_machine_little_endian(void)
+{
+#if defined(__LITTLE_ENDIAN)
+       return true;
+#else
+       return false;
+#endif
+}
+
+/*
+ * MIPI DBI Type C Option 1
+ *
+ * If the SPI controller doesn't have 9 bits per word support,
+ * use blocks of 9 bytes to send 8x 9-bit words using a 8-bit SPI transfer.
+ * Pad partial blocks with MIPI_DCS_NOP (zero).
+ * This is how the D/C bit (x) is added:
+ *     x7654321
+ *     0x765432
+ *     10x76543
+ *     210x7654
+ *     3210x765
+ *     43210x76
+ *     543210x7
+ *     6543210x
+ *     76543210
+ */
+
+static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc,
+                                  const void *buf, size_t len,
+                                  unsigned int bpw)
+{
+       bool swap_bytes = (bpw == 16 && mipi_dbi_machine_little_endian());
+       size_t chunk, max_chunk = dbi->tx_buf9_len;
+       struct spi_device *spi = dbi->spi;
+       struct spi_transfer tr = {
+               .tx_buf = dbi->tx_buf9,
+               .bits_per_word = 8,
+       };
+       struct spi_message m;
+       const u8 *src = buf;
+       int i, ret;
+       u8 *dst;
+
+       if (drm_debug & DRM_UT_DRIVER)
+               pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
+                        __func__, dc, max_chunk);
+
+       tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len);
+       spi_message_init_with_transfers(&m, &tr, 1);
+
+       if (!dc) {
+               if (WARN_ON_ONCE(len != 1))
+                       return -EINVAL;
+
+               /* Command: pad no-op's (zeroes) at beginning of block */
+               dst = dbi->tx_buf9;
+               memset(dst, 0, 9);
+               dst[8] = *src;
+               tr.len = 9;
+
+               return spi_sync(spi, &m);
+       }
+
+       /* max with room for adding one bit per byte */
+       max_chunk = max_chunk / 9 * 8;
+       /* but no bigger than len */
+       max_chunk = min(max_chunk, len);
+       /* 8 byte blocks */
+       max_chunk = max_t(size_t, 8, max_chunk & ~0x7);
+
+       while (len) {
+               size_t added = 0;
+
+               chunk = min(len, max_chunk);
+               len -= chunk;
+               dst = dbi->tx_buf9;
+
+               if (chunk < 8) {
+                       u8 val, carry = 0;
+
+                       /* Data: pad no-op's (zeroes) at end of block */
+                       memset(dst, 0, 9);
+
+                       if (swap_bytes) {
+                               for (i = 1; i < (chunk + 1); i++) {
+                                       val = src[1];
+                                       *dst++ = carry | BIT(8 - i) | (val >> i);
+                                       carry = val << (8 - i);
+                                       i++;
+                                       val = src[0];
+                                       *dst++ = carry | BIT(8 - i) | (val >> i);
+                                       carry = val << (8 - i);
+                                       src += 2;
+                               }
+                               *dst++ = carry;
+                       } else {
+                               for (i = 1; i < (chunk + 1); i++) {
+                                       val = *src++;
+                                       *dst++ = carry | BIT(8 - i) | (val >> i);
+                                       carry = val << (8 - i);
+                               }
+                               *dst++ = carry;
+                       }
+
+                       chunk = 8;
+                       added = 1;
+               } else {
+                       for (i = 0; i < chunk; i += 8) {
+                               if (swap_bytes) {
+                                       *dst++ =                 BIT(7) | (src[1] >> 1);
+                                       *dst++ = (src[1] << 7) | BIT(6) | (src[0] >> 2);
+                                       *dst++ = (src[0] << 6) | BIT(5) | (src[3] >> 3);
+                                       *dst++ = (src[3] << 5) | BIT(4) | (src[2] >> 4);
+                                       *dst++ = (src[2] << 4) | BIT(3) | (src[5] >> 5);
+                                       *dst++ = (src[5] << 3) | BIT(2) | (src[4] >> 6);
+                                       *dst++ = (src[4] << 2) | BIT(1) | (src[7] >> 7);
+                                       *dst++ = (src[7] << 1) | BIT(0);
+                                       *dst++ = src[6];
+                               } else {
+                                       *dst++ =                 BIT(7) | (src[0] >> 1);
+                                       *dst++ = (src[0] << 7) | BIT(6) | (src[1] >> 2);
+                                       *dst++ = (src[1] << 6) | BIT(5) | (src[2] >> 3);
+                                       *dst++ = (src[2] << 5) | BIT(4) | (src[3] >> 4);
+                                       *dst++ = (src[3] << 4) | BIT(3) | (src[4] >> 5);
+                                       *dst++ = (src[4] << 3) | BIT(2) | (src[5] >> 6);
+                                       *dst++ = (src[5] << 2) | BIT(1) | (src[6] >> 7);
+                                       *dst++ = (src[6] << 1) | BIT(0);
+                                       *dst++ = src[7];
+                               }
+
+                               src += 8;
+                               added++;
+                       }
+               }
+
+               tr.len = chunk + added;
+
+               ret = spi_sync(spi, &m);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
+                                 const void *buf, size_t len,
+                                 unsigned int bpw)
+{
+       struct spi_device *spi = dbi->spi;
+       struct spi_transfer tr = {
+               .bits_per_word = 9,
+       };
+       const u16 *src16 = buf;
+       const u8 *src8 = buf;
+       struct spi_message m;
+       size_t max_chunk;
+       u16 *dst16;
+       int ret;
+
+       if (!spi_is_bpw_supported(spi, 9))
+               return mipi_dbi_spi1e_transfer(dbi, dc, buf, len, bpw);
+
+       tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len);
+       max_chunk = dbi->tx_buf9_len;
+       dst16 = dbi->tx_buf9;
+
+       if (drm_debug & DRM_UT_DRIVER)
+               pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
+                        __func__, dc, max_chunk);
+
+       max_chunk = min(max_chunk / 2, len);
+
+       spi_message_init_with_transfers(&m, &tr, 1);
+       tr.tx_buf = dst16;
+
+       while (len) {
+               size_t chunk = min(len, max_chunk);
+               unsigned int i;
+
+               if (bpw == 16 && mipi_dbi_machine_little_endian()) {
+                       for (i = 0; i < (chunk * 2); i += 2) {
+                               dst16[i]     = *src16 >> 8;
+                               dst16[i + 1] = *src16++ & 0xFF;
+                               if (dc) {
+                                       dst16[i]     |= 0x0100;
+                                       dst16[i + 1] |= 0x0100;
+                               }
+                       }
+               } else {
+                       for (i = 0; i < chunk; i++) {
+                               dst16[i] = *src8++;
+                               if (dc)
+                                       dst16[i] |= 0x0100;
+                       }
+               }
+
+               tr.len = chunk;
+               len -= chunk;
+
+               ret = spi_sync(spi, &m);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
+                                  u8 *parameters, size_t num)
+{
+       unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8;
+       int ret;
+
+       if (mipi_dbi_command_is_read(dbi, *cmd))
+               return -ENOTSUPP;
+
+       MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num);
+
+       ret = mipi_dbi_spi1_transfer(dbi, 0, cmd, 1, 8);
+       if (ret || !num)
+               return ret;
+
+       return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw);
+}
+
+/* MIPI DBI Type C Option 3 */
+
+static int mipi_dbi_typec3_command_read(struct mipi_dbi *dbi, u8 *cmd,
+                                       u8 *data, size_t len)
+{
+       struct spi_device *spi = dbi->spi;
+       u32 speed_hz = min_t(u32, MIPI_DBI_MAX_SPI_READ_SPEED,
+                            spi->max_speed_hz / 2);
+       struct spi_transfer tr[2] = {
+               {
+                       .speed_hz = speed_hz,
+                       .tx_buf = cmd,
+                       .len = 1,
+               }, {
+                       .speed_hz = speed_hz,
+                       .len = len,
+               },
+       };
+       struct spi_message m;
+       u8 *buf;
+       int ret;
+
+       if (!len)
+               return -EINVAL;
+
+       /*
+        * Support non-standard 24-bit and 32-bit Nokia read commands which
+        * start with a dummy clock, so we need to read an extra byte.
+        */
+       if (*cmd == MIPI_DCS_GET_DISPLAY_ID ||
+           *cmd == MIPI_DCS_GET_DISPLAY_STATUS) {
+               if (!(len == 3 || len == 4))
+                       return -EINVAL;
+
+               tr[1].len = len + 1;
+       }
+
+       buf = kmalloc(tr[1].len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       tr[1].rx_buf = buf;
+       gpiod_set_value_cansleep(dbi->dc, 0);
+
+       spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr));
+       ret = spi_sync(spi, &m);
+       if (ret)
+               goto err_free;
+
+       if (tr[1].len == len) {
+               memcpy(data, buf, len);
+       } else {
+               unsigned int i;
+
+               for (i = 0; i < len; i++)
+                       data[i] = (buf[i] << 1) | !!(buf[i + 1] & BIT(7));
+       }
+
+       MIPI_DBI_DEBUG_COMMAND(*cmd, data, len);
+
+err_free:
+       kfree(buf);
+
+       return ret;
+}
+
+static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
+                                  u8 *par, size_t num)
+{
+       struct spi_device *spi = dbi->spi;
+       unsigned int bpw = 8;
+       u32 speed_hz;
+       int ret;
+
+       if (mipi_dbi_command_is_read(dbi, *cmd))
+               return mipi_dbi_typec3_command_read(dbi, cmd, par, num);
+
+       MIPI_DBI_DEBUG_COMMAND(*cmd, par, num);
+
+       gpiod_set_value_cansleep(dbi->dc, 0);
+       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
+       ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1);
+       if (ret || !num)
+               return ret;
+
+       if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes)
+               bpw = 16;
+
+       gpiod_set_value_cansleep(dbi->dc, 1);
+       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
+
+       return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+}
+
+/**
+ * mipi_dbi_spi_init - Initialize MIPI DBI SPI interface
+ * @spi: SPI device
+ * @dbi: MIPI DBI structure to initialize
+ * @dc: D/C gpio (optional)
+ *
+ * This function sets &mipi_dbi->command, enables &mipi_dbi->read_commands for the
+ * usual read commands. It should be followed by a call to mipi_dbi_dev_init() or
+ * a driver-specific init.
+ *
+ * If @dc is set, a Type C Option 3 interface is assumed, if not
+ * Type C Option 1.
+ *
+ * If the SPI master driver doesn't support the necessary bits per word,
+ * the following transformation is used:
+ *
+ * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command.
+ * - 16-bit: if big endian send as 8-bit, if little endian swap bytes
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
+                     struct gpio_desc *dc)
+{
+       struct device *dev = &spi->dev;
+       int ret;
+
+       /*
+        * Even though it's not the SPI device that does DMA (the master does),
+        * the dma mask is necessary for the dma_alloc_wc() in
+        * drm_gem_cma_create(). The dma_addr returned will be a physical
+        * address which might be different from the bus address, but this is
+        * not a problem since the address will not be used.
+        * The virtual address is used in the transfer and the SPI core
+        * re-maps it on the SPI master device using the DMA streaming API
+        * (spi_map_buf()).
+        */
+       if (!dev->coherent_dma_mask) {
+               ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+               if (ret) {
+                       dev_warn(dev, "Failed to set dma mask %d\n", ret);
+                       return ret;
+               }
+       }
+
+       dbi->spi = spi;
+       dbi->read_commands = mipi_dbi_dcs_read_commands;
+
+       if (dc) {
+               dbi->command = mipi_dbi_typec3_command;
+               dbi->dc = dc;
+               if (mipi_dbi_machine_little_endian() && !spi_is_bpw_supported(spi, 16))
+                       dbi->swap_bytes = true;
+       } else {
+               dbi->command = mipi_dbi_typec1_command;
+               dbi->tx_buf9_len = SZ_16K;
+               dbi->tx_buf9 = devm_kmalloc(dev, dbi->tx_buf9_len, GFP_KERNEL);
+               if (!dbi->tx_buf9)
+                       return -ENOMEM;
+       }
+
+       mutex_init(&dbi->cmdlock);
+
+       DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_spi_init);
+
+/**
+ * mipi_dbi_spi_transfer - SPI transfer helper
+ * @spi: SPI device
+ * @speed_hz: Override speed (optional)
+ * @bpw: Bits per word
+ * @buf: Buffer to transfer
+ * @len: Buffer length
+ *
+ * This SPI transfer helper breaks up the transfer of @buf into chunks which
+ * the SPI controller driver can handle.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
+                         u8 bpw, const void *buf, size_t len)
+{
+       size_t max_chunk = spi_max_transfer_size(spi);
+       struct spi_transfer tr = {
+               .bits_per_word = bpw,
+               .speed_hz = speed_hz,
+       };
+       struct spi_message m;
+       size_t chunk;
+       int ret;
+
+       spi_message_init_with_transfers(&m, &tr, 1);
+
+       while (len) {
+               chunk = min(len, max_chunk);
+
+               tr.tx_buf = buf;
+               tr.len = chunk;
+               buf += chunk;
+               len -= chunk;
+
+               ret = spi_sync(spi, &m);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_spi_transfer);
+
+#endif /* CONFIG_SPI */
+
+#ifdef CONFIG_DEBUG_FS
+
+static ssize_t mipi_dbi_debugfs_command_write(struct file *file,
+                                             const char __user *ubuf,
+                                             size_t count, loff_t *ppos)
+{
+       struct seq_file *m = file->private_data;
+       struct mipi_dbi_dev *dbidev = m->private;
+       u8 val, cmd = 0, parameters[64];
+       char *buf, *pos, *token;
+       unsigned int i;
+       int ret, idx;
+
+       if (!drm_dev_enter(&dbidev->drm, &idx))
+               return -ENODEV;
+
+       buf = memdup_user_nul(ubuf, count);
+       if (IS_ERR(buf)) {
+               ret = PTR_ERR(buf);
+               goto err_exit;
+       }
+
+       /* strip trailing whitespace */
+       for (i = count - 1; i > 0; i--)
+               if (isspace(buf[i]))
+                       buf[i] = '\0';
+               else
+                       break;
+       i = 0;
+       pos = buf;
+       while (pos) {
+               token = strsep(&pos, " ");
+               if (!token) {
+                       ret = -EINVAL;
+                       goto err_free;
+               }
+
+               ret = kstrtou8(token, 16, &val);
+               if (ret < 0)
+                       goto err_free;
+
+               if (token == buf)
+                       cmd = val;
+               else
+                       parameters[i++] = val;
+
+               if (i == 64) {
+                       ret = -E2BIG;
+                       goto err_free;
+               }
+       }
+
+       ret = mipi_dbi_command_buf(&dbidev->dbi, cmd, parameters, i);
+
+err_free:
+       kfree(buf);
+err_exit:
+       drm_dev_exit(idx);
+
+       return ret < 0 ? ret : count;
+}
+
+static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused)
+{
+       struct mipi_dbi_dev *dbidev = m->private;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       u8 cmd, val[4];
+       int ret, idx;
+       size_t len;
+
+       if (!drm_dev_enter(&dbidev->drm, &idx))
+               return -ENODEV;
+
+       for (cmd = 0; cmd < 255; cmd++) {
+               if (!mipi_dbi_command_is_read(dbi, cmd))
+                       continue;
+
+               switch (cmd) {
+               case MIPI_DCS_READ_MEMORY_START:
+               case MIPI_DCS_READ_MEMORY_CONTINUE:
+                       len = 2;
+                       break;
+               case MIPI_DCS_GET_DISPLAY_ID:
+                       len = 3;
+                       break;
+               case MIPI_DCS_GET_DISPLAY_STATUS:
+                       len = 4;
+                       break;
+               default:
+                       len = 1;
+                       break;
+               }
+
+               seq_printf(m, "%02x: ", cmd);
+               ret = mipi_dbi_command_buf(dbi, cmd, val, len);
+               if (ret) {
+                       seq_puts(m, "XX\n");
+                       continue;
+               }
+               seq_printf(m, "%*phN\n", (int)len, val);
+       }
+
+       drm_dev_exit(idx);
+
+       return 0;
+}
+
+static int mipi_dbi_debugfs_command_open(struct inode *inode,
+                                        struct file *file)
+{
+       return single_open(file, mipi_dbi_debugfs_command_show,
+                          inode->i_private);
+}
+
+static const struct file_operations mipi_dbi_debugfs_command_fops = {
+       .owner = THIS_MODULE,
+       .open = mipi_dbi_debugfs_command_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .write = mipi_dbi_debugfs_command_write,
+};
+
+/**
+ * mipi_dbi_debugfs_init - Create debugfs entries
+ * @minor: DRM minor
+ *
+ * This function creates a 'command' debugfs file for sending commands to the
+ * controller or getting the read command values.
+ * Drivers can use this as their &drm_driver->debugfs_init callback.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_debugfs_init(struct drm_minor *minor)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(minor->dev);
+       umode_t mode = S_IFREG | S_IWUSR;
+
+       if (dbidev->dbi.read_commands)
+               mode |= S_IRUGO;
+       debugfs_create_file("command", mode, minor->debugfs_root, dbidev,
+                           &mipi_dbi_debugfs_command_fops);
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_debugfs_init);
+
+#endif
+
+MODULE_LICENSE("GPL");
index 9a59865..4581c53 100644 (file)
@@ -472,7 +472,7 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm,
        u64 remainder_mask;
        bool once;
 
-       DRM_MM_BUG_ON(range_start >= range_end);
+       DRM_MM_BUG_ON(range_start > range_end);
 
        if (unlikely(size == 0 || range_end - range_start < size))
                return -ENOSPC;
index 1c6e511..c355ba8 100644 (file)
@@ -42,6 +42,8 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
 {
        int ret;
 
+       WARN_ON(dev->registered && !obj_free_cb);
+
        mutex_lock(&dev->mode_config.idr_mutex);
        ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
                        1, 0, GFP_KERNEL);
@@ -102,6 +104,8 @@ void drm_mode_object_register(struct drm_device *dev,
 void drm_mode_object_unregister(struct drm_device *dev,
                                struct drm_mode_object *object)
 {
+       WARN_ON(dev->registered && !object->free_cb);
+
        mutex_lock(&dev->mode_config.idr_mutex);
        if (object->id) {
                idr_remove(&dev->mode_config.object_idr, object->id);
index 80fcd5d..226a1d0 100644 (file)
@@ -1912,8 +1912,11 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
        case HDMI_PICTURE_ASPECT_256_135:
                out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
                break;
-       case HDMI_PICTURE_ASPECT_RESERVED:
        default:
+               WARN(1, "Invalid aspect ratio (0%x) on mode\n",
+                    in->picture_aspect_ratio);
+               /* fall through */
+       case HDMI_PICTURE_ASPECT_NONE:
                out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
                break;
        }
@@ -1972,20 +1975,22 @@ int drm_mode_convert_umode(struct drm_device *dev,
 
        switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
        case DRM_MODE_FLAG_PIC_AR_4_3:
-               out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3;
+               out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
                break;
        case DRM_MODE_FLAG_PIC_AR_16_9:
-               out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9;
+               out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
                break;
        case DRM_MODE_FLAG_PIC_AR_64_27:
-               out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27;
+               out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
                break;
        case DRM_MODE_FLAG_PIC_AR_256_135:
-               out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135;
+               out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
                break;
-       default:
+       case DRM_MODE_FLAG_PIC_AR_NONE:
                out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
                break;
+       default:
+               return -EINVAL;
        }
 
        out->status = drm_mode_validate_driver(dev, out);
index d0c0131..0a2316e 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/dma-buf.h>
 #include <linux/rbtree.h>
 
+#include <drm/drm.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_file.h>
 #include <drm/drm_framebuffer.h>
 
 #include "drm_internal.h"
 
-/*
- * DMA-BUF/GEM Object references and lifetime overview:
- *
- * On the export the dma_buf holds a reference to the exporting GEM
- * object. It takes this reference in handle_to_fd_ioctl, when it
- * first calls .prime_export and stores the exporting GEM object in
- * the dma_buf priv. This reference needs to be released when the
- * final reference to the &dma_buf itself is dropped and its
- * &dma_buf_ops.release function is called. For GEM-based drivers,
- * the dma_buf should be exported using drm_gem_dmabuf_export() and
- * then released by drm_gem_dmabuf_release().
- *
- * On the import the importing GEM object holds a reference to the
- * dma_buf (which in turn holds a ref to the exporting GEM object).
- * It takes that reference in the fd_to_handle ioctl.
- * It calls dma_buf_get, creates an attachment to it and stores the
- * attachment in the GEM object. When this attachment is destroyed
- * when the imported object is destroyed, we remove the attachment
- * and drop the reference to the dma_buf.
- *
- * When all the references to the &dma_buf are dropped, i.e. when
- * userspace has closed both handles to the imported GEM object (through the
- * FD_TO_HANDLE IOCTL) and closed the file descriptor of the exported
- * (through the HANDLE_TO_FD IOCTL) dma_buf, and all kernel-internal references
- * are also gone, then the dma_buf gets destroyed.  This can also happen as a
- * part of the clean up procedure in the drm_release() function if userspace
- * fails to properly clean up.  Note that both the kernel and userspace (by
- * keeeping the PRIME file descriptors open) can hold references onto a
- * &dma_buf.
- *
- * Thus the chain of references always flows in one direction
- * (avoiding loops): importing_gem -> dmabuf -> exporting_gem
- *
- * Self-importing: if userspace is using PRIME as a replacement for flink
- * then it will get a fd->handle request for a GEM object that it created.
- * Drivers should detect this situation and return back the gem object
- * from the dma-buf private.  Prime will do this automatically for drivers that
- * use the drm_gem_prime_{import,export} helpers.
- *
- * GEM struct &dma_buf_ops symbols are now exported. They can be resued by
- * drivers which implement GEM interface.
+/**
+ * DOC: overview and lifetime rules
+ *
+ * Similar to GEM global names, PRIME file descriptors are also used to share
+ * buffer objects across processes. They offer additional security: as file
+ * descriptors must be explicitly sent over UNIX domain sockets to be shared
+ * between applications, they can't be guessed like the globally unique GEM
+ * names.
+ *
+ * Drivers that support the PRIME API implement the
+ * &drm_driver.prime_handle_to_fd and &drm_driver.prime_fd_to_handle operations.
+ * GEM based drivers must use drm_gem_prime_handle_to_fd() and
+ * drm_gem_prime_fd_to_handle() to implement these. For GEM based drivers the
+ * actual driver interfaces is provided through the &drm_gem_object_funcs.export
+ * and &drm_driver.gem_prime_import hooks.
+ *
+ * &dma_buf_ops implementations for GEM drivers are all individually exported
+ * for drivers which need to overwrite or reimplement some of them.
+ *
+ * Reference Counting for GEM Drivers
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * On the export the &dma_buf holds a reference to the exported buffer object,
+ * usually a &drm_gem_object. It takes this reference in the PRIME_HANDLE_TO_FD
+ * IOCTL, when it first calls &drm_gem_object_funcs.export
+ * and stores the exporting GEM object in the &dma_buf.priv field. This
+ * reference needs to be released when the final reference to the &dma_buf
+ * itself is dropped and its &dma_buf_ops.release function is called.  For
+ * GEM-based drivers, the &dma_buf should be exported using
+ * drm_gem_dmabuf_export() and then released by drm_gem_dmabuf_release().
+ *
+ * Thus the chain of references always flows in one direction, avoiding loops:
+ * importing GEM object -> dma-buf -> exported GEM bo. A further complication
+ * are the lookup caches for import and export. These are required to guarantee
+ * that any given object will always have only one uniqe userspace handle. This
+ * is required to allow userspace to detect duplicated imports, since some GEM
+ * drivers do fail command submissions if a given buffer object is listed more
+ * than once. These import and export caches in &drm_prime_file_private only
+ * retain a weak reference, which is cleaned up when the corresponding object is
+ * released.
+ *
+ * Self-importing: If userspace is using PRIME as a replacement for flink then
+ * it will get a fd->handle request for a GEM object that it created.  Drivers
+ * should detect this situation and return back the underlying object from the
+ * dma-buf private. For GEM based drivers this is handled in
+ * drm_gem_prime_import() already.
  */
 
 struct drm_prime_member {
@@ -181,42 +187,6 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
        return -ENOENT;
 }
 
-/**
- * drm_gem_map_attach - dma_buf attach implementation for GEM
- * @dma_buf: buffer to attach device to
- * @attach: buffer attachment data
- *
- * Calls &drm_driver.gem_prime_pin for device specific handling. This can be
- * used as the &dma_buf_ops.attach callback.
- *
- * Returns 0 on success, negative error code on failure.
- */
-int drm_gem_map_attach(struct dma_buf *dma_buf,
-                      struct dma_buf_attachment *attach)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-
-       return drm_gem_pin(obj);
-}
-EXPORT_SYMBOL(drm_gem_map_attach);
-
-/**
- * drm_gem_map_detach - dma_buf detach implementation for GEM
- * @dma_buf: buffer to detach from
- * @attach: attachment to be detached
- *
- * Cleans up &dma_buf_attachment. This can be used as the &dma_buf_ops.detach
- * callback.
- */
-void drm_gem_map_detach(struct dma_buf *dma_buf,
-                       struct dma_buf_attachment *attach)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-
-       drm_gem_unpin(obj);
-}
-EXPORT_SYMBOL(drm_gem_map_detach);
-
 void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
                                        struct dma_buf *dma_buf)
 {
@@ -242,67 +212,21 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr
        }
 }
 
-/**
- * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
- * @attach: attachment whose scatterlist is to be returned
- * @dir: direction of DMA transfer
- *
- * Calls &drm_driver.gem_prime_get_sg_table and then maps the scatterlist. This
- * can be used as the &dma_buf_ops.map_dma_buf callback.
- *
- * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- * on error. May return -EINTR if it is interrupted by a signal.
- */
-
-struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
-                                    enum dma_data_direction dir)
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
 {
-       struct drm_gem_object *obj = attach->dmabuf->priv;
-       struct sg_table *sgt;
-
-       if (WARN_ON(dir == DMA_NONE))
-               return ERR_PTR(-EINVAL);
-
-       if (obj->funcs)
-               sgt = obj->funcs->get_sg_table(obj);
-       else
-               sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
-
-       if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
-                             DMA_ATTR_SKIP_CPU_SYNC)) {
-               sg_free_table(sgt);
-               kfree(sgt);
-               sgt = ERR_PTR(-ENOMEM);
-       }
-
-       return sgt;
+       mutex_init(&prime_fpriv->lock);
+       prime_fpriv->dmabufs = RB_ROOT;
+       prime_fpriv->handles = RB_ROOT;
 }
-EXPORT_SYMBOL(drm_gem_map_dma_buf);
 
-/**
- * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
- * @attach: attachment to unmap buffer from
- * @sgt: scatterlist info of the buffer to unmap
- * @dir: direction of DMA transfer
- *
- * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
- */
-void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
-                          struct sg_table *sgt,
-                          enum dma_data_direction dir)
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
 {
-       if (!sgt)
-               return;
-
-       dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
-                          DMA_ATTR_SKIP_CPU_SYNC);
-       sg_free_table(sgt);
-       kfree(sgt);
+       /* by now drm_gem_release should've made sure the list is empty */
+       WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
 }
-EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
 
 /**
- * drm_gem_dmabuf_export - dma_buf export implementation for GEM
+ * drm_gem_dmabuf_export - &dma_buf export implementation for GEM
  * @dev: parent device for the exported dmabuf
  * @exp_info: the export information used by dma_buf_export()
  *
@@ -330,11 +254,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
 EXPORT_SYMBOL(drm_gem_dmabuf_export);
 
 /**
- * drm_gem_dmabuf_release - dma_buf release implementation for GEM
+ * drm_gem_dmabuf_release - &dma_buf release implementation for GEM
  * @dma_buf: buffer to be released
  *
  * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
- * must use this in their dma_buf ops structure as the release callback.
+ * must use this in their &dma_buf_ops structure as the release callback.
  * drm_gem_dmabuf_release() should be used in conjunction with
  * drm_gem_dmabuf_export().
  */
@@ -351,128 +275,100 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
 EXPORT_SYMBOL(drm_gem_dmabuf_release);
 
 /**
- * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
- * @dma_buf: buffer to be mapped
+ * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
+ * @dev: dev to export the buffer from
+ * @file_priv: drm file-private structure
+ * @prime_fd: fd id of the dma-buf which should be imported
+ * @handle: pointer to storage for the handle of the imported buffer object
  *
- * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
- * callback.
+ * This is the PRIME import function which must be used mandatorily by GEM
+ * drivers to ensure correct lifetime management of the underlying GEM object.
+ * The actual importing of GEM object from the dma-buf is done through the
+ * &drm_driver.gem_prime_import driver callback.
  *
- * Returns the kernel virtual address.
+ * Returns 0 on success or a negative error code on failure.
  */
-void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+                              struct drm_file *file_priv, int prime_fd,
+                              uint32_t *handle)
 {
-       struct drm_gem_object *obj = dma_buf->priv;
-       void *vaddr;
+       struct dma_buf *dma_buf;
+       struct drm_gem_object *obj;
+       int ret;
 
-       vaddr = drm_gem_vmap(obj);
-       if (IS_ERR(vaddr))
-               vaddr = NULL;
+       dma_buf = dma_buf_get(prime_fd);
+       if (IS_ERR(dma_buf))
+               return PTR_ERR(dma_buf);
 
-       return vaddr;
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
+       mutex_lock(&file_priv->prime.lock);
 
-/**
- * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
- * @dma_buf: buffer to be unmapped
- * @vaddr: the virtual address of the buffer
- *
- * Releases a kernel virtual mapping. This can be used as the
- * &dma_buf_ops.vunmap callback.
- */
-void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
+       ret = drm_prime_lookup_buf_handle(&file_priv->prime,
+                       dma_buf, handle);
+       if (ret == 0)
+               goto out_put;
 
-       drm_gem_vunmap(obj, vaddr);
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
+       /* never seen this one, need to import */
+       mutex_lock(&dev->object_name_lock);
+       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;
+       }
 
-/**
- * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
- * @dma_buf: buffer to be mapped
- * @vma: virtual address range
- *
- * Provides memory mapping for the buffer. This can be used as the
- * &dma_buf_ops.mmap callback.
- *
- * Returns 0 on success or a negative error code on failure.
- */
-int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
+       if (obj->dma_buf) {
+               WARN_ON(obj->dma_buf != dma_buf);
+       } else {
+               obj->dma_buf = dma_buf;
+               get_dma_buf(dma_buf);
+       }
 
-       if (!dev->driver->gem_prime_mmap)
-               return -ENOSYS;
+       /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
+       ret = drm_gem_handle_create_tail(file_priv, obj, handle);
+       drm_gem_object_put_unlocked(obj);
+       if (ret)
+               goto out_put;
 
-       return dev->driver->gem_prime_mmap(obj, vma);
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
+       ret = drm_prime_add_buf_handle(&file_priv->prime,
+                       dma_buf, *handle);
+       mutex_unlock(&file_priv->prime.lock);
+       if (ret)
+               goto fail;
 
-static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
-       .cache_sgt_mapping = true,
-       .attach = drm_gem_map_attach,
-       .detach = drm_gem_map_detach,
-       .map_dma_buf = drm_gem_map_dma_buf,
-       .unmap_dma_buf = drm_gem_unmap_dma_buf,
-       .release = drm_gem_dmabuf_release,
-       .mmap = drm_gem_dmabuf_mmap,
-       .vmap = drm_gem_dmabuf_vmap,
-       .vunmap = drm_gem_dmabuf_vunmap,
-};
+       dma_buf_put(dma_buf);
 
-/**
- * DOC: PRIME Helpers
- *
- * Drivers can implement @gem_prime_export and @gem_prime_import in terms of
- * simpler APIs by using the helper functions @drm_gem_prime_export and
- * @drm_gem_prime_import.  These functions implement dma-buf support in terms of
- * six lower-level driver callbacks:
- *
- * Export callbacks:
- *
- *  * @gem_prime_pin (optional): prepare a GEM object for exporting
- *  * @gem_prime_get_sg_table: provide a scatter/gather table of pinned pages
- *  * @gem_prime_vmap: vmap a buffer exported by your driver
- *  * @gem_prime_vunmap: vunmap a buffer exported by your driver
- *  * @gem_prime_mmap (optional): mmap a buffer exported by your driver
- *
- * Import callback:
- *
- *  * @gem_prime_import_sg_table (import): produce a GEM object from another
- *    driver's scatter/gather table
- */
+       return 0;
 
-/**
- * drm_gem_prime_export - helper library implementation of the export callback
- * @dev: drm_device to export from
- * @obj: GEM object to export
- * @flags: flags like DRM_CLOEXEC and DRM_RDWR
- *
- * This is the implementation of the gem_prime_export functions for GEM drivers
- * using the PRIME helpers.
- */
-struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj,
-                                    int flags)
+fail:
+       /* hmm, if driver attached, we are relying on the free-object path
+        * to detach.. which seems ok..
+        */
+       drm_gem_handle_delete(file_priv, *handle);
+       dma_buf_put(dma_buf);
+       return ret;
+
+out_unlock:
+       mutex_unlock(&dev->object_name_lock);
+out_put:
+       mutex_unlock(&file_priv->prime.lock);
+       dma_buf_put(dma_buf);
+       return ret;
+}
+EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
+
+int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
 {
-       struct dma_buf_export_info exp_info = {
-               .exp_name = KBUILD_MODNAME, /* white lie for debug */
-               .owner = dev->driver->fops->owner,
-               .ops = &drm_gem_prime_dmabuf_ops,
-               .size = obj->size,
-               .flags = flags,
-               .priv = obj,
-               .resv = obj->resv,
-       };
+       struct drm_prime_handle *args = data;
 
-       if (dev->driver->gem_prime_res_obj)
-               exp_info.resv = dev->driver->gem_prime_res_obj(obj);
+       if (!dev->driver->prime_fd_to_handle)
+               return -ENOSYS;
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       return dev->driver->prime_fd_to_handle(dev, file_priv,
+                       args->fd, &args->handle);
 }
-EXPORT_SYMBOL(drm_gem_prime_export);
 
 static struct dma_buf *export_and_register_object(struct drm_device *dev,
                                                  struct drm_gem_object *obj,
@@ -489,9 +385,9 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev,
        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);
+               dmabuf = dev->driver->gem_prime_export(obj, flags);
        else
-               dmabuf = drm_gem_prime_export(dev, obj, flags);
+               dmabuf = drm_gem_prime_export(obj, flags);
        if (IS_ERR(dmabuf)) {
                /* normally the created dma-buf takes ownership of the ref,
                 * but if that fails then drop the ref
@@ -521,7 +417,7 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev,
  * This is the PRIME export function which must be used mandatorily by GEM
  * drivers to ensure correct lifetime management of the underlying GEM object.
  * The actual exporting from GEM object to a dma-buf is done through the
- * gem_prime_export driver callback.
+ * &drm_driver.gem_prime_export driver callback.
  */
 int drm_gem_prime_handle_to_fd(struct drm_device *dev,
                               struct drm_file *file_priv, uint32_t handle,
@@ -610,16 +506,205 @@ 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.
- *
+int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_prime_handle *args = data;
+
+       if (!dev->driver->prime_handle_to_fd)
+               return -ENOSYS;
+
+       /* check flags are valid */
+       if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
+               return -EINVAL;
+
+       return dev->driver->prime_handle_to_fd(dev, file_priv,
+                       args->handle, args->flags, &args->fd);
+}
+
+/**
+ * DOC: PRIME Helpers
+ *
+ * Drivers can implement &drm_gem_object_funcs.export and
+ * &drm_driver.gem_prime_import in terms of simpler APIs by using the helper
+ * functions drm_gem_prime_export() and drm_gem_prime_import(). These functions
+ * implement dma-buf support in terms of some lower-level helpers, which are
+ * again exported for drivers to use individually:
+ *
+ * Exporting buffers
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Optional pinning of buffers is handled at dma-buf attach and detach time in
+ * drm_gem_map_attach() and drm_gem_map_detach(). Backing storage itself is
+ * handled by drm_gem_map_dma_buf() and drm_gem_unmap_dma_buf(), which relies on
+ * &drm_gem_object_funcs.get_sg_table.
+ *
+ * For kernel-internal access there's drm_gem_dmabuf_vmap() and
+ * drm_gem_dmabuf_vunmap(). Userspace mmap support is provided by
+ * drm_gem_dmabuf_mmap().
+ *
+ * Note that these export helpers can only be used if the underlying backing
+ * storage is fully coherent and either permanently pinned, or it is safe to pin
+ * it indefinitely.
+ *
+ * FIXME: The underlying helper functions are named rather inconsistently.
+ *
+ * Exporting buffers
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Importing dma-bufs using drm_gem_prime_import() relies on
+ * &drm_driver.gem_prime_import_sg_table.
+ *
+ * Note that similarly to the export helpers this permanently pins the
+ * underlying backing storage. Which is ok for scanout, but is not the best
+ * option for sharing lots of buffers for rendering.
+ */
+
+/**
+ * drm_gem_map_attach - dma_buf attach implementation for GEM
+ * @dma_buf: buffer to attach device to
+ * @attach: buffer attachment data
+ *
+ * Calls &drm_gem_object_funcs.pin for device specific handling. This can be
+ * used as the &dma_buf_ops.attach callback. Must be used together with
+ * drm_gem_map_detach().
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int drm_gem_map_attach(struct dma_buf *dma_buf,
+                      struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       return drm_gem_pin(obj);
+}
+EXPORT_SYMBOL(drm_gem_map_attach);
+
+/**
+ * drm_gem_map_detach - dma_buf detach implementation for GEM
+ * @dma_buf: buffer to detach from
+ * @attach: attachment to be detached
+ *
+ * Calls &drm_gem_object_funcs.pin for device specific handling.  Cleans up
+ * &dma_buf_attachment from drm_gem_map_attach(). This can be used as the
+ * &dma_buf_ops.detach callback.
+ */
+void drm_gem_map_detach(struct dma_buf *dma_buf,
+                       struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       drm_gem_unpin(obj);
+}
+EXPORT_SYMBOL(drm_gem_map_detach);
+
+/**
+ * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
+ * @attach: attachment whose scatterlist is to be returned
+ * @dir: direction of DMA transfer
+ *
+ * Calls &drm_gem_object_funcs.get_sg_table and then maps the scatterlist. This
+ * can be used as the &dma_buf_ops.map_dma_buf callback. Should be used together
+ * with drm_gem_unmap_dma_buf().
+ *
+ * Returns:sg_table containing the scatterlist to be returned; returns ERR_PTR
+ * on error. May return -EINTR if it is interrupted by a signal.
+ */
+struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
+                                    enum dma_data_direction dir)
+{
+       struct drm_gem_object *obj = attach->dmabuf->priv;
+       struct sg_table *sgt;
+
+       if (WARN_ON(dir == DMA_NONE))
+               return ERR_PTR(-EINVAL);
+
+       if (obj->funcs)
+               sgt = obj->funcs->get_sg_table(obj);
+       else
+               sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
+
+       if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+                             DMA_ATTR_SKIP_CPU_SYNC)) {
+               sg_free_table(sgt);
+               kfree(sgt);
+               sgt = ERR_PTR(-ENOMEM);
+       }
+
+       return sgt;
+}
+EXPORT_SYMBOL(drm_gem_map_dma_buf);
+
+/**
+ * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
+ * @attach: attachment to unmap buffer from
+ * @sgt: scatterlist info of the buffer to unmap
+ * @dir: direction of DMA transfer
+ *
+ * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
+ */
+void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
+                          struct sg_table *sgt,
+                          enum dma_data_direction dir)
+{
+       if (!sgt)
+               return;
+
+       dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+                          DMA_ATTR_SKIP_CPU_SYNC);
+       sg_free_table(sgt);
+       kfree(sgt);
+}
+EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
+
+/**
+ * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
+ * @dma_buf: buffer to be mapped
+ *
+ * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
+ * callback. Calls into &drm_gem_object_funcs.vmap for device specific handling.
+ *
+ * Returns the kernel virtual address or NULL on failure.
+ */
+void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       void *vaddr;
+
+       vaddr = drm_gem_vmap(obj);
+       if (IS_ERR(vaddr))
+               vaddr = NULL;
+
+       return vaddr;
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
+
+/**
+ * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
+ * @dma_buf: buffer to be unmapped
+ * @vaddr: the virtual address of the buffer
+ *
+ * Releases a kernel virtual mapping. This can be used as the
+ * &dma_buf_ops.vunmap callback. Calls into &drm_gem_object_funcs.vunmap for device specific handling.
+ */
+void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       drm_gem_vunmap(obj, vaddr);
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
+
+/**
+ * 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)
@@ -656,15 +741,118 @@ out:
 }
 EXPORT_SYMBOL(drm_gem_prime_mmap);
 
+/**
+ * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
+ * @dma_buf: buffer to be mapped
+ * @vma: virtual address range
+ *
+ * Provides memory mapping for the buffer. This can be used as the
+ * &dma_buf_ops.mmap callback. It just forwards to &drm_driver.gem_prime_mmap,
+ * which should be set to drm_gem_prime_mmap().
+ *
+ * FIXME: There's really no point to this wrapper, drivers which need anything
+ * else but drm_gem_prime_mmap can roll their own &dma_buf_ops.mmap callback.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+
+       if (!dev->driver->gem_prime_mmap)
+               return -ENOSYS;
+
+       return dev->driver->gem_prime_mmap(obj, vma);
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
+
+static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
+       .cache_sgt_mapping = true,
+       .attach = drm_gem_map_attach,
+       .detach = drm_gem_map_detach,
+       .map_dma_buf = drm_gem_map_dma_buf,
+       .unmap_dma_buf = drm_gem_unmap_dma_buf,
+       .release = drm_gem_dmabuf_release,
+       .mmap = drm_gem_dmabuf_mmap,
+       .vmap = drm_gem_dmabuf_vmap,
+       .vunmap = drm_gem_dmabuf_vunmap,
+};
+
+/**
+ * drm_prime_pages_to_sg - converts a page array into an sg list
+ * @pages: pointer to the array of page pointers to convert
+ * @nr_pages: length of the page vector
+ *
+ * This helper creates an sg table object from a set of pages
+ * the driver is responsible for mapping the pages into the
+ * importers address space for use with dma_buf itself.
+ *
+ * This is useful for implementing &drm_gem_object_funcs.get_sg_table.
+ */
+struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages)
+{
+       struct sg_table *sg = NULL;
+       int ret;
+
+       sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+       if (!sg) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
+                               nr_pages << PAGE_SHIFT, GFP_KERNEL);
+       if (ret)
+               goto out;
+
+       return sg;
+out:
+       kfree(sg);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(drm_prime_pages_to_sg);
+
+/**
+ * drm_gem_prime_export - helper library implementation of the export callback
+ * @obj: GEM object to export
+ * @flags: flags like DRM_CLOEXEC and DRM_RDWR
+ *
+ * This is the implementation of the &drm_gem_object_funcs.export functions for GEM drivers
+ * using the PRIME helpers. It is used as the default in
+ * drm_gem_prime_handle_to_fd().
+ */
+struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
+                                    int flags)
+{
+       struct drm_device *dev = obj->dev;
+       struct dma_buf_export_info exp_info = {
+               .exp_name = KBUILD_MODNAME, /* white lie for debug */
+               .owner = dev->driver->fops->owner,
+               .ops = &drm_gem_prime_dmabuf_ops,
+               .size = obj->size,
+               .flags = flags,
+               .priv = obj,
+               .resv = obj->resv,
+       };
+
+       return drm_gem_dmabuf_export(dev, &exp_info);
+}
+EXPORT_SYMBOL(drm_gem_prime_export);
+
 /**
  * drm_gem_prime_import_dev - core implementation of the import callback
  * @dev: drm_device to import into
  * @dma_buf: dma-buf object to import
  * @attach_dev: struct device to dma_buf attach
  *
- * This is the core of drm_gem_prime_import. It's designed to be called by
- * drivers who want to use a different device structure than dev->dev for
- * attaching via dma_buf.
+ * This is the core of drm_gem_prime_import(). It's designed to be called by
+ * drivers who want to use a different device structure than &drm_device.dev for
+ * attaching via dma_buf. This function calls
+ * &drm_driver.gem_prime_import_sg_table internally.
+ *
+ * Drivers must arrange to call drm_prime_gem_destroy() from their
+ * &drm_gem_object_funcs.free hook when using this function.
  */
 struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
                                            struct dma_buf *dma_buf,
@@ -709,6 +897,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
        }
 
        obj->import_attach = attach;
+       obj->resv = dma_buf->resv;
 
        return obj;
 
@@ -728,7 +917,12 @@ EXPORT_SYMBOL(drm_gem_prime_import_dev);
  * @dma_buf: dma-buf object to import
  *
  * This is the implementation of the gem_prime_import functions for GEM drivers
- * using the PRIME helpers.
+ * using the PRIME helpers. Drivers can use this as their
+ * &drm_driver.gem_prime_import implementation. It is used as the default
+ * implementation in drm_gem_prime_fd_to_handle().
+ *
+ * Drivers must arrange to call drm_prime_gem_destroy() from their
+ * &drm_gem_object_funcs.free hook when using this function.
  */
 struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
                                            struct dma_buf *dma_buf)
@@ -737,154 +931,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_prime_import);
 
-/**
- * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
- * @dev: dev to export the buffer from
- * @file_priv: drm file-private structure
- * @prime_fd: fd id of the dma-buf which should be imported
- * @handle: pointer to storage for the handle of the imported buffer object
- *
- * This is the PRIME import function which must be used mandatorily by GEM
- * drivers to ensure correct lifetime management of the underlying GEM object.
- * The actual importing of GEM object from the dma-buf is done through the
- * gem_import_export driver callback.
- */
-int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-                              struct drm_file *file_priv, int prime_fd,
-                              uint32_t *handle)
-{
-       struct dma_buf *dma_buf;
-       struct drm_gem_object *obj;
-       int ret;
-
-       dma_buf = dma_buf_get(prime_fd);
-       if (IS_ERR(dma_buf))
-               return PTR_ERR(dma_buf);
-
-       mutex_lock(&file_priv->prime.lock);
-
-       ret = drm_prime_lookup_buf_handle(&file_priv->prime,
-                       dma_buf, handle);
-       if (ret == 0)
-               goto out_put;
-
-       /* never seen this one, need to import */
-       mutex_lock(&dev->object_name_lock);
-       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;
-       }
-
-       if (obj->dma_buf) {
-               WARN_ON(obj->dma_buf != dma_buf);
-       } else {
-               obj->dma_buf = dma_buf;
-               get_dma_buf(dma_buf);
-       }
-
-       /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
-       ret = drm_gem_handle_create_tail(file_priv, obj, handle);
-       drm_gem_object_put_unlocked(obj);
-       if (ret)
-               goto out_put;
-
-       ret = drm_prime_add_buf_handle(&file_priv->prime,
-                       dma_buf, *handle);
-       mutex_unlock(&file_priv->prime.lock);
-       if (ret)
-               goto fail;
-
-       dma_buf_put(dma_buf);
-
-       return 0;
-
-fail:
-       /* hmm, if driver attached, we are relying on the free-object path
-        * to detach.. which seems ok..
-        */
-       drm_gem_handle_delete(file_priv, *handle);
-       dma_buf_put(dma_buf);
-       return ret;
-
-out_unlock:
-       mutex_unlock(&dev->object_name_lock);
-out_put:
-       mutex_unlock(&file_priv->prime.lock);
-       dma_buf_put(dma_buf);
-       return ret;
-}
-EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
-
-int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
-{
-       struct drm_prime_handle *args = data;
-
-       if (!drm_core_check_feature(dev, DRIVER_PRIME))
-               return -EOPNOTSUPP;
-
-       if (!dev->driver->prime_handle_to_fd)
-               return -ENOSYS;
-
-       /* check flags are valid */
-       if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
-               return -EINVAL;
-
-       return dev->driver->prime_handle_to_fd(dev, file_priv,
-                       args->handle, args->flags, &args->fd);
-}
-
-int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
-{
-       struct drm_prime_handle *args = data;
-
-       if (!drm_core_check_feature(dev, DRIVER_PRIME))
-               return -EOPNOTSUPP;
-
-       if (!dev->driver->prime_fd_to_handle)
-               return -ENOSYS;
-
-       return dev->driver->prime_fd_to_handle(dev, file_priv,
-                       args->fd, &args->handle);
-}
-
-/**
- * drm_prime_pages_to_sg - converts a page array into an sg list
- * @pages: pointer to the array of page pointers to convert
- * @nr_pages: length of the page vector
- *
- * This helper creates an sg table object from a set of pages
- * the driver is responsible for mapping the pages into the
- * importers address space for use with dma_buf itself.
- */
-struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages)
-{
-       struct sg_table *sg = NULL;
-       int ret;
-
-       sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-       if (!sg) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
-                               nr_pages << PAGE_SHIFT, GFP_KERNEL);
-       if (ret)
-               goto out;
-
-       return sg;
-out:
-       kfree(sg);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(drm_prime_pages_to_sg);
-
 /**
  * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
  * @sgt: scatter-gather table to convert
@@ -894,6 +940,9 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg);
  *
  * Exports an sg table into an array of pages and addresses. This is currently
  * required by the TTM driver in order to do correct fault handling.
+ *
+ * Drivers can use this in their &drm_driver.gem_prime_import_sg_table
+ * implementation.
  */
 int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
                                     dma_addr_t *addrs, int max_entries)
@@ -934,7 +983,7 @@ EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
  * @sg: the sg-table which was pinned at import time
  *
  * This is the cleanup functions which GEM drivers need to call when they use
- * @drm_gem_prime_import to import dma-bufs.
+ * drm_gem_prime_import() or drm_gem_prime_import_dev() to import dma-bufs.
  */
 void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
 {
@@ -949,16 +998,3 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
        dma_buf_put(dma_buf);
 }
 EXPORT_SYMBOL(drm_prime_gem_destroy);
-
-void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
-{
-       mutex_init(&prime_fpriv->lock);
-       prime_fpriv->dmabufs = RB_ROOT;
-       prime_fpriv->handles = RB_ROOT;
-}
-
-void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
-{
-       /* by now drm_gem_release should've made sure the list is empty */
-       WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
-}
index 2d7790f..d5c3861 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_scatter.c
  * IOCTLs to manage scatter/gather memory
  *
index a199c8d..1438dcb 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/sync_file.h>
 #include <linux/uaccess.h>
 
+#include <drm/drm.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_file.h>
 #include <drm/drm_gem.h>
@@ -1297,14 +1298,14 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data,
                        struct dma_fence *iter, *last_signaled = NULL;
 
                        dma_fence_chain_for_each(iter, fence) {
-                               if (!iter)
-                                       break;
-                               dma_fence_put(last_signaled);
-                               last_signaled = dma_fence_get(iter);
-                               if (!to_dma_fence_chain(last_signaled)->prev_seqno)
+                               if (iter->context != fence->context) {
+                                       dma_fence_put(iter);
                                        /* It is most likely that timeline has
                                         * unorder points. */
                                        break;
+                               }
+                               dma_fence_put(last_signaled);
+                               last_signaled = dma_fence_get(iter);
                        }
                        point = dma_fence_is_signaled(last_signaled) ?
                                last_signaled->seqno :
index ad10810..dd2bc85 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
+#include <linux/i2c.h>
 #include <linux/kdev_t.h>
 #include <linux/slab.h>
 
@@ -26,6 +27,7 @@
 #include <drm/drm_sysfs.h>
 
 #include "drm_internal.h"
+#include "drm_crtc_internal.h"
 
 #define to_drm_minor(d) dev_get_drvdata(d)
 #define to_drm_connector(d) dev_get_drvdata(d)
@@ -294,6 +296,9 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
        /* Let userspace know we have a new connector */
        drm_sysfs_hotplug_event(dev);
 
+       if (connector->ddc)
+               return sysfs_create_link(&connector->kdev->kobj,
+                                &connector->ddc->dev.kobj, "ddc");
        return 0;
 }
 
@@ -301,6 +306,10 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
 {
        if (!connector->kdev)
                return;
+
+       if (connector->ddc)
+               sysfs_remove_link(&connector->kdev->kobj, "ddc");
+
        DRM_DEBUG("removing \"%s\" from sysfs\n",
                  connector->name);
 
@@ -325,6 +334,9 @@ void drm_sysfs_lease_event(struct drm_device *dev)
  * Send a uevent for the DRM device specified by @dev.  Currently we only
  * set HOTPLUG=1 in the uevent environment, but this could be expanded to
  * deal with other types of events.
+ *
+ * Any new uapi should be using the drm_sysfs_connector_status_event()
+ * for uevents on connector status change.
  */
 void drm_sysfs_hotplug_event(struct drm_device *dev)
 {
@@ -337,6 +349,37 @@ void drm_sysfs_hotplug_event(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_sysfs_hotplug_event);
 
+/**
+ * drm_sysfs_connector_status_event - generate a DRM uevent for connector
+ * property status change
+ * @connector: connector on which property status changed
+ * @property: connector property whose status changed.
+ *
+ * Send a uevent for the DRM device specified by @dev.  Currently we
+ * set HOTPLUG=1 and connector id along with the attached property id
+ * related to the status change.
+ */
+void drm_sysfs_connector_status_event(struct drm_connector *connector,
+                                     struct drm_property *property)
+{
+       struct drm_device *dev = connector->dev;
+       char hotplug_str[] = "HOTPLUG=1", conn_id[21], prop_id[21];
+       char *envp[4] = { hotplug_str, conn_id, prop_id, NULL };
+
+       WARN_ON(!drm_mode_obj_find_prop_id(&connector->base,
+                                          property->base.id));
+
+       snprintf(conn_id, ARRAY_SIZE(conn_id),
+                "CONNECTOR=%u", connector->base.id);
+       snprintf(prop_id, ARRAY_SIZE(prop_id),
+                "PROPERTY=%u", property->base.id);
+
+       DRM_DEBUG("generating connector status event\n");
+
+       kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
+}
+EXPORT_SYMBOL(drm_sysfs_connector_status_event);
+
 static void drm_sysfs_release(struct device *dev)
 {
        kfree(dev);
index 603ab10..fd1fbc7 100644 (file)
@@ -31,7 +31,6 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_print.h>
-#include <drm/drm_os_linux.h>
 #include <drm/drm_vblank.h>
 
 #include "drm_internal.h"
@@ -1670,12 +1669,28 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
        }
 
        if (req_seq != seq) {
+               int wait;
+
                DRM_DEBUG("waiting on vblank count %llu, crtc %u\n",
                          req_seq, pipe);
-               DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
-                           vblank_passed(drm_vblank_count(dev, pipe),
-                                         req_seq) ||
-                           !READ_ONCE(vblank->enabled));
+               wait = wait_event_interruptible_timeout(vblank->queue,
+                       vblank_passed(drm_vblank_count(dev, pipe), req_seq) ||
+                                     !READ_ONCE(vblank->enabled),
+                       msecs_to_jiffies(3000));
+
+               switch (wait) {
+               case 0:
+                       /* timeout */
+                       ret = -EBUSY;
+                       break;
+               case -ERESTARTSYS:
+                       /* interrupted by signal */
+                       ret = -EINTR;
+                       break;
+               default:
+                       ret = 0;
+                       break;
+               }
        }
 
        if (ret != -EINTR) {
index 05f7c58..52e87e4 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_vm.c
  * Memory mapping for DRM
  *
index 7eb7cf9..08e033c 100644 (file)
@@ -430,17 +430,17 @@ static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data,
 static const struct drm_ioctl_desc etnaviv_ioctls[] = {
 #define ETNA_IOCTL(n, func, flags) \
        DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
-       ETNA_IOCTL(GET_PARAM,    get_param,    DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_NEW,      gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_INFO,     gem_info,     DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_SUBMIT,   gem_submit,   DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(WAIT_FENCE,   wait_fence,   DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_USERPTR,  gem_userptr,  DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(GEM_WAIT,     gem_wait,     DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW),
-       ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GET_PARAM,    get_param,    DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_NEW,      gem_new,      DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_INFO,     gem_info,     DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_SUBMIT,   gem_submit,   DRM_RENDER_ALLOW),
+       ETNA_IOCTL(WAIT_FENCE,   wait_fence,   DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_USERPTR,  gem_userptr,  DRM_RENDER_ALLOW),
+       ETNA_IOCTL(GEM_WAIT,     gem_wait,     DRM_RENDER_ALLOW),
+       ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_RENDER_ALLOW),
+       ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
 };
 
 static const struct vm_operations_struct vm_ops = {
@@ -462,17 +462,13 @@ static const struct file_operations fops = {
 };
 
 static struct drm_driver etnaviv_drm_driver = {
-       .driver_features    = DRIVER_GEM |
-                               DRIVER_PRIME |
-                               DRIVER_RENDER,
+       .driver_features    = DRIVER_GEM | DRIVER_RENDER,
        .open               = etnaviv_open,
        .postclose           = etnaviv_postclose,
        .gem_free_object_unlocked = etnaviv_gem_free_object,
        .gem_vm_ops         = &vm_ops,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export   = drm_gem_prime_export,
-       .gem_prime_import   = drm_gem_prime_import,
        .gem_prime_pin      = etnaviv_gem_prime_pin,
        .gem_prime_unpin    = etnaviv_gem_prime_unpin,
        .gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table,
index e8778eb..17ca602 100644 (file)
@@ -565,8 +565,7 @@ void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
 }
 
 static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
-       struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
-       struct drm_gem_object **obj)
+       const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
 {
        struct etnaviv_gem_object *etnaviv_obj;
        unsigned sz = sizeof(*etnaviv_obj);
@@ -594,8 +593,6 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
 
        etnaviv_obj->flags = flags;
        etnaviv_obj->ops = ops;
-       if (robj)
-               etnaviv_obj->base.resv = robj;
 
        mutex_init(&etnaviv_obj->lock);
        INIT_LIST_HEAD(&etnaviv_obj->vram_list);
@@ -614,7 +611,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
 
        size = PAGE_ALIGN(size);
 
-       ret = etnaviv_gem_new_impl(dev, size, flags, NULL,
+       ret = etnaviv_gem_new_impl(dev, size, flags,
                                   &etnaviv_gem_shmem_ops, &obj);
        if (ret)
                goto fail;
@@ -646,13 +643,12 @@ fail:
 }
 
 int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
-       struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
-       struct etnaviv_gem_object **res)
+       const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res)
 {
        struct drm_gem_object *obj;
        int ret;
 
-       ret = etnaviv_gem_new_impl(dev, size, flags, robj, ops, &obj);
+       ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj);
        if (ret)
                return ret;
 
@@ -734,7 +730,7 @@ int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
        struct etnaviv_gem_object *etnaviv_obj;
        int ret;
 
-       ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, NULL,
+       ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED,
                                      &etnaviv_gem_userptr_ops, &etnaviv_obj);
        if (ret)
                return ret;
index 753c458..fcd5d71 100644 (file)
@@ -112,8 +112,7 @@ void etnaviv_submit_put(struct etnaviv_gem_submit * submit);
 int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
        struct timespec *timeout);
 int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
-       struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
-       struct etnaviv_gem_object **res);
+       const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res);
 void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj);
 struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *obj);
 void etnaviv_gem_put_pages(struct etnaviv_gem_object *obj);
index 00e8b6a..a05292e 100644 (file)
@@ -109,7 +109,6 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
        int ret, npages;
 
        ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
-                                     attach->dmabuf->resv,
                                      &etnaviv_gem_prime_ops, &etnaviv_obj);
        if (ret < 0)
                return ERR_PTR(ret);
index 58baf49..cc53dca 100644 (file)
@@ -75,29 +75,29 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
 
 static const struct drm_ioctl_desc exynos_ioctls[] = {
        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP, exynos_drm_gem_map_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl,
                        DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl,
                        DRM_AUTH),
        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_RESOURCES,
                        exynos_drm_ipp_get_res_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_CAPS, exynos_drm_ipp_get_caps_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_LIMITS,
                        exynos_drm_ipp_get_limits_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_COMMIT, exynos_drm_ipp_commit_ioctl,
-                       DRM_AUTH | DRM_RENDER_ALLOW),
+                       DRM_RENDER_ALLOW),
 };
 
 static const struct file_operations exynos_drm_driver_fops = {
@@ -112,7 +112,7 @@ static const struct file_operations exynos_drm_driver_fops = {
 };
 
 static struct drm_driver exynos_drm_driver = {
-       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
+       .driver_features        = DRIVER_MODESET | DRIVER_GEM
                                  | DRIVER_ATOMIC | DRIVER_RENDER,
        .open                   = exynos_drm_open,
        .lastclose              = drm_fb_helper_lastclose,
@@ -122,7 +122,6 @@ static struct drm_driver exynos_drm_driver = {
        .dumb_create            = exynos_drm_gem_dumb_create,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_import       = exynos_drm_gem_prime_import,
        .gem_prime_get_sg_table = exynos_drm_gem_prime_get_sg_table,
        .gem_prime_import_sg_table      = exynos_drm_gem_prime_import_sg_table,
index f4635be..b9ca81a 100644 (file)
@@ -8,12 +8,13 @@
 #include <linux/clk.h>
 #include <linux/regmap.h>
 
-#include <drm/drmP.h>
+#include <video/videomode.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_probe_helper.h>
-#include <video/videomode.h>
+#include <drm/drm_vblank.h>
 
 #include "fsl_dcu_drm_crtc.h"
 #include "fsl_dcu_drm_drv.h"
index e81daaa..f15d2e7 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_irq.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "fsl_dcu_drm_crtc.h"
 #include "fsl_dcu_drm_drv.h"
@@ -133,8 +135,7 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
 DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops);
 
 static struct drm_driver fsl_dcu_drm_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET
-                               | DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .load                   = fsl_dcu_load,
        .unload                 = fsl_dcu_unload,
        .irq_handler            = fsl_dcu_drm_irq,
@@ -144,8 +145,6 @@ static struct drm_driver fsl_dcu_drm_driver = {
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 2467c89..d763f53 100644 (file)
@@ -5,7 +5,6 @@
  * Freescale DCU drm device driver
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
index 6f2f650..86fac67 100644 (file)
@@ -7,10 +7,10 @@
 
 #include <linux/regmap.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
index c49e9e3..279d83e 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/backlight.h>
 #include <linux/of_graph.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index 08657a3..cc4c417 100644 (file)
  *     Jianhua Li <lijianhua@huawei.com>
  */
 
+#include <linux/delay.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
index ce89e56..2ae5388 100644 (file)
 
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_vram_mm_helper.h>
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
@@ -51,10 +58,9 @@ static struct drm_driver hibmc_driver = {
        .desc                   = "hibmc drm driver",
        .major                  = 1,
        .minor                  = 0,
-       .gem_free_object_unlocked =
-               drm_gem_vram_driver_gem_free_object_unlocked,
        .dumb_create            = hibmc_dumb_create,
        .dumb_map_offset        = drm_gem_vram_driver_dumb_mmap_offset,
+       .gem_prime_mmap         = drm_gem_prime_mmap,
        .irq_handler            = hibmc_drm_interrupt,
 };
 
index 69348bf..e58ecd7 100644 (file)
 #ifndef HIBMC_DRM_DRV_H
 #define HIBMC_DRM_DRV_H
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_vram_mm_helper.h>
+#include <drm/drm_framebuffer.h>
+
+struct drm_device;
+struct drm_gem_object;
 
 struct hibmc_framebuffer {
        struct drm_framebuffer fb;
index af1ea4c..b4c1cea 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "hibmc_drm_drv.h"
index 634a3bf..6d98fdc 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
index 5d4a03c..9f6e473 100644 (file)
  *     Jianhua Li <lijianhua@huawei.com>
  */
 
+#include <linux/pci.h>
+
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vram_mm_helper.h>
 
 #include "hibmc_drm_drv.h"
 
@@ -60,7 +66,7 @@ int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
                        DRM_ERROR("failed to allocate GEM object: %d\n", ret);
                return ret;
        }
-       *obj = &gbo->gem;
+       *obj = &gbo->bo.base;
        return 0;
 }
 
index ad7042a..0df1afd 100644 (file)
 
 #include <linux/bitops.h>
 #include <linux/clk.h>
-#include <video/display_timing.h>
 #include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
-#include <drm/drmP.h>
+#include <video/display_timing.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "kirin_drm_drv.h"
 #include "kirin_ade_reg.h"
index 4a7fe10..204c94c 100644 (file)
 
 #include <linux/of_platform.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_graph.h>
+#include <linux/platform_device.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "kirin_drm_drv.h"
 
@@ -113,8 +116,7 @@ static int kirin_gem_cma_dumb_create(struct drm_file *file,
 }
 
 static struct drm_driver kirin_drm_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &kirin_drm_fops,
 
        .gem_free_object_unlocked = drm_gem_cma_free_object,
@@ -123,8 +125,6 @@ static struct drm_driver kirin_drm_driver = {
 
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_export       = drm_gem_prime_export,
-       .gem_prime_import       = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index b6e0919..986b045 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef __DRM_I2C_CH7006_PRIV_H__
 #define __DRM_I2C_CH7006_PRIV_H__
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_encoder_slave.h>
 #include <drm/drm_probe_helper.h>
index 878ba8d..8bcf0d1 100644 (file)
@@ -26,8 +26,9 @@
 
 #include <linux/module.h>
 
-#include <drm/drmP.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_encoder_slave.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/i2c/sil164.h>
 
index 3b37893..2a77823 100644 (file)
  *
  */
 
-#include <drm/drmP.h>
+#include <linux/delay.h>
+#include <linux/mman.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_print.h>
 #include <drm/i810_drm.h>
+
 #include "i810_drv.h"
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
 
 #define I810_BUF_FREE          2
 #define I810_BUF_CLIENT                1
index c69d5c4..5dd26a0 100644 (file)
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include "i810_drv.h"
 #include <linux/module.h>
 
-#include <drm/drmP.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_pciids.h>
 #include <drm/i810_drm.h>
-#include "i810_drv.h"
 
-#include <drm/drm_pciids.h>
 
 static struct pci_device_id pciidlist[] = {
        i810_PCI_IDS
index c73d2f2..9df3981 100644 (file)
@@ -32,7 +32,9 @@
 #ifndef _I810_DRV_H_
 #define _I810_DRV_H_
 
+#include <drm/drm_ioctl.h>
 #include <drm/drm_legacy.h>
+#include <drm/i810_drm.h>
 
 /* General customization:
  */
index c6f38c7..cf3c3fd 100644 (file)
@@ -3562,7 +3562,8 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
        /* Enable hdcp if it's desired */
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED)
-               intel_hdcp_enable(to_intel_connector(conn_state->connector));
+               intel_hdcp_enable(to_intel_connector(conn_state->connector),
+                                 (u8)conn_state->hdcp_content_type);
 }
 
 static void intel_disable_ddi_dp(struct intel_encoder *encoder,
@@ -3631,15 +3632,41 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
                                  const struct intel_crtc_state *crtc_state,
                                  const struct drm_connector_state *conn_state)
 {
+       struct intel_connector *connector =
+                               to_intel_connector(conn_state->connector);
+       struct intel_hdcp *hdcp = &connector->hdcp;
+       bool content_protection_type_changed =
+                       (conn_state->hdcp_content_type != hdcp->content_type &&
+                        conn_state->content_protection !=
+                        DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
+
        if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
                intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state);
 
+       /*
+        * During the HDCP encryption session if Type change is requested,
+        * disable the HDCP and reenable it with new TYPE value.
+        */
        if (conn_state->content_protection ==
-           DRM_MODE_CONTENT_PROTECTION_DESIRED)
-               intel_hdcp_enable(to_intel_connector(conn_state->connector));
-       else if (conn_state->content_protection ==
-                DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
-               intel_hdcp_disable(to_intel_connector(conn_state->connector));
+           DRM_MODE_CONTENT_PROTECTION_UNDESIRED ||
+           content_protection_type_changed)
+               intel_hdcp_disable(connector);
+
+       /*
+        * Mark the hdcp state as DESIRED after the hdcp disable of type
+        * change procedure.
+        */
+       if (content_protection_type_changed) {
+               mutex_lock(&hdcp->mutex);
+               hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+               schedule_work(&hdcp->prop_work);
+               mutex_unlock(&hdcp->mutex);
+       }
+
+       if (conn_state->content_protection ==
+           DRM_MODE_CONTENT_PROTECTION_DESIRED ||
+           content_protection_type_changed)
+               intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
 }
 
 static void
index a78139f..845eb8f 100644 (file)
@@ -869,7 +869,6 @@ static void intel_hdcp_prop_work(struct work_struct *work)
                                               prop_work);
        struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
        struct drm_device *dev = connector->base.dev;
-       struct drm_connector_state *state;
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
        mutex_lock(&hdcp->mutex);
@@ -879,10 +878,9 @@ static void intel_hdcp_prop_work(struct work_struct *work)
         * those to UNDESIRED is handled by core. If value == UNDESIRED,
         * we're running just after hdcp has been disabled, so just exit
         */
-       if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-               state = connector->base.state;
-               state->content_protection = hdcp->value;
-       }
+       if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+               drm_hdcp_update_content_protection(&connector->base,
+                                                  hdcp->value);
 
        mutex_unlock(&hdcp->mutex);
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -1754,14 +1752,15 @@ static const struct component_ops i915_hdcp_component_ops = {
        .unbind = i915_hdcp_component_unbind,
 };
 
-static inline int initialize_hdcp_port_data(struct intel_connector *connector)
+static inline int initialize_hdcp_port_data(struct intel_connector *connector,
+                                           const struct intel_hdcp_shim *shim)
 {
        struct intel_hdcp *hdcp = &connector->hdcp;
        struct hdcp_port_data *data = &hdcp->port_data;
 
        data->port = connector->encoder->port;
        data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
-       data->protocol = (u8)hdcp->shim->protocol;
+       data->protocol = (u8)shim->protocol;
 
        data->k = 1;
        if (!data->streams)
@@ -1811,12 +1810,13 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv)
        }
 }
 
-static void intel_hdcp2_init(struct intel_connector *connector)
+static void intel_hdcp2_init(struct intel_connector *connector,
+                            const struct intel_hdcp_shim *shim)
 {
        struct intel_hdcp *hdcp = &connector->hdcp;
        int ret;
 
-       ret = initialize_hdcp_port_data(connector);
+       ret = initialize_hdcp_port_data(connector, shim);
        if (ret) {
                DRM_DEBUG_KMS("Mei hdcp data init failed\n");
                return;
@@ -1835,23 +1835,28 @@ int intel_hdcp_init(struct intel_connector *connector,
        if (!shim)
                return -EINVAL;
 
-       ret = drm_connector_attach_content_protection_property(&connector->base);
-       if (ret)
+       if (is_hdcp2_supported(dev_priv))
+               intel_hdcp2_init(connector, shim);
+
+       ret =
+       drm_connector_attach_content_protection_property(&connector->base,
+                                                        hdcp->hdcp2_supported);
+       if (ret) {
+               hdcp->hdcp2_supported = false;
+               kfree(hdcp->port_data.streams);
                return ret;
+       }
 
        hdcp->shim = shim;
        mutex_init(&hdcp->mutex);
        INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work);
        INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work);
-
-       if (is_hdcp2_supported(dev_priv))
-               intel_hdcp2_init(connector);
        init_waitqueue_head(&hdcp->cp_irq_queue);
 
        return 0;
 }
 
-int intel_hdcp_enable(struct intel_connector *connector)
+int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
 {
        struct intel_hdcp *hdcp = &connector->hdcp;
        unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
@@ -1862,6 +1867,7 @@ int intel_hdcp_enable(struct intel_connector *connector)
 
        mutex_lock(&hdcp->mutex);
        WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
+       hdcp->content_type = content_type;
 
        /*
         * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
@@ -1873,8 +1879,12 @@ int intel_hdcp_enable(struct intel_connector *connector)
                        check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS;
        }
 
-       /* When HDCP2.2 fails, HDCP1.4 will be attempted */
-       if (ret && intel_hdcp_capable(connector)) {
+       /*
+        * When HDCP2.2 fails and Content Type is not Type1, HDCP1.4 will
+        * be attempted.
+        */
+       if (ret && intel_hdcp_capable(connector) &&
+           hdcp->content_type != DRM_MODE_HDCP_CONTENT_TYPE1) {
                ret = _intel_hdcp_enable(connector);
        }
 
@@ -1956,12 +1966,15 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 
        /*
         * Nothing to do if the state didn't change, or HDCP was activated since
-        * the last commit
+        * the last commit. And also no change in hdcp content type.
         */
        if (old_cp == new_cp ||
            (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
-            new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
-               return;
+            new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) {
+               if (old_state->hdcp_content_type ==
+                               new_state->hdcp_content_type)
+                       return;
+       }
 
        crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
                                                   new_state->crtc);
index be8da85..13555b0 100644 (file)
@@ -21,7 +21,7 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
                             struct drm_connector_state *new_state);
 int intel_hdcp_init(struct intel_connector *connector,
                    const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector);
+int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
 int intel_hdcp_disable(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
index cbf1701..570b20a 100644 (file)
@@ -204,8 +204,7 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
        .end_cpu_access = i915_gem_end_cpu_access,
 };
 
-struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
-                                     struct drm_gem_object *gem_obj, int flags)
+struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
 {
        struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
@@ -222,7 +221,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                        return ERR_PTR(ret);
        }
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       return drm_gem_dmabuf_export(gem_obj->dev, &exp_info);
 }
 
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
index 26ec657..fa46a54 100644 (file)
@@ -35,7 +35,6 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
                                 unsigned int flags,
                                 long timeout)
 {
-       unsigned int seq = __read_seqcount_begin(&resv->seq);
        struct dma_fence *excl;
        bool prune_fences = false;
 
@@ -83,15 +82,12 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
 
        /*
         * Opportunistically prune the fences iff we know they have *all* been
-        * signaled and that the reservation object has not been changed (i.e.
-        * no new fences have been added).
+        * signaled.
         */
-       if (prune_fences && !__read_seqcount_retry(&resv->seq, seq)) {
-               if (reservation_object_trylock(resv)) {
-                       if (!__read_seqcount_retry(&resv->seq, seq))
-                               reservation_object_add_excl_fence(resv, NULL);
-                       reservation_object_unlock(resv);
-               }
+       if (prune_fences && reservation_object_trylock(resv)) {
+               if (reservation_object_test_signaled_rcu(resv, true))
+                       reservation_object_add_excl_fence(resv, NULL);
+               reservation_object_unlock(resv);
        }
 
        return timeout;
index e3a64ed..d85d1ce 100644 (file)
@@ -20,7 +20,7 @@ static int igt_dmabuf_export(void *arg)
        if (IS_ERR(obj))
                return PTR_ERR(obj);
 
-       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+       dmabuf = i915_gem_prime_export(&obj->base, 0);
        i915_gem_object_put(obj);
        if (IS_ERR(dmabuf)) {
                pr_err("i915_gem_prime_export failed with err=%d\n",
@@ -44,7 +44,7 @@ static int igt_dmabuf_import_self(void *arg)
        if (IS_ERR(obj))
                return PTR_ERR(obj);
 
-       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+       dmabuf = i915_gem_prime_export(&obj->base, 0);
        if (IS_ERR(dmabuf)) {
                pr_err("i915_gem_prime_export failed with err=%d\n",
                       (int)PTR_ERR(dmabuf));
@@ -219,7 +219,7 @@ static int igt_dmabuf_export_vmap(void *arg)
        if (IS_ERR(obj))
                return PTR_ERR(obj);
 
-       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+       dmabuf = i915_gem_prime_export(&obj->base, 0);
        if (IS_ERR(dmabuf)) {
                pr_err("i915_gem_prime_export failed with err=%d\n",
                       (int)PTR_ERR(dmabuf));
@@ -266,7 +266,7 @@ static int igt_dmabuf_export_kmap(void *arg)
        if (IS_ERR(obj))
                return PTR_ERR(obj);
 
-       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+       dmabuf = i915_gem_prime_export(&obj->base, 0);
        i915_gem_object_put(obj);
        if (IS_ERR(dmabuf)) {
                err = PTR_ERR(dmabuf);
index 41c8ebc..13044c0 100644 (file)
@@ -491,7 +491,7 @@ int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id)
 
        obj->gvt_info = dmabuf_obj->info;
 
-       dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR);
+       dmabuf = i915_gem_prime_export(&obj->base, DRM_CLOEXEC | DRM_RDWR);
        if (IS_ERR(dmabuf)) {
                gvt_vgpu_err("export dma-buf failed\n");
                ret = PTR_ERR(dmabuf);
index 7d08131..f2d3d75 100644 (file)
@@ -3195,9 +3195,9 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW),
 };
@@ -3207,7 +3207,7 @@ static struct drm_driver driver = {
         * deal with them for Intel hardware.
         */
        .driver_features =
-           DRIVER_GEM | DRIVER_PRIME |
+           DRIVER_GEM |
            DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ,
        .release = i915_driver_release,
        .open = i915_driver_open,
index 991eaea..2e13ecc 100644 (file)
@@ -2495,8 +2495,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
                                struct dma_buf *dma_buf);
 
-struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
-                               struct drm_gem_object *gem_obj, int flags);
+struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags);
 
 static inline struct i915_gem_context *
 __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
index 06393cd..5a3ad6f 100644 (file)
@@ -3,19 +3,21 @@
  *
  * derived from imx-hdmi.c(renamed to bridge/dw_hdmi.c now)
  */
-#include <linux/module.h>
-#include <linux/platform_device.h>
+
 #include <linux/component.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <drm/bridge/dw_hdmi.h>
-#include <video/imx-ipu-v3.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
+
+#include <video/imx-ipu-v3.h>
+
+#include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder_slave.h>
+#include <drm/drm_of.h>
 
 #include "imx-drm.h"
 
index 3e8bece..da87c70 100644 (file)
@@ -4,14 +4,18 @@
  *
  * Copyright (C) 2011 Sascha Hauer, Pengutronix
  */
+
 #include <linux/component.h>
 #include <linux/device.h>
 #include <linux/dma-buf.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <drm/drmP.h>
+
+#include <video/imx-ipu-v3.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
@@ -19,7 +23,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <video/imx-ipu-v3.h>
+#include <drm/drm_vblank.h>
 
 #include "imx-drm.h"
 #include "ipuv3-plane.h"
@@ -147,16 +151,13 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 };
 
 static struct drm_driver imx_drm_driver = {
-       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
+       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .dumb_create            = drm_gem_cma_dumb_create,
 
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 3837333..db461b6 100644 (file)
@@ -5,25 +5,27 @@
  * Copyright (C) 2012 Sascha Hauer, Pengutronix
  */
 
-#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/component.h>
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
-#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
 #include <linux/regmap.h>
 #include <linux/videodev2.h>
 
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
 #include "imx-drm.h"
 
 #define DRIVER_NAME "imx-ldb"
@@ -460,9 +462,10 @@ static int imx_ldb_register(struct drm_device *drm,
                 */
                drm_connector_helper_add(&imx_ldb_ch->connector,
                                &imx_ldb_connector_helper_funcs);
-               drm_connector_init(drm, &imx_ldb_ch->connector,
-                               &imx_ldb_connector_funcs,
-                               DRM_MODE_CONNECTOR_LVDS);
+               drm_connector_init_with_ddc(drm, &imx_ldb_ch->connector,
+                                           &imx_ldb_connector_funcs,
+                                           DRM_MODE_CONNECTOR_LVDS,
+                                           imx_ldb_ch->ddc);
                drm_connector_attach_encoder(&imx_ldb_ch->connector, encoder);
        }
 
index e725af8..5bbfaa2 100644 (file)
@@ -5,20 +5,22 @@
  * Copyright (C) 2013 Philipp Zabel, Pengutronix
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <linux/component.h>
-#include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
-#include <drm/drmP.h>
+
+#include <video/imx-ipu-v3.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <video/imx-ipu-v3.h>
 
 #include "imx-drm.h"
 
@@ -482,8 +484,10 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
 
        drm_connector_helper_add(&tve->connector,
                        &imx_tve_connector_helper_funcs);
-       drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
-                          DRM_MODE_CONNECTOR_VGA);
+       drm_connector_init_with_ddc(drm, &tve->connector,
+                                   &imx_tve_connector_funcs,
+                                   DRM_MODE_CONNECTOR_VGA,
+                                   tve->ddc);
 
        drm_connector_attach_encoder(&tve->connector, &tve->encoder);
 
index c436a28..63c0284 100644 (file)
@@ -4,21 +4,25 @@
  *
  * Copyright (C) 2011 Sascha Hauer, Pengutronix
  */
+
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <drm/drmP.h>
+
+#include <video/imx-ipu-v3.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
-#include <video/imx-ipu-v3.h>
 #include "imx-drm.h"
 #include "ipuv3-plane.h"
 
index 2a1e071..28826c0 100644 (file)
@@ -5,15 +5,16 @@
  * Copyright (C) 2013 Philipp Zabel, Pengutronix
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 
-#include "video/imx-ipu-v3.h"
+#include <video/imx-ipu-v3.h>
+
 #include "imx-drm.h"
 #include "ipuv3-plane.h"
 
index 1a76de1..2e51b2f 100644 (file)
@@ -7,14 +7,16 @@
 
 #include <linux/component.h>
 #include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+
+#include <video/of_display_timing.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
-#include <linux/videodev2.h>
-#include <video/of_display_timing.h>
 
 #include "imx-drm.h"
 
index e9f9e9f..ce1fae3 100644 (file)
@@ -166,6 +166,8 @@ struct ingenic_drm {
 
        struct ingenic_dma_hwdesc *dma_hwdesc;
        dma_addr_t dma_hwdesc_phys;
+
+       bool panel_is_sharp;
 };
 
 static const u32 ingenic_drm_primary_formats[] = {
@@ -283,6 +285,13 @@ static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv,
        regmap_write(priv->map, JZ_REG_LCD_DAV,
                     vds << JZ_LCD_DAV_VDS_OFFSET |
                     vde << JZ_LCD_DAV_VDE_OFFSET);
+
+       if (priv->panel_is_sharp) {
+               regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1));
+               regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1));
+               regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1));
+               regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16);
+       }
 }
 
 static void ingenic_drm_crtc_update_ctrl(struct ingenic_drm *priv,
@@ -378,11 +387,18 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
 {
        struct ingenic_drm *priv = drm_encoder_get_priv(encoder);
        struct drm_display_mode *mode = &crtc_state->adjusted_mode;
-       struct drm_display_info *info = &conn_state->connector->display_info;
-       unsigned int cfg = JZ_LCD_CFG_PS_DISABLE
-                        | JZ_LCD_CFG_CLS_DISABLE
-                        | JZ_LCD_CFG_SPL_DISABLE
-                        | JZ_LCD_CFG_REV_DISABLE;
+       struct drm_connector *conn = conn_state->connector;
+       struct drm_display_info *info = &conn->display_info;
+       unsigned int cfg;
+
+       priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
+
+       if (priv->panel_is_sharp) {
+               cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
+       } else {
+               cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE
+                   | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
+       }
 
        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
                cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
@@ -393,24 +409,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
        if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
                cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
 
-       if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) {
-               if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-                       cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
-               else
-                       cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
-       } else {
-               switch (*info->bus_formats) {
-               case MEDIA_BUS_FMT_RGB565_1X16:
-                       cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
-                       break;
-               case MEDIA_BUS_FMT_RGB666_1X18:
-                       cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT;
-                       break;
-               case MEDIA_BUS_FMT_RGB888_1X24:
-                       cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT;
-                       break;
-               default:
-                       break;
+       if (!priv->panel_is_sharp) {
+               if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
+                       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+                               cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
+                       else
+                               cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
+               } else {
+                       switch (*info->bus_formats) {
+                       case MEDIA_BUS_FMT_RGB565_1X16:
+                               cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
+                               break;
+                       case MEDIA_BUS_FMT_RGB666_1X18:
+                               cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT;
+                               break;
+                       case MEDIA_BUS_FMT_RGB888_1X24:
+                               cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT;
+                               break;
+                       case MEDIA_BUS_FMT_RGB888_3X8:
+                               cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL;
+                               break;
+                       default:
+                               break;
+                       }
                }
        }
 
@@ -433,6 +454,7 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
        case MEDIA_BUS_FMT_RGB565_1X16:
        case MEDIA_BUS_FMT_RGB666_1X18:
        case MEDIA_BUS_FMT_RGB888_1X24:
+       case MEDIA_BUS_FMT_RGB888_3X8:
                return 0;
        default:
                return -EINVAL;
@@ -484,8 +506,7 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc)
 DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
 
 static struct drm_driver ingenic_drm_driver_data = {
-       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
-                               | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .name                   = "ingenic-drm",
        .desc                   = "DRM module for Ingenic SoCs",
        .date                   = "20190422",
@@ -581,7 +602,6 @@ static int ingenic_drm_probe(struct platform_device *pdev)
        struct drm_bridge *bridge;
        struct drm_panel *panel;
        struct drm_device *drm;
-       struct resource *mem;
        void __iomem *base;
        long parent_rate;
        int ret, irq;
@@ -615,8 +635,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
        drm->mode_config.max_height = 600;
        drm->mode_config.funcs = &ingenic_drm_mode_config_funcs;
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(dev, mem);
+       base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base)) {
                dev_err(dev, "Failed to get memory resource");
                return PTR_ERR(base);
index 570d0e9..d86b8d8 100644 (file)
@@ -80,26 +80,23 @@ const char *lima_ip_name(struct lima_ip *ip)
 static int lima_clk_init(struct lima_device *dev)
 {
        int err;
-       unsigned long bus_rate, gpu_rate;
 
        dev->clk_bus = devm_clk_get(dev->dev, "bus");
        if (IS_ERR(dev->clk_bus)) {
-               dev_err(dev->dev, "get bus clk failed %ld\n", PTR_ERR(dev->clk_bus));
-               return PTR_ERR(dev->clk_bus);
+               err = PTR_ERR(dev->clk_bus);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev->dev, "get bus clk failed %d\n", err);
+               return err;
        }
 
        dev->clk_gpu = devm_clk_get(dev->dev, "core");
        if (IS_ERR(dev->clk_gpu)) {
-               dev_err(dev->dev, "get core clk failed %ld\n", PTR_ERR(dev->clk_gpu));
-               return PTR_ERR(dev->clk_gpu);
+               err = PTR_ERR(dev->clk_gpu);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev->dev, "get core clk failed %d\n", err);
+               return err;
        }
 
-       bus_rate = clk_get_rate(dev->clk_bus);
-       dev_info(dev->dev, "bus rate = %lu\n", bus_rate);
-
-       gpu_rate = clk_get_rate(dev->clk_gpu);
-       dev_info(dev->dev, "mod rate = %lu", gpu_rate);
-
        err = clk_prepare_enable(dev->clk_bus);
        if (err)
                return err;
@@ -111,11 +108,17 @@ static int lima_clk_init(struct lima_device *dev)
        dev->reset = devm_reset_control_get_optional(dev->dev, NULL);
        if (IS_ERR(dev->reset)) {
                err = PTR_ERR(dev->reset);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev->dev, "get reset controller failed %d\n",
+                               err);
                goto error_out1;
        } else if (dev->reset != NULL) {
                err = reset_control_deassert(dev->reset);
-               if (err)
+               if (err) {
+                       dev_err(dev->dev,
+                               "reset controller deassert failed %d\n", err);
                        goto error_out1;
+               }
        }
 
        return 0;
@@ -145,7 +148,8 @@ static int lima_regulator_init(struct lima_device *dev)
                dev->regulator = NULL;
                if (ret == -ENODEV)
                        return 0;
-               dev_err(dev->dev, "failed to get regulator: %d\n", ret);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev->dev, "failed to get regulator: %d\n", ret);
                return ret;
        }
 
@@ -291,16 +295,12 @@ int lima_device_init(struct lima_device *ldev)
        dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32));
 
        err = lima_clk_init(ldev);
-       if (err) {
-               dev_err(ldev->dev, "clk init fail %d\n", err);
+       if (err)
                return err;
-       }
 
        err = lima_regulator_init(ldev);
-       if (err) {
-               dev_err(ldev->dev, "regulator init fail %d\n", err);
+       if (err)
                goto err_out0;
-       }
 
        ldev->empty_vm = lima_vm_create(ldev);
        if (!ldev->empty_vm) {
@@ -343,6 +343,9 @@ int lima_device_init(struct lima_device *ldev)
        if (err)
                goto err_out5;
 
+       dev_info(ldev->dev, "bus rate = %lu\n", clk_get_rate(ldev->clk_bus));
+       dev_info(ldev->dev, "mod rate = %lu", clk_get_rate(ldev->clk_gpu));
+
        return 0;
 
 err_out5:
index b29c26c..75ec703 100644 (file)
@@ -231,13 +231,13 @@ static void lima_drm_driver_postclose(struct drm_device *dev, struct drm_file *f
 }
 
 static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM, lima_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE, lima_ioctl_ctx_create, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE, lima_ioctl_ctx_free, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM, lima_ioctl_get_param, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE, lima_ioctl_ctx_create, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE, lima_ioctl_ctx_free, DRM_RENDER_ALLOW),
 };
 
 static const struct file_operations lima_drm_driver_fops = {
@@ -252,7 +252,7 @@ static const struct file_operations lima_drm_driver_fops = {
 };
 
 static struct drm_driver lima_drm_driver = {
-       .driver_features    = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME | DRIVER_SYNCOBJ,
+       .driver_features    = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,
        .open               = lima_drm_driver_open,
        .postclose          = lima_drm_driver_postclose,
        .ioctls             = lima_drm_driver_ioctls,
@@ -307,10 +307,8 @@ static int lima_pdev_probe(struct platform_device *pdev)
        ldev->ddev = ddev;
 
        err = lima_device_init(ldev);
-       if (err) {
-               dev_err(&pdev->dev, "Fatal error during GPU init\n");
+       if (err)
                goto err_out1;
-       }
 
        /*
         * Register the DRM device with the core and the connectors with
index 477c0f7..fd1a024 100644 (file)
@@ -24,7 +24,7 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
        struct lima_bo *bo;
        struct lima_device *ldev = to_lima_dev(dev);
 
-       bo = lima_bo_create(ldev, size, flags, NULL, NULL);
+       bo = lima_bo_create(ldev, size, flags, NULL);
        if (IS_ERR(bo))
                return PTR_ERR(bo);
 
index 9c6d9f1..e3eb251 100644 (file)
@@ -18,8 +18,7 @@ struct drm_gem_object *lima_gem_prime_import_sg_table(
        struct lima_device *ldev = to_lima_dev(dev);
        struct lima_bo *bo;
 
-       bo = lima_bo_create(ldev, attach->dmabuf->size, 0, sgt,
-                           attach->dmabuf->resv);
+       bo = lima_bo_create(ldev, attach->dmabuf->size, 0, sgt);
        if (IS_ERR(bo))
                return ERR_CAST(bo);
 
index 5c41f85..87123b1 100644 (file)
@@ -33,8 +33,7 @@ void lima_bo_destroy(struct lima_bo *bo)
        kfree(bo);
 }
 
-static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, u32 flags,
-                                            struct reservation_object *resv)
+static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, u32 flags)
 {
        struct lima_bo *bo;
        int err;
@@ -47,7 +46,6 @@ static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size,
 
        mutex_init(&bo->lock);
        INIT_LIST_HEAD(&bo->va);
-       bo->gem.resv = resv;
 
        err = drm_gem_object_init(dev->ddev, &bo->gem, size);
        if (err) {
@@ -59,14 +57,13 @@ static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size,
 }
 
 struct lima_bo *lima_bo_create(struct lima_device *dev, u32 size,
-                              u32 flags, struct sg_table *sgt,
-                              struct reservation_object *resv)
+                              u32 flags, struct sg_table *sgt)
 {
        int i, err;
        size_t npages;
        struct lima_bo *bo, *ret;
 
-       bo = lima_bo_create_struct(dev, size, flags, resv);
+       bo = lima_bo_create_struct(dev, size, flags);
        if (IS_ERR(bo))
                return bo;
 
index 6738724..31ca2d8 100644 (file)
@@ -27,8 +27,7 @@ to_lima_bo(struct drm_gem_object *obj)
 }
 
 struct lima_bo *lima_bo_create(struct lima_device *dev, u32 size,
-                              u32 flags, struct sg_table *sgt,
-                              struct reservation_object *resv);
+                              u32 flags, struct sg_table *sgt);
 void lima_bo_destroy(struct lima_bo *bo);
 void *lima_bo_vmap(struct lima_bo *bo);
 void lima_bo_vunmap(struct lima_bo *bo);
index caee2f8..e0bdedc 100644 (file)
@@ -15,9 +15,9 @@
 #define LIMA_VM_NUM_PT_PER_BT (1 << LIMA_VM_NUM_PT_PER_BT_SHIFT)
 #define LIMA_VM_NUM_BT (LIMA_PAGE_ENT_NUM >> LIMA_VM_NUM_PT_PER_BT_SHIFT)
 
-#define LIMA_VA_RESERVE_START  0xFFF00000
+#define LIMA_VA_RESERVE_START  0x0FFF00000ULL
 #define LIMA_VA_RESERVE_DLBU   LIMA_VA_RESERVE_START
-#define LIMA_VA_RESERVE_END    0x100000000
+#define LIMA_VA_RESERVE_END    0x100000000ULL
 
 struct lima_device;
 
index baf63fb..982fe84 100644 (file)
@@ -237,7 +237,7 @@ DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
 
 static struct drm_driver mcde_drm_driver = {
        .driver_features =
-               DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+               DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .release = mcde_release,
        .lastclose = drm_fb_helper_lastclose,
        .ioctls = NULL,
@@ -254,8 +254,6 @@ static struct drm_driver mcde_drm_driver = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_import = drm_gem_prime_import,
-       .gem_prime_export = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
@@ -319,7 +317,7 @@ static int mcde_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct drm_device *drm;
        struct mcde *mcde;
-       struct component_match *match;
+       struct component_match *match = NULL;
        struct resource *res;
        u32 pid;
        u32 val;
@@ -485,6 +483,10 @@ static int mcde_probe(struct platform_device *pdev)
                }
                put_device(p);
        }
+       if (!match) {
+               dev_err(dev, "no matching components\n");
+               return -ENODEV;
+       }
        if (IS_ERR(match)) {
                dev_err(dev, "could not create component match\n");
                ret = PTR_ERR(match);
index f33d98b..59de2a4 100644 (file)
@@ -3,9 +3,9 @@
  * Copyright (c) 2017 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
index c4f07c2..2185175 100644 (file)
@@ -3,9 +3,9 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
index 9a6f0a2..405afef 100644 (file)
@@ -3,9 +3,9 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
index bacd989..be6d95c 100644 (file)
@@ -3,21 +3,23 @@
  * Copyright (c) 2014 MediaTek Inc.
  * Author: Jie Qiu <jie.qiu@mediatek.com>
  */
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_of.h>
-#include <linux/kernel.h>
+
+#include <linux/clk.h>
 #include <linux/component.h>
-#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
-#include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <linux/types.h>
-#include <linux/clk.h>
+
 #include <video/videomode.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_of.h>
+
 #include "mtk_dpi_regs.h"
 #include "mtk_drm_ddp_comp.h"
 
index a900721..34a7317 100644 (file)
@@ -3,14 +3,16 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
 #include <asm/barrier.h>
-#include <drm/drmP.h>
+#include <soc/mediatek/smi.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <soc/mediatek/smi.h>
+#include <drm/drm_vblank.h>
 
 #include "mtk_drm_drv.h"
 #include "mtk_drm_crtc.h"
index b38963f..efa8597 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <drm/drmP.h>
+
 #include "mtk_drm_drv.h"
 #include "mtk_drm_plane.h"
 #include "mtk_drm_ddp_comp.h"
index 95fdbd0..2ee809a 100644 (file)
@@ -4,22 +4,26 @@
  * Author: YT SHEN <yt.shen@mediatek.com>
  */
 
-#include <drm/drmP.h>
+#include <linux/component.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
-#include <linux/component.h>
-#include <linux/iommu.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/pm_runtime.h>
+#include <drm/drm_vblank.h>
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp.h"
+#include "mtk_drm_ddp.h"
 #include "mtk_drm_ddp_comp.h"
 #include "mtk_drm_drv.h"
 #include "mtk_drm_fb.h"
@@ -38,22 +42,12 @@ static void mtk_atomic_schedule(struct mtk_drm_private *private,
        schedule_work(&private->commit.work);
 }
 
-static void mtk_atomic_wait_for_fences(struct drm_atomic_state *state)
-{
-       struct drm_plane *plane;
-       struct drm_plane_state *new_plane_state;
-       int i;
-
-       for_each_new_plane_in_state(state, plane, new_plane_state, i)
-               mtk_fb_wait(new_plane_state->fb);
-}
-
 static void mtk_atomic_complete(struct mtk_drm_private *private,
                                struct drm_atomic_state *state)
 {
        struct drm_device *drm = private->drm;
 
-       mtk_atomic_wait_for_fences(state);
+       drm_atomic_helper_wait_for_fences(drm, state, false);
 
        /*
         * Mediatek drm supports runtime PM, so plane registers cannot be
@@ -321,8 +315,7 @@ static const struct file_operations mtk_drm_fops = {
 };
 
 static struct drm_driver mtk_drm_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 
        .gem_free_object_unlocked = mtk_drm_gem_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
@@ -330,8 +323,6 @@ static struct drm_driver mtk_drm_driver = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
        .gem_prime_mmap = mtk_drm_gem_mmap_buf,
index 4c3ad7d..ae40b08 100644 (file)
@@ -3,13 +3,14 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
+#include <linux/dma-buf.h>
+#include <linux/reservation.h>
+
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <linux/dma-buf.h>
-#include <linux/reservation.h>
 
 #include "mtk_drm_drv.h"
 #include "mtk_drm_fb.h"
@@ -49,34 +50,6 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev,
        return fb;
 }
 
-/*
- * Wait for any exclusive fence in fb's gem object's reservation object.
- *
- * Returns -ERESTARTSYS if interrupted, else 0.
- */
-int mtk_fb_wait(struct drm_framebuffer *fb)
-{
-       struct drm_gem_object *gem;
-       struct reservation_object *resv;
-       long ret;
-
-       if (!fb)
-               return 0;
-
-       gem = fb->obj[0];
-       if (!gem || !gem->dma_buf || !gem->dma_buf->resv)
-               return 0;
-
-       resv = gem->dma_buf->resv;
-       ret = reservation_object_wait_timeout_rcu(resv, false, true,
-                                                 MAX_SCHEDULE_TIMEOUT);
-       /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */
-       if (WARN_ON(ret < 0))
-               return ret;
-
-       return 0;
-}
-
 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
                                               struct drm_file *file,
                                               const struct drm_mode_fb_cmd2 *cmd)
index 6b80c28..eb64d26 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef MTK_DRM_FB_H
 #define MTK_DRM_FB_H
 
-int mtk_fb_wait(struct drm_framebuffer *fb);
 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
                                               struct drm_file *file,
                                               const struct drm_mode_fb_cmd2 *cmd);
index 0d69698..ca672f1 100644 (file)
@@ -3,10 +3,13 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_gem.h>
 #include <linux/dma-buf.h>
 
+#include <drm/drm.h>
+#include <drm/drm_device.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_prime.h>
+
 #include "mtk_drm_drv.h"
 #include "mtk_drm_gem.h"
 
index f2ef83a..584a9ec 100644 (file)
@@ -4,10 +4,11 @@
  * Author: CK Hu <ck.hu@mediatek.com>
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp_comp.h"
@@ -146,6 +147,7 @@ static void mtk_plane_atomic_disable(struct drm_plane *plane,
 }
 
 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
+       .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = mtk_plane_atomic_check,
        .atomic_update = mtk_plane_atomic_update,
        .atomic_disable = mtk_plane_atomic_disable,
index b91c461..224afb6 100644 (file)
@@ -3,12 +3,6 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/iopoll.h>
 #include <linux/of_platform.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+
 #include <video/mipi_display.h>
 #include <video/videomode.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
 #include "mtk_drm_ddp_comp.h"
 
 #define DSI_START              0x00
index 5d6a9f0..ce91b61 100644 (file)
@@ -3,11 +3,7 @@
  * Copyright (c) 2014 MediaTek Inc.
  * Author: Jie Qiu <jie.qiu@mediatek.com>
  */
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_edid.h>
+
 #include <linux/arm-smccc.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+
 #include <sound/hdmi-codec.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
 #include "mtk_cec.h"
 #include "mtk_hdmi.h"
 #include "mtk_hdmi_regs.h"
index aa8ea10..3320a74 100644 (file)
@@ -9,23 +9,21 @@
  *     Jasper St. Pierre <jstpierre@mecheye.net>
  */
 
-#include <linux/kernel.h>
-#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 <linux/soc/amlogic/meson-canvas.h>
+
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_flip_work.h>
+#include <drm/drm_device.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "meson_crtc.h"
 #include "meson_plane.h"
+#include "meson_registers.h"
 #include "meson_venc.h"
-#include "meson_vpp.h"
 #include "meson_viu.h"
-#include "meson_registers.h"
+#include "meson_vpp.h"
 
 #define MESON_G12A_VIU_OFFSET  0x5ec0
 
index 2310c96..42af49a 100644 (file)
@@ -8,35 +8,30 @@
  *     Jasper St. Pierre <jstpierre@mecheye.net>
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/soc/amlogic/meson-canvas.h>
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_flip_work.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
 
+#include "meson_crtc.h"
 #include "meson_drv.h"
-#include "meson_plane.h"
 #include "meson_overlay.h"
-#include "meson_crtc.h"
+#include "meson_plane.h"
+#include "meson_registers.h"
 #include "meson_venc_cvbs.h"
-
-#include "meson_vpp.h"
 #include "meson_viu.h"
-#include "meson_venc.h"
-#include "meson_registers.h"
+#include "meson_vpp.h"
 
 #define DRIVER_NAME "meson"
 #define DRIVER_DESC "Amlogic Meson DRM driver"
@@ -93,9 +88,7 @@ static int meson_dumb_create(struct drm_file *file, struct drm_device *dev,
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver meson_driver = {
-       .driver_features        = DRIVER_GEM |
-                                 DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 
        /* IRQ */
        .irq_handler            = meson_irq,
@@ -103,8 +96,6 @@ static struct drm_driver meson_driver = {
        /* PRIME Ops */
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 7b6593f..c9aaec1 100644 (file)
@@ -7,11 +7,14 @@
 #ifndef __MESON_DRV_H
 #define __MESON_DRV_H
 
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
+#include <linux/device.h>
 #include <linux/of.h>
-#include <linux/soc/amlogic/meson-canvas.h>
-#include <drm/drmP.h>
+#include <linux/regmap.h>
+
+struct drm_crtc;
+struct drm_device;
+struct drm_plane;
+struct meson_drm;
 
 struct meson_drm {
        struct device *dev;
index df3f9dd..9f0b08e 100644 (file)
@@ -5,29 +5,30 @@
  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  */
 
+#include <linux/clk.h>
+#include <linux/component.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/component.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
-#include <linux/reset.h>
-#include <linux/clk.h>
 #include <linux/regulator/consumer.h>
+#include <linux/reset.h>
 
-#include <drm/drmP.h>
+#include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_device.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_print.h>
 
-#include <uapi/linux/media-bus-format.h>
-#include <uapi/linux/videodev2.h>
+#include <linux/media-bus-format.h>
+#include <linux/videodev2.h>
 
 #include "meson_drv.h"
-#include "meson_venc.h"
-#include "meson_vclk.h"
 #include "meson_dw_hdmi.h"
 #include "meson_registers.h"
+#include "meson_vclk.h"
+#include "meson_venc.h"
 
 #define DRIVER_NAME "meson-dw-hdmi"
 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
index cc7c6ae..5aa9dcb 100644 (file)
@@ -5,24 +5,21 @@
  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/bitfield.h>
-#include <linux/platform_device.h>
-#include <drm/drmP.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_device.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_rect.h>
 
 #include "meson_overlay.h"
-#include "meson_vpp.h"
-#include "meson_viu.h"
 #include "meson_registers.h"
+#include "meson_viu.h"
+#include "meson_vpp.h"
 
 /* VD1_IF0_GEN_REG */
 #define VD_URGENT_CHROMA               BIT(28)
index 7a7e88d..80b8d70 100644 (file)
@@ -9,24 +9,20 @@
  *     Jasper St. Pierre <jstpierre@mecheye.net>
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/bitfield.h>
-#include <linux/platform_device.h>
-#include <drm/drmP.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_device.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_rect.h>
+#include <drm/drm_plane_helper.h>
 
 #include "meson_plane.h"
-#include "meson_vpp.h"
-#include "meson_viu.h"
 #include "meson_registers.h"
+#include "meson_viu.h"
 
 /* OSD_SCI_WH_M1 */
 #define SCI_WH_M1_W(w)                 FIELD_PREP(GENMASK(28, 16), w)
index 410e324..057453c 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __MESON_REGISTERS_H
 #define __MESON_REGISTERS_H
 
+#include <linux/io.h>
+
 /* Shift all registers by 2 */
 #define _REG(reg)      ((reg) << 2)
 
index 26732f0..8abff51 100644 (file)
@@ -5,9 +5,10 @@
  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/export.h>
+
+#include <drm/drm_print.h>
+
 #include "meson_drv.h"
 #include "meson_vclk.h"
 
index ed993d2..b621255 100644 (file)
@@ -9,6 +9,10 @@
 #ifndef __MESON_VCLK_H
 #define __MESON_VCLK_H
 
+#include <drm/drm_modes.h>
+
+struct meson_drm;
+
 enum {
        MESON_VCLK_TARGET_CVBS = 0,
        MESON_VCLK_TARGET_HDMI = 1,
index 7b7a0d8..3d47917 100644 (file)
@@ -5,14 +5,14 @@
  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/export.h>
+
+#include <drm/drm_modes.h>
+
 #include "meson_drv.h"
+#include "meson_registers.h"
 #include "meson_venc.h"
 #include "meson_vpp.h"
-#include "meson_vclk.h"
-#include "meson_registers.h"
 
 /**
  * DOC: Video Encoder
index 985642a..576768b 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __MESON_VENC_H
 #define __MESON_VENC_H
 
+struct drm_display_mode;
+
 enum {
        MESON_VENC_MODE_NONE = 0,
        MESON_VENC_MODE_CVBS_PAL,
index 6313a51..45a467f 100644 (file)
@@ -9,19 +9,18 @@
  *     Jasper St. Pierre <jstpierre@mecheye.net>
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/of_graph.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_device.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
 
-#include "meson_venc_cvbs.h"
-#include "meson_venc.h"
-#include "meson_vclk.h"
 #include "meson_registers.h"
+#include "meson_vclk.h"
+#include "meson_venc_cvbs.h"
 
 /* HHI VDAC Registers */
 #define HHI_VDAC_CNTL0         0x2F4 /* 0xbd offset in data sheet */
index 4b2b302..9f8a450 100644 (file)
@@ -6,13 +6,10 @@
  * Copyright (C) 2014 Endless Mobile
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/export.h>
+
 #include "meson_drv.h"
 #include "meson_viu.h"
-#include "meson_vpp.h"
-#include "meson_venc.h"
 #include "meson_registers.h"
 
 /**
index bfee30f..cbe6cf4 100644 (file)
@@ -6,12 +6,11 @@
  * Copyright (C) 2014 Endless Mobile
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/export.h>
+
 #include "meson_drv.h"
-#include "meson_vpp.h"
 #include "meson_registers.h"
+#include "meson_vpp.h"
 
 /**
  * DOC: Video Post Processing
index 9fc82db..afc9553 100644 (file)
@@ -9,6 +9,9 @@
 #ifndef __MESON_VPP_H
 #define __MESON_VPP_H
 
+struct drm_rect;
+struct meson_drm;
+
 /* Mux VIU/VPP to ENCI */
 #define MESON_VIU_VPP_MUX_ENCI 0x5
 /* Mux VIU/VPP to ENCP */
index 1ffdafe..85c7436 100644 (file)
@@ -35,8 +35,8 @@
  * \author Gareth Hughes <gareth@valinux.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
+#include <linux/delay.h>
+
 #include "mga_drv.h"
 
 #define MGA_DEFAULT_USEC_TIMEOUT       10000
@@ -62,7 +62,7 @@ int mga_do_wait_for_idle(drm_mga_private_t *dev_priv)
                        MGA_WRITE8(MGA_CRTC_INDEX, 0);
                        return 0;
                }
-               DRM_UDELAY(1);
+               udelay(1);
        }
 
 #if MGA_DMA_DEBUG
@@ -114,7 +114,7 @@ void mga_do_dma_flush(drm_mga_private_t *dev_priv)
                status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
                if (status == MGA_ENDPRDMASTS)
                        break;
-               DRM_UDELAY(1);
+               udelay(1);
        }
 
        if (primary->tail == primary->last_flush) {
@@ -1120,7 +1120,7 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
         */
        if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d->send_count);
+                         task_pid_nr(current), d->send_count);
                return -EINVAL;
        }
 
@@ -1128,7 +1128,8 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
         */
        if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+                         task_pid_nr(current), d->request_count,
+                         dma->buf_count);
                return -EINVAL;
        }
 
index 6e1d105..71128e6 100644 (file)
 
 #include <linux/module.h>
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
-#include "mga_drv.h"
-
+#include <drm/drm_drv.h>
 #include <drm/drm_pciids.h>
 
+#include "mga_drv.h"
+
 static struct pci_device_id pciidlist[] = {
        mga_PCI_IDS
 };
index a45bb22..d5deecb 100644 (file)
 #ifndef __MGA_DRV_H__
 #define __MGA_DRV_H__
 
+#include <linux/irqreturn.h>
+#include <linux/slab.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_irq.h>
 #include <drm/drm_legacy.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_print.h>
+#include <drm/drm_sarea.h>
+#include <drm/drm_vblank.h>
+#include <drm/mga_drm.h>
 
 /* General customization:
  */
@@ -188,7 +201,7 @@ extern int mga_warp_init(drm_mga_private_t *dev_priv);
 extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe);
 extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe);
 extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
-extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
+extern void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(int irq, void *arg);
 extern void mga_driver_irq_preinstall(struct drm_device *dev);
@@ -199,10 +212,14 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 
 #define mga_flush_write_combine()      wmb()
 
-#define MGA_READ8(reg)         DRM_READ8(dev_priv->mmio, (reg))
-#define MGA_READ(reg)          DRM_READ32(dev_priv->mmio, (reg))
-#define MGA_WRITE8(reg, val)   DRM_WRITE8(dev_priv->mmio, (reg), (val))
-#define MGA_WRITE(reg, val)    DRM_WRITE32(dev_priv->mmio, (reg), (val))
+#define MGA_READ8(reg) \
+       readb(((void __iomem *)dev_priv->mmio->handle) + (reg))
+#define MGA_READ(reg) \
+       readl(((void __iomem *)dev_priv->mmio->handle) + (reg))
+#define MGA_WRITE8(reg, val) \
+       writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg))
+#define MGA_WRITE(reg, val) \
+       writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg))
 
 #define DWGREG0                0x1c00
 #define DWGREG0_END    0x1dff
index 245fb2e..6ccd270 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
+
 #include <linux/compat.h>
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
 #include "mga_drv.h"
 
 typedef struct drm32_mga_init {
index 693ba70..a7e6ffc 100644 (file)
@@ -31,8 +31,6 @@
  *    Eric Anholt <anholt@FreeBSD.org>
  */
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
 #include "mga_drv.h"
 
 u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
@@ -118,23 +116,21 @@ void mga_disable_vblank(struct drm_device *dev, unsigned int pipe)
        /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 
-int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
+void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
        unsigned int cur_fence;
-       int ret = 0;
 
        /* Assume that the user has missed the current sequence number
         * by about a day rather than she wants to wait for years
         * using fences.
         */
-       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * HZ,
+       wait_event_timeout(dev_priv->fence_queue,
                    (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
-                     - *sequence) <= (1 << 23)));
+                     - *sequence) <= (1 << 23)),
+                   msecs_to_jiffies(3000));
 
        *sequence = cur_fence;
-
-       return ret;
 }
 
 void mga_driver_irq_preinstall(struct drm_device *dev)
index e5f6b73..77a0b00 100644 (file)
@@ -32,8 +32,6 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
 #include "mga_drv.h"
 
 /* ================================================================
@@ -1016,7 +1014,7 @@ int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
                return -EINVAL;
        }
 
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+       DRM_DEBUG("pid=%d\n", task_pid_nr(current));
 
        switch (param->param) {
        case MGA_PARAM_IRQ_NR:
@@ -1048,7 +1046,7 @@ static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *fi
                return -EINVAL;
        }
 
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+       DRM_DEBUG("pid=%d\n", task_pid_nr(current));
 
        /* I would normal do this assignment in the declaration of fence,
         * but dev_priv may be NULL.
@@ -1077,7 +1075,7 @@ file_priv)
                return -EINVAL;
        }
 
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+       DRM_DEBUG("pid=%d\n", task_pid_nr(current));
 
        mga_driver_fence_wait(dev, fence);
        return 0;
index 0b76352..b5ef1d2 100644 (file)
 
 #include <linux/firmware.h>
 #include <linux/ihex.h>
-#include <linux/platform_device.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 
-#include <drm/drmP.h>
-#include <drm/mga_drm.h>
 #include "mga_drv.h"
 
 #define FIRMWARE_G200 "matrox/g200_warp.fw"
index 98d2044..04b281b 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mgag200-y   := mgag200_main.o mgag200_mode.o mgag200_cursor.o \
-       mgag200_drv.o mgag200_fb.o mgag200_i2c.o mgag200_ttm.o
+       mgag200_drv.o mgag200_i2c.o mgag200_ttm.o
 
 obj-$(CONFIG_DRM_MGAG200) += mgag200.o
index f0c61a9..289ce3e 100644 (file)
@@ -5,7 +5,8 @@
  * Author: Christopher Harvey <charvey@matrox.com>
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_pci.h>
+
 #include "mgag200_drv.h"
 
 static bool warn_transparent = true;
@@ -98,11 +99,12 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        }
 
        /* Pin and map up-coming buffer to write colour indices */
-       ret = drm_gem_vram_pin(pixels_next, 0);
-       if (ret)
+       ret = drm_gem_vram_pin(pixels_next, DRM_GEM_VRAM_PL_FLAG_VRAM);
+       if (ret) {
                dev_err(&dev->pdev->dev,
                        "failed to pin cursor buffer: %d\n", ret);
                goto err_drm_gem_vram_kunmap_src;
+       }
        dst = drm_gem_vram_kmap(pixels_next, true, NULL);
        if (IS_ERR(dst)) {
                ret = PTR_ERR(dst);
@@ -110,7 +112,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
                        "failed to kmap cursor updates: %d\n", ret);
                goto err_drm_gem_vram_unpin_dst;
        }
-       gpu_addr = drm_gem_vram_offset(pixels_2);
+       gpu_addr = drm_gem_vram_offset(pixels_next);
        if (gpu_addr < 0) {
                ret = (int)gpu_addr;
                dev_err(&dev->pdev->dev,
@@ -211,7 +213,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        mdev->cursor.pixels_current = pixels_next;
 
        drm_gem_vram_kunmap(pixels_next);
-       drm_gem_vram_unpin(pixels_next);
        drm_gem_vram_kunmap(gbo);
        drm_gem_vram_unpin(gbo);
        drm_gem_object_put_unlocked(obj);
index aafa1cb..afd9119 100644 (file)
@@ -5,14 +5,18 @@
  * Authors: Matthew Garrett
  *          Dave Airlie
  */
+
 #include <linux/module.h>
 #include <linux/console.h>
-#include <drm/drmP.h>
-
-#include "mgag200_drv.h"
 
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_pci.h>
 #include <drm/drm_pciids.h>
 
+#include "mgag200_drv.h"
+
 /*
  * This is the generic driver code. This binds the driver to the drm core,
  * which then performs further device association and calls our graphics init
index c47671c..1c93f8d 100644 (file)
 #ifndef __MGAG200_DRV_H__
 #define __MGAG200_DRV_H__
 
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c.h>
+
 #include <video/vga.h>
 
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
-
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
-
 #include <drm/drm_vram_mm_helper.h>
 
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
 #include "mgag200_reg.h"
 
 #define DRIVER_AUTHOR          "Matthew Garrett"
 #define to_mga_crtc(x) container_of(x, struct mga_crtc, base)
 #define to_mga_encoder(x) container_of(x, struct mga_encoder, base)
 #define to_mga_connector(x) container_of(x, struct mga_connector, base)
-#define to_mga_framebuffer(x) container_of(x, struct mga_framebuffer, base)
-
-struct mga_framebuffer {
-       struct drm_framebuffer base;
-       struct drm_gem_object *obj;
-};
-
-struct mga_fbdev {
-       struct drm_fb_helper helper; /* must be first */
-       struct mga_framebuffer mfb;
-       void *sysram;
-       int size;
-       int x1, y1, x2, y2; /* dirty rect */
-       spinlock_t dirty_lock;
-};
 
 struct mga_crtc {
        struct drm_crtc base;
@@ -189,7 +172,6 @@ struct mga_device {
        struct mga_mc                   mc;
        struct mga_mode_info            mode_info;
 
-       struct mga_fbdev *mfbdev;
        struct mga_cursor cursor;
 
        bool                            suspended;
@@ -210,25 +192,9 @@ struct mga_device {
 int mgag200_modeset_init(struct mga_device *mdev);
 void mgag200_modeset_fini(struct mga_device *mdev);
 
-                               /* mgag200_fb.c */
-int mgag200_fbdev_init(struct mga_device *mdev);
-void mgag200_fbdev_fini(struct mga_device *mdev);
-
                                /* mgag200_main.c */
-int mgag200_framebuffer_init(struct drm_device *dev,
-                            struct mga_framebuffer *mfb,
-                            const struct drm_mode_fb_cmd2 *mode_cmd,
-                            struct drm_gem_object *obj);
-
-
 int mgag200_driver_load(struct drm_device *dev, unsigned long flags);
 void mgag200_driver_unload(struct drm_device *dev);
-int mgag200_gem_create(struct drm_device *dev,
-                  u32 size, bool iskernel,
-                      struct drm_gem_object **obj);
-int mgag200_dumb_create(struct drm_file *file,
-                       struct drm_device *dev,
-                       struct drm_mode_create_dumb *args);
 
                                /* mgag200_i2c.c */
 struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
deleted file mode 100644 (file)
index 8adb332..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2010 Matt Turner.
- * Copyright 2012 Red Hat
- *
- * Authors: Matthew Garrett
- *          Matt Turner
- *          Dave Airlie
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_util.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "mgag200_drv.h"
-
-static void mga_dirty_update(struct mga_fbdev *mfbdev,
-                            int x, int y, int width, int height)
-{
-       int i;
-       struct drm_gem_object *obj;
-       struct drm_gem_vram_object *gbo;
-       int src_offset, dst_offset;
-       int bpp = mfbdev->mfb.base.format->cpp[0];
-       int ret;
-       u8 *dst;
-       bool unmap = false;
-       bool store_for_later = false;
-       int x2, y2;
-       unsigned long flags;
-
-       obj = mfbdev->mfb.obj;
-       gbo = drm_gem_vram_of_gem(obj);
-
-       if (drm_can_sleep()) {
-               /* We pin the BO so it won't be moved during the
-                * update. The actual location, video RAM or system
-                * memory, is not important.
-                */
-               ret = drm_gem_vram_pin(gbo, 0);
-               if (ret) {
-                       if (ret != -EBUSY)
-                               return;
-                       store_for_later = true;
-               }
-       } else {
-               store_for_later = true;
-       }
-
-       x2 = x + width - 1;
-       y2 = y + height - 1;
-       spin_lock_irqsave(&mfbdev->dirty_lock, flags);
-
-       if (mfbdev->y1 < y)
-               y = mfbdev->y1;
-       if (mfbdev->y2 > y2)
-               y2 = mfbdev->y2;
-       if (mfbdev->x1 < x)
-               x = mfbdev->x1;
-       if (mfbdev->x2 > x2)
-               x2 = mfbdev->x2;
-
-       if (store_for_later) {
-               mfbdev->x1 = x;
-               mfbdev->x2 = x2;
-               mfbdev->y1 = y;
-               mfbdev->y2 = y2;
-               spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
-               return;
-       }
-
-       mfbdev->x1 = mfbdev->y1 = INT_MAX;
-       mfbdev->x2 = mfbdev->y2 = 0;
-       spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
-
-       dst = drm_gem_vram_kmap(gbo, false, NULL);
-       if (IS_ERR(dst)) {
-               DRM_ERROR("failed to kmap fb updates\n");
-               goto out;
-       } else if (!dst) {
-               dst = drm_gem_vram_kmap(gbo, true, NULL);
-               if (IS_ERR(dst)) {
-                       DRM_ERROR("failed to kmap fb updates\n");
-                       goto out;
-               }
-               unmap = true;
-       }
-
-       for (i = y; i <= y2; i++) {
-               /* assume equal stride for now */
-               src_offset = dst_offset =
-                       i * mfbdev->mfb.base.pitches[0] + (x * bpp);
-               memcpy_toio(dst + dst_offset, mfbdev->sysram + src_offset,
-                           (x2 - x + 1) * bpp);
-       }
-
-       if (unmap)
-               drm_gem_vram_kunmap(gbo);
-
-out:
-       drm_gem_vram_unpin(gbo);
-}
-
-static void mga_fillrect(struct fb_info *info,
-                        const struct fb_fillrect *rect)
-{
-       struct mga_fbdev *mfbdev = info->par;
-       drm_fb_helper_sys_fillrect(info, rect);
-       mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width,
-                        rect->height);
-}
-
-static void mga_copyarea(struct fb_info *info,
-                        const struct fb_copyarea *area)
-{
-       struct mga_fbdev *mfbdev = info->par;
-       drm_fb_helper_sys_copyarea(info, area);
-       mga_dirty_update(mfbdev, area->dx, area->dy, area->width,
-                        area->height);
-}
-
-static void mga_imageblit(struct fb_info *info,
-                         const struct fb_image *image)
-{
-       struct mga_fbdev *mfbdev = info->par;
-       drm_fb_helper_sys_imageblit(info, image);
-       mga_dirty_update(mfbdev, image->dx, image->dy, image->width,
-                        image->height);
-}
-
-
-static struct fb_ops mgag200fb_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = mga_fillrect,
-       .fb_copyarea = mga_copyarea,
-       .fb_imageblit = mga_imageblit,
-       .fb_pan_display = drm_fb_helper_pan_display,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcmap = drm_fb_helper_setcmap,
-};
-
-static int mgag200fb_create_object(struct mga_fbdev *afbdev,
-                                  const struct drm_mode_fb_cmd2 *mode_cmd,
-                                  struct drm_gem_object **gobj_p)
-{
-       struct drm_device *dev = afbdev->helper.dev;
-       u32 size;
-       struct drm_gem_object *gobj;
-       int ret = 0;
-
-       size = mode_cmd->pitches[0] * mode_cmd->height;
-       ret = mgag200_gem_create(dev, size, true, &gobj);
-       if (ret)
-               return ret;
-
-       *gobj_p = gobj;
-       return ret;
-}
-
-static int mgag200fb_create(struct drm_fb_helper *helper,
-                          struct drm_fb_helper_surface_size *sizes)
-{
-       struct mga_fbdev *mfbdev =
-               container_of(helper, struct mga_fbdev, helper);
-       struct drm_device *dev = mfbdev->helper.dev;
-       struct drm_mode_fb_cmd2 mode_cmd;
-       struct mga_device *mdev = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
-       struct drm_gem_object *gobj = NULL;
-       int ret;
-       void *sysram;
-       int size;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
-
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-
-       ret = mgag200fb_create_object(mfbdev, &mode_cmd, &gobj);
-       if (ret) {
-               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
-               return ret;
-       }
-
-       sysram = vmalloc(size);
-       if (!sysram) {
-               ret = -ENOMEM;
-               goto err_sysram;
-       }
-
-       info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info)) {
-               ret = PTR_ERR(info);
-               goto err_alloc_fbi;
-       }
-
-       ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj);
-       if (ret)
-               goto err_alloc_fbi;
-
-       mfbdev->sysram = sysram;
-       mfbdev->size = size;
-
-       fb = &mfbdev->mfb.base;
-
-       /* setup helper */
-       mfbdev->helper.fb = fb;
-
-       info->fbops = &mgag200fb_ops;
-
-       /* setup aperture base/size for vesafb takeover */
-       info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base;
-       info->apertures->ranges[0].size = mdev->mc.vram_size;
-
-       drm_fb_helper_fill_info(info, &mfbdev->helper, sizes);
-
-       info->screen_base = sysram;
-       info->screen_size = size;
-       info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-       DRM_DEBUG_KMS("allocated %dx%d\n",
-                     fb->width, fb->height);
-
-       return 0;
-
-err_alloc_fbi:
-       vfree(sysram);
-err_sysram:
-       drm_gem_object_put_unlocked(gobj);
-
-       return ret;
-}
-
-static int mga_fbdev_destroy(struct drm_device *dev,
-                               struct mga_fbdev *mfbdev)
-{
-       struct mga_framebuffer *mfb = &mfbdev->mfb;
-
-       drm_fb_helper_unregister_fbi(&mfbdev->helper);
-
-       if (mfb->obj) {
-               drm_gem_object_put_unlocked(mfb->obj);
-               mfb->obj = NULL;
-       }
-       drm_fb_helper_fini(&mfbdev->helper);
-       vfree(mfbdev->sysram);
-       drm_framebuffer_unregister_private(&mfb->base);
-       drm_framebuffer_cleanup(&mfb->base);
-
-       return 0;
-}
-
-static const struct drm_fb_helper_funcs mga_fb_helper_funcs = {
-       .fb_probe = mgag200fb_create,
-};
-
-int mgag200_fbdev_init(struct mga_device *mdev)
-{
-       struct mga_fbdev *mfbdev;
-       int ret;
-       int bpp_sel = 32;
-
-       /* prefer 16bpp on low end gpus with limited VRAM */
-       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
-               bpp_sel = 16;
-
-       mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL);
-       if (!mfbdev)
-               return -ENOMEM;
-
-       mdev->mfbdev = mfbdev;
-       spin_lock_init(&mfbdev->dirty_lock);
-
-       drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
-
-       ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
-                                MGAG200FB_CONN_LIMIT);
-       if (ret)
-               goto err_fb_helper;
-
-       ret = drm_fb_helper_single_add_all_connectors(&mfbdev->helper);
-       if (ret)
-               goto err_fb_setup;
-
-       /* disable all the possible outputs/crtcs before entering KMS mode */
-       drm_helper_disable_unused_functions(mdev->dev);
-
-       ret = drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
-       if (ret)
-               goto err_fb_setup;
-
-       return 0;
-
-err_fb_setup:
-       drm_fb_helper_fini(&mfbdev->helper);
-err_fb_helper:
-       mdev->mfbdev = NULL;
-
-       return ret;
-}
-
-void mgag200_fbdev_fini(struct mga_device *mdev)
-{
-       if (!mdev->mfbdev)
-               return;
-
-       mga_fbdev_destroy(mdev->dev, mdev->mfbdev);
-}
index 77d1c47..51d4037 100644 (file)
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
+
 #include <linux/export.h>
-#include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <drm/drmP.h>
+#include <linux/i2c.h>
+
+#include <drm/drm_pci.h>
 
 #include "mgag200_drv.h"
 
index dd61ccc..a977333 100644 (file)
@@ -7,70 +7,15 @@
  *          Matt Turner
  *          Dave Airlie
  */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include "mgag200_drv.h"
 
-static void mga_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct mga_framebuffer *mga_fb = to_mga_framebuffer(fb);
-
-       drm_gem_object_put_unlocked(mga_fb->obj);
-       drm_framebuffer_cleanup(fb);
-       kfree(fb);
-}
-
-static const struct drm_framebuffer_funcs mga_fb_funcs = {
-       .destroy = mga_user_framebuffer_destroy,
-};
-
-int mgag200_framebuffer_init(struct drm_device *dev,
-                            struct mga_framebuffer *gfb,
-                            const struct drm_mode_fb_cmd2 *mode_cmd,
-                            struct drm_gem_object *obj)
-{
-       int ret;
-
-       drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd);
-       gfb->obj = obj;
-       ret = drm_framebuffer_init(dev, &gfb->base, &mga_fb_funcs);
-       if (ret) {
-               DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
-               return ret;
-       }
-       return 0;
-}
-
-static struct drm_framebuffer *
-mgag200_user_framebuffer_create(struct drm_device *dev,
-                               struct drm_file *filp,
-                               const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       struct drm_gem_object *obj;
-       struct mga_framebuffer *mga_fb;
-       int ret;
-
-       obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
-       if (obj == NULL)
-               return ERR_PTR(-ENOENT);
-
-       mga_fb = kzalloc(sizeof(*mga_fb), GFP_KERNEL);
-       if (!mga_fb) {
-               drm_gem_object_put_unlocked(obj);
-               return ERR_PTR(-ENOMEM);
-       }
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_pci.h>
 
-       ret = mgag200_framebuffer_init(dev, mga_fb, mode_cmd, obj);
-       if (ret) {
-               drm_gem_object_put_unlocked(obj);
-               kfree(mga_fb);
-               return ERR_PTR(ret);
-       }
-       return &mga_fb->base;
-}
+#include "mgag200_drv.h"
 
 static const struct drm_mode_config_funcs mga_mode_funcs = {
-       .fb_create = mgag200_user_framebuffer_create,
+       .fb_create = drm_gem_fb_create
 };
 
 static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
@@ -217,7 +162,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
                dev->mode_config.preferred_depth = 16;
        else
-               dev->mode_config.preferred_depth = 24;
+               dev->mode_config.preferred_depth = 32;
        dev->mode_config.prefer_shadow = 1;
 
        r = mgag200_modeset_init(mdev);
@@ -241,6 +186,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
        }
        mdev->cursor.pixels_current = NULL;
 
+       r = drm_fbdev_generic_setup(mdev->dev, 0);
+       if (r)
+               goto err_modeset;
+
        return 0;
 
 err_modeset:
@@ -259,32 +208,7 @@ void mgag200_driver_unload(struct drm_device *dev)
        if (mdev == NULL)
                return;
        mgag200_modeset_fini(mdev);
-       mgag200_fbdev_fini(mdev);
        drm_mode_config_cleanup(dev);
        mgag200_mm_fini(mdev);
        dev->dev_private = NULL;
 }
-
-int mgag200_gem_create(struct drm_device *dev,
-                  u32 size, bool iskernel,
-                  struct drm_gem_object **obj)
-{
-       struct drm_gem_vram_object *gbo;
-       int ret;
-
-       *obj = NULL;
-
-       size = roundup(size, PAGE_SIZE);
-       if (size == 0)
-               return -EINVAL;
-
-       gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false);
-       if (IS_ERR(gbo)) {
-               ret = PTR_ERR(gbo);
-               if (ret != -ERESTARTSYS)
-                       DRM_ERROR("failed to allocate GEM object\n");
-               return ret;
-       }
-       *obj = &gbo->gem;
-       return 0;
-}
index a250540..5e778b5 100644 (file)
@@ -10,8 +10,9 @@
 
 #include <linux/delay.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_pci.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 
@@ -859,28 +860,16 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                int x, int y, int atomic)
 {
-       struct mga_device *mdev = crtc->dev->dev_private;
-       struct drm_gem_object *obj;
-       struct mga_framebuffer *mga_fb;
        struct drm_gem_vram_object *gbo;
        int ret;
        s64 gpu_addr;
-       void *base;
 
        if (!atomic && fb) {
-               mga_fb = to_mga_framebuffer(fb);
-               obj = mga_fb->obj;
-               gbo = drm_gem_vram_of_gem(obj);
-
-               /* unmap if console */
-               if (&mdev->mfbdev->mfb == mga_fb)
-                       drm_gem_vram_kunmap(gbo);
+               gbo = drm_gem_vram_of_gem(fb->obj[0]);
                drm_gem_vram_unpin(gbo);
        }
 
-       mga_fb = to_mga_framebuffer(crtc->primary->fb);
-       obj = mga_fb->obj;
-       gbo = drm_gem_vram_of_gem(obj);
+       gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]);
 
        ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
        if (ret)
@@ -891,15 +880,6 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
                goto err_drm_gem_vram_unpin;
        }
 
-       if (&mdev->mfbdev->mfb == mga_fb) {
-               /* if pushing console in kmap it */
-               base = drm_gem_vram_kmap(gbo, true, NULL);
-               if (IS_ERR(base)) {
-                       ret = PTR_ERR(base);
-                       DRM_ERROR("failed to kmap fbcon\n");
-               }
-       }
-
        mga_set_start_address(crtc, (u32)gpu_addr);
 
        return 0;
@@ -1423,14 +1403,9 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
        DRM_DEBUG_KMS("\n");
        mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
        if (crtc->primary->fb) {
-               struct mga_device *mdev = crtc->dev->dev_private;
-               struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);
-               struct drm_gem_object *obj = mga_fb->obj;
-               struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj);
-
-               /* unmap if console */
-               if (&mdev->mfbdev->mfb == mga_fb)
-                       drm_gem_vram_kunmap(gbo);
+               struct drm_framebuffer *fb = crtc->primary->fb;
+               struct drm_gem_vram_object *gbo =
+                       drm_gem_vram_of_gem(fb->obj[0]);
                drm_gem_vram_unpin(gbo);
        }
        crtc->primary->fb = NULL;
@@ -1703,18 +1678,19 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev)
                return NULL;
 
        connector = &mga_connector->base;
+       mga_connector->i2c = mgag200_i2c_create(dev);
+       if (!mga_connector->i2c)
+               DRM_ERROR("failed to add ddc bus\n");
 
-       drm_connector_init(dev, connector,
-                          &mga_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+       drm_connector_init_with_ddc(dev, connector,
+                                   &mga_vga_connector_funcs,
+                                   DRM_MODE_CONNECTOR_VGA,
+                                   &mga_connector->i2c->adapter);
 
        drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
 
        drm_connector_register(connector);
 
-       mga_connector->i2c = mgag200_i2c_create(dev);
-       if (!mga_connector->i2c)
-               DRM_ERROR("failed to add ddc bus\n");
-
        return connector;
 }
 
@@ -1723,7 +1699,6 @@ int mgag200_modeset_init(struct mga_device *mdev)
 {
        struct drm_encoder *encoder;
        struct drm_connector *connector;
-       int ret;
 
        mdev->mode_info.mode_config_initialized = true;
 
@@ -1748,12 +1723,6 @@ int mgag200_modeset_init(struct mga_device *mdev)
 
        drm_connector_attach_encoder(connector, encoder);
 
-       ret = mgag200_fbdev_init(mdev);
-       if (ret) {
-               DRM_ERROR("mga_fbdev_init failed\n");
-               return ret;
-       }
-
        return 0;
 }
 
index 59294c0..73a6b84 100644 (file)
@@ -25,7 +25,8 @@
 /*
  * Authors: Dave Airlie <airlied@redhat.com>
  */
-#include <drm/drmP.h>
+
+#include <drm/drm_pci.h>
 
 #include "mgag200_drv.h"
 
index 45bfac9..8cf0b8a 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "msm_drv.h"
 #include "dpu_kms.h"
@@ -764,8 +765,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
        struct dpu_plane *pdpu = to_dpu_plane(plane);
        struct dpu_plane_state *pstate = to_dpu_plane_state(new_state);
        struct dpu_hw_fmt_layout layout;
-       struct drm_gem_object *obj;
-       struct dma_fence *fence;
        struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
        int ret;
 
@@ -782,10 +781,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
         *       we can use msm_atomic_prepare_fb() instead of doing the
         *       implicit fence and fb prepare by hand here.
         */
-       obj = msm_framebuffer_bo(new_state->fb, 0);
-       fence = reservation_object_get_excl_rcu(obj->resv);
-       if (fence)
-               drm_atomic_set_fence_for_plane(new_state, fence);
+       drm_gem_fb_prepare_fb(plane, new_state);
 
        if (pstate->aspace) {
                ret = msm_framebuffer_prepare(new_state->fb,
index dd16bab..169d5f9 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "msm_drv.h"
 #include "msm_gem.h"
@@ -37,16 +38,11 @@ int msm_atomic_prepare_fb(struct drm_plane *plane,
 {
        struct msm_drm_private *priv = plane->dev->dev_private;
        struct msm_kms *kms = priv->kms;
-       struct drm_gem_object *obj;
-       struct dma_fence *fence;
 
        if (!new_state->fb)
                return 0;
 
-       obj = msm_framebuffer_bo(new_state->fb, 0);
-       fence = reservation_object_get_excl_rcu(obj->resv);
-
-       drm_atomic_set_fence_for_plane(new_state, fence);
+       drm_gem_fb_prepare_fb(plane, new_state);
 
        return msm_framebuffer_prepare(new_state->fb, kms->aspace);
 }
index c356f5c..ee031c0 100644 (file)
@@ -984,17 +984,17 @@ static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data,
 }
 
 static const struct drm_ioctl_desc msm_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(MSM_GET_PARAM,    msm_ioctl_get_param,    DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_NEW,      msm_ioctl_gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_INFO,     msm_ioctl_gem_info,     DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT,   msm_ioctl_gem_submit,   DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE,   msm_ioctl_wait_fence,   DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE,  msm_ioctl_gem_madvise,  DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW,   msm_ioctl_submitqueue_new,   DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GET_PARAM,    msm_ioctl_get_param,    DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_NEW,      msm_ioctl_gem_new,      DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_INFO,     msm_ioctl_gem_info,     DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT,   msm_ioctl_gem_submit,   DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE,   msm_ioctl_wait_fence,   DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE,  msm_ioctl_gem_madvise,  DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW,   msm_ioctl_submitqueue_new,   DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
 };
 
 static const struct vm_operations_struct vm_ops = {
@@ -1017,7 +1017,6 @@ static const struct file_operations fops = {
 
 static struct drm_driver msm_driver = {
        .driver_features    = DRIVER_GEM |
-                               DRIVER_PRIME |
                                DRIVER_RENDER |
                                DRIVER_ATOMIC |
                                DRIVER_MODESET,
@@ -1036,8 +1035,6 @@ static struct drm_driver msm_driver = {
        .dumb_map_offset    = msm_gem_dumb_map_offset,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export   = drm_gem_prime_export,
-       .gem_prime_import   = drm_gem_prime_import,
        .gem_prime_pin      = msm_gem_prime_pin,
        .gem_prime_unpin    = msm_gem_prime_unpin,
        .gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
index 8cf6362..8cc7002 100644 (file)
@@ -975,7 +975,6 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
 
 static int msm_gem_new_impl(struct drm_device *dev,
                uint32_t size, uint32_t flags,
-               struct reservation_object *resv,
                struct drm_gem_object **obj,
                bool struct_mutex_locked)
 {
@@ -1002,9 +1001,6 @@ static int msm_gem_new_impl(struct drm_device *dev,
        msm_obj->flags = flags;
        msm_obj->madv = MSM_MADV_WILLNEED;
 
-       if (resv)
-               msm_obj->base.resv = resv;
-
        INIT_LIST_HEAD(&msm_obj->submit_entry);
        INIT_LIST_HEAD(&msm_obj->vmas);
 
@@ -1046,7 +1042,7 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev,
        if (size == 0)
                return ERR_PTR(-EINVAL);
 
-       ret = msm_gem_new_impl(dev, size, flags, NULL, &obj, struct_mutex_locked);
+       ret = msm_gem_new_impl(dev, size, flags, &obj, struct_mutex_locked);
        if (ret)
                goto fail;
 
@@ -1123,7 +1119,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
 
        size = PAGE_ALIGN(dmabuf->size);
 
-       ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj, false);
+       ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj, false);
        if (ret)
                goto fail;
 
index 4edb874..f7308d6 100644 (file)
@@ -95,7 +95,8 @@ static void msm_devfreq_init(struct msm_gpu *gpu)
         */
 
        gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
-                       &msm_devfreq_profile, "simple_ondemand", NULL);
+                       &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
+                       NULL);
 
        if (IS_ERR(gpu->devfreq.devfreq)) {
                DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
index 93f4133..1242156 100644 (file)
@@ -8,21 +8,23 @@
  * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  */
 
-#include <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of_graph.h>
+#include <linux/platform_data/simplefb.h>
+
+#include <video/videomode.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
-#include <linux/clk.h>
-#include <linux/iopoll.h>
-#include <linux/of_graph.h>
-#include <linux/platform_data/simplefb.h>
-#include <video/videomode.h>
+#include <drm/drm_vblank.h>
 
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
index 6fafc90..878ef68 100644 (file)
@@ -8,29 +8,32 @@
  * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  */
 
-#include <linux/module.h>
-#include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/dma-mapping.h>
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/pm_runtime.h>
 #include <linux/reservation.h>
+#include <linux/spinlock.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_irq.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
@@ -313,8 +316,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver mxsfb_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET |
-                                 DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .irq_handler            = mxsfb_irq_handler,
        .irq_preinstall         = mxsfb_irq_preinstall,
        .irq_uninstall          = mxsfb_irq_preinstall,
@@ -323,8 +325,6 @@ static struct drm_driver mxsfb_driver = {
        .dumb_create            = drm_gem_cma_dumb_create,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_export       = drm_gem_prime_export,
-       .gem_prime_import       = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 91e76f9..231d016 100644 (file)
@@ -15,7 +15,6 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
-#include <drm/drmP.h>
 
 #include "mxsfb_drv.h"
 
index 283ff69..89f8e76 100644 (file)
@@ -457,7 +457,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
                asyw->image.handle[0] = ctxdma->object.handle;
        }
 
-       asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv);
+       asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.base.resv);
        asyw->image.offset[0] = fb->nvbo->bo.offset;
 
        if (wndw->func->prepare) {
index c3fd5dd..e2bae14 100644 (file)
@@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
        if (chan->ntfy) {
                nouveau_vma_del(&chan->ntfy_vma);
                nouveau_bo_unpin(chan->ntfy);
-               drm_gem_object_put_unlocked(&chan->ntfy->gem);
+               drm_gem_object_put_unlocked(&chan->ntfy->bo.base);
        }
 
        if (chan->heap.block_size)
@@ -244,12 +244,6 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
        return 0;
 }
 
-int
-nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS)
-{
-       return -EINVAL;
-}
-
 int
 nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 {
@@ -345,7 +339,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
                        goto done;
        }
 
-       ret = drm_gem_handle_create(file_priv, &chan->ntfy->gem,
+       ret = drm_gem_handle_create(file_priv, &chan->ntfy->bo.base,
                                    &init->notifier_handle);
        if (ret)
                goto done;
index 1955467..70f6aa5 100644 (file)
@@ -6,7 +6,6 @@
        struct drm_device *dev, void *data, struct drm_file *file_priv
 
 int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS);
-int nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS);
 int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS);
 int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS);
 int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS);
index 34a9980..99e391b 100644 (file)
@@ -136,7 +136,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
        struct drm_device *dev = drm->dev;
        struct nouveau_bo *nvbo = nouveau_bo(bo);
 
-       if (unlikely(nvbo->gem.filp))
+       if (unlikely(nvbo->bo.base.filp))
                DRM_ERROR("bo %p still attached to GEM object\n", bo);
        WARN_ON(nvbo->pin_refcnt > 0);
        nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
@@ -299,6 +299,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
                          type, &nvbo->placement,
                          align >> PAGE_SHIFT, false, acc_size, sg,
                          robj, nouveau_bo_del_ttm);
+
        if (ret) {
                /* ttm will call nouveau_bo_del_ttm if it fails.. */
                return ret;
@@ -1323,7 +1324,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
 {
        struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct drm_device *dev = drm->dev;
-       struct dma_fence *fence = reservation_object_get_excl(bo->resv);
+       struct dma_fence *fence = reservation_object_get_excl(bo->base.resv);
 
        nv10_bo_put_tile_region(dev, *old_tile, fence);
        *old_tile = new_tile;
@@ -1400,7 +1401,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
 
-       return drm_vma_node_verify_access(&nvbo->gem.vma_node,
+       return drm_vma_node_verify_access(&nvbo->bo.base.vma_node,
                                          filp->private_data);
 }
 
@@ -1654,7 +1655,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
 void
 nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive)
 {
-       struct reservation_object *resv = nvbo->bo.resv;
+       struct reservation_object *resv = nvbo->bo.base.resv;
 
        if (exclusive)
                reservation_object_add_excl_fence(resv, &fence->base);
index 383ac36..d675efe 100644 (file)
@@ -35,11 +35,6 @@ struct nouveau_bo {
 
        struct nouveau_drm_tile *tile;
 
-       /* Only valid if allocated via nouveau_gem_new() and iff you hold a
-        * gem reference to it! For debugging, use gem.filp != NULL to test
-        * whether it is valid. */
-       struct drm_gem_object gem;
-
        /* protect by the ttm reservation lock */
        int pin_refcnt;
 
index 8f15281..330d7d2 100644 (file)
@@ -1349,7 +1349,7 @@ nouveau_connector_create(struct drm_device *dev,
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
        case DRM_MODE_CONNECTOR_eDP:
-               nv_connector->aux.dev = dev->dev;
+               nv_connector->aux.dev = connector->kdev;
                nv_connector->aux.transfer = nouveau_connector_aux_xfer;
                snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
                         dcbe->hasht, dcbe->hashm);
index 832da8e..98afc50 100644 (file)
@@ -201,7 +201,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
 
        if (fb->nvbo)
-               drm_gem_object_put_unlocked(&fb->nvbo->gem);
+               drm_gem_object_put_unlocked(&fb->nvbo->bo.base);
 
        drm_framebuffer_cleanup(drm_fb);
        kfree(fb);
@@ -214,7 +214,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
 {
        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
 
-       return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);
+       return drm_gem_handle_create(file_priv, &fb->nvbo->bo.base, handle);
 }
 
 static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
@@ -660,8 +660,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
        if (ret)
                return ret;
 
-       ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
-       drm_gem_object_put_unlocked(&bo->gem);
+       ret = drm_gem_handle_create(file_priv, &bo->bo.base, &args->handle);
+       drm_gem_object_put_unlocked(&bo->bo.base);
        return ret;
 }
 
@@ -675,7 +675,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
        gem = drm_gem_object_lookup(file_priv, handle);
        if (gem) {
                struct nouveau_bo *bo = nouveau_gem_object(gem);
-               *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
+               *poffset = drm_vma_node_offset_addr(&bo->bo.base.vma_node);
                drm_gem_object_put_unlocked(gem);
                return 0;
        }
index 7c2fcab..7e04558 100644 (file)
@@ -1046,20 +1046,20 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
 
 static const struct drm_ioctl_desc
 nouveau_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_RENDER_ALLOW),
 };
 
 long
@@ -1105,7 +1105,7 @@ nouveau_driver_fops = {
 static struct drm_driver
 driver_stub = {
        .driver_features =
-               DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER
+               DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER
 #if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT)
                | DRIVER_KMS_LEGACY_CONTEXT
 #endif
@@ -1130,10 +1130,7 @@ driver_stub = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = nouveau_gem_prime_pin,
-       .gem_prime_res_obj = nouveau_gem_prime_res_obj,
        .gem_prime_unpin = nouveau_gem_prime_unpin,
        .gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table,
index d4964f3..e5f249a 100644 (file)
@@ -335,7 +335,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 {
        struct nouveau_fence_chan *fctx = chan->fence;
        struct dma_fence *fence;
-       struct reservation_object *resv = nvbo->bo.resv;
+       struct reservation_object *resv = nvbo->bo.base.resv;
        struct reservation_object_list *fobj;
        struct nouveau_fence *f;
        int ret = 0, i;
index b4bda71..c7368aa 100644 (file)
@@ -205,13 +205,13 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
 
        /* Initialize the embedded gem-object. We return a single gem-reference
         * to the caller, instead of a normal nouveau_bo ttm reference. */
-       ret = drm_gem_object_init(drm->dev, &nvbo->gem, nvbo->bo.mem.size);
+       ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, nvbo->bo.mem.size);
        if (ret) {
                nouveau_bo_ref(NULL, pnvbo);
                return -ENOMEM;
        }
 
-       nvbo->bo.persistent_swap_storage = nvbo->gem.filp;
+       nvbo->bo.persistent_swap_storage = nvbo->bo.base.filp;
        return 0;
 }
 
@@ -240,7 +240,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
        }
 
        rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
-       rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node);
+       rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node);
        rep->tile_mode = nvbo->mode;
        rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG;
        if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
@@ -268,15 +268,16 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
        if (ret)
                return ret;
 
-       ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle);
+       ret = drm_gem_handle_create(file_priv, &nvbo->bo.base,
+                                   &req->info.handle);
        if (ret == 0) {
-               ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info);
+               ret = nouveau_gem_info(file_priv, &nvbo->bo.base, &req->info);
                if (ret)
                        drm_gem_handle_delete(file_priv, req->info.handle);
        }
 
        /* drop reference from allocate - handle holds it now */
-       drm_gem_object_put_unlocked(&nvbo->gem);
+       drm_gem_object_put_unlocked(&nvbo->bo.base);
        return ret;
 }
 
@@ -355,7 +356,7 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan,
                list_del(&nvbo->entry);
                nvbo->reserved_by = NULL;
                ttm_bo_unreserve(&nvbo->bo);
-               drm_gem_object_put_unlocked(&nvbo->gem);
+               drm_gem_object_put_unlocked(&nvbo->bo.base);
        }
 }
 
@@ -493,7 +494,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-               ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
+               ret = nouveau_gem_set_domain(&nvbo->bo.base, b->read_domains,
                                             b->write_domains,
                                             b->valid_domains);
                if (unlikely(ret)) {
@@ -886,7 +887,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
                return -ENOENT;
        nvbo = nouveau_gem_object(gem);
 
-       lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true,
+       lret = reservation_object_wait_timeout_rcu(nvbo->bo.base.resv, write, true,
                                                   no_wait ? 0 : 30 * HZ);
        if (!lret)
                ret = -EBUSY;
index 0337120..40ba0f1 100644 (file)
@@ -10,7 +10,7 @@
 static inline struct nouveau_bo *
 nouveau_gem_object(struct drm_gem_object *gem)
 {
-       return gem ? container_of(gem, struct nouveau_bo, gem) : NULL;
+       return gem ? container_of(gem, struct nouveau_bo, bo.base) : NULL;
 }
 
 /* nouveau_gem.c */
@@ -33,7 +33,6 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
                                  struct drm_file *);
 
 extern int nouveau_gem_prime_pin(struct drm_gem_object *);
-struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *);
 extern void nouveau_gem_prime_unpin(struct drm_gem_object *);
 extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *);
 extern struct drm_gem_object *nouveau_gem_prime_import_sg_table(
index 1fefc93..e86ad7a 100644 (file)
@@ -68,10 +68,10 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
 
        flags = TTM_PL_FLAG_TT;
 
-       ww_mutex_lock(&robj->lock, NULL);
+       reservation_object_lock(robj, NULL);
        ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0, 0,
                             sg, robj, &nvbo);
-       ww_mutex_unlock(&robj->lock);
+       reservation_object_unlock(robj);
        if (ret)
                return ERR_PTR(ret);
 
@@ -79,13 +79,13 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
 
        /* Initialize the embedded gem-object. We return a single gem-reference
         * to the caller, instead of a normal nouveau_bo ttm reference. */
-       ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size);
+       ret = drm_gem_object_init(dev, &nvbo->bo.base, nvbo->bo.mem.size);
        if (ret) {
                nouveau_bo_ref(NULL, &nvbo);
                return ERR_PTR(-ENOMEM);
        }
 
-       return &nvbo->gem;
+       return &nvbo->bo.base;
 }
 
 int nouveau_gem_prime_pin(struct drm_gem_object *obj)
@@ -107,10 +107,3 @@ void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
 
        nouveau_bo_unpin(nvbo);
 }
-
-struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj)
-{
-       struct nouveau_bo *nvbo = nouveau_gem_object(obj);
-
-       return nvbo->bo.resv;
-}
index f9ac9af..3c5ddbf 100644 (file)
@@ -4,12 +4,14 @@
  * Author: Rob Clark <rob@ti.com>
  */
 
+#include <linux/math64.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_plane_helper.h>
-#include <linux/math64.h>
+#include <drm/drm_vblank.h>
 
 #include "omap_drv.h"
 
index 2b283f6..34dfb33 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/seq_file.h>
 
 #include <drm/drm_crtc.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_file.h>
 #include <drm/drm_fb_helper.h>
 
 #include "omap_drv.h"
index 288c59d..9f652d2 100644 (file)
@@ -4,15 +4,21 @@
  * Author: Rob Clark <rob@ti.com>
  */
 
-#include <linux/of.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 #include <linux/sort.h>
 #include <linux/sys_soc.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_probe_helper.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_prime.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_drv.h"
@@ -466,19 +472,19 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
 
 static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
        DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, drm_invalid_op,
                          DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        /* Deprecated, to be removed. */
        DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, drm_noop,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        /* Deprecated, to be removed. */
        DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, drm_noop,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 };
 
 /*
@@ -513,7 +519,7 @@ static const struct file_operations omapdriver_fops = {
 };
 
 static struct drm_driver omap_drm_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
+       .driver_features = DRIVER_MODESET | DRIVER_GEM  |
                DRIVER_ATOMIC | DRIVER_RENDER,
        .open = dev_open,
        .lastclose = drm_fb_helper_lastclose,
index 025bd57..7c4b66e 100644 (file)
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
-#include <drm/drmP.h>
+#include "dss/omapdss.h"
+
 #include <drm/drm_gem.h>
 #include <drm/omap_drm.h>
 
-#include "dss/omapdss.h"
-
 #include "omap_connector.h"
 #include "omap_crtc.h"
 #include "omap_encoder.h"
index 7e89e5c..1b8b510 100644 (file)
@@ -4,10 +4,10 @@
  * Author: Rob Clark <rob@ti.com>
  */
 
-#include <linux/seq_file.h>
+#include <linux/dma-mapping.h>
 
-#include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 
 #include "omap_dmm_tiler.h"
index 561c481..58f5394 100644 (file)
@@ -7,6 +7,8 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_util.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
 
 #include "omap_drv.h"
 
@@ -76,8 +78,6 @@ static struct fb_ops omap_fb_ops = {
        .fb_setcmap     = drm_fb_helper_setcmap,
        .fb_blank       = drm_fb_helper_blank,
        .fb_pan_display = omap_fbdev_pan_display,
-       .fb_debug_enter = drm_fb_helper_debug_enter,
-       .fb_debug_leave = drm_fb_helper_debug_leave,
        .fb_ioctl       = drm_fb_helper_ioctl,
 
        .fb_read = drm_fb_helper_sys_read,
index 37378db..08f539e 100644 (file)
@@ -4,11 +4,13 @@
  * Author: Rob Clark <rob.clark@linaro.org>
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/seq_file.h>
 #include <linux/shmem_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pfn_t.h>
 
+#include <drm/drm_prime.h>
 #include <drm/drm_vma_manager.h>
 
 #include "omap_drv.h"
index 31cf345..729b781 100644 (file)
@@ -65,8 +65,7 @@ u64 omap_gem_mmap_offset(struct drm_gem_object *obj);
 size_t omap_gem_mmap_size(struct drm_gem_object *obj);
 
 /* PRIME Interface */
-struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
-               struct drm_gem_object *obj, int flags);
+struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags);
 struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
                struct dma_buf *buffer);
 
index 07c0b1b..e8c3ae7 100644 (file)
@@ -5,6 +5,9 @@
  */
 
 #include <linux/dma-buf.h>
+#include <linux/highmem.h>
+
+#include <drm/drm_prime.h>
 
 #include "omap_drv.h"
 
@@ -125,8 +128,7 @@ static const struct dma_buf_ops omap_dmabuf_ops = {
        .mmap = omap_gem_dmabuf_mmap,
 };
 
-struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
-               struct drm_gem_object *obj, int flags)
+struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags)
 {
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
@@ -135,7 +137,7 @@ struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
        exp_info.flags = flags;
        exp_info.priv = obj;
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       return drm_gem_dmabuf_export(obj->dev, &exp_info);
 }
 
 /* -----------------------------------------------------------------------------
index 726a013..382bcdc 100644 (file)
@@ -4,6 +4,8 @@
  * Author: Rob Clark <rob.clark@linaro.org>
  */
 
+#include <drm/drm_vblank.h>
+
 #include "omap_drv.h"
 
 struct omap_irq_wait {
index d9d931a..eaecd40 100644 (file)
@@ -111,6 +111,15 @@ config DRM_PANEL_LG_LG4573
          Say Y here if you want to enable support for LG4573 RGB panel.
          To compile this driver as a module, choose M here.
 
+config DRM_PANEL_NOVATEK_NT39016
+       tristate "Novatek NT39016 RGB/SPI panel"
+       depends on OF && SPI
+       depends on BACKLIGHT_CLASS_DEVICE
+       select REGMAP_SPI
+       help
+         Say Y here if you want to enable support for the panels built
+         around the Novatek NT39016 display controller.
+
 config DRM_PANEL_OLIMEX_LCD_OLINUXINO
        tristate "Olimex LCD-OLinuXino panel"
        depends on OF
@@ -159,6 +168,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
          Pi 7" Touchscreen.  To compile this driver as a module,
          choose M here.
 
+config DRM_PANEL_RAYDIUM_RM67191
+       tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel"
+       depends on OF
+       depends on DRM_MIPI_DSI
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         Say Y here if you want to enable support for Raydium RM67191 FHD
+         (1080x1920) DSI panel.
+
 config DRM_PANEL_RAYDIUM_RM68200
        tristate "Raydium RM68200 720x1280 DSI video mode panel"
        depends on OF
index fb0cb3a..62dae45 100644 (file)
@@ -9,11 +9,13 @@ obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
+obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
 obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
 obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
 obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o
+obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
index 1ec57d0..ad47cc9 100644 (file)
@@ -147,8 +147,11 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds)
        int ret;
 
        ret = of_get_display_timing(np, "panel-timing", &timing);
-       if (ret < 0)
+       if (ret < 0) {
+               dev_err(lvds->dev, "%pOF: problems parsing panel-timing (%d)\n",
+                       np, ret);
                return ret;
+       }
 
        videomode_from_timing(&timing, &lvds->video_mode);
 
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c
new file mode 100644 (file)
index 0000000..2ad1063
--- /dev/null
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Novatek NT39016 TFT LCD panel driver
+ *
+ * Copyright (C) 2017, Maarten ter Huurne <maarten@treewalker.org>
+ * Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+enum nt39016_regs {
+       NT39016_REG_SYSTEM,
+       NT39016_REG_TIMING,
+       NT39016_REG_OP,
+       NT39016_REG_DATA_IN,
+       NT39016_REG_SRC_TIMING_DELAY,
+       NT39016_REG_GATE_TIMING_DELAY,
+       NT39016_REG_RESERVED,
+       NT39016_REG_INITIAL_FUNC,
+       NT39016_REG_CONTRAST,
+       NT39016_REG_BRIGHTNESS,
+       NT39016_REG_HUE_SATURATION,
+       NT39016_REG_RB_SUBCONTRAST,
+       NT39016_REG_R_SUBBRIGHTNESS,
+       NT39016_REG_B_SUBBRIGHTNESS,
+       NT39016_REG_VCOMDC,
+       NT39016_REG_VCOMAC,
+       NT39016_REG_VGAM2,
+       NT39016_REG_VGAM34,
+       NT39016_REG_VGAM56,
+       NT39016_REG_VCOMDC_TRIM = 0x1e,
+       NT39016_REG_DISPLAY_MODE = 0x20,
+};
+
+#define NT39016_SYSTEM_RESET_N BIT(0)
+#define NT39016_SYSTEM_STANDBY BIT(1)
+
+struct nt39016_panel_info {
+       struct drm_display_mode display_mode;
+       u16 width_mm, height_mm;
+       u32 bus_format, bus_flags;
+};
+
+struct nt39016 {
+       struct drm_panel drm_panel;
+       struct device *dev;
+       struct regmap *map;
+       struct regulator *supply;
+       const struct nt39016_panel_info *panel_info;
+
+       struct gpio_desc *reset_gpio;
+
+       struct backlight_device *backlight;
+};
+
+static inline struct nt39016 *to_nt39016(struct drm_panel *panel)
+{
+       return container_of(panel, struct nt39016, drm_panel);
+}
+
+#define RV(REG, VAL) { .reg = (REG), .def = (VAL), .delay_us = 2 }
+static const struct reg_sequence nt39016_panel_regs[] = {
+       RV(NT39016_REG_SYSTEM, 0x00),
+       RV(NT39016_REG_TIMING, 0x00),
+       RV(NT39016_REG_OP, 0x03),
+       RV(NT39016_REG_DATA_IN, 0xCC),
+       RV(NT39016_REG_SRC_TIMING_DELAY, 0x46),
+       RV(NT39016_REG_GATE_TIMING_DELAY, 0x05),
+       RV(NT39016_REG_RESERVED, 0x00),
+       RV(NT39016_REG_INITIAL_FUNC, 0x00),
+       RV(NT39016_REG_CONTRAST, 0x08),
+       RV(NT39016_REG_BRIGHTNESS, 0x40),
+       RV(NT39016_REG_HUE_SATURATION, 0x88),
+       RV(NT39016_REG_RB_SUBCONTRAST, 0x88),
+       RV(NT39016_REG_R_SUBBRIGHTNESS, 0x20),
+       RV(NT39016_REG_B_SUBBRIGHTNESS, 0x20),
+       RV(NT39016_REG_VCOMDC, 0x67),
+       RV(NT39016_REG_VCOMAC, 0xA4),
+       RV(NT39016_REG_VGAM2, 0x04),
+       RV(NT39016_REG_VGAM34, 0x24),
+       RV(NT39016_REG_VGAM56, 0x24),
+       RV(NT39016_REG_DISPLAY_MODE, 0x00),
+};
+
+#undef RV
+
+static const struct regmap_range nt39016_regmap_no_ranges[] = {
+       regmap_reg_range(0x13, 0x1D),
+       regmap_reg_range(0x1F, 0x1F),
+};
+
+static const struct regmap_access_table nt39016_regmap_access_table = {
+       .no_ranges = nt39016_regmap_no_ranges,
+       .n_no_ranges = ARRAY_SIZE(nt39016_regmap_no_ranges),
+};
+
+static const struct regmap_config nt39016_regmap_config = {
+       .reg_bits = 6,
+       .pad_bits = 2,
+       .val_bits = 8,
+
+       .max_register = NT39016_REG_DISPLAY_MODE,
+       .wr_table = &nt39016_regmap_access_table,
+       .write_flag_mask = 0x02,
+
+       .cache_type = REGCACHE_FLAT,
+};
+
+static int nt39016_prepare(struct drm_panel *drm_panel)
+{
+       struct nt39016 *panel = to_nt39016(drm_panel);
+       int err;
+
+       err = regulator_enable(panel->supply);
+       if (err) {
+               dev_err(panel->dev, "Failed to enable power supply: %d", err);
+               return err;
+       }
+
+       /*
+        * Reset the NT39016.
+        * The documentation says the reset pulse should be at least 40 us to
+        * pass the glitch filter, but when testing I see some resets fail and
+        * some succeed when using a 70 us delay, so we use 100 us instead.
+        */
+       gpiod_set_value_cansleep(panel->reset_gpio, 1);
+       usleep_range(100, 1000);
+       gpiod_set_value_cansleep(panel->reset_gpio, 0);
+       udelay(2);
+
+       /* Init all registers. */
+       err = regmap_multi_reg_write(panel->map, nt39016_panel_regs,
+                                    ARRAY_SIZE(nt39016_panel_regs));
+       if (err) {
+               dev_err(panel->dev, "Failed to init registers: %d", err);
+               goto err_disable_regulator;
+       }
+
+       return 0;
+
+err_disable_regulator:
+       regulator_disable(panel->supply);
+       return err;
+}
+
+static int nt39016_unprepare(struct drm_panel *drm_panel)
+{
+       struct nt39016 *panel = to_nt39016(drm_panel);
+
+       gpiod_set_value_cansleep(panel->reset_gpio, 1);
+
+       regulator_disable(panel->supply);
+
+       return 0;
+}
+
+static int nt39016_enable(struct drm_panel *drm_panel)
+{
+       struct nt39016 *panel = to_nt39016(drm_panel);
+       int ret;
+
+       ret = regmap_write(panel->map, NT39016_REG_SYSTEM,
+                          NT39016_SYSTEM_RESET_N | NT39016_SYSTEM_STANDBY);
+       if (ret) {
+               dev_err(panel->dev, "Unable to enable panel: %d", ret);
+               return ret;
+       }
+
+       if (panel->backlight) {
+               /* Wait for the picture to be ready before enabling backlight */
+               msleep(150);
+
+               ret = backlight_enable(panel->backlight);
+       }
+
+       return ret;
+}
+
+static int nt39016_disable(struct drm_panel *drm_panel)
+{
+       struct nt39016 *panel = to_nt39016(drm_panel);
+       int err;
+
+       backlight_disable(panel->backlight);
+
+       err = regmap_write(panel->map, NT39016_REG_SYSTEM,
+                          NT39016_SYSTEM_RESET_N);
+       if (err) {
+               dev_err(panel->dev, "Unable to disable panel: %d", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int nt39016_get_modes(struct drm_panel *drm_panel)
+{
+       struct nt39016 *panel = to_nt39016(drm_panel);
+       const struct nt39016_panel_info *panel_info = panel->panel_info;
+       struct drm_connector *connector = drm_panel->connector;
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(drm_panel->drm, &panel_info->display_mode);
+       if (!mode)
+               return -ENOMEM;
+
+       drm_mode_set_name(mode);
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       drm_mode_probed_add(connector, mode);
+
+       connector->display_info.bpc = 8;
+       connector->display_info.width_mm = panel_info->width_mm;
+       connector->display_info.height_mm = panel_info->height_mm;
+
+       drm_display_info_set_bus_formats(&connector->display_info,
+                                        &panel_info->bus_format, 1);
+       connector->display_info.bus_flags = panel_info->bus_flags;
+
+       return 1;
+}
+
+static const struct drm_panel_funcs nt39016_funcs = {
+       .prepare        = nt39016_prepare,
+       .unprepare      = nt39016_unprepare,
+       .enable         = nt39016_enable,
+       .disable        = nt39016_disable,
+       .get_modes      = nt39016_get_modes,
+};
+
+static int nt39016_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct nt39016 *panel;
+       int err;
+
+       panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
+       if (!panel)
+               return -ENOMEM;
+
+       panel->dev = dev;
+       spi_set_drvdata(spi, panel);
+
+       panel->panel_info = of_device_get_match_data(dev);
+       if (!panel->panel_info)
+               return -EINVAL;
+
+       panel->supply = devm_regulator_get(dev, "power");
+       if (IS_ERR(panel->supply)) {
+               dev_err(dev, "Failed to get power supply");
+               return PTR_ERR(panel->supply);
+       }
+
+       panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(panel->reset_gpio)) {
+               dev_err(dev, "Failed to get reset GPIO");
+               return PTR_ERR(panel->reset_gpio);
+       }
+
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_3 | SPI_3WIRE;
+       err = spi_setup(spi);
+       if (err) {
+               dev_err(dev, "Failed to setup SPI");
+               return err;
+       }
+
+       panel->map = devm_regmap_init_spi(spi, &nt39016_regmap_config);
+       if (IS_ERR(panel->map)) {
+               dev_err(dev, "Failed to init regmap");
+               return PTR_ERR(panel->map);
+       }
+
+       panel->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(panel->backlight)) {
+               err = PTR_ERR(panel->backlight);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get backlight handle");
+               return err;
+       }
+
+       drm_panel_init(&panel->drm_panel);
+       panel->drm_panel.dev = dev;
+       panel->drm_panel.funcs = &nt39016_funcs;
+
+       err = drm_panel_add(&panel->drm_panel);
+       if (err < 0) {
+               dev_err(dev, "Failed to register panel");
+               return err;
+       }
+
+       return 0;
+}
+
+static int nt39016_remove(struct spi_device *spi)
+{
+       struct nt39016 *panel = spi_get_drvdata(spi);
+
+       drm_panel_remove(&panel->drm_panel);
+
+       nt39016_disable(&panel->drm_panel);
+       nt39016_unprepare(&panel->drm_panel);
+
+       return 0;
+}
+
+static const struct nt39016_panel_info kd035g6_info = {
+       .display_mode = {
+               .clock = 6000,
+               .hdisplay = 320,
+               .hsync_start = 320 + 10,
+               .hsync_end = 320 + 10 + 50,
+               .htotal = 320 + 10 + 50 + 20,
+               .vdisplay = 240,
+               .vsync_start = 240 + 5,
+               .vsync_end = 240 + 5 + 1,
+               .vtotal = 240 + 5 + 1 + 4,
+               .vrefresh = 60,
+               .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+       },
+       .width_mm = 71,
+       .height_mm = 53,
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+       .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE,
+};
+
+static const struct of_device_id nt39016_of_match[] = {
+       { .compatible = "kingdisplay,kd035g6-54nt", .data = &kd035g6_info },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, nt39016_of_match);
+
+static struct spi_driver nt39016_driver = {
+       .driver = {
+               .name = "nt39016",
+               .of_match_table = nt39016_of_match,
+       },
+       .probe = nt39016_probe,
+       .remove = nt39016_remove,
+};
+
+module_spi_driver(nt39016_driver);
+
+MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_LICENSE("GPL v2");
index 28c0620..b5b14aa 100644 (file)
@@ -399,7 +399,13 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c,
 
        /* Look up the DSI host.  It needs to probe before we do. */
        endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+       if (!endpoint)
+               return -ENODEV;
+
        dsi_host_node = of_graph_get_remote_port_parent(endpoint);
+       if (!dsi_host_node)
+               goto error;
+
        host = of_find_mipi_dsi_host_by_node(dsi_host_node);
        of_node_put(dsi_host_node);
        if (!host) {
@@ -408,6 +414,9 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c,
        }
 
        info.node = of_graph_get_remote_port(endpoint);
+       if (!info.node)
+               goto error;
+
        of_node_put(endpoint);
 
        ts->dsi = mipi_dsi_device_register_full(host, &info);
@@ -428,6 +437,10 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c,
                return ret;
 
        return 0;
+
+error:
+       of_node_put(endpoint);
+       return -ENODEV;
 }
 
 static int rpi_touchscreen_remove(struct i2c_client *i2c)
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
new file mode 100644 (file)
index 0000000..6a5d370
--- /dev/null
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raydium RM67191 MIPI-DSI panel driver
+ *
+ * Copyright 2019 NXP
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+/* Panel specific color-format bits */
+#define COL_FMT_16BPP 0x55
+#define COL_FMT_18BPP 0x66
+#define COL_FMT_24BPP 0x77
+
+/* Write Manufacture Command Set Control */
+#define WRMAUCCTR 0xFE
+
+/* Manufacturer Command Set pages (CMD2) */
+struct cmd_set_entry {
+       u8 cmd;
+       u8 param;
+};
+
+/*
+ * There is no description in the Reference Manual about these commands.
+ * We received them from vendor, so just use them as is.
+ */
+static const struct cmd_set_entry manufacturer_cmd_set[] = {
+       {0xFE, 0x0B},
+       {0x28, 0x40},
+       {0x29, 0x4F},
+       {0xFE, 0x0E},
+       {0x4B, 0x00},
+       {0x4C, 0x0F},
+       {0x4D, 0x20},
+       {0x4E, 0x40},
+       {0x4F, 0x60},
+       {0x50, 0xA0},
+       {0x51, 0xC0},
+       {0x52, 0xE0},
+       {0x53, 0xFF},
+       {0xFE, 0x0D},
+       {0x18, 0x08},
+       {0x42, 0x00},
+       {0x08, 0x41},
+       {0x46, 0x02},
+       {0x72, 0x09},
+       {0xFE, 0x0A},
+       {0x24, 0x17},
+       {0x04, 0x07},
+       {0x1A, 0x0C},
+       {0x0F, 0x44},
+       {0xFE, 0x04},
+       {0x00, 0x0C},
+       {0x05, 0x08},
+       {0x06, 0x08},
+       {0x08, 0x08},
+       {0x09, 0x08},
+       {0x0A, 0xE6},
+       {0x0B, 0x8C},
+       {0x1A, 0x12},
+       {0x1E, 0xE0},
+       {0x29, 0x93},
+       {0x2A, 0x93},
+       {0x2F, 0x02},
+       {0x31, 0x02},
+       {0x33, 0x05},
+       {0x37, 0x2D},
+       {0x38, 0x2D},
+       {0x3A, 0x1E},
+       {0x3B, 0x1E},
+       {0x3D, 0x27},
+       {0x3F, 0x80},
+       {0x40, 0x40},
+       {0x41, 0xE0},
+       {0x4F, 0x2F},
+       {0x50, 0x1E},
+       {0xFE, 0x06},
+       {0x00, 0xCC},
+       {0x05, 0x05},
+       {0x07, 0xA2},
+       {0x08, 0xCC},
+       {0x0D, 0x03},
+       {0x0F, 0xA2},
+       {0x32, 0xCC},
+       {0x37, 0x05},
+       {0x39, 0x83},
+       {0x3A, 0xCC},
+       {0x41, 0x04},
+       {0x43, 0x83},
+       {0x44, 0xCC},
+       {0x49, 0x05},
+       {0x4B, 0xA2},
+       {0x4C, 0xCC},
+       {0x51, 0x03},
+       {0x53, 0xA2},
+       {0x75, 0xCC},
+       {0x7A, 0x03},
+       {0x7C, 0x83},
+       {0x7D, 0xCC},
+       {0x82, 0x02},
+       {0x84, 0x83},
+       {0x85, 0xEC},
+       {0x86, 0x0F},
+       {0x87, 0xFF},
+       {0x88, 0x00},
+       {0x8A, 0x02},
+       {0x8C, 0xA2},
+       {0x8D, 0xEA},
+       {0x8E, 0x01},
+       {0x8F, 0xE8},
+       {0xFE, 0x06},
+       {0x90, 0x0A},
+       {0x92, 0x06},
+       {0x93, 0xA0},
+       {0x94, 0xA8},
+       {0x95, 0xEC},
+       {0x96, 0x0F},
+       {0x97, 0xFF},
+       {0x98, 0x00},
+       {0x9A, 0x02},
+       {0x9C, 0xA2},
+       {0xAC, 0x04},
+       {0xFE, 0x06},
+       {0xB1, 0x12},
+       {0xB2, 0x17},
+       {0xB3, 0x17},
+       {0xB4, 0x17},
+       {0xB5, 0x17},
+       {0xB6, 0x11},
+       {0xB7, 0x08},
+       {0xB8, 0x09},
+       {0xB9, 0x06},
+       {0xBA, 0x07},
+       {0xBB, 0x17},
+       {0xBC, 0x17},
+       {0xBD, 0x17},
+       {0xBE, 0x17},
+       {0xBF, 0x17},
+       {0xC0, 0x17},
+       {0xC1, 0x17},
+       {0xC2, 0x17},
+       {0xC3, 0x17},
+       {0xC4, 0x0F},
+       {0xC5, 0x0E},
+       {0xC6, 0x00},
+       {0xC7, 0x01},
+       {0xC8, 0x10},
+       {0xFE, 0x06},
+       {0x95, 0xEC},
+       {0x8D, 0xEE},
+       {0x44, 0xEC},
+       {0x4C, 0xEC},
+       {0x32, 0xEC},
+       {0x3A, 0xEC},
+       {0x7D, 0xEC},
+       {0x75, 0xEC},
+       {0x00, 0xEC},
+       {0x08, 0xEC},
+       {0x85, 0xEC},
+       {0xA6, 0x21},
+       {0xA7, 0x05},
+       {0xA9, 0x06},
+       {0x82, 0x06},
+       {0x41, 0x06},
+       {0x7A, 0x07},
+       {0x37, 0x07},
+       {0x05, 0x06},
+       {0x49, 0x06},
+       {0x0D, 0x04},
+       {0x51, 0x04},
+};
+
+static const u32 rad_bus_formats[] = {
+       MEDIA_BUS_FMT_RGB888_1X24,
+       MEDIA_BUS_FMT_RGB666_1X18,
+       MEDIA_BUS_FMT_RGB565_1X16,
+};
+
+static const u32 rad_bus_flags = DRM_BUS_FLAG_DE_LOW |
+                                DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+
+struct rad_panel {
+       struct drm_panel panel;
+       struct mipi_dsi_device *dsi;
+
+       struct gpio_desc *reset;
+       struct backlight_device *backlight;
+
+       struct regulator_bulk_data *supplies;
+       unsigned int num_supplies;
+
+       bool prepared;
+       bool enabled;
+};
+
+static const struct drm_display_mode default_mode = {
+       .clock = 132000,
+       .hdisplay = 1080,
+       .hsync_start = 1080 + 20,
+       .hsync_end = 1080 + 20 + 2,
+       .htotal = 1080 + 20 + 2 + 34,
+       .vdisplay = 1920,
+       .vsync_start = 1920 + 10,
+       .vsync_end = 1920 + 10 + 2,
+       .vtotal = 1920 + 10 + 2 + 4,
+       .vrefresh = 60,
+       .width_mm = 68,
+       .height_mm = 121,
+       .flags = DRM_MODE_FLAG_NHSYNC |
+                DRM_MODE_FLAG_NVSYNC,
+};
+
+static inline struct rad_panel *to_rad_panel(struct drm_panel *panel)
+{
+       return container_of(panel, struct rad_panel, panel);
+}
+
+static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi)
+{
+       size_t i;
+       size_t count = ARRAY_SIZE(manufacturer_cmd_set);
+       int ret = 0;
+
+       for (i = 0; i < count; i++) {
+               const struct cmd_set_entry *entry = &manufacturer_cmd_set[i];
+               u8 buffer[2] = { entry->cmd, entry->param };
+
+               ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer));
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
+};
+
+static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format)
+{
+       switch (format) {
+       case MIPI_DSI_FMT_RGB565:
+               return COL_FMT_16BPP;
+       case MIPI_DSI_FMT_RGB666:
+       case MIPI_DSI_FMT_RGB666_PACKED:
+               return COL_FMT_18BPP;
+       case MIPI_DSI_FMT_RGB888:
+               return COL_FMT_24BPP;
+       default:
+               return COL_FMT_24BPP; /* for backward compatibility */
+       }
+};
+
+static int rad_panel_prepare(struct drm_panel *panel)
+{
+       struct rad_panel *rad = to_rad_panel(panel);
+       int ret;
+
+       if (rad->prepared)
+               return 0;
+
+       ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
+       if (ret)
+               return ret;
+
+       if (rad->reset) {
+               gpiod_set_value_cansleep(rad->reset, 1);
+               usleep_range(3000, 5000);
+               gpiod_set_value_cansleep(rad->reset, 0);
+               usleep_range(18000, 20000);
+       }
+
+       rad->prepared = true;
+
+       return 0;
+}
+
+static int rad_panel_unprepare(struct drm_panel *panel)
+{
+       struct rad_panel *rad = to_rad_panel(panel);
+       int ret;
+
+       if (!rad->prepared)
+               return 0;
+
+       /*
+        * Right after asserting the reset, we need to release it, so that the
+        * touch driver can have an active connection with the touch controller
+        * even after the display is turned off.
+        */
+       if (rad->reset) {
+               gpiod_set_value_cansleep(rad->reset, 1);
+               usleep_range(15000, 17000);
+               gpiod_set_value_cansleep(rad->reset, 0);
+       }
+
+       ret = regulator_bulk_disable(rad->num_supplies, rad->supplies);
+       if (ret)
+               return ret;
+
+       rad->prepared = false;
+
+       return 0;
+}
+
+static int rad_panel_enable(struct drm_panel *panel)
+{
+       struct rad_panel *rad = to_rad_panel(panel);
+       struct mipi_dsi_device *dsi = rad->dsi;
+       struct device *dev = &dsi->dev;
+       int color_format = color_format_from_dsi_format(dsi->format);
+       int ret;
+
+       if (rad->enabled)
+               return 0;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       ret = rad_panel_push_cmd_list(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to send MCS (%d)\n", ret);
+               goto fail;
+       }
+
+       /* Select User Command Set table (CMD1) */
+       ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2);
+       if (ret < 0)
+               goto fail;
+
+       /* Software reset */
+       ret = mipi_dsi_dcs_soft_reset(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to do Software Reset (%d)\n", ret);
+               goto fail;
+       }
+
+       usleep_range(15000, 17000);
+
+       /* Set DSI mode */
+       ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set DSI mode (%d)\n", ret);
+               goto fail;
+       }
+       /* Set tear ON */
+       ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set tear ON (%d)\n", ret);
+               goto fail;
+       }
+       /* Set tear scanline */
+       ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set tear scanline (%d)\n", ret);
+               goto fail;
+       }
+       /* Set pixel format */
+       ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format);
+       DRM_DEV_DEBUG_DRIVER(dev, "Interface color format set to 0x%x\n",
+                            color_format);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set pixel format (%d)\n", ret);
+               goto fail;
+       }
+       /* Exit sleep mode */
+       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to exit sleep mode (%d)\n", ret);
+               goto fail;
+       }
+
+       usleep_range(5000, 7000);
+
+       ret = mipi_dsi_dcs_set_display_on(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set display ON (%d)\n", ret);
+               goto fail;
+       }
+
+       backlight_enable(rad->backlight);
+
+       rad->enabled = true;
+
+       return 0;
+
+fail:
+       gpiod_set_value_cansleep(rad->reset, 1);
+
+       return ret;
+}
+
+static int rad_panel_disable(struct drm_panel *panel)
+{
+       struct rad_panel *rad = to_rad_panel(panel);
+       struct mipi_dsi_device *dsi = rad->dsi;
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       if (!rad->enabled)
+               return 0;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       backlight_disable(rad->backlight);
+
+       usleep_range(10000, 12000);
+
+       ret = mipi_dsi_dcs_set_display_off(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to set display OFF (%d)\n", ret);
+               return ret;
+       }
+
+       usleep_range(5000, 10000);
+
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "Failed to enter sleep mode (%d)\n", ret);
+               return ret;
+       }
+
+       rad->enabled = false;
+
+       return 0;
+}
+
+static int rad_panel_get_modes(struct drm_panel *panel)
+{
+       struct drm_connector *connector = panel->connector;
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(panel->drm, &default_mode);
+       if (!mode) {
+               DRM_DEV_ERROR(panel->dev, "failed to add mode %ux%ux@%u\n",
+                             default_mode.hdisplay, default_mode.vdisplay,
+                             default_mode.vrefresh);
+               return -ENOMEM;
+       }
+
+       drm_mode_set_name(mode);
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       drm_mode_probed_add(panel->connector, mode);
+
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+       connector->display_info.bus_flags = rad_bus_flags;
+
+       drm_display_info_set_bus_formats(&connector->display_info,
+                                        rad_bus_formats,
+                                        ARRAY_SIZE(rad_bus_formats));
+       return 1;
+}
+
+static int rad_bl_get_brightness(struct backlight_device *bl)
+{
+       struct mipi_dsi_device *dsi = bl_get_data(bl);
+       struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
+       u16 brightness;
+       int ret;
+
+       if (!rad->prepared)
+               return 0;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
+       if (ret < 0)
+               return ret;
+
+       bl->props.brightness = brightness;
+
+       return brightness & 0xff;
+}
+
+static int rad_bl_update_status(struct backlight_device *bl)
+{
+       struct mipi_dsi_device *dsi = bl_get_data(bl);
+       struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
+       int ret = 0;
+
+       if (!rad->prepared)
+               return 0;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static const struct backlight_ops rad_bl_ops = {
+       .update_status = rad_bl_update_status,
+       .get_brightness = rad_bl_get_brightness,
+};
+
+static const struct drm_panel_funcs rad_panel_funcs = {
+       .prepare = rad_panel_prepare,
+       .unprepare = rad_panel_unprepare,
+       .enable = rad_panel_enable,
+       .disable = rad_panel_disable,
+       .get_modes = rad_panel_get_modes,
+};
+
+static const char * const rad_supply_names[] = {
+       "v3p3",
+       "v1p8",
+};
+
+static int rad_init_regulators(struct rad_panel *rad)
+{
+       struct device *dev = &rad->dsi->dev;
+       int i;
+
+       rad->num_supplies = ARRAY_SIZE(rad_supply_names);
+       rad->supplies = devm_kcalloc(dev, rad->num_supplies,
+                                    sizeof(*rad->supplies), GFP_KERNEL);
+       if (!rad->supplies)
+               return -ENOMEM;
+
+       for (i = 0; i < rad->num_supplies; i++)
+               rad->supplies[i].supply = rad_supply_names[i];
+
+       return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies);
+};
+
+static int rad_panel_probe(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       struct device_node *np = dev->of_node;
+       struct rad_panel *panel;
+       struct backlight_properties bl_props;
+       int ret;
+       u32 video_mode;
+
+       panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
+       if (!panel)
+               return -ENOMEM;
+
+       mipi_dsi_set_drvdata(dsi, panel);
+
+       panel->dsi = dsi;
+
+       dsi->format = MIPI_DSI_FMT_RGB888;
+       dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
+                          MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+       ret = of_property_read_u32(np, "video-mode", &video_mode);
+       if (!ret) {
+               switch (video_mode) {
+               case 0:
+                       /* burst mode */
+                       dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST;
+                       break;
+               case 1:
+                       /* non-burst mode with sync event */
+                       break;
+               case 2:
+                       /* non-burst mode with sync pulse */
+                       dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+                       break;
+               default:
+                       dev_warn(dev, "invalid video mode %d\n", video_mode);
+                       break;
+               }
+       }
+
+       ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes);
+       if (ret) {
+               dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret);
+               return ret;
+       }
+
+       panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(panel->reset))
+               return PTR_ERR(panel->reset);
+
+       memset(&bl_props, 0, sizeof(bl_props));
+       bl_props.type = BACKLIGHT_RAW;
+       bl_props.brightness = 255;
+       bl_props.max_brightness = 255;
+
+       panel->backlight = devm_backlight_device_register(dev, dev_name(dev),
+                                                         dev, dsi, &rad_bl_ops,
+                                                         &bl_props);
+       if (IS_ERR(panel->backlight)) {
+               ret = PTR_ERR(panel->backlight);
+               dev_err(dev, "Failed to register backlight (%d)\n", ret);
+               return ret;
+       }
+
+       ret = rad_init_regulators(panel);
+       if (ret)
+               return ret;
+
+       drm_panel_init(&panel->panel);
+       panel->panel.funcs = &rad_panel_funcs;
+       panel->panel.dev = dev;
+       dev_set_drvdata(dev, panel);
+
+       ret = drm_panel_add(&panel->panel);
+       if (ret)
+               return ret;
+
+       ret = mipi_dsi_attach(dsi);
+       if (ret)
+               drm_panel_remove(&panel->panel);
+
+       return ret;
+}
+
+static int rad_panel_remove(struct mipi_dsi_device *dsi)
+{
+       struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       ret = mipi_dsi_detach(dsi);
+       if (ret)
+               DRM_DEV_ERROR(dev, "Failed to detach from host (%d)\n",
+                             ret);
+
+       drm_panel_remove(&rad->panel);
+
+       return 0;
+}
+
+static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+       struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
+
+       rad_panel_disable(&rad->panel);
+       rad_panel_unprepare(&rad->panel);
+}
+
+static const struct of_device_id rad_of_match[] = {
+       { .compatible = "raydium,rm67191", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rad_of_match);
+
+static struct mipi_dsi_driver rad_panel_driver = {
+       .driver = {
+               .name = "panel-raydium-rm67191",
+               .of_match_table = rad_of_match,
+       },
+       .probe = rad_panel_probe,
+       .remove = rad_panel_remove,
+       .shutdown = rad_panel_shutdown,
+};
+module_mipi_dsi_driver(rad_panel_driver);
+
+MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
+MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
+MODULE_LICENSE("GPL v2");
index 6dcb692..b910992 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/media-bus-format.h>
 #include <linux/module.h>
+#include <linux/regulator/consumer.h>
 #include <video/display_timing.h>
 #include <video/mipi_display.h>
 
@@ -33,6 +34,7 @@
 #define ST7703_CMD_SETEXTC      0xB9
 #define ST7703_CMD_SETMIPI      0xBA
 #define ST7703_CMD_SETVDC       0xBC
+#define ST7703_CMD_UNKNOWN0     0xBF
 #define ST7703_CMD_SETSCR       0xC0
 #define ST7703_CMD_SETPOWER     0xC1
 #define ST7703_CMD_SETPANEL     0xCC
@@ -46,6 +48,8 @@ struct jh057n {
        struct drm_panel panel;
        struct gpio_desc *reset_gpio;
        struct backlight_device *backlight;
+       struct regulator *vcc;
+       struct regulator *iovcc;
        bool prepared;
 
        struct dentry *debugfs;
@@ -94,7 +98,7 @@ static int jh057n_init_sequence(struct jh057n *ctx)
        msleep(20);
 
        dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
-       dsi_generic_write_seq(dsi, 0xBF, 0x02, 0x11, 0x00);
+       dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN0, 0x02, 0x11, 0x00);
        dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
                              0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
                              0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
@@ -123,7 +127,7 @@ static int jh057n_init_sequence(struct jh057n *ctx)
 
        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
        if (ret < 0) {
-               DRM_DEV_ERROR(dev, "Failed to exit sleep mode\n");
+               DRM_DEV_ERROR(dev, "Failed to exit sleep mode: %d\n", ret);
                return ret;
        }
        /* Panel is operational 120 msec after reset */
@@ -139,6 +143,14 @@ static int jh057n_init_sequence(struct jh057n *ctx)
 static int jh057n_enable(struct drm_panel *panel)
 {
        struct jh057n *ctx = panel_to_jh057n(panel);
+       int ret;
+
+       ret = jh057n_init_sequence(ctx);
+       if (ret < 0) {
+               DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n",
+                             ret);
+               return ret;
+       }
 
        return backlight_enable(ctx->backlight);
 }
@@ -146,19 +158,21 @@ static int jh057n_enable(struct drm_panel *panel)
 static int jh057n_disable(struct drm_panel *panel)
 {
        struct jh057n *ctx = panel_to_jh057n(panel);
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 
-       return backlight_disable(ctx->backlight);
+       backlight_disable(ctx->backlight);
+       return mipi_dsi_dcs_set_display_off(dsi);
 }
 
 static int jh057n_unprepare(struct drm_panel *panel)
 {
        struct jh057n *ctx = panel_to_jh057n(panel);
-       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 
        if (!ctx->prepared)
                return 0;
 
-       mipi_dsi_dcs_set_display_off(dsi);
+       regulator_disable(ctx->iovcc);
+       regulator_disable(ctx->vcc);
        ctx->prepared = false;
 
        return 0;
@@ -173,21 +187,31 @@ static int jh057n_prepare(struct drm_panel *panel)
                return 0;
 
        DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n");
+       ret = regulator_enable(ctx->vcc);
+       if (ret < 0) {
+               DRM_DEV_ERROR(ctx->dev,
+                             "Failed to enable vcc supply: %d\n", ret);
+               return ret;
+       }
+       ret = regulator_enable(ctx->iovcc);
+       if (ret < 0) {
+               DRM_DEV_ERROR(ctx->dev,
+                             "Failed to enable iovcc supply: %d\n", ret);
+               goto disable_vcc;
+       }
+
        gpiod_set_value_cansleep(ctx->reset_gpio, 1);
        usleep_range(20, 40);
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
        msleep(20);
 
-       ret = jh057n_init_sequence(ctx);
-       if (ret < 0) {
-               DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n",
-                             ret);
-               return ret;
-       }
-
        ctx->prepared = true;
 
        return 0;
+
+disable_vcc:
+       regulator_disable(ctx->vcc);
+       return ret;
 }
 
 static const struct drm_display_mode default_mode = {
@@ -300,6 +324,25 @@ static int jh057n_probe(struct mipi_dsi_device *dsi)
        if (IS_ERR(ctx->backlight))
                return PTR_ERR(ctx->backlight);
 
+       ctx->vcc = devm_regulator_get(dev, "vcc");
+       if (IS_ERR(ctx->vcc)) {
+               ret = PTR_ERR(ctx->vcc);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev,
+                                     "Failed to request vcc regulator: %d\n",
+                                     ret);
+               return ret;
+       }
+       ctx->iovcc = devm_regulator_get(dev, "iovcc");
+       if (IS_ERR(ctx->iovcc)) {
+               ret = PTR_ERR(ctx->iovcc);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev,
+                                     "Failed to request iovcc regulator: %d\n",
+                                     ret);
+               return ret;
+       }
+
        drm_panel_init(&ctx->panel);
        ctx->panel.dev = dev;
        ctx->panel.funcs = &jh057n_drm_funcs;
@@ -308,7 +351,9 @@ static int jh057n_probe(struct mipi_dsi_device *dsi)
 
        ret = mipi_dsi_attach(dsi);
        if (ret < 0) {
-               DRM_DEV_ERROR(dev, "mipi_dsi_attach failed. Is host ready?\n");
+               DRM_DEV_ERROR(dev,
+                             "mipi_dsi_attach failed (%d). Is host ready?\n",
+                             ret);
                drm_panel_remove(&ctx->panel);
                return ret;
        }
@@ -327,12 +372,12 @@ static void jh057n_shutdown(struct mipi_dsi_device *dsi)
        struct jh057n *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
 
-       ret = jh057n_unprepare(&ctx->panel);
+       ret = drm_panel_unprepare(&ctx->panel);
        if (ret < 0)
                DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n",
                              ret);
 
-       ret = jh057n_disable(&ctx->panel);
+       ret = drm_panel_disable(&ctx->panel);
        if (ret < 0)
                DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n",
                              ret);
index 5a93c4e..bff7578 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <video/display_timing.h>
+#include <video/of_display_timing.h>
 #include <video/videomode.h>
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
 
+/**
+ * @modes: Pointer to array of fixed modes appropriate for this panel.  If
+ *         only one mode then this can just be the address of this the mode.
+ *         NOTE: cannot be used with "timings" and also if this is specified
+ *         then you cannot override the mode in the device tree.
+ * @num_modes: Number of elements in modes array.
+ * @timings: Pointer to array of display timings.  NOTE: cannot be used with
+ *           "modes" and also these will be used to validate a device tree
+ *           override if one is present.
+ * @num_timings: Number of elements in timings array.
+ * @bpc: Bits per color.
+ * @size: Structure containing the physical size of this panel.
+ * @delay: Structure containing various delay values for this panel.
+ * @bus_format: See MEDIA_BUS_FMT_... defines.
+ * @bus_flags: See DRM_BUS_FLAG_... defines.
+ */
 struct panel_desc {
        const struct drm_display_mode *modes;
        unsigned int num_modes;
@@ -92,6 +109,8 @@ struct panel_simple {
        struct i2c_adapter *ddc;
 
        struct gpio_desc *enable_gpio;
+
+       struct drm_display_mode override_mode;
 };
 
 static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
@@ -99,16 +118,13 @@ static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
        return container_of(panel, struct panel_simple, base);
 }
 
-static int panel_simple_get_fixed_modes(struct panel_simple *panel)
+static unsigned int panel_simple_get_timings_modes(struct panel_simple *panel)
 {
        struct drm_connector *connector = panel->base.connector;
        struct drm_device *drm = panel->base.drm;
        struct drm_display_mode *mode;
        unsigned int i, num = 0;
 
-       if (!panel->desc)
-               return 0;
-
        for (i = 0; i < panel->desc->num_timings; i++) {
                const struct display_timing *dt = &panel->desc->timings[i];
                struct videomode vm;
@@ -132,6 +148,16 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
                num++;
        }
 
+       return num;
+}
+
+static unsigned int panel_simple_get_display_modes(struct panel_simple *panel)
+{
+       struct drm_connector *connector = panel->base.connector;
+       struct drm_device *drm = panel->base.drm;
+       struct drm_display_mode *mode;
+       unsigned int i, num = 0;
+
        for (i = 0; i < panel->desc->num_modes; i++) {
                const struct drm_display_mode *m = &panel->desc->modes[i];
 
@@ -153,6 +179,44 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
                num++;
        }
 
+       return num;
+}
+
+static int panel_simple_get_non_edid_modes(struct panel_simple *panel)
+{
+       struct drm_connector *connector = panel->base.connector;
+       struct drm_device *drm = panel->base.drm;
+       struct drm_display_mode *mode;
+       bool has_override = panel->override_mode.type;
+       unsigned int num = 0;
+
+       if (!panel->desc)
+               return 0;
+
+       if (has_override) {
+               mode = drm_mode_duplicate(drm, &panel->override_mode);
+               if (mode) {
+                       drm_mode_probed_add(connector, mode);
+                       num = 1;
+               } else {
+                       dev_err(drm->dev, "failed to add override mode\n");
+               }
+       }
+
+       /* Only add timings if override was not there or failed to validate */
+       if (num == 0 && panel->desc->num_timings)
+               num = panel_simple_get_timings_modes(panel);
+
+       /*
+        * Only add fixed modes if timings/override added no mode.
+        *
+        * We should only ever have either the display timings specified
+        * or a fixed mode. Anything else is rather bogus.
+        */
+       WARN_ON(panel->desc->num_timings && panel->desc->num_modes);
+       if (num == 0)
+               num = panel_simple_get_display_modes(panel);
+
        connector->display_info.bpc = panel->desc->bpc;
        connector->display_info.width_mm = panel->desc->size.width;
        connector->display_info.height_mm = panel->desc->size.height;
@@ -269,7 +333,7 @@ static int panel_simple_get_modes(struct drm_panel *panel)
        }
 
        /* add hard-coded panel modes */
-       num += panel_simple_get_fixed_modes(p);
+       num += panel_simple_get_non_edid_modes(p);
 
        return num;
 }
@@ -300,10 +364,58 @@ static const struct drm_panel_funcs panel_simple_funcs = {
        .get_timings = panel_simple_get_timings,
 };
 
+#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \
+       (to_check->field.typ >= bounds->field.min && \
+        to_check->field.typ <= bounds->field.max)
+static void panel_simple_parse_panel_timing_node(struct device *dev,
+                                                struct panel_simple *panel,
+                                                const struct display_timing *ot)
+{
+       const struct panel_desc *desc = panel->desc;
+       struct videomode vm;
+       unsigned int i;
+
+       if (WARN_ON(desc->num_modes)) {
+               dev_err(dev, "Reject override mode: panel has a fixed mode\n");
+               return;
+       }
+       if (WARN_ON(!desc->num_timings)) {
+               dev_err(dev, "Reject override mode: no timings specified\n");
+               return;
+       }
+
+       for (i = 0; i < panel->desc->num_timings; i++) {
+               const struct display_timing *dt = &panel->desc->timings[i];
+
+               if (!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hactive) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hfront_porch) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hback_porch) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hsync_len) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vactive) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vfront_porch) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vback_porch) ||
+                   !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vsync_len))
+                       continue;
+
+               if (ot->flags != dt->flags)
+                       continue;
+
+               videomode_from_timing(ot, &vm);
+               drm_display_mode_from_videomode(&vm, &panel->override_mode);
+               panel->override_mode.type |= DRM_MODE_TYPE_DRIVER |
+                                            DRM_MODE_TYPE_PREFERRED;
+               break;
+       }
+
+       if (WARN_ON(!panel->override_mode.type))
+               dev_err(dev, "Reject override mode: No display_timing found\n");
+}
+
 static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
 {
        struct device_node *backlight, *ddc;
        struct panel_simple *panel;
+       struct display_timing dt;
        int err;
 
        panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
@@ -349,6 +461,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
                }
        }
 
+       if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
+               panel_simple_parse_panel_timing_node(dev, panel, &dt);
+
        drm_panel_init(&panel->base);
        panel->base.dev = dev;
        panel->base.funcs = &panel_simple_funcs;
@@ -496,22 +611,21 @@ static const struct panel_desc auo_b101aw03 = {
        },
 };
 
-static const struct drm_display_mode auo_b101ean01_mode = {
-       .clock = 72500,
-       .hdisplay = 1280,
-       .hsync_start = 1280 + 119,
-       .hsync_end = 1280 + 119 + 32,
-       .htotal = 1280 + 119 + 32 + 21,
-       .vdisplay = 800,
-       .vsync_start = 800 + 4,
-       .vsync_end = 800 + 4 + 20,
-       .vtotal = 800 + 4 + 20 + 8,
-       .vrefresh = 60,
+static const struct display_timing auo_b101ean01_timing = {
+       .pixelclock = { 65300000, 72500000, 75000000 },
+       .hactive = { 1280, 1280, 1280 },
+       .hfront_porch = { 18, 119, 119 },
+       .hback_porch = { 21, 21, 21 },
+       .hsync_len = { 32, 32, 32 },
+       .vactive = { 800, 800, 800 },
+       .vfront_porch = { 4, 4, 4 },
+       .vback_porch = { 8, 8, 8 },
+       .vsync_len = { 18, 20, 20 },
 };
 
 static const struct panel_desc auo_b101ean01 = {
-       .modes = &auo_b101ean01_mode,
-       .num_modes = 1,
+       .timings = &auo_b101ean01_timing,
+       .num_timings = 1,
        .bpc = 6,
        .size = {
                .width = 217,
@@ -724,9 +838,9 @@ static const struct panel_desc auo_g133han01 = {
 static const struct display_timing auo_g185han01_timings = {
        .pixelclock = { 120000000, 144000000, 175000000 },
        .hactive = { 1920, 1920, 1920 },
-       .hfront_porch = { 18, 60, 74 },
-       .hback_porch = { 12, 44, 54 },
-       .hsync_len = { 10, 24, 32 },
+       .hfront_porch = { 36, 120, 148 },
+       .hback_porch = { 24, 88, 108 },
+       .hsync_len = { 20, 48, 64 },
        .vactive = { 1080, 1080, 1080 },
        .vfront_porch = { 6, 10, 40 },
        .vback_porch = { 2, 5, 20 },
@@ -1335,6 +1449,31 @@ static const struct panel_desc giantplus_gpg482739qs5 = {
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 };
 
+static const struct display_timing giantplus_gpm940b0_timing = {
+       .pixelclock = { 13500000, 27000000, 27500000 },
+       .hactive = { 320, 320, 320 },
+       .hfront_porch = { 14, 686, 718 },
+       .hback_porch = { 50, 70, 255 },
+       .hsync_len = { 1, 1, 1 },
+       .vactive = { 240, 240, 240 },
+       .vfront_porch = { 1, 1, 179 },
+       .vback_porch = { 1, 21, 31 },
+       .vsync_len = { 1, 1, 6 },
+       .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
+};
+
+static const struct panel_desc giantplus_gpm940b0 = {
+       .timings = &giantplus_gpm940b0_timing,
+       .num_timings = 1,
+       .bpc = 8,
+       .size = {
+               .width = 60,
+               .height = 45,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_3X8,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_NEGEDGE,
+};
+
 static const struct display_timing hannstar_hsd070pww1_timing = {
        .pixelclock = { 64300000, 71100000, 82000000 },
        .hactive = { 1280, 1280, 1280 },
@@ -1578,23 +1717,32 @@ static const struct panel_desc innolux_g121x1_l03 = {
        },
 };
 
-static const struct drm_display_mode innolux_n116bge_mode = {
-       .clock = 76420,
-       .hdisplay = 1366,
-       .hsync_start = 1366 + 136,
-       .hsync_end = 1366 + 136 + 30,
-       .htotal = 1366 + 136 + 30 + 60,
-       .vdisplay = 768,
-       .vsync_start = 768 + 8,
-       .vsync_end = 768 + 8 + 12,
-       .vtotal = 768 + 8 + 12 + 12,
-       .vrefresh = 60,
-       .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+/*
+ * Datasheet specifies that at 60 Hz refresh rate:
+ * - total horizontal time: { 1506, 1592, 1716 }
+ * - total vertical time: { 788, 800, 868 }
+ *
+ * ...but doesn't go into exactly how that should be split into a front
+ * porch, back porch, or sync length.  For now we'll leave a single setting
+ * here which allows a bit of tweaking of the pixel clock at the expense of
+ * refresh rate.
+ */
+static const struct display_timing innolux_n116bge_timing = {
+       .pixelclock = { 72600000, 76420000, 80240000 },
+       .hactive = { 1366, 1366, 1366 },
+       .hfront_porch = { 136, 136, 136 },
+       .hback_porch = { 60, 60, 60 },
+       .hsync_len = { 30, 30, 30 },
+       .vactive = { 768, 768, 768 },
+       .vfront_porch = { 8, 8, 8 },
+       .vback_porch = { 12, 12, 12 },
+       .vsync_len = { 12, 12, 12 },
+       .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW,
 };
 
 static const struct panel_desc innolux_n116bge = {
-       .modes = &innolux_n116bge_mode,
-       .num_modes = 1,
+       .timings = &innolux_n116bge_timing,
+       .num_timings = 1,
        .bpc = 6,
        .size = {
                .width = 256,
@@ -2157,6 +2305,33 @@ static const struct panel_desc ontat_yx700wv03 = {
        .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
 };
 
+static const struct drm_display_mode ortustech_com37h3m_mode  = {
+       .clock = 22153,
+       .hdisplay = 480,
+       .hsync_start = 480 + 8,
+       .hsync_end = 480 + 8 + 10,
+       .htotal = 480 + 8 + 10 + 10,
+       .vdisplay = 640,
+       .vsync_start = 640 + 4,
+       .vsync_end = 640 + 4 + 3,
+       .vtotal = 640 + 4 + 3 + 4,
+       .vrefresh = 60,
+       .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc ortustech_com37h3m = {
+       .modes = &ortustech_com37h3m_mode,
+       .num_modes = 1,
+       .bpc = 8,
+       .size = {
+               .width = 56,    /* 56.16mm */
+               .height = 75,   /* 74.88mm */
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE |
+                    DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
+};
+
 static const struct drm_display_mode ortustech_com43h4m85ulc_mode  = {
        .clock = 25000,
        .hdisplay = 480,
@@ -2354,6 +2529,59 @@ static const struct panel_desc samsung_ltn140at29_301 = {
        },
 };
 
+static const struct drm_display_mode sharp_ld_d5116z01b_mode = {
+       .clock = 168480,
+       .hdisplay = 1920,
+       .hsync_start = 1920 + 48,
+       .hsync_end = 1920 + 48 + 32,
+       .htotal = 1920 + 48 + 32 + 80,
+       .vdisplay = 1280,
+       .vsync_start = 1280 + 3,
+       .vsync_end = 1280 + 3 + 10,
+       .vtotal = 1280 + 3 + 10 + 57,
+       .vrefresh = 60,
+       .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
+};
+
+static const struct panel_desc sharp_ld_d5116z01b = {
+       .modes = &sharp_ld_d5116z01b_mode,
+       .num_modes = 1,
+       .bpc = 8,
+       .size = {
+               .width = 260,
+               .height = 120,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+       .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
+};
+
+static const struct drm_display_mode sharp_lq070y3dg3b_mode = {
+       .clock = 33260,
+       .hdisplay = 800,
+       .hsync_start = 800 + 64,
+       .hsync_end = 800 + 64 + 128,
+       .htotal = 800 + 64 + 128 + 64,
+       .vdisplay = 480,
+       .vsync_start = 480 + 8,
+       .vsync_end = 480 + 8 + 2,
+       .vtotal = 480 + 8 + 2 + 35,
+       .vrefresh = 60,
+       .flags = DISPLAY_FLAGS_PIXDATA_POSEDGE,
+};
+
+static const struct panel_desc sharp_lq070y3dg3b = {
+       .modes = &sharp_lq070y3dg3b_mode,
+       .num_modes = 1,
+       .bpc = 8,
+       .size = {
+               .width = 152,   /* 152.4mm */
+               .height = 91,   /* 91.4mm */
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE |
+                    DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
+};
+
 static const struct drm_display_mode sharp_lq035q7db03_mode = {
        .clock = 5500,
        .hdisplay = 240,
@@ -2454,6 +2682,33 @@ static const struct panel_desc sharp_lq150x1lg11 = {
        .bus_format = MEDIA_BUS_FMT_RGB565_1X16,
 };
 
+static const struct display_timing sharp_ls020b1dd01d_timing = {
+       .pixelclock = { 2000000, 4200000, 5000000 },
+       .hactive = { 240, 240, 240 },
+       .hfront_porch = { 66, 66, 66 },
+       .hback_porch = { 1, 1, 1 },
+       .hsync_len = { 1, 1, 1 },
+       .vactive = { 160, 160, 160 },
+       .vfront_porch = { 52, 52, 52 },
+       .vback_porch = { 6, 6, 6 },
+       .vsync_len = { 10, 10, 10 },
+       .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW,
+};
+
+static const struct panel_desc sharp_ls020b1dd01d = {
+       .timings = &sharp_ls020b1dd01d_timing,
+       .num_timings = 1,
+       .bpc = 6,
+       .size = {
+               .width = 42,
+               .height = 28,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB565_1X16,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH
+                  | DRM_BUS_FLAG_PIXDATA_NEGEDGE
+                  | DRM_BUS_FLAG_SHARP_SIGNALS,
+};
+
 static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
        .clock = 33300,
        .hdisplay = 800,
@@ -2882,6 +3137,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "giantplus,gpg482739qs5",
                .data = &giantplus_gpg482739qs5
+       }, {
+               .compatible = "giantplus,gpm940b0",
+               .data = &giantplus_gpm940b0,
        }, {
                .compatible = "hannstar,hsd070pww1",
                .data = &hannstar_hsd070pww1,
@@ -2978,6 +3236,12 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "ontat,yx700wv03",
                .data = &ontat_yx700wv03,
+       }, {
+               .compatible = "ortustech,com37h3m05dtc",
+               .data = &ortustech_com37h3m,
+       }, {
+               .compatible = "ortustech,com37h3m99dtc",
+               .data = &ortustech_com37h3m,
        }, {
                .compatible = "ortustech,com43h4m85ulc",
                .data = &ortustech_com43h4m85ulc,
@@ -3002,9 +3266,15 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "samsung,ltn140at29-301",
                .data = &samsung_ltn140at29_301,
+       }, {
+               .compatible = "sharp,ld-d5116z01b",
+               .data = &sharp_ld_d5116z01b,
        }, {
                .compatible = "sharp,lq035q7db03",
                .data = &sharp_lq035q7db03,
+       }, {
+               .compatible = "sharp,lq070y3dg3b",
+               .data = &sharp_lq070y3dg3b,
        }, {
                .compatible = "sharp,lq101k1ly04",
                .data = &sharp_lq101k1ly04,
@@ -3014,6 +3284,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "sharp,lq150x1lg11",
                .data = &sharp_lq150x1lg11,
+       }, {
+               .compatible = "sharp,ls020b1dd01d",
+               .data = &sharp_ls020b1dd01d,
        }, {
                .compatible = "shelly,sca07010-bfn-lnn",
                .data = &shelly_sca07010_bfn_lnn,
index db79853..a7c18bc 100644 (file)
@@ -157,7 +157,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
        dev_pm_opp_put(opp);
 
        pfdev->devfreq.devfreq = devm_devfreq_add_device(&pfdev->pdev->dev,
-                       &panfrost_devfreq_profile, "simple_ondemand", NULL);
+                       &panfrost_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
+                       NULL);
        if (IS_ERR(pfdev->devfreq.devfreq)) {
                DRM_DEV_ERROR(&pfdev->pdev->dev, "Couldn't initialize GPU devfreq\n");
                ret = PTR_ERR(pfdev->devfreq.devfreq);
index 83cc01c..ea5948f 100644 (file)
@@ -43,6 +43,7 @@ struct panfrost_features {
        u32 js_features[16];
 
        u32 nr_core_groups;
+       u32 thread_tls_alloc;
 
        unsigned long hw_features[64 / BITS_PER_LONG];
        unsigned long hw_issues[64 / BITS_PER_LONG];
index 85b4b51..b187daa 100644 (file)
@@ -32,10 +32,42 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct
        if (param->pad != 0)
                return -EINVAL;
 
+#define PANFROST_FEATURE(name, member)                 \
+       case DRM_PANFROST_PARAM_ ## name:               \
+               param->value = pfdev->features.member;  \
+               break
+#define PANFROST_FEATURE_ARRAY(name, member, max)                      \
+       case DRM_PANFROST_PARAM_ ## name ## 0 ...                       \
+               DRM_PANFROST_PARAM_ ## name ## max:                     \
+               param->value = pfdev->features.member[param->param -    \
+                       DRM_PANFROST_PARAM_ ## name ## 0];              \
+               break
+
        switch (param->param) {
-       case DRM_PANFROST_PARAM_GPU_PROD_ID:
-               param->value = pfdev->features.id;
-               break;
+               PANFROST_FEATURE(GPU_PROD_ID, id);
+               PANFROST_FEATURE(GPU_REVISION, revision);
+               PANFROST_FEATURE(SHADER_PRESENT, shader_present);
+               PANFROST_FEATURE(TILER_PRESENT, tiler_present);
+               PANFROST_FEATURE(L2_PRESENT, l2_present);
+               PANFROST_FEATURE(STACK_PRESENT, stack_present);
+               PANFROST_FEATURE(AS_PRESENT, as_present);
+               PANFROST_FEATURE(JS_PRESENT, js_present);
+               PANFROST_FEATURE(L2_FEATURES, l2_features);
+               PANFROST_FEATURE(CORE_FEATURES, core_features);
+               PANFROST_FEATURE(TILER_FEATURES, tiler_features);
+               PANFROST_FEATURE(MEM_FEATURES, mem_features);
+               PANFROST_FEATURE(MMU_FEATURES, mmu_features);
+               PANFROST_FEATURE(THREAD_FEATURES, thread_features);
+               PANFROST_FEATURE(MAX_THREADS, max_threads);
+               PANFROST_FEATURE(THREAD_MAX_WORKGROUP_SZ,
+                               thread_max_workgroup_sz);
+               PANFROST_FEATURE(THREAD_MAX_BARRIER_SZ,
+                               thread_max_barrier_sz);
+               PANFROST_FEATURE(COHERENCY_FEATURES, coherency_features);
+               PANFROST_FEATURE_ARRAY(TEXTURE_FEATURES, texture_features, 3);
+               PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15);
+               PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups);
+               PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc);
        default:
                return -EINVAL;
        }
@@ -357,8 +389,7 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = {
 DEFINE_DRM_GEM_SHMEM_FOPS(panfrost_drm_driver_fops);
 
 static struct drm_driver panfrost_drm_driver = {
-       .driver_features        = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME |
-                                 DRIVER_SYNCOBJ,
+       .driver_features        = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,
        .open                   = panfrost_open,
        .postclose              = panfrost_postclose,
        .ioctls                 = panfrost_drm_driver_ioctls,
index b46416b..543ab1b 100644 (file)
@@ -92,8 +92,6 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev,
 
        pobj = to_panfrost_bo(obj);
 
-       obj->resv = attach->dmabuf->resv;
-
        panfrost_mmu_map(pobj);
 
        return obj;
index 20ab333..f67ed92 100644 (file)
@@ -232,6 +232,8 @@ static void panfrost_gpu_init_features(struct panfrost_device *pfdev)
        pfdev->features.stack_present = gpu_read(pfdev, GPU_STACK_PRESENT_LO);
        pfdev->features.stack_present |= (u64)gpu_read(pfdev, GPU_STACK_PRESENT_HI) << 32;
 
+       pfdev->features.thread_tls_alloc = gpu_read(pfdev, GPU_THREAD_TLS_ALLOC);
+
        gpu_id = gpu_read(pfdev, GPU_ID);
        pfdev->features.revision = gpu_id & 0xffff;
        pfdev->features.id = gpu_id >> 16;
index 8d6a404..3c8e820 100644 (file)
@@ -5,8 +5,10 @@
 
 #include <linux/amba/clcd-regs.h>
 #include <linux/seq_file.h>
+
 #include <drm/drm_debugfs.h>
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
+
 #include "pl111_drm.h"
 
 #define REGDEF(reg) { reg, #reg }
index 15d2755..9a15312 100644 (file)
 
 #include <linux/amba/clcd-regs.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/version.h>
 #include <linux/dma-buf.h>
 #include <linux/of_graph.h>
 
-#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "pl111_drm.h"
 
@@ -546,25 +548,8 @@ pl111_init_clock_divider(struct drm_device *drm)
 int pl111_display_init(struct drm_device *drm)
 {
        struct pl111_drm_dev_private *priv = drm->dev_private;
-       struct device *dev = drm->dev;
-       struct device_node *endpoint;
-       u32 tft_r0b0g0[3];
        int ret;
 
-       endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-       if (!endpoint)
-               return -ENODEV;
-
-       if (of_property_read_u32_array(endpoint,
-                                      "arm,pl11x,tft-r0g0b0-pads",
-                                      tft_r0b0g0,
-                                      ARRAY_SIZE(tft_r0b0g0)) != 0) {
-               dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n");
-               of_node_put(endpoint);
-               return -ENOENT;
-       }
-       of_node_put(endpoint);
-
        ret = pl111_init_clock_divider(drm);
        if (ret)
                return ret;
index b2c5e9f..77d2da9 100644 (file)
 #ifndef _PL111_DRM_H_
 #define _PL111_DRM_H_
 
-#include <drm/drm_gem.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <linux/clk-provider.h>
+#include <linux/interrupt.h>
+
+#include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_gem.h>
 #include <drm/drm_panel.h>
-#include <drm/drm_bridge.h>
-#include <linux/clk-provider.h>
-#include <linux/interrupt.h>
+#include <drm/drm_simple_kms_helper.h>
 
 #define CLCD_IRQ_NEXTBASE_UPDATE BIT(2)
 
index 01f8462..276b534 100644 (file)
 
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd-regs.h>
-#include <linux/version.h>
-#include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <linux/module.h>
-#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
+#include <linux/shmem_fs.h>
+#include <linux/slab.h>
+#include <linux/version.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
@@ -67,6 +67,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "pl111_drm.h"
 #include "pl111_versatile.h"
@@ -224,7 +225,7 @@ DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
 
 static struct drm_driver pl111_drm_driver = {
        .driver_features =
-               DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+               DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .ioctls = NULL,
        .fops = &drm_fops,
        .name = "pl111",
@@ -238,9 +239,7 @@ static struct drm_driver pl111_drm_driver = {
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_import_sg_table = pl111_gem_import_sg_table,
-       .gem_prime_export = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_mmap = drm_gem_cma_prime_mmap,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 19d663d..47ccf5c 100644 (file)
@@ -1,10 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0+
-#include <linux/device.h>
 
 #ifndef PL111_NOMADIK_H
 #define PL111_NOMADIK_H
 #endif
 
+struct device;
+
 #ifdef CONFIG_ARCH_NOMADIK
 
 void pl111_nomadik_init(struct device *dev);
index 38f4ee0..09aeaff 100644 (file)
@@ -1,13 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0-only
+
 #include <linux/amba/clcd-regs.h>
+#include <linux/bitops.h>
 #include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/bitops.h>
-#include <linux/module.h>
-#include <drm/drmP.h>
+
 #include "pl111_versatile.h"
 #include "pl111_vexpress.h"
 #include "pl111_drm.h"
index 41aa6d9..1438770 100644 (file)
@@ -4,6 +4,9 @@
 #ifndef PL111_VERSATILE_H
 #define PL111_VERSATILE_H
 
+struct device;
+struct pl111_drm_dev_private;
+
 int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv);
 
 #endif
index 38c938c..350570f 100644 (file)
@@ -51,6 +51,7 @@ int pl111_vexpress_clcd_init(struct device *dev,
                }
                if (of_device_is_compatible(child, "arm,hdlcd")) {
                        has_coretile_hdlcd = true;
+                       of_node_put(child);
                        break;
                }
        }
index 0a2e51a..ef09dc6 100644 (file)
@@ -25,6 +25,8 @@
 
 /* QXL cmd/ring handling */
 
+#include <linux/delay.h>
+
 #include <drm/drm_util.h>
 
 #include "qxl_drv.h"
@@ -375,7 +377,7 @@ void qxl_io_destroy_primary(struct qxl_device *qdev)
 {
        wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC);
        qdev->primary_bo->is_primary = false;
-       drm_gem_object_put_unlocked(&qdev->primary_bo->gem_base);
+       drm_gem_object_put_unlocked(&qdev->primary_bo->tbo.base);
        qdev->primary_bo = NULL;
 }
 
@@ -402,7 +404,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
        wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC);
        qdev->primary_bo = bo;
        qdev->primary_bo->is_primary = true;
-       drm_gem_object_get(&qdev->primary_bo->gem_base);
+       drm_gem_object_get(&qdev->primary_bo->tbo.base);
 }
 
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
index 1184225..9443921 100644 (file)
@@ -28,9 +28,9 @@
  *  Alon Levy <alevy@redhat.com>
  */
 
-#include <linux/debugfs.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_file.h>
 
-#include <drm/drmP.h>
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
@@ -61,12 +61,12 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data)
                int rel;
 
                rcu_read_lock();
-               fobj = rcu_dereference(bo->tbo.resv->fence);
+               fobj = rcu_dereference(bo->tbo.base.resv->fence);
                rel = fobj ? fobj->shared_count : 0;
                rcu_read_unlock();
 
                seq_printf(m, "size %ld, pc %d, num releases %d\n",
-                          (unsigned long)bo->gem_base.size,
+                          (unsigned long)bo->tbo.base.size,
                           bo->pin_count, rel);
        }
        return 0;
index 8b319eb..16d73b2 100644 (file)
  */
 
 #include <linux/crc32.h>
+#include <linux/delay.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "qxl_drv.h"
 #include "qxl_object.h"
@@ -794,7 +797,7 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
                    qdev->dumb_shadow_bo->surf.height != surf.height) {
                        if (qdev->dumb_shadow_bo) {
                                drm_gem_object_put_unlocked
-                                       (&qdev->dumb_shadow_bo->gem_base);
+                                       (&qdev->dumb_shadow_bo->tbo.base);
                                qdev->dumb_shadow_bo = NULL;
                        }
                        qxl_bo_create(qdev, surf.height * surf.stride,
@@ -804,10 +807,10 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
                if (user_bo->shadow != qdev->dumb_shadow_bo) {
                        if (user_bo->shadow) {
                                drm_gem_object_put_unlocked
-                                       (&user_bo->shadow->gem_base);
+                                       (&user_bo->shadow->tbo.base);
                                user_bo->shadow = NULL;
                        }
-                       drm_gem_object_get(&qdev->dumb_shadow_bo->gem_base);
+                       drm_gem_object_get(&qdev->dumb_shadow_bo->tbo.base);
                        user_bo->shadow = qdev->dumb_shadow_bo;
                }
        }
@@ -838,7 +841,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
        qxl_bo_unpin(user_bo);
 
        if (old_state->fb != plane->state->fb && user_bo->shadow) {
-               drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
+               drm_gem_object_put_unlocked(&user_bo->shadow->tbo.base);
                user_bo->shadow = NULL;
        }
 }
index 97c3f1a..5bebf1e 100644 (file)
@@ -20,6 +20,8 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <drm/drm_fourcc.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
index f33e349..c1802e0 100644 (file)
  *    Alon Levy <alevy@redhat.com>
  */
 
-#include <linux/module.h>
+#include "qxl_drv.h"
 #include <linux/console.h>
+#include <linux/module.h>
+#include <linux/pci.h>
 
-#include <drm/drmP.h>
 #include <drm/drm.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
 #include <drm/drm_modeset_helper.h>
+#include <drm/drm_prime.h>
 #include <drm/drm_probe_helper.h>
-#include "qxl_drv.h"
+
 #include "qxl_object.h"
 
 static const struct pci_device_id pciidlist[] = {
@@ -206,16 +210,14 @@ static int qxl_pm_resume(struct device *dev)
 
 static int qxl_pm_thaw(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
 
        return qxl_drm_resume(drm_dev, true);
 }
 
 static int qxl_pm_freeze(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
 
        return qxl_drm_freeze(drm_dev);
 }
@@ -247,8 +249,7 @@ static struct pci_driver qxl_pci_driver = {
 };
 
 static struct drm_driver qxl_driver = {
-       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 
        .dumb_create = qxl_mode_dumb_create,
        .dumb_map_offset = qxl_mode_dumb_mmap,
@@ -257,8 +258,6 @@ static struct drm_driver qxl_driver = {
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = qxl_gem_prime_pin,
        .gem_prime_unpin = qxl_gem_prime_unpin,
        .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
index 2896bb6..9e034c5 100644 (file)
  */
 
 #include <linux/dma-fence.h>
-#include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/workqueue.h>
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_gem.h>
-#include <drm/drmP.h>
+#include <drm/qxl_drm.h>
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
-/* just for ttm_validate_buffer */
 #include <drm/ttm/ttm_execbuf_util.h>
 #include <drm/ttm/ttm_module.h>
 #include <drm/ttm/ttm_placement.h>
-#include <drm/qxl_drm.h>
 
 #include "qxl_dev.h"
 
@@ -72,12 +71,13 @@ extern int qxl_max_ioctls;
        QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)
 
 struct qxl_bo {
+       struct ttm_buffer_object        tbo;
+
        /* Protected by gem.mutex */
        struct list_head                list;
        /* Protected by tbo.reserved */
        struct ttm_place                placements[3];
        struct ttm_placement            placement;
-       struct ttm_buffer_object        tbo;
        struct ttm_bo_kmap_obj          kmap;
        unsigned int pin_count;
        void                            *kptr;
@@ -85,7 +85,6 @@ struct qxl_bo {
        int                             type;
 
        /* Constant after initialization */
-       struct drm_gem_object           gem_base;
        unsigned int is_primary:1; /* is this now a primary surface */
        unsigned int is_dumb:1;
        struct qxl_bo *shadow;
@@ -94,7 +93,7 @@ struct qxl_bo {
        uint32_t surface_id;
        struct qxl_release *surf_create;
 };
-#define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, gem_base)
+#define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, tbo.base)
 #define to_qxl_bo(tobj) container_of((tobj), struct qxl_bo, tbo)
 
 struct qxl_gem {
index 89606c8..69f37db 100644 (file)
@@ -23,7 +23,6 @@
  *          Alon Levy
  */
 
-#include <drm/drmP.h>
 #include <drm/drm.h>
 
 #include "qxl_drv.h"
@@ -64,7 +63,7 @@ int qxl_gem_object_create(struct qxl_device *qdev, int size,
                                  size, initial_domain, alignment, r);
                return r;
        }
-       *obj = &qbo->gem_base;
+       *obj = &qbo->tbo.base;
 
        mutex_lock(&qdev->gem.mutex);
        list_add_tail(&qbo->list, &qdev->gem.objects);
index d410e29..8117a45 100644 (file)
@@ -23,6 +23,9 @@
  *          Alon Levy
  */
 
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
index 3bb31ad..8435af1 100644 (file)
  *          Alon Levy
  */
 
+#include <linux/pci.h>
+
+#include <drm/drm_irq.h>
+
 #include "qxl_drv.h"
 
 irqreturn_t qxl_irq_handler(int irq, void *arg)
index bee61fa..611cbe7 100644 (file)
  *          Alon Levy
  */
 
-#include "qxl_drv.h"
-#include "qxl_object.h"
+#include <linux/io-mapping.h>
+#include <linux/pci.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_probe_helper.h>
-#include <linux/io-mapping.h>
+
+#include "qxl_drv.h"
+#include "qxl_object.h"
 
 int qxl_log_level;
 
index 4928fa6..548dfe6 100644 (file)
@@ -33,14 +33,14 @@ static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
        struct qxl_device *qdev;
 
        bo = to_qxl_bo(tbo);
-       qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
+       qdev = (struct qxl_device *)bo->tbo.base.dev->dev_private;
 
        qxl_surface_evict(qdev, bo, false);
        WARN_ON_ONCE(bo->map_count > 0);
        mutex_lock(&qdev->gem.mutex);
        list_del_init(&bo->list);
        mutex_unlock(&qdev->gem.mutex);
-       drm_gem_object_release(&bo->gem_base);
+       drm_gem_object_release(&bo->tbo.base);
        kfree(bo);
 }
 
@@ -95,7 +95,7 @@ int qxl_bo_create(struct qxl_device *qdev,
        if (bo == NULL)
                return -ENOMEM;
        size = roundup(size, PAGE_SIZE);
-       r = drm_gem_object_init(&qdev->ddev, &bo->gem_base, size);
+       r = drm_gem_object_init(&qdev->ddev, &bo->tbo.base, size);
        if (unlikely(r)) {
                kfree(bo);
                return r;
@@ -214,20 +214,20 @@ void qxl_bo_unref(struct qxl_bo **bo)
        if ((*bo) == NULL)
                return;
 
-       drm_gem_object_put_unlocked(&(*bo)->gem_base);
+       drm_gem_object_put_unlocked(&(*bo)->tbo.base);
        *bo = NULL;
 }
 
 struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo)
 {
-       drm_gem_object_get(&bo->gem_base);
+       drm_gem_object_get(&bo->tbo.base);
        return bo;
 }
 
 static int __qxl_bo_pin(struct qxl_bo *bo)
 {
        struct ttm_operation_ctx ctx = { false, false };
-       struct drm_device *ddev = bo->gem_base.dev;
+       struct drm_device *ddev = bo->tbo.base.dev;
        int r;
 
        if (bo->pin_count) {
@@ -247,7 +247,7 @@ static int __qxl_bo_pin(struct qxl_bo *bo)
 static int __qxl_bo_unpin(struct qxl_bo *bo)
 {
        struct ttm_operation_ctx ctx = { false, false };
-       struct drm_device *ddev = bo->gem_base.dev;
+       struct drm_device *ddev = bo->tbo.base.dev;
        int r, i;
 
        if (!bo->pin_count) {
@@ -310,13 +310,13 @@ void qxl_bo_force_delete(struct qxl_device *qdev)
        dev_err(qdev->ddev.dev, "Userspace still has active objects !\n");
        list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) {
                dev_err(qdev->ddev.dev, "%p %p %lu %lu force free\n",
-                       &bo->gem_base, bo, (unsigned long)bo->gem_base.size,
-                       *((unsigned long *)&bo->gem_base.refcount));
+                       &bo->tbo.base, bo, (unsigned long)bo->tbo.base.size,
+                       *((unsigned long *)&bo->tbo.base.refcount));
                mutex_lock(&qdev->gem.mutex);
                list_del_init(&bo->list);
                mutex_unlock(&qdev->gem.mutex);
                /* this should unref the ttm bo */
-               drm_gem_object_put_unlocked(&bo->gem_base);
+               drm_gem_object_put_unlocked(&bo->tbo.base);
        }
 }
 
index 255b914..8ae54ba 100644 (file)
@@ -34,7 +34,7 @@ static inline int qxl_bo_reserve(struct qxl_bo *bo, bool no_wait)
        r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
        if (unlikely(r != 0)) {
                if (r != -ERESTARTSYS) {
-                       struct drm_device *ddev = bo->gem_base.dev;
+                       struct drm_device *ddev = bo->tbo.base.dev;
 
                        dev_err(ddev->dev, "%p reserve failed\n", bo);
                }
@@ -60,7 +60,7 @@ static inline unsigned long qxl_bo_size(struct qxl_bo *bo)
 
 static inline u64 qxl_bo_mmap_offset(struct qxl_bo *bo)
 {
-       return drm_vma_node_offset_addr(&bo->tbo.vma_node);
+       return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
 static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type,
@@ -71,7 +71,7 @@ static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type,
        r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
        if (unlikely(r != 0)) {
                if (r != -ERESTARTSYS) {
-                       struct drm_device *ddev = bo->gem_base.dev;
+                       struct drm_device *ddev = bo->tbo.base.dev;
 
                        dev_err(ddev->dev, "%p reserve failed for wait\n",
                                bo);
index 49f9a93..df55b83 100644 (file)
  * 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/delay.h>
+
+#include <trace/events/dma_fence.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
-#include <trace/events/dma_fence.h>
 
 /*
  * drawable cmd cache - allocate a bunch of VRAM pages, suballocate
@@ -234,12 +238,12 @@ static int qxl_release_validate_bo(struct qxl_bo *bo)
                        return ret;
        }
 
-       ret = reservation_object_reserve_shared(bo->tbo.resv, 1);
+       ret = reservation_object_reserve_shared(bo->tbo.base.resv, 1);
        if (ret)
                return ret;
 
        /* allocate a surface for reserved + validated buffers */
-       ret = qxl_bo_check_id(bo->gem_base.dev->dev_private, bo);
+       ret = qxl_bo_check_id(bo->tbo.base.dev->dev_private, bo);
        if (ret)
                return ret;
        return 0;
@@ -454,9 +458,9 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release)
        list_for_each_entry(entry, &release->bos, head) {
                bo = entry->bo;
 
-               reservation_object_add_shared_fence(bo->resv, &release->base);
+               reservation_object_add_shared_fence(bo->base.resv, &release->base);
                ttm_bo_add_to_lru(bo);
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        }
        spin_unlock(&glob->lru_lock);
        ww_acquire_fini(&release->ticket);
index 0234f85..9b24514 100644 (file)
  *          Alon Levy
  */
 
+#include <linux/delay.h>
+
+#include <drm/drm.h>
+#include <drm/drm_file.h>
+#include <drm/drm_debugfs.h>
+#include <drm/qxl_drm.h>
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_placement.h>
-#include <drm/ttm/ttm_page_alloc.h>
 #include <drm/ttm/ttm_module.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/qxl_drm.h>
+#include <drm/ttm/ttm_page_alloc.h>
+#include <drm/ttm/ttm_placement.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
-#include <linux/delay.h>
-
 static struct qxl_device *qxl_get_qdev(struct ttm_bo_device *bdev)
 {
        struct qxl_mman *mman;
@@ -153,7 +155,7 @@ static int qxl_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
        struct qxl_bo *qbo = to_qxl_bo(bo);
 
-       return drm_vma_node_verify_access(&qbo->gem_base.vma_node,
+       return drm_vma_node_verify_access(&qbo->tbo.base.vma_node,
                                          filp->private_data);
 }
 
@@ -295,7 +297,7 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
        if (!qxl_ttm_bo_is_qxl_bo(bo))
                return;
        qbo = to_qxl_bo(bo);
-       qdev = qbo->gem_base.dev->dev_private;
+       qdev = qbo->tbo.base.dev->dev_private;
 
        if (bo->mem.mem_type == TTM_PL_PRIV && qbo->surface_id)
                qxl_surface_evict(qdev, qbo, new_mem ? true : false);
index 6589f9e..6ac7175 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
+
 #include <linux/compat.h>
 
-#include <drm/drmP.h>
 #include <drm/r128_drm.h>
+
 #include "r128_drv.h"
 
 typedef struct drm_r128_init32 {
index 9730f49..d84e9c9 100644 (file)
  *    Eric Anholt <anholt@FreeBSD.org>
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_device.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
 #include <drm/r128_drm.h>
+
 #include "r128_drv.h"
 
 u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
index 32808e5..3f77013 100644 (file)
@@ -505,7 +505,6 @@ struct radeon_bo {
        struct list_head                va;
        /* Constant after initialization */
        struct radeon_device            *rdev;
-       struct drm_gem_object           gem_base;
 
        struct ttm_bo_kmap_obj          dma_buf_vmap;
        pid_t                           pid;
@@ -513,7 +512,7 @@ struct radeon_bo {
        struct radeon_mn                *mn;
        struct list_head                mn_list;
 };
-#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
+#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base)
 
 int radeon_gem_debugfs_init(struct radeon_device *rdev);
 
index 7ce5064..1ea50ce 100644 (file)
@@ -122,7 +122,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
        if (rdev->asic->copy.dma) {
                time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
                                                RADEON_BENCHMARK_COPY_DMA, n,
-                                               dobj->tbo.resv);
+                                               dobj->tbo.base.resv);
                if (time < 0)
                        goto out_cleanup;
                if (time > 0)
@@ -133,7 +133,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
        if (rdev->asic->copy.blit) {
                time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
                                                RADEON_BENCHMARK_COPY_BLIT, n,
-                                               dobj->tbo.resv);
+                                               dobj->tbo.base.resv);
                if (time < 0)
                        goto out_cleanup;
                if (time > 0)
index cef0e69..7e5254a 100644 (file)
@@ -257,7 +257,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
        list_for_each_entry(reloc, &p->validated, tv.head) {
                struct reservation_object *resv;
 
-               resv = reloc->robj->tbo.resv;
+               resv = reloc->robj->tbo.base.resv;
                r = radeon_sync_resv(p->rdev, &p->ib.sync, resv,
                                     reloc->tv.num_shared);
                if (r)
@@ -443,7 +443,7 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bo
                        if (bo == NULL)
                                continue;
 
-                       drm_gem_object_put_unlocked(&bo->gem_base);
+                       drm_gem_object_put_unlocked(&bo->tbo.base);
                }
        }
        kfree(parser->track);
index bd52f15..7bf7323 100644 (file)
@@ -275,7 +275,7 @@ static void radeon_unpin_work_func(struct work_struct *__work)
        } else
                DRM_ERROR("failed to reserve buffer after flip\n");
 
-       drm_gem_object_put_unlocked(&work->old_rbo->gem_base);
+       drm_gem_object_put_unlocked(&work->old_rbo->tbo.base);
        kfree(work);
 }
 
@@ -533,7 +533,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
                DRM_ERROR("failed to pin new rbo buffer before flip\n");
                goto cleanup;
        }
-       work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
+       work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.base.resv));
        radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(new_rbo);
 
@@ -607,7 +607,7 @@ pflip_cleanup:
        radeon_bo_unreserve(new_rbo);
 
 cleanup:
-       drm_gem_object_put_unlocked(&work->old_rbo->gem_base);
+       drm_gem_object_put_unlocked(&work->old_rbo->tbo.base);
        dma_fence_put(work->fence);
        kfree(work);
        return r;
index a6cbe11..a4a78df 100644 (file)
@@ -130,8 +130,7 @@ int radeon_gem_object_open(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
 void radeon_gem_object_close(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
-struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
-                                       struct drm_gem_object *gobj,
+struct dma_buf *radeon_gem_prime_export(struct drm_gem_object *gobj,
                                        int flags);
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int crtc,
                                      unsigned int flags, int *vpos, int *hpos,
@@ -153,7 +152,6 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
                                                        struct sg_table *sg);
 int radeon_gem_prime_pin(struct drm_gem_object *obj);
 void radeon_gem_prime_unpin(struct drm_gem_object *obj);
-struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *);
 void *radeon_gem_prime_vmap(struct drm_gem_object *obj);
 void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 
@@ -539,7 +537,7 @@ radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,
+           DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER,
        .load = radeon_driver_load_kms,
        .open = radeon_driver_open_kms,
        .postclose = radeon_driver_postclose_kms,
@@ -565,10 +563,8 @@ static struct drm_driver kms_driver = {
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = radeon_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = radeon_gem_prime_pin,
        .gem_prime_unpin = radeon_gem_prime_unpin,
-       .gem_prime_res_obj = radeon_gem_prime_res_obj,
        .gem_prime_get_sg_table = radeon_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
        .gem_prime_vmap = radeon_gem_prime_vmap,
index d8bc5d2..03873f2 100644 (file)
@@ -83,7 +83,7 @@ retry:
                }
                return r;
        }
-       *obj = &robj->gem_base;
+       *obj = &robj->tbo.base;
        robj->pid = task_pid_nr(current);
 
        mutex_lock(&rdev->gem.mutex);
@@ -114,7 +114,7 @@ static int radeon_gem_set_domain(struct drm_gem_object *gobj,
        }
        if (domain == RADEON_GEM_DOMAIN_CPU) {
                /* Asking for cpu access wait for object idle */
-               r = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ);
+               r = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ);
                if (!r)
                        r = -EBUSY;
 
@@ -449,7 +449,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
        }
        robj = gem_to_radeon_bo(gobj);
 
-       r = reservation_object_test_signaled_rcu(robj->tbo.resv, true);
+       r = reservation_object_test_signaled_rcu(robj->tbo.base.resv, true);
        if (r == 0)
                r = -EBUSY;
        else
@@ -478,7 +478,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
        }
        robj = gem_to_radeon_bo(gobj);
 
-       ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ);
+       ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ);
        if (ret == 0)
                r = -EBUSY;
        else if (ret < 0)
index 8c3871e..0d64ace 100644 (file)
@@ -163,7 +163,7 @@ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
                                continue;
                        }
 
-                       r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
+                       r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv,
                                true, false, MAX_SCHEDULE_TIMEOUT);
                        if (r <= 0)
                                DRM_ERROR("(%ld) failed to wait for user bo\n", r);
index 21f73fc..9db8ba2 100644 (file)
@@ -85,9 +85,9 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
        mutex_unlock(&bo->rdev->gem.mutex);
        radeon_bo_clear_surface_reg(bo);
        WARN_ON_ONCE(!list_empty(&bo->va));
-       if (bo->gem_base.import_attach)
-               drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg);
-       drm_gem_object_release(&bo->gem_base);
+       if (bo->tbo.base.import_attach)
+               drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg);
+       drm_gem_object_release(&bo->tbo.base);
        kfree(bo);
 }
 
@@ -209,7 +209,7 @@ int radeon_bo_create(struct radeon_device *rdev,
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
-       drm_gem_private_object_init(rdev->ddev, &bo->gem_base, size);
+       drm_gem_private_object_init(rdev->ddev, &bo->tbo.base, size);
        bo->rdev = rdev;
        bo->surface_reg = -1;
        INIT_LIST_HEAD(&bo->list);
@@ -442,13 +442,13 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
        dev_err(rdev->dev, "Userspace still has active objects !\n");
        list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
                dev_err(rdev->dev, "%p %p %lu %lu force free\n",
-                       &bo->gem_base, bo, (unsigned long)bo->gem_base.size,
-                       *((unsigned long *)&bo->gem_base.refcount));
+                       &bo->tbo.base, bo, (unsigned long)bo->tbo.base.size,
+                       *((unsigned long *)&bo->tbo.base.refcount));
                mutex_lock(&bo->rdev->gem.mutex);
                list_del_init(&bo->list);
                mutex_unlock(&bo->rdev->gem.mutex);
                /* this should unref the ttm bo */
-               drm_gem_object_put_unlocked(&bo->gem_base);
+               drm_gem_object_put_unlocked(&bo->tbo.base);
        }
 }
 
@@ -610,7 +610,7 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo)
        int steal;
        int i;
 
-       lockdep_assert_held(&bo->tbo.resv->lock.base);
+       reservation_object_assert_held(bo->tbo.base.resv);
 
        if (!bo->tiling_flags)
                return 0;
@@ -736,7 +736,7 @@ void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
                                uint32_t *tiling_flags,
                                uint32_t *pitch)
 {
-       lockdep_assert_held(&bo->tbo.resv->lock.base);
+       reservation_object_assert_held(bo->tbo.base.resv);
 
        if (tiling_flags)
                *tiling_flags = bo->tiling_flags;
@@ -748,7 +748,7 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
                                bool force_drop)
 {
        if (!force_drop)
-               lockdep_assert_held(&bo->tbo.resv->lock.base);
+               reservation_object_assert_held(bo->tbo.base.resv);
 
        if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
                return 0;
@@ -870,7 +870,7 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
 void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence,
                     bool shared)
 {
-       struct reservation_object *resv = bo->tbo.resv;
+       struct reservation_object *resv = bo->tbo.base.resv;
 
        if (shared)
                reservation_object_add_shared_fence(resv, &fence->base);
index 9ffd821..e5554bf 100644 (file)
@@ -116,7 +116,7 @@ static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo)
  */
 static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo)
 {
-       return drm_vma_node_offset_addr(&bo->tbo.vma_node);
+       return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
 extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
index d3a5bea..52b0d0c 100644 (file)
@@ -68,10 +68,10 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
        struct radeon_bo *bo;
        int ret;
 
-       ww_mutex_lock(&resv->lock, NULL);
+       reservation_object_lock(resv, NULL);
        ret = radeon_bo_create(rdev, attach->dmabuf->size, PAGE_SIZE, false,
                               RADEON_GEM_DOMAIN_GTT, 0, sg, resv, &bo);
-       ww_mutex_unlock(&resv->lock);
+       reservation_object_unlock(resv);
        if (ret)
                return ERR_PTR(ret);
 
@@ -80,7 +80,7 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
        mutex_unlock(&rdev->gem.mutex);
 
        bo->prime_shared_count = 1;
-       return &bo->gem_base;
+       return &bo->tbo.base;
 }
 
 int radeon_gem_prime_pin(struct drm_gem_object *obj)
@@ -117,19 +117,11 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj)
 }
 
 
-struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj)
-{
-       struct radeon_bo *bo = gem_to_radeon_bo(obj);
-
-       return bo->tbo.resv;
-}
-
-struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
-                                       struct drm_gem_object *gobj,
+struct dma_buf *radeon_gem_prime_export(struct drm_gem_object *gobj,
                                        int flags)
 {
        struct radeon_bo *bo = gem_to_radeon_bo(gobj);
        if (radeon_ttm_tt_has_userptr(bo->tbo.ttm))
                return ERR_PTR(-EPERM);
-       return drm_gem_prime_export(dev, gobj, flags);
+       return drm_gem_prime_export(gobj, flags);
 }
index 0f6ba81..a5e1d21 100644 (file)
@@ -120,11 +120,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
                if (ring == R600_RING_TYPE_DMA_INDEX)
                        fence = radeon_copy_dma(rdev, gtt_addr, vram_addr,
                                                size / RADEON_GPU_PAGE_SIZE,
-                                               vram_obj->tbo.resv);
+                                               vram_obj->tbo.base.resv);
                else
                        fence = radeon_copy_blit(rdev, gtt_addr, vram_addr,
                                                 size / RADEON_GPU_PAGE_SIZE,
-                                                vram_obj->tbo.resv);
+                                                vram_obj->tbo.base.resv);
                if (IS_ERR(fence)) {
                        DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
                        r = PTR_ERR(fence);
@@ -171,11 +171,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
                if (ring == R600_RING_TYPE_DMA_INDEX)
                        fence = radeon_copy_dma(rdev, vram_addr, gtt_addr,
                                                size / RADEON_GPU_PAGE_SIZE,
-                                               vram_obj->tbo.resv);
+                                               vram_obj->tbo.base.resv);
                else
                        fence = radeon_copy_blit(rdev, vram_addr, gtt_addr,
                                                 size / RADEON_GPU_PAGE_SIZE,
-                                                vram_obj->tbo.resv);
+                                                vram_obj->tbo.base.resv);
                if (IS_ERR(fence)) {
                        DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
                        r = PTR_ERR(fence);
index fb3696b..35ac75a 100644 (file)
@@ -184,7 +184,7 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 
        if (radeon_ttm_tt_has_userptr(bo->ttm))
                return -EPERM;
-       return drm_vma_node_verify_access(&rbo->gem_base.vma_node,
+       return drm_vma_node_verify_access(&rbo->tbo.base.vma_node,
                                          filp->private_data);
 }
 
@@ -244,7 +244,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
        BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0);
 
        num_pages = new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
-       fence = radeon_copy(rdev, old_start, new_start, num_pages, bo->resv);
+       fence = radeon_copy(rdev, old_start, new_start, num_pages, bo->base.resv);
        if (IS_ERR(fence))
                return PTR_ERR(fence);
 
index ff4f794..311e69c 100644 (file)
@@ -477,7 +477,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
-       f = reservation_object_get_excl(bo->tbo.resv);
+       f = reservation_object_get_excl(bo->tbo.base.resv);
        if (f) {
                r = radeon_fence_wait((struct radeon_fence *)f, false);
                if (r) {
index 8512b02..e48a055 100644 (file)
@@ -702,7 +702,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
        if (ib.length_dw != 0) {
                radeon_asic_vm_pad_ib(rdev, &ib);
 
-               radeon_sync_resv(rdev, &ib.sync, pd->tbo.resv, true);
+               radeon_sync_resv(rdev, &ib.sync, pd->tbo.base.resv, true);
                WARN_ON(ib.length_dw > ndw);
                r = radeon_ib_schedule(rdev, &ib, NULL, false);
                if (r) {
@@ -830,8 +830,8 @@ static int radeon_vm_update_ptes(struct radeon_device *rdev,
                uint64_t pte;
                int r;
 
-               radeon_sync_resv(rdev, &ib->sync, pt->tbo.resv, true);
-               r = reservation_object_reserve_shared(pt->tbo.resv, 1);
+               radeon_sync_resv(rdev, &ib->sync, pt->tbo.base.resv, true);
+               r = reservation_object_reserve_shared(pt->tbo.base.resv, 1);
                if (r)
                        return r;
 
index 6df37c2..9c93eb4 100644 (file)
@@ -441,14 +441,11 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
 DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
 
 static struct drm_driver rcar_du_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
-                               | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 524684b..17a9e7e 100644 (file)
@@ -4,8 +4,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-               rockchip_drm_gem.o rockchip_drm_psr.o \
-               rockchip_drm_vop.o rockchip_vop_reg.o
+               rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
index 95e5c51..7d7cb57 100644 (file)
 #include <linux/reset.h>
 #include <linux/clk.h>
 
-#include <drm/drmP.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-
 #include <video/of_videomode.h>
 #include <video/videomode.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/bridge/analogix_dp.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
-#include "rockchip_drm_psr.h"
 #include "rockchip_drm_vop.h"
 
 #define RK3288_GRF_SOC_CON6            0x25c
@@ -73,29 +72,6 @@ struct rockchip_dp_device {
        struct analogix_dp_plat_data plat_data;
 };
 
-static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
-{
-       struct rockchip_dp_device *dp = to_dp(encoder);
-       int ret;
-
-       if (!analogix_dp_psr_enabled(dp->adp))
-               return 0;
-
-       DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
-
-       ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
-                                        PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
-       if (ret) {
-               DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n");
-               return -ETIMEDOUT;
-       }
-
-       if (enabled)
-               return analogix_dp_enable_psr(dp->adp);
-       else
-               return analogix_dp_disable_psr(dp->adp);
-}
-
 static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
 {
        reset_control_assert(dp->rst);
@@ -126,21 +102,9 @@ static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data)
        return ret;
 }
 
-static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data)
-{
-       struct rockchip_dp_device *dp = to_dp(plat_data);
-
-       return rockchip_drm_psr_inhibit_put(&dp->encoder);
-}
-
 static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
 {
        struct rockchip_dp_device *dp = to_dp(plat_data);
-       int ret;
-
-       ret = rockchip_drm_psr_inhibit_get(&dp->encoder);
-       if (ret != 0)
-               return ret;
 
        clk_disable_unprepare(dp->pclk);
 
@@ -180,12 +144,42 @@ static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder,
        /* do nothing */
 }
 
-static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
+static
+struct drm_crtc *rockchip_dp_drm_get_new_crtc(struct drm_encoder *encoder,
+                                             struct drm_atomic_state *state)
+{
+       struct drm_connector *connector;
+       struct drm_connector_state *conn_state;
+
+       connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+       if (!connector)
+               return NULL;
+
+       conn_state = drm_atomic_get_new_connector_state(state, connector);
+       if (!conn_state)
+               return NULL;
+
+       return conn_state->crtc;
+}
+
+static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
+                                          struct drm_atomic_state *state)
 {
        struct rockchip_dp_device *dp = to_dp(encoder);
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state;
        int ret;
        u32 val;
 
+       crtc = rockchip_dp_drm_get_new_crtc(encoder, state);
+       if (!crtc)
+               return;
+
+       old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+       /* Coming back from self refresh, nothing to do */
+       if (old_crtc_state && old_crtc_state->self_refresh_active)
+               return;
+
        ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
        if (ret < 0)
                return;
@@ -210,9 +204,27 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
        clk_disable_unprepare(dp->grfclk);
 }
 
-static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
+static void rockchip_dp_drm_encoder_disable(struct drm_encoder *encoder,
+                                           struct drm_atomic_state *state)
 {
-       /* do nothing */
+       struct rockchip_dp_device *dp = to_dp(encoder);
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *new_crtc_state = NULL;
+       int ret;
+
+       crtc = rockchip_dp_drm_get_new_crtc(encoder, state);
+       /* No crtc means we're doing a full shutdown */
+       if (!crtc)
+               return;
+
+       new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+       /* If we're not entering self-refresh, no need to wait for vact */
+       if (!new_crtc_state || !new_crtc_state->self_refresh_active)
+               return;
+
+       ret = rockchip_drm_wait_vact_end(crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+       if (ret)
+               DRM_DEV_ERROR(dp->dev, "line flag irq timed out\n");
 }
 
 static int
@@ -241,8 +253,8 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
 static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
        .mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
        .mode_set = rockchip_dp_drm_encoder_mode_set,
-       .enable = rockchip_dp_drm_encoder_enable,
-       .disable = rockchip_dp_drm_encoder_nop,
+       .atomic_enable = rockchip_dp_drm_encoder_enable,
+       .atomic_disable = rockchip_dp_drm_encoder_disable,
        .atomic_check = rockchip_dp_drm_encoder_atomic_check,
 };
 
@@ -334,23 +346,16 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
 
        dp->plat_data.dev_type = dp->data->chip_type;
        dp->plat_data.power_on_start = rockchip_dp_poweron_start;
-       dp->plat_data.power_on_end = rockchip_dp_poweron_end;
        dp->plat_data.power_off = rockchip_dp_powerdown;
        dp->plat_data.get_modes = rockchip_dp_get_modes;
 
-       ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
-       if (ret < 0)
-               goto err_cleanup_encoder;
-
        dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
        if (IS_ERR(dp->adp)) {
                ret = PTR_ERR(dp->adp);
-               goto err_unreg_psr;
+               goto err_cleanup_encoder;
        }
 
        return 0;
-err_unreg_psr:
-       rockchip_drm_psr_unregister(&dp->encoder);
 err_cleanup_encoder:
        dp->encoder.funcs->destroy(&dp->encoder);
        return ret;
@@ -362,7 +367,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master,
        struct rockchip_dp_device *dp = dev_get_drvdata(dev);
 
        analogix_dp_unbind(dp->adp);
-       rockchip_drm_psr_unregister(&dp->encoder);
        dp->encoder.funcs->destroy(&dp->encoder);
 
        dp->adp = ERR_PTR(-ENODEV);
index 8c32c32..d505ea7 100644 (file)
@@ -4,24 +4,23 @@
  * Author: Chris Zhong <zyw@rock-chips.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
-
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/extcon.h>
 #include <linux/firmware.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
 #include <linux/mfd/syscon.h>
 #include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
 
 #include <sound/hdmi-codec.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+
 #include "cdn-dp-core.h"
 #include "cdn-dp-reg.h"
 #include "rockchip_drm_vop.h"
index f18a01e..b85ea89 100644 (file)
@@ -7,10 +7,10 @@
 #ifndef _CDN_DP_CORE_H
 #define _CDN_DP_CORE_H
 
-#include <drm/drmP.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
+
 #include "rockchip_drm_drv.h"
 
 #define MAX_PHY                2
index ef8486e..bc073ec 100644 (file)
@@ -6,10 +6,6 @@
  *      Nickey Yang <nickey.yang@rock-chips.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/bridge/dw_mipi_dsi.h>
-#include <drm/drm_of.h>
 #include <linux/clk.h>
 #include <linux/iopoll.h>
 #include <linux/math64.h>
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+
 #include <video/mipi_display.h>
 
+#include <drm/bridge/dw_mipi_dsi.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
 
index cdc304d..906891b 100644 (file)
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
 
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
+#include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/bridge/dw_hdmi.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
index f8ca98d..ed344a7 100644 (file)
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
index 53d2c5b..30c177e 100644 (file)
@@ -6,11 +6,6 @@
  * based on exynos_drm_drv.c
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-iommu.h>
 #include <linux/pm_runtime.h>
 #include <linux/console.h>
 #include <linux/iommu.h>
 
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_fbdev.h"
@@ -212,16 +214,13 @@ static const struct file_operations rockchip_drm_driver_fops = {
 };
 
 static struct drm_driver rockchip_drm_driver = {
-       .driver_features        = DRIVER_MODESET | DRIVER_GEM |
-                                 DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .lastclose              = drm_fb_helper_lastclose,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .gem_free_object_unlocked = rockchip_gem_free_object,
        .dumb_create            = rockchip_gem_dumb_create,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table,
        .gem_prime_import_sg_table      = rockchip_gem_prime_import_sg_table,
        .gem_prime_vmap         = rockchip_gem_prime_vmap,
index 64ca87c..ca01234 100644 (file)
@@ -5,18 +5,18 @@
  */
 
 #include <linux/kernel.h>
+
 #include <drm/drm.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_gem.h"
-#include "rockchip_drm_psr.h"
 
 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
        .destroy       = drm_gem_fb_destroy,
@@ -105,31 +105,8 @@ err_gem_object_unreference:
        return ERR_PTR(ret);
 }
 
-static void
-rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
-{
-       struct drm_device *dev = old_state->dev;
-
-       rockchip_drm_psr_inhibit_get_state(old_state);
-
-       drm_atomic_helper_commit_modeset_disables(dev, old_state);
-
-       drm_atomic_helper_commit_modeset_enables(dev, old_state);
-
-       drm_atomic_helper_commit_planes(dev, old_state,
-                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
-
-       rockchip_drm_psr_inhibit_put_state(old_state);
-
-       drm_atomic_helper_commit_hw_done(old_state);
-
-       drm_atomic_helper_wait_for_vblanks(dev, old_state);
-
-       drm_atomic_helper_cleanup_planes(dev, old_state);
-}
-
 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
-       .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm,
+       .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
index bb8ac18..02be6c5 100644 (file)
@@ -5,8 +5,8 @@
  */
 
 #include <drm/drm.h>
-#include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
index ba9e77a..291e89b 100644 (file)
@@ -4,14 +4,14 @@
  * Author:Mark Yao <mark.yao@rock-chips.com>
  */
 
+#include <linux/dma-buf.h>
+#include <linux/iommu.h>
+
 #include <drm/drm.h>
-#include <drm/drmP.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_prime.h>
 #include <drm/drm_vma_manager.h>
 
-#include <linux/dma-buf.h>
-#include <linux/iommu.h>
-
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
deleted file mode 100644 (file)
index b604747..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- * Author: Yakir Yang <ykk@rock-chips.com>
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_probe_helper.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_psr.h"
-
-#define PSR_FLUSH_TIMEOUT_MS   100
-
-struct psr_drv {
-       struct list_head        list;
-       struct drm_encoder      *encoder;
-
-       struct mutex            lock;
-       int                     inhibit_count;
-       bool                    enabled;
-
-       struct delayed_work     flush_work;
-
-       int (*set)(struct drm_encoder *encoder, bool enable);
-};
-
-static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
-{
-       struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
-       struct psr_drv *psr;
-
-       mutex_lock(&drm_drv->psr_list_lock);
-       list_for_each_entry(psr, &drm_drv->psr_list, list) {
-               if (psr->encoder == encoder)
-                       goto out;
-       }
-       psr = ERR_PTR(-ENODEV);
-
-out:
-       mutex_unlock(&drm_drv->psr_list_lock);
-       return psr;
-}
-
-static int psr_set_state_locked(struct psr_drv *psr, bool enable)
-{
-       int ret;
-
-       if (psr->inhibit_count > 0)
-               return -EINVAL;
-
-       if (enable == psr->enabled)
-               return 0;
-
-       ret = psr->set(psr->encoder, enable);
-       if (ret)
-               return ret;
-
-       psr->enabled = enable;
-       return 0;
-}
-
-static void psr_flush_handler(struct work_struct *work)
-{
-       struct psr_drv *psr = container_of(to_delayed_work(work),
-                                          struct psr_drv, flush_work);
-
-       mutex_lock(&psr->lock);
-       psr_set_state_locked(psr, true);
-       mutex_unlock(&psr->lock);
-}
-
-/**
- * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
- * @encoder: encoder to obtain the PSR encoder
- *
- * Decrements PSR inhibit count on given encoder. Should be called only
- * for a PSR inhibit count increment done before. If PSR inhibit counter
- * reaches zero, PSR flush work is scheduled to make the hardware enter
- * PSR mode in PSR_FLUSH_TIMEOUT_MS.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
-{
-       struct psr_drv *psr = find_psr_by_encoder(encoder);
-
-       if (IS_ERR(psr))
-               return PTR_ERR(psr);
-
-       mutex_lock(&psr->lock);
-       --psr->inhibit_count;
-       WARN_ON(psr->inhibit_count < 0);
-       if (!psr->inhibit_count)
-               mod_delayed_work(system_wq, &psr->flush_work,
-                                PSR_FLUSH_TIMEOUT_MS);
-       mutex_unlock(&psr->lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
-
-void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       struct drm_encoder *encoder;
-       u32 encoder_mask = 0;
-       int i;
-
-       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
-               encoder_mask |= crtc_state->encoder_mask;
-               encoder_mask |= crtc->state->encoder_mask;
-       }
-
-       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
-               rockchip_drm_psr_inhibit_get(encoder);
-}
-EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state);
-
-void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       struct drm_encoder *encoder;
-       u32 encoder_mask = 0;
-       int i;
-
-       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
-               encoder_mask |= crtc_state->encoder_mask;
-               encoder_mask |= crtc->state->encoder_mask;
-       }
-
-       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
-               rockchip_drm_psr_inhibit_put(encoder);
-}
-EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state);
-
-/**
- * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
- * @encoder: encoder to obtain the PSR encoder
- *
- * Increments PSR inhibit count on given encoder. This function guarantees
- * that after it returns PSR is turned off on given encoder and no PSR-related
- * hardware state change occurs at least until a matching call to
- * rockchip_drm_psr_inhibit_put() is done.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder)
-{
-       struct psr_drv *psr = find_psr_by_encoder(encoder);
-
-       if (IS_ERR(psr))
-               return PTR_ERR(psr);
-
-       mutex_lock(&psr->lock);
-       psr_set_state_locked(psr, false);
-       ++psr->inhibit_count;
-       mutex_unlock(&psr->lock);
-       cancel_delayed_work_sync(&psr->flush_work);
-
-       return 0;
-}
-EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
-
-static void rockchip_drm_do_flush(struct psr_drv *psr)
-{
-       cancel_delayed_work_sync(&psr->flush_work);
-
-       mutex_lock(&psr->lock);
-       if (!psr_set_state_locked(psr, false))
-               mod_delayed_work(system_wq, &psr->flush_work,
-                                PSR_FLUSH_TIMEOUT_MS);
-       mutex_unlock(&psr->lock);
-}
-
-/**
- * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
- * @dev: drm device
- *
- * Disable the PSR function for all registered encoders, and then enable the
- * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
- * changed during flush time, then keep the state no change after flush
- * timeout.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-void rockchip_drm_psr_flush_all(struct drm_device *dev)
-{
-       struct rockchip_drm_private *drm_drv = dev->dev_private;
-       struct psr_drv *psr;
-
-       mutex_lock(&drm_drv->psr_list_lock);
-       list_for_each_entry(psr, &drm_drv->psr_list, list)
-               rockchip_drm_do_flush(psr);
-       mutex_unlock(&drm_drv->psr_list_lock);
-}
-EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
-
-/**
- * rockchip_drm_psr_register - register encoder to psr driver
- * @encoder: encoder that obtain the PSR function
- * @psr_set: call back to set PSR state
- *
- * The function returns with PSR inhibit counter initialized with one
- * and the caller (typically encoder driver) needs to call
- * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR
- * enable request.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int rockchip_drm_psr_register(struct drm_encoder *encoder,
-                       int (*psr_set)(struct drm_encoder *, bool enable))
-{
-       struct rockchip_drm_private *drm_drv;
-       struct psr_drv *psr;
-
-       if (!encoder || !psr_set)
-               return -EINVAL;
-
-       drm_drv = encoder->dev->dev_private;
-
-       psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
-       if (!psr)
-               return -ENOMEM;
-
-       INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
-       mutex_init(&psr->lock);
-
-       psr->inhibit_count = 1;
-       psr->enabled = false;
-       psr->encoder = encoder;
-       psr->set = psr_set;
-
-       mutex_lock(&drm_drv->psr_list_lock);
-       list_add_tail(&psr->list, &drm_drv->psr_list);
-       mutex_unlock(&drm_drv->psr_list_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(rockchip_drm_psr_register);
-
-/**
- * rockchip_drm_psr_unregister - unregister encoder to psr driver
- * @encoder: encoder that obtain the PSR function
- * @psr_set: call back to set PSR state
- *
- * It is expected that the PSR inhibit counter is 1 when this function is
- * called, which corresponds to a state when related encoder has been
- * disconnected from any CRTCs and its driver called
- * rockchip_drm_psr_inhibit_get() to stop the PSR logic.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
-{
-       struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
-       struct psr_drv *psr, *n;
-
-       mutex_lock(&drm_drv->psr_list_lock);
-       list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
-               if (psr->encoder == encoder) {
-                       /*
-                        * Any other value would mean that the encoder
-                        * is still in use.
-                        */
-                       WARN_ON(psr->inhibit_count != 1);
-
-                       list_del(&psr->list);
-                       kfree(psr);
-               }
-       }
-       mutex_unlock(&drm_drv->psr_list_lock);
-}
-EXPORT_SYMBOL(rockchip_drm_psr_unregister);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
deleted file mode 100644 (file)
index 28a9c39..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- * Author: Yakir Yang <ykk@rock-chips.com>
- */
-
-#ifndef __ROCKCHIP_DRM_PSR___
-#define __ROCKCHIP_DRM_PSR___
-
-void rockchip_drm_psr_flush_all(struct drm_device *dev);
-
-int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder);
-int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder);
-
-void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state);
-void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state);
-
-int rockchip_drm_psr_register(struct drm_encoder *encoder,
-                       int (*psr_set)(struct drm_encoder *, bool enable));
-void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
-
-#endif /* __ROCKCHIP_DRM_PSR__ */
index 09a790c..2f821c5 100644 (file)
@@ -4,40 +4,43 @@
  * Author:Mark Yao <mark.yao@rock-chips.com>
  */
 
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
 #include <drm/drm.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_flip_work.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_self_refresh_helper.h>
+#include <drm/drm_vblank.h>
+
 #ifdef CONFIG_DRM_ANALOGIX_DP
 #include <drm/bridge/analogix_dp.h>
 #endif
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/iopoll.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/component.h>
-#include <linux/overflow.h>
-
-#include <linux/reset.h>
-#include <linux/delay.h>
-
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 #include "rockchip_drm_fb.h"
-#include "rockchip_drm_psr.h"
 #include "rockchip_drm_vop.h"
 #include "rockchip_rgb.h"
 
+#define VOP_SELF_REFRESH_ENTRY_DELAY_MS 100
+
 #define VOP_WIN_SET(vop, win, name, v) \
                vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
 #define VOP_SCL_SET(vop, win, name, v) \
@@ -79,7 +82,7 @@
                vop_get_intr_type(vop, &vop->data->intr->name, type)
 
 #define VOP_WIN_GET(vop, win, name) \
-               vop_read_reg(vop, win->offset, win->phy->name)
+               vop_read_reg(vop, win->base, &win->phy->name)
 
 #define VOP_WIN_HAS_REG(win, name) \
        (!!(win->phy->name.mask))
@@ -124,6 +127,7 @@ struct vop {
        bool is_enabled;
 
        struct completion dsp_hold_completion;
+       unsigned int win_enabled;
 
        /* protected by dev->event_lock */
        struct drm_pending_vblank_event *event;
@@ -528,8 +532,10 @@ static void vop_core_clks_disable(struct vop *vop)
        clk_disable(vop->hclk);
 }
 
-static void vop_win_disable(struct vop *vop, const struct vop_win_data *win)
+static void vop_win_disable(struct vop *vop, const struct vop_win *vop_win)
 {
+       const struct vop_win_data *win = vop_win->data;
+
        if (win->phy->scl && win->phy->scl->ext) {
                VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE);
                VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE);
@@ -538,9 +544,10 @@ static void vop_win_disable(struct vop *vop, const struct vop_win_data *win)
        }
 
        VOP_WIN_SET(vop, win, enable, 0);
+       vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win));
 }
 
-static int vop_enable(struct drm_crtc *crtc)
+static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
 {
        struct vop *vop = to_vop(crtc);
        int ret, i;
@@ -580,12 +587,17 @@ static int vop_enable(struct drm_crtc *crtc)
         * We need to make sure that all windows are disabled before we
         * enable the crtc. Otherwise we might try to scan from a destroyed
         * buffer later.
+        *
+        * In the case of enable-after-PSR, we don't need to worry about this
+        * case since the buffer is guaranteed to be valid and disabling the
+        * window will result in screen glitches on PSR exit.
         */
-       for (i = 0; i < vop->data->win_size; i++) {
-               struct vop_win *vop_win = &vop->win[i];
-               const struct vop_win_data *win = vop_win->data;
+       if (!old_state || !old_state->self_refresh_active) {
+               for (i = 0; i < vop->data->win_size; i++) {
+                       struct vop_win *vop_win = &vop->win[i];
 
-               vop_win_disable(vop, win);
+                       vop_win_disable(vop, vop_win);
+               }
        }
        spin_unlock(&vop->reg_lock);
 
@@ -615,6 +627,25 @@ err_put_pm_runtime:
        return ret;
 }
 
+static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled)
+{
+        struct vop *vop = to_vop(crtc);
+        int i;
+
+        spin_lock(&vop->reg_lock);
+
+        for (i = 0; i < vop->data->win_size; i++) {
+                struct vop_win *vop_win = &vop->win[i];
+                const struct vop_win_data *win = vop_win->data;
+
+                VOP_WIN_SET(vop, win, enable,
+                            enabled && (vop->win_enabled & BIT(i)));
+        }
+        vop_cfg_done(vop);
+
+        spin_unlock(&vop->reg_lock);
+}
+
 static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
@@ -622,9 +653,16 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
 
        WARN_ON(vop->event);
 
+       if (crtc->state->self_refresh_active)
+               rockchip_drm_set_win_enabled(crtc, false);
+
        mutex_lock(&vop->vop_lock);
+
        drm_crtc_vblank_off(crtc);
 
+       if (crtc->state->self_refresh_active)
+               goto out;
+
        /*
         * Vop standby will take effect at end of current frame,
         * if dsp hold valid irq happen, it means standby complete.
@@ -655,6 +693,8 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
        clk_disable(vop->dclk);
        vop_core_clks_disable(vop);
        pm_runtime_put(vop->dev);
+
+out:
        mutex_unlock(&vop->vop_lock);
 
        if (crtc->state->event && !crtc->state->active) {
@@ -726,7 +766,6 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
                                     struct drm_plane_state *old_state)
 {
        struct vop_win *vop_win = to_vop_win(plane);
-       const struct vop_win_data *win = vop_win->data;
        struct vop *vop = to_vop(old_state->crtc);
 
        if (!old_state->crtc)
@@ -734,7 +773,7 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
 
        spin_lock(&vop->reg_lock);
 
-       vop_win_disable(vop, win);
+       vop_win_disable(vop, vop_win);
 
        spin_unlock(&vop->reg_lock);
 }
@@ -873,6 +912,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        }
 
        VOP_WIN_SET(vop, win, enable, 1);
+       vop->win_enabled |= BIT(win_index);
        spin_unlock(&vop->reg_lock);
 }
 
@@ -924,12 +964,10 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
        swap(plane->state->fb, new_state->fb);
 
        if (vop->is_enabled) {
-               rockchip_drm_psr_inhibit_get_state(new_state->state);
                vop_plane_atomic_update(plane, plane->state);
                spin_lock(&vop->reg_lock);
                vop_cfg_done(vop);
                spin_unlock(&vop->reg_lock);
-               rockchip_drm_psr_inhibit_put_state(new_state->state);
 
                /*
                 * A scanout can still be occurring, so we can't drop the
@@ -1033,11 +1071,17 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
        int dither_bpc = s->output_bpc ? s->output_bpc : 10;
        int ret;
 
+       if (old_state && old_state->self_refresh_active) {
+               drm_crtc_vblank_on(crtc);
+               rockchip_drm_set_win_enabled(crtc, true);
+               return;
+       }
+
        mutex_lock(&vop->vop_lock);
 
        WARN_ON(vop->event);
 
-       ret = vop_enable(crtc);
+       ret = vop_enable(crtc, old_state);
        if (ret) {
                mutex_unlock(&vop->vop_lock);
                DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret);
@@ -1519,6 +1563,13 @@ static int vop_create_crtc(struct vop *vop)
        init_completion(&vop->line_flag_completion);
        crtc->port = port;
 
+       ret = drm_self_refresh_helper_init(crtc,
+                                          VOP_SELF_REFRESH_ENTRY_DELAY_MS);
+       if (ret)
+               DRM_DEV_DEBUG_KMS(vop->dev,
+                       "Failed to init %s with SR helpers %d, ignoring\n",
+                       crtc->name, ret);
+
        return 0;
 
 err_cleanup_crtc:
@@ -1536,6 +1587,8 @@ static void vop_destroy_crtc(struct vop *vop)
        struct drm_device *drm_dev = vop->drm_dev;
        struct drm_plane *plane, *tmp;
 
+       drm_self_refresh_helper_cleanup(crtc);
+
        of_node_put(crtc->port);
 
        /*
@@ -1560,7 +1613,6 @@ static void vop_destroy_crtc(struct vop *vop)
 
 static int vop_initial(struct vop *vop)
 {
-       const struct vop_data *vop_data = vop->data;
        struct reset_control *ahb_rst;
        int i, ret;
 
@@ -1627,12 +1679,13 @@ static int vop_initial(struct vop *vop)
        VOP_REG_SET(vop, misc, global_regdone_en, 1);
        VOP_REG_SET(vop, common, dsp_blank, 0);
 
-       for (i = 0; i < vop_data->win_size; i++) {
-               const struct vop_win_data *win = &vop_data->win[i];
+       for (i = 0; i < vop->data->win_size; i++) {
+               struct vop_win *vop_win = &vop->win[i];
+               const struct vop_win_data *win = vop_win->data;
                int channel = i * 2 + 1;
 
                VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel);
-               vop_win_disable(vop, win);
+               vop_win_disable(vop, vop_win);
                VOP_WIN_SET(vop, win, gate, 1);
        }
 
index 830858a..64aefa8 100644 (file)
@@ -6,21 +6,21 @@
  *      Sandy Huang <hjc@rock-chips.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
-
-#include <linux/component.h>
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of_graph.h>
 #include <linux/pinctrl/devinfo.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
+#include <drm/drm_atomic_helper.h>
+
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
index ce4d82d..89e0bb0 100644 (file)
@@ -5,16 +5,15 @@
  *      Sandy Huang <hjc@rock-chips.com>
  */
 
-#include <drm/drmP.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
-#include <drm/drm_panel.h>
 #include <drm/drm_of.h>
+#include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 
-#include <linux/component.h>
-#include <linux/of_graph.h>
-
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
 
index 7b9c747..d1494be 100644 (file)
@@ -4,10 +4,15 @@
  * Author:Mark Yao <mark.yao@rock-chips.com>
  */
 
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
 #include <linux/component.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
 
 #include "rockchip_drm_vop.h"
 #include "rockchip_vop_reg.h"
index 1626f39..d790864 100644 (file)
@@ -28,8 +28,6 @@
 #include <linux/types.h>
 #include <linux/tracepoint.h>
 
-#include <drm/drmP.h>
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM gpu_scheduler
 #define TRACE_INCLUDE_FILE gpu_scheduler_trace
index 35ddbec..d5a6a94 100644 (file)
@@ -22,6 +22,9 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/slab.h>
+
+#include <drm/drm_print.h>
 #include <drm/gpu_scheduler.h>
 
 #include "gpu_scheduler_trace.h"
index d8d2dff..5497740 100644 (file)
  */
 
 #include <linux/kthread.h>
-#include <linux/wait.h>
+#include <linux/module.h>
 #include <linux/sched.h>
-#include <drm/drmP.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
 #include <drm/gpu_scheduler.h>
 
 static struct kmem_cache *sched_fence_slab;
index c1058ee..9a0ee74 100644 (file)
@@ -48,7 +48,8 @@
 #include <linux/wait.h>
 #include <linux/sched.h>
 #include <uapi/linux/sched/types.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_print.h>
 #include <drm/gpu_scheduler.h>
 #include <drm/spsc_queue.h>
 
index a04d02d..74d5561 100644 (file)
@@ -3,7 +3,12 @@
  * Test cases for the drm_framebuffer functions
  */
 
-#include <drm/drmP.h>
+#include <linux/kernel.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_fourcc.h>
+
 #include "../drm_crtc_internal.h"
 
 #include "test-drm_modeset_common.h"
index b6988a6..75a752d 100644 (file)
 #include <linux/backlight.h>
 #include <linux/clk.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "shmob_drm_backlight.h"
 #include "shmob_drm_crtc.h"
index 9ca6920..2171884 100644 (file)
 #ifndef __SHMOB_DRM_CRTC_H__
 #define __SHMOB_DRM_CRTC_H__
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
 
 struct backlight_device;
+struct drm_pending_vblank_event;
 struct shmob_drm_device;
+struct shmob_drm_format_info;
 
 struct shmob_drm_crtc {
        struct drm_crtc crtc;
index cb821ad..b8c0930 100644 (file)
 #include <linux/pm.h>
 #include <linux/slab.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_irq.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "shmob_drm_drv.h"
 #include "shmob_drm_kms.h"
@@ -127,15 +129,12 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
 DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops);
 
 static struct drm_driver shmob_drm_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET
-                               | DRIVER_PRIME,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET,
        .irq_handler            = shmob_drm_irq,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 2e08bc2..c51197b 100644 (file)
@@ -7,7 +7,6 @@
  * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
index 1d1ee5e..cbc464f 100644 (file)
@@ -7,10 +7,10 @@
  * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 
 #include "shmob_drm_drv.h"
index bae67cc..e72b21a 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef __SHMOB_DRM_PLANE_H__
 #define __SHMOB_DRM_PLANE_H__
 
+struct drm_plane;
 struct shmob_drm_device;
 
 int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index);
index 9eb0b3d..0585336 100644 (file)
@@ -11,6 +11,9 @@
 #define __SHMOB_DRM_REGS_H__
 
 #include <linux/io.h>
+#include <linux/jiffies.h>
+
+#include "shmob_drm_drv.h"
 
 /* Register definitions */
 #define LDDCKPAT1R             0x400
index bb6ae6d..a39fc36 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "sti_crtc.h"
 #include "sti_drv.h"
-#include "sti_drv.h"
 #include "sti_plane.h"
 
 #define DRIVER_NAME    "sti"
@@ -141,8 +140,7 @@ static void sti_mode_config_init(struct drm_device *dev)
 DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops);
 
 static struct drm_driver sti_driver = {
-       .driver_features = DRIVER_MODESET |
-           DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
@@ -153,8 +151,6 @@ static struct drm_driver sti_driver = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 9e6d5d8..e558701 100644 (file)
@@ -221,8 +221,7 @@ static void sti_dvo_disable(struct drm_bridge *bridge)
 
        writel(0x00000000, dvo->regs + DVO_DOF_CFG);
 
-       if (dvo->panel)
-               dvo->panel->funcs->disable(dvo->panel);
+       drm_panel_disable(dvo->panel);
 
        /* Disable/unprepare dvo clock */
        clk_disable_unprepare(dvo->clk_pix);
@@ -262,8 +261,7 @@ static void sti_dvo_pre_enable(struct drm_bridge *bridge)
        if (clk_prepare_enable(dvo->clk))
                DRM_ERROR("Failed to prepare/enable dvo clk\n");
 
-       if (dvo->panel)
-               dvo->panel->funcs->enable(dvo->panel);
+       drm_panel_enable(dvo->panel);
 
        /* Set LUT */
        writel(config->lowbyte,  dvo->regs + DVO_LUT_PROG_LOW);
@@ -340,7 +338,7 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector)
        struct sti_dvo *dvo = dvo_connector->dvo;
 
        if (dvo->panel)
-               return dvo->panel->funcs->get_modes(dvo->panel);
+               return drm_panel_get_modes(dvo->panel);
 
        return 0;
 }
index f03d617..9862c32 100644 (file)
@@ -849,10 +849,13 @@ static int hdmi_audio_configure(struct sti_hdmi *hdmi)
        switch (info->channels) {
        case 8:
                audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
+               /* fall through */
        case 6:
                audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
+               /* fall through */
        case 4:
                audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
+               /* fall through */
        case 2:
                audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
                break;
@@ -1284,8 +1287,10 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
 
        drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-       drm_connector_init(drm_dev, drm_connector,
-                       &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
+       drm_connector_init_with_ddc(drm_dev, drm_connector,
+                                   &sti_hdmi_connector_funcs,
+                                   DRM_MODE_CONNECTOR_HDMIA,
+                                   hdmi->ddc_adapt);
        drm_connector_helper_add(drm_connector,
                        &sti_hdmi_connector_helper_funcs);
 
index e1b3c8c..aba79c1 100644 (file)
@@ -669,10 +669,9 @@ sti_tvout_create_dvo_encoder(struct drm_device *dev,
 
        encoder->tvout = tvout;
 
-       drm_encoder = (struct drm_encoder *)encoder;
+       drm_encoder = &encoder->encoder;
 
        drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
-       drm_encoder->possible_clones = 1 << 0;
 
        drm_encoder_init(dev, drm_encoder,
                         &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS,
@@ -722,10 +721,9 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
 
        encoder->tvout = tvout;
 
-       drm_encoder = (struct drm_encoder *) encoder;
+       drm_encoder = &encoder->encoder;
 
        drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
-       drm_encoder->possible_clones = 1 << 0;
 
        drm_encoder_init(dev, drm_encoder,
                        &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL);
@@ -771,10 +769,9 @@ static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
 
        encoder->tvout = tvout;
 
-       drm_encoder = (struct drm_encoder *) encoder;
+       drm_encoder = &encoder->encoder;
 
        drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
-       drm_encoder->possible_clones = 1 << 1;
 
        drm_encoder_init(dev, drm_encoder,
                        &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL);
@@ -790,6 +787,13 @@ static void sti_tvout_create_encoders(struct drm_device *dev,
        tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout);
        tvout->hda = sti_tvout_create_hda_encoder(dev, tvout);
        tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout);
+
+       tvout->hdmi->possible_clones = drm_encoder_mask(tvout->hdmi) |
+               drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo);
+       tvout->hda->possible_clones = drm_encoder_mask(tvout->hdmi) |
+               drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo);
+       tvout->dvo->possible_clones = drm_encoder_mask(tvout->hdmi) |
+               drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo);
 }
 
 static void sti_tvout_destroy_encoders(struct sti_tvout *tvout)
index 9dee4e4..5a9f9ac 100644 (file)
@@ -54,8 +54,7 @@ static int stm_gem_cma_dumb_create(struct drm_file *file,
 DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
 
 static struct drm_driver drv_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .name = "stm",
        .desc = "STMicroelectronics SoC DRM",
        .date = "20170330",
@@ -68,8 +67,6 @@ static struct drm_driver drv_driver = {
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 0ab32fe..a03a642 100644 (file)
@@ -8,13 +8,17 @@
 
 #include <linux/clk.h>
 #include <linux/iopoll.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <drm/drmP.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/bridge/dw_mipi_dsi.h>
+
 #include <video/mipi_display.h>
 
+#include <drm/bridge/dw_mipi_dsi.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_print.h>
+
 #define HWVER_130                      0x31333000      /* IP version 1.30 */
 #define HWVER_131                      0x31333100      /* IP version 1.31 */
 
index 2fe6c4a..3ab4fbf 100644 (file)
@@ -26,6 +26,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
@@ -922,6 +923,7 @@ static const struct drm_plane_funcs ltdc_plane_funcs = {
 };
 
 static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
+       .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = ltdc_plane_atomic_check,
        .atomic_update = ltdc_plane_atomic_update,
        .atomic_disable = ltdc_plane_atomic_disable,
index 78d8c3a..4e29f4f 100644 (file)
@@ -6,21 +6,23 @@
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
 
-#include <drm/drmP.h>
+#include <linux/component.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 
-#include <linux/component.h>
-#include <linux/list.h>
-#include <linux/of_device.h>
-#include <linux/of_graph.h>
-#include <linux/reset.h>
-
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
 #include "sun4i_frontend.h"
index 9d8504f..3a15364 100644 (file)
@@ -6,12 +6,6 @@
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_modes.h>
-#include <drm/drm_probe_helper.h>
-
 #include <linux/clk-provider.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
 
 #include <video/videomode.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
 #include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
index 1a1b52e..a5757b1 100644 (file)
@@ -8,16 +8,19 @@
 
 #include <linux/component.h>
 #include <linux/kfifo.h>
+#include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "sun4i_drv.h"
 #include "sun4i_frontend.h"
@@ -38,7 +41,7 @@ static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv,
 DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
 
 static struct drm_driver sun4i_drv_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 
        /* Generic Operations */
        .fops                   = &sun4i_drv_fops,
index 35c0407..1568f68 100644 (file)
@@ -9,7 +9,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drmP.h>
 
 #include "sun4i_drv.h"
 #include "sun4i_framebuffer.h"
index 346c807..ec2a032 100644 (file)
@@ -3,9 +3,6 @@
  * Copyright (C) 2017 Free Electrons
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
-#include <drm/drmP.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
 
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
+#include <drm/drm_device.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane.h>
+
 #include "sun4i_drv.h"
 #include "sun4i_frontend.h"
 
index 9c3f993..eb8071a 100644 (file)
@@ -5,23 +5,24 @@
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/iopoll.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
 #include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
@@ -639,9 +640,10 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
 
        drm_connector_helper_add(&hdmi->connector,
                                 &sun4i_hdmi_connector_helper_funcs);
-       ret = drm_connector_init(drm, &hdmi->connector,
-                                &sun4i_hdmi_connector_funcs,
-                                DRM_MODE_CONNECTOR_HDMIA);
+       ret = drm_connector_init_with_ddc(drm, &hdmi->connector,
+                                         &sun4i_hdmi_connector_funcs,
+                                         DRM_MODE_CONNECTOR_HDMIA,
+                                         hdmi->ddc_i2c);
        if (ret) {
                dev_err(dev,
                        "Couldn't initialise the HDMI connector\n");
index e72dd4d..c04f4ba 100644 (file)
@@ -7,9 +7,8 @@
  */
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drmP.h>
+#include <drm/drm_plane_helper.h>
 
 #include "sun4i_backend.h"
 #include "sun4i_frontend.h"
index 3a3ba99..7fbf425 100644 (file)
@@ -6,10 +6,10 @@
 
 #include <linux/clk.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_crtc.h"
index a901ec6..aac5698 100644 (file)
@@ -8,10 +8,10 @@
 
 #include <linux/clk.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_crtc.h"
index 64c43ee..690aeb8 100644 (file)
@@ -6,7 +6,15 @@
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
 
-#include <drm/drmP.h>
+#include <linux/component.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modes.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include <uapi/drm/drm_mode.h>
 
-#include <linux/component.h>
-#include <linux/ioport.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
@@ -478,7 +480,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
                                     const struct drm_display_mode *mode)
 {
        struct drm_connector *connector = sun4i_tcon_get_connector(encoder);
-       struct drm_display_info display_info = connector->display_info;
+       const struct drm_display_info *info = &connector->display_info;
        unsigned int bp, hsync, vsync;
        u8 clk_delay;
        u32 val = 0;
@@ -539,7 +541,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
        if (mode->flags & DRM_MODE_FLAG_PVSYNC)
                val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
 
-       if (display_info.bus_flags & DRM_BUS_FLAG_DE_LOW)
+       if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
                val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
 
        /*
@@ -557,10 +559,10 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
         * Following code is a way to avoid quirks all around TCON
         * and DOTCLOCK drivers.
         */
-       if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
+       if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
                clk_set_phase(tcon->dclk, 240);
 
-       if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
+       if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
                clk_set_phase(tcon->dclk, 0);
 
        regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
index f998153..39c1528 100644 (file)
@@ -8,14 +8,16 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_crtc.h"
index a1fc8b5..472f739 100644 (file)
@@ -9,19 +9,20 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/crc-ccitt.h>
+#include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/phy/phy-mipi-dphy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 
-#include <linux/phy/phy.h>
-#include <linux/phy/phy-mipi-dphy.h>
-
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_crtc.h"
index b8c059f..781955d 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_print.h>
 
 #include "sun8i_csc.h"
 #include "sun8i_mixer.h"
@@ -18,16 +18,59 @@ static const u32 ccsc_base[2][2] = {
  * First tree values in each line are multiplication factor and last
  * value is constant, which is added at the end.
  */
-static const u32 yuv2rgb[] = {
-       0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A,
-       0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4,
-       0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A,
+
+static const u32 yuv2rgb[2][2][12] = {
+       [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x000004A8, 0x00000000, 0x00000662, 0xFFFC8451,
+                       0x000004A8, 0xFFFFFE6F, 0xFFFFFCC0, 0x00021E4D,
+                       0x000004A8, 0x00000811, 0x00000000, 0xFFFBACA9,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x000004A8, 0x00000000, 0x0000072B, 0xFFFC1F99,
+                       0x000004A8, 0xFFFFFF26, 0xFFFFFDDF, 0x00013383,
+                       0x000004A8, 0x00000873, 0x00000000, 0xFFFB7BEF,
+               }
+       },
+       [DRM_COLOR_YCBCR_FULL_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x00000400, 0x00000000, 0x0000059B, 0xFFFD322E,
+                       0x00000400, 0xFFFFFEA0, 0xFFFFFD25, 0x00021DD5,
+                       0x00000400, 0x00000716, 0x00000000, 0xFFFC74BD,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x00000400, 0x00000000, 0x0000064C, 0xFFFCD9B4,
+                       0x00000400, 0xFFFFFF41, 0xFFFFFE21, 0x00014F96,
+                       0x00000400, 0x0000076C, 0x00000000, 0xFFFC49EF,
+               }
+       },
 };
 
-static const u32 yvu2rgb[] = {
-       0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A,
-       0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4,
-       0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A,
+static const u32 yvu2rgb[2][2][12] = {
+       [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x000004A8, 0x00000662, 0x00000000, 0xFFFC8451,
+                       0x000004A8, 0xFFFFFCC0, 0xFFFFFE6F, 0x00021E4D,
+                       0x000004A8, 0x00000000, 0x00000811, 0xFFFBACA9,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x000004A8, 0x0000072B, 0x00000000, 0xFFFC1F99,
+                       0x000004A8, 0xFFFFFDDF, 0xFFFFFF26, 0x00013383,
+                       0x000004A8, 0x00000000, 0x00000873, 0xFFFB7BEF,
+               }
+       },
+       [DRM_COLOR_YCBCR_FULL_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x00000400, 0x0000059B, 0x00000000, 0xFFFD322E,
+                       0x00000400, 0xFFFFFD25, 0xFFFFFEA0, 0x00021DD5,
+                       0x00000400, 0x00000000, 0x00000716, 0xFFFC74BD,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x00000400, 0x0000064C, 0x00000000, 0xFFFCD9B4,
+                       0x00000400, 0xFFFFFE21, 0xFFFFFF41, 0x00014F96,
+                       0x00000400, 0x00000000, 0x0000076C, 0xFFFC49EF,
+               }
+       },
 };
 
 /*
@@ -53,57 +96,98 @@ static const u32 yvu2rgb[] = {
  * c20 c21 c22 [d2 const2]
  */
 
-static const u32 yuv2rgb_de3[] = {
-       0x0002542a, 0x00000000, 0x0003312a, 0xffc00000,
-       0x0002542a, 0xffff376b, 0xfffe5fc3, 0xfe000000,
-       0x0002542a, 0x000408d3, 0x00000000, 0xfe000000,
+static const u32 yuv2rgb_de3[2][2][12] = {
+       [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x0002542A, 0x00000000, 0x0003312A, 0xFFC00000,
+                       0x0002542A, 0xFFFF376B, 0xFFFE5FC3, 0xFE000000,
+                       0x0002542A, 0x000408D2, 0x00000000, 0xFE000000,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x0002542A, 0x00000000, 0x000395E2, 0xFFC00000,
+                       0x0002542A, 0xFFFF92D2, 0xFFFEEF27, 0xFE000000,
+                       0x0002542A, 0x0004398C, 0x00000000, 0xFE000000,
+               }
+       },
+       [DRM_COLOR_YCBCR_FULL_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x00020000, 0x00000000, 0x0002CDD2, 0x00000000,
+                       0x00020000, 0xFFFF4FCE, 0xFFFE925D, 0xFE000000,
+                       0x00020000, 0x00038B43, 0x00000000, 0xFE000000,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x00020000, 0x00000000, 0x0003264C, 0x00000000,
+                       0x00020000, 0xFFFFA018, 0xFFFF1053, 0xFE000000,
+                       0x00020000, 0x0003B611, 0x00000000, 0xFE000000,
+               }
+       },
 };
 
-static const u32 yvu2rgb_de3[] = {
-       0x0002542a, 0x0003312a, 0x00000000, 0xffc00000,
-       0x0002542a, 0xfffe5fc3, 0xffff376b, 0xfe000000,
-       0x0002542a, 0x00000000, 0x000408d3, 0xfe000000,
+static const u32 yvu2rgb_de3[2][2][12] = {
+       [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x0002542A, 0x0003312A, 0x00000000, 0xFFC00000,
+                       0x0002542A, 0xFFFE5FC3, 0xFFFF376B, 0xFE000000,
+                       0x0002542A, 0x00000000, 0x000408D2, 0xFE000000,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x0002542A, 0x000395E2, 0x00000000, 0xFFC00000,
+                       0x0002542A, 0xFFFEEF27, 0xFFFF92D2, 0xFE000000,
+                       0x0002542A, 0x00000000, 0x0004398C, 0xFE000000,
+               }
+       },
+       [DRM_COLOR_YCBCR_FULL_RANGE] = {
+               [DRM_COLOR_YCBCR_BT601] = {
+                       0x00020000, 0x0002CDD2, 0x00000000, 0x00000000,
+                       0x00020000, 0xFFFE925D, 0xFFFF4FCE, 0xFE000000,
+                       0x00020000, 0x00000000, 0x00038B43, 0xFE000000,
+               },
+               [DRM_COLOR_YCBCR_BT709] = {
+                       0x00020000, 0x0003264C, 0x00000000, 0x00000000,
+                       0x00020000, 0xFFFF1053, 0xFFFFA018, 0xFE000000,
+                       0x00020000, 0x00000000, 0x0003B611, 0xFE000000,
+               }
+       },
 };
 
 static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
-                                      enum sun8i_csc_mode mode)
+                                      enum sun8i_csc_mode mode,
+                                      enum drm_color_encoding encoding,
+                                      enum drm_color_range range)
 {
        const u32 *table;
-       int i, data;
+       u32 base_reg;
 
        switch (mode) {
        case SUN8I_CSC_MODE_YUV2RGB:
-               table = yuv2rgb;
+               table = yuv2rgb[range][encoding];
                break;
        case SUN8I_CSC_MODE_YVU2RGB:
-               table = yvu2rgb;
+               table = yvu2rgb[range][encoding];
                break;
        default:
                DRM_WARN("Wrong CSC mode specified.\n");
                return;
        }
 
-       for (i = 0; i < 12; i++) {
-               data = table[i];
-               /* For some reason, 0x200 must be added to constant parts */
-               if (((i + 1) & 3) == 0)
-                       data += 0x200;
-               regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
-       }
+       base_reg = SUN8I_CSC_COEFF(base, 0);
+       regmap_bulk_write(map, base_reg, table, 12);
 }
 
 static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
-                                           enum sun8i_csc_mode mode)
+                                           enum sun8i_csc_mode mode,
+                                           enum drm_color_encoding encoding,
+                                           enum drm_color_range range)
 {
        const u32 *table;
        u32 base_reg;
 
        switch (mode) {
        case SUN8I_CSC_MODE_YUV2RGB:
-               table = yuv2rgb_de3;
+               table = yuv2rgb_de3[range][encoding];
                break;
        case SUN8I_CSC_MODE_YVU2RGB:
-               table = yvu2rgb_de3;
+               table = yvu2rgb_de3[range][encoding];
                break;
        default:
                DRM_WARN("Wrong CSC mode specified.\n");
@@ -142,19 +226,22 @@ static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable)
 }
 
 void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
-                                    enum sun8i_csc_mode mode)
+                                    enum sun8i_csc_mode mode,
+                                    enum drm_color_encoding encoding,
+                                    enum drm_color_range range)
 {
        u32 base;
 
        if (mixer->cfg->is_de3) {
-               sun8i_de3_ccsc_set_coefficients(mixer->engine.regs,
-                                               layer, mode);
+               sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer,
+                                               mode, encoding, range);
                return;
        }
 
        base = ccsc_base[mixer->cfg->ccsc][layer];
 
-       sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
+       sun8i_csc_set_coefficients(mixer->engine.regs, base,
+                                  mode, encoding, range);
 }
 
 void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
index dce4c44..f42441b 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef _SUN8I_CSC_H_
 #define _SUN8I_CSC_H_
 
+#include <drm/drm_color_mgmt.h>
+
 struct sun8i_mixer;
 
 /* VI channel CSC units offsets */
@@ -26,7 +28,9 @@ enum sun8i_csc_mode {
 };
 
 void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
-                                    enum sun8i_csc_mode mode);
+                                    enum sun8i_csc_mode mode,
+                                    enum drm_color_encoding encoding,
+                                    enum drm_color_range range);
 void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable);
 
 #endif
index 39d8509..8ca5af0 100644 (file)
@@ -8,9 +8,8 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 
 #include "sun8i_dw_hdmi.h"
 #include "sun8i_tcon_top.h"
index c2eedf5..8b803eb 100644 (file)
@@ -7,7 +7,13 @@
  *   Copyright (C) 2015 NextThing Co
  */
 
-#include <drm/drmP.h>
+#include <linux/component.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/reset.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 
-#include <linux/component.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_device.h>
-#include <linux/of_graph.h>
-#include <linux/reset.h>
-
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
 #include "sun8i_ui_layer.h"
index 3267d0f..75d8e60 100644 (file)
@@ -1,18 +1,18 @@
 // SPDX-License-Identifier: GPL-2.0+
 /* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
 
-#include <drm/drmP.h>
-
-#include <dt-bindings/clock/sun8i-tcon-top.h>
 
 #include <linux/bitfield.h>
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+
 #include "sun8i_tcon_top.h"
 
 struct sun8i_tcon_top_quirks {
index dd2a1c8..c87fd84 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
 
 #include "sun8i_ui_layer.h"
 #include "sun8i_mixer.h"
index bd0e6a5..42d445d 100644 (file)
@@ -11,7 +11,6 @@
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
 
 #include "sun8i_vi_layer.h"
 #include "sun8i_mixer.h"
@@ -232,7 +231,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
 
        if (fmt_info->csc != SUN8I_CSC_MODE_OFF) {
-               sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc);
+               sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc,
+                                               state->color_encoding,
+                                               state->color_range);
                sun8i_csc_enable_ccsc(mixer, channel, true);
        } else {
                sun8i_csc_enable_ccsc(mixer, channel, false);
@@ -441,6 +442,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                                               struct sun8i_mixer *mixer,
                                               int index)
 {
+       u32 supported_encodings, supported_ranges;
        struct sun8i_vi_layer *layer;
        unsigned int plane_cnt;
        int ret;
@@ -469,6 +471,22 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                return ERR_PTR(ret);
        }
 
+       supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
+                             BIT(DRM_COLOR_YCBCR_BT709);
+
+       supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+                          BIT(DRM_COLOR_YCBCR_FULL_RANGE);
+
+       ret = drm_plane_create_color_properties(&layer->plane,
+                                               supported_encodings,
+                                               supported_ranges,
+                                               DRM_COLOR_YCBCR_BT709,
+                                               DRM_COLOR_YCBCR_LIMITED_RANGE);
+       if (ret) {
+               dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
+               return ERR_PTR(ret);
+       }
+
        drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
        layer->mixer = mixer;
        layer->channel = index;
index 3a14768..c243af1 100644 (file)
 
 #include <linux/module.h>
 
-#include <drm/drmP.h>
-#include "tdfx_drv.h"
-
-#include <drm/drm_pciids.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_legacy.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_pciids.h>
+
+#include "tdfx_drv.h"
 
 static struct pci_device_id pciidlist[] = {
        tdfx_PCI_IDS
index ddb802b..870904b 100644 (file)
@@ -888,33 +888,33 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
 static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
 #ifdef CONFIG_DRM_TEGRA_STAGING
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags,
-                         DRM_UNLOCKED | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 #endif
 };
 
@@ -1004,7 +1004,7 @@ static int tegra_debugfs_init(struct drm_minor *minor)
 #endif
 
 static struct drm_driver tegra_drm_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+       .driver_features = DRIVER_MODESET | DRIVER_GEM |
                           DRIVER_ATOMIC | DRIVER_RENDER,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
index df53a46..0a3d925 100644 (file)
@@ -626,20 +626,19 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
        .vunmap = tegra_gem_prime_vunmap,
 };
 
-struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
-                                      struct drm_gem_object *gem,
+struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem,
                                       int flags)
 {
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
        exp_info.exp_name = KBUILD_MODNAME;
-       exp_info.owner = drm->driver->fops->owner;
+       exp_info.owner = gem->dev->driver->fops->owner;
        exp_info.ops = &tegra_gem_prime_dmabuf_ops;
        exp_info.size = gem->size;
        exp_info.flags = flags;
        exp_info.priv = gem;
 
-       return drm_gem_dmabuf_export(drm, &exp_info);
+       return drm_gem_dmabuf_export(gem->dev, &exp_info);
 }
 
 struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
index 413eae8..f1f758b 100644 (file)
@@ -70,8 +70,7 @@ extern const struct vm_operations_struct tegra_bo_vm_ops;
 int __tegra_gem_mmap(struct drm_gem_object *gem, struct vm_area_struct *vma);
 int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
 
-struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
-                                      struct drm_gem_object *gem,
+struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem,
                                       int flags);
 struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
                                              struct dma_buf *buf);
index 650d162..e9dd5e5 100644 (file)
@@ -4,16 +4,20 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_flip_work.h>
-#include <drm/drm_plane_helper.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_graph.h>
-#include <linux/math64.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
@@ -646,9 +650,6 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
 static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
                                    struct drm_crtc_state *state)
 {
-       struct drm_display_mode *mode = &state->mode;
-       int ret;
-
        /* If we are not active we don't care */
        if (!state->active)
                return 0;
@@ -660,12 +661,6 @@ static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
-       ret = tilcdc_crtc_mode_valid(crtc, mode);
-       if (ret) {
-               dev_dbg(crtc->dev->dev, "Mode \"%s\" not valid", mode->name);
-               return -EINVAL;
-       }
-
        return 0;
 }
 
@@ -717,13 +712,6 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
        .disable_vblank = tilcdc_crtc_disable_vblank,
 };
 
-static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
-               .mode_fixup     = tilcdc_crtc_mode_fixup,
-               .atomic_check   = tilcdc_crtc_atomic_check,
-               .atomic_enable  = tilcdc_crtc_atomic_enable,
-               .atomic_disable = tilcdc_crtc_atomic_disable,
-};
-
 int tilcdc_crtc_max_width(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -738,7 +726,9 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
        return max_width;
 }
 
-int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
+static enum drm_mode_status
+tilcdc_crtc_mode_valid(struct drm_crtc *crtc,
+                      const struct drm_display_mode *mode)
 {
        struct tilcdc_drm_private *priv = crtc->dev->dev_private;
        unsigned int bandwidth;
@@ -826,6 +816,14 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
        return MODE_OK;
 }
 
+static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
+       .mode_valid     = tilcdc_crtc_mode_valid,
+       .mode_fixup     = tilcdc_crtc_mode_fixup,
+       .atomic_check   = tilcdc_crtc_atomic_check,
+       .atomic_enable  = tilcdc_crtc_atomic_enable,
+       .atomic_disable = tilcdc_crtc_atomic_disable,
+};
+
 void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
                const struct tilcdc_panel_info *info)
 {
index 7339bab..2a9e675 100644 (file)
@@ -7,19 +7,30 @@
 /* LCDC DRM driver, based on da8xx-fb */
 
 #include <linux/component.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
-#include <linux/suspend.h>
-#include <drm/drm_atomic.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_mm.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
 
 #include "tilcdc_drv.h"
+#include "tilcdc_external.h"
+#include "tilcdc_panel.h"
 #include "tilcdc_regs.h"
 #include "tilcdc_tfp410.h"
-#include "tilcdc_panel.h"
-#include "tilcdc_external.h"
 
 static LIST_HEAD(module_list);
 
@@ -188,7 +199,6 @@ static void tilcdc_fini(struct drm_device *dev)
        drm_kms_helper_poll_fini(dev);
        drm_irq_uninstall(dev);
        drm_mode_config_cleanup(dev);
-       tilcdc_remove_external_device(dev);
 
        if (priv->clk)
                clk_put(priv->clk);
@@ -501,8 +511,7 @@ static int tilcdc_debugfs_init(struct drm_minor *minor)
 DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver tilcdc_driver = {
-       .driver_features    = (DRIVER_GEM | DRIVER_MODESET |
-                              DRIVER_PRIME | DRIVER_ATOMIC),
+       .driver_features    = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .irq_handler        = tilcdc_irq,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_print_info     = drm_gem_cma_print_info,
@@ -511,8 +520,6 @@ static struct drm_driver tilcdc_driver = {
 
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-       .gem_prime_import       = drm_gem_prime_import,
-       .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
index 9943229..18815e7 100644 (file)
@@ -7,21 +7,24 @@
 #ifndef __TILCDC_DRV_H__
 #define __TILCDC_DRV_H__
 
-#include <linux/clk.h>
 #include <linux/cpufreq.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/list.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <linux/irqreturn.h>
+
+#include <drm/drm_print.h>
+
+struct clk;
+struct workqueue_struct;
+
+struct drm_connector;
+struct drm_connector_helper_funcs;
+struct drm_crtc;
+struct drm_device;
+struct drm_display_mode;
+struct drm_encoder;
+struct drm_framebuffer;
+struct drm_minor;
+struct drm_pending_vblank_event;
+struct drm_plane;
 
 /* Defaulting to pixel clock defined on AM335x */
 #define TILCDC_DEFAULT_MAX_PIXELCLOCK  126000
@@ -74,7 +77,6 @@ struct tilcdc_drm_private {
 
        struct drm_encoder *external_encoder;
        struct drm_connector *external_connector;
-       const struct drm_connector_helper_funcs *connector_funcs;
 
        bool is_registered;
        bool is_componentized;
@@ -156,7 +158,6 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
                const struct tilcdc_panel_info *info);
 void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
                                        bool simulate_vesa_sync);
-int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
 int tilcdc_crtc_max_width(struct drm_crtc *crtc);
 void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
 int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
index 7050eb4..43d756b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/component.h>
 #include <linux/of_graph.h>
+
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 
@@ -37,64 +38,6 @@ static const struct tilcdc_panel_info panel_info_default = {
                .raster_order           = 0,
 };
 
-static int tilcdc_external_mode_valid(struct drm_connector *connector,
-                                     struct drm_display_mode *mode)
-{
-       struct tilcdc_drm_private *priv = connector->dev->dev_private;
-       int ret;
-
-       ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
-       if (ret != MODE_OK)
-               return ret;
-
-       BUG_ON(priv->external_connector != connector);
-       BUG_ON(!priv->connector_funcs);
-
-       /* If the connector has its own mode_valid call it. */
-       if (!IS_ERR(priv->connector_funcs) &&
-           priv->connector_funcs->mode_valid)
-               return priv->connector_funcs->mode_valid(connector, mode);
-
-       return MODE_OK;
-}
-
-static int tilcdc_add_external_connector(struct drm_device *dev,
-                                        struct drm_connector *connector)
-{
-       struct tilcdc_drm_private *priv = dev->dev_private;
-       struct drm_connector_helper_funcs *connector_funcs;
-
-       /* There should never be more than one connector */
-       if (WARN_ON(priv->external_connector))
-               return -EINVAL;
-
-       priv->external_connector = connector;
-       connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs),
-                                      GFP_KERNEL);
-       if (!connector_funcs)
-               return -ENOMEM;
-
-       /* connector->helper_private contains always struct
-        * connector_helper_funcs pointer. For tilcdc crtc to have a
-        * say if a specific mode is Ok, we need to install our own
-        * helper functions. In our helper functions we copy
-        * everything else but use our own mode_valid() (above).
-        */
-       if (connector->helper_private) {
-               priv->connector_funcs = connector->helper_private;
-               *connector_funcs = *priv->connector_funcs;
-       } else {
-               priv->connector_funcs = ERR_PTR(-ENOENT);
-       }
-       connector_funcs->mode_valid = tilcdc_external_mode_valid;
-       drm_connector_helper_add(connector, connector_funcs);
-
-       dev_dbg(dev->dev, "External connector '%s' connected\n",
-               connector->name);
-
-       return 0;
-}
-
 static
 struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
                                                    struct drm_encoder *encoder)
@@ -115,7 +58,6 @@ struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
 int tilcdc_add_component_encoder(struct drm_device *ddev)
 {
        struct tilcdc_drm_private *priv = ddev->dev_private;
-       struct drm_connector *connector;
        struct drm_encoder *encoder;
 
        list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head)
@@ -127,28 +69,17 @@ int tilcdc_add_component_encoder(struct drm_device *ddev)
                return -ENODEV;
        }
 
-       connector = tilcdc_encoder_find_connector(ddev, encoder);
+       priv->external_connector =
+               tilcdc_encoder_find_connector(ddev, encoder);
 
-       if (!connector)
+       if (!priv->external_connector)
                return -ENODEV;
 
        /* Only tda998x is supported at the moment. */
        tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
        tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
 
-       return tilcdc_add_external_connector(ddev, connector);
-}
-
-void tilcdc_remove_external_device(struct drm_device *dev)
-{
-       struct tilcdc_drm_private *priv = dev->dev_private;
-
-       /* Restore the original helper functions, if any. */
-       if (IS_ERR(priv->connector_funcs))
-               drm_connector_helper_add(priv->external_connector, NULL);
-       else if (priv->connector_funcs)
-               drm_connector_helper_add(priv->external_connector,
-                                        priv->connector_funcs);
+       return 0;
 }
 
 static const struct drm_encoder_funcs tilcdc_external_encoder_funcs = {
@@ -159,7 +90,6 @@ static
 int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
 {
        struct tilcdc_drm_private *priv = ddev->dev_private;
-       struct drm_connector *connector;
        int ret;
 
        priv->external_encoder->possible_crtcs = BIT(0);
@@ -172,13 +102,12 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
 
        tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
 
-       connector = tilcdc_encoder_find_connector(ddev, priv->external_encoder);
-       if (!connector)
+       priv->external_connector =
+               tilcdc_encoder_find_connector(ddev, priv->external_encoder);
+       if (!priv->external_connector)
                return -ENODEV;
 
-       ret = tilcdc_add_external_connector(ddev, connector);
-
-       return ret;
+       return 0;
 }
 
 int tilcdc_attach_external_device(struct drm_device *ddev)
index 7024b48..fb44766 100644 (file)
@@ -8,7 +8,6 @@
 #define __TILCDC_EXTERNAL_H__
 
 int tilcdc_add_component_encoder(struct drm_device *dev);
-void tilcdc_remove_external_device(struct drm_device *dev);
 int tilcdc_get_external_components(struct device *dev,
                                   struct component_match **match);
 int tilcdc_attach_external_device(struct drm_device *ddev);
index 22b100d..5584e65 100644 (file)
@@ -4,14 +4,17 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/backlight.h>
 #include <linux/gpio/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
 #include <video/display_timing.h>
 #include <video/of_display_timing.h>
 #include <video/videomode.h>
-#include <drm/drm_atomic_helper.h>
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_probe_helper.h>
 
 #include "tilcdc_drv.h"
@@ -160,14 +163,6 @@ static int panel_connector_get_modes(struct drm_connector *connector)
        return i;
 }
 
-static int panel_connector_mode_valid(struct drm_connector *connector,
-                 struct drm_display_mode *mode)
-{
-       struct tilcdc_drm_private *priv = connector->dev->dev_private;
-       /* our only constraints are what the crtc can generate: */
-       return tilcdc_crtc_mode_valid(priv->crtc, mode);
-}
-
 static struct drm_encoder *panel_connector_best_encoder(
                struct drm_connector *connector)
 {
@@ -185,7 +180,6 @@ static const struct drm_connector_funcs panel_connector_funcs = {
 
 static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
        .get_modes          = panel_connector_get_modes,
-       .mode_valid         = panel_connector_mode_valid,
        .best_encoder       = panel_connector_best_encoder,
 };
 
index 8c2776a..3abb964 100644 (file)
@@ -4,12 +4,10 @@
  * Author: Jyri Sarha <jsarha@ti.com>
  */
 
-#include <drm/drmP.h>
-
 #include <drm/drm_atomic.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_atomic_helper.h>
-#include <uapi/drm/drm_fourcc.h>
+#include <drm/drm_fourcc.h>
 
 #include "tilcdc_drv.h"
 
index 62d014c..525dc1c 100644 (file)
@@ -4,12 +4,14 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
-#include <linux/i2c.h>
 #include <linux/gpio.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of_gpio.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_probe_helper.h>
 
 #include "tilcdc_drv.h"
@@ -173,14 +175,6 @@ static int tfp410_connector_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-static int tfp410_connector_mode_valid(struct drm_connector *connector,
-                 struct drm_display_mode *mode)
-{
-       struct tilcdc_drm_private *priv = connector->dev->dev_private;
-       /* our only constraints are what the crtc can generate: */
-       return tilcdc_crtc_mode_valid(priv->crtc, mode);
-}
-
 static struct drm_encoder *tfp410_connector_best_encoder(
                struct drm_connector *connector)
 {
@@ -199,7 +193,6 @@ static const struct drm_connector_funcs tfp410_connector_funcs = {
 
 static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
        .get_modes          = tfp410_connector_get_modes,
-       .mode_valid         = tfp410_connector_mode_valid,
        .best_encoder       = tfp410_connector_best_encoder,
 };
 
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
new file mode 100644 (file)
index 0000000..5047634
--- /dev/null
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config DRM_GM12U320
+       tristate "GM12U320 driver for USB projectors"
+       depends on DRM && USB
+       select DRM_KMS_HELPER
+       select DRM_GEM_SHMEM_HELPER
+       help
+        This is a KMS driver for projectors which use the GM12U320 chipset
+        for video transfer over USB2/3, such as the Acer C120 mini projector.
+
+config TINYDRM_HX8357D
+       tristate "DRM support for HX8357D display panels"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       select BACKLIGHT_CLASS_DEVICE
+       help
+         DRM driver for the following HX8357D panels:
+         * YX350HV15-T 3.5" 340x350 TFT (Adafruit 3.5")
+
+         If M is selected the module will be called hx8357d.
+
+config TINYDRM_ILI9225
+       tristate "DRM support for ILI9225 display panels"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       help
+         DRM driver for the following Ilitek ILI9225 panels:
+         * No-name 2.2" color screen module
+
+         If M is selected the module will be called ili9225.
+
+config TINYDRM_ILI9341
+       tristate "DRM support for ILI9341 display panels"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       select BACKLIGHT_CLASS_DEVICE
+       help
+         DRM driver for the following Ilitek ILI9341 panels:
+         * YX240QV29-T 2.4" 240x320 TFT (Adafruit 2.4")
+
+         If M is selected the module will be called ili9341.
+
+config TINYDRM_MI0283QT
+       tristate "DRM support for MI0283QT"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       select BACKLIGHT_CLASS_DEVICE
+       help
+         DRM driver for the Multi-Inno MI0283QT display panel
+         If M is selected the module will be called mi0283qt.
+
+config TINYDRM_REPAPER
+       tristate "DRM support for Pervasive Displays RePaper panels (V231)"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       depends on THERMAL || !THERMAL
+       help
+         DRM driver for the following Pervasive Displays panels:
+         1.44" TFT EPD Panel (E1144CS021)
+         1.90" TFT EPD Panel (E1190CS021)
+         2.00" TFT EPD Panel (E2200CS021)
+         2.71" TFT EPD Panel (E2271CS021)
+
+         If M is selected the module will be called repaper.
+
+config TINYDRM_ST7586
+       tristate "DRM support for Sitronix ST7586 display panels"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       help
+         DRM driver for the following Sitronix ST7586 panels:
+         * LEGO MINDSTORMS EV3
+
+         If M is selected the module will be called st7586.
+
+config TINYDRM_ST7735R
+       tristate "DRM support for Sitronix ST7735R display panels"
+       depends on DRM && SPI
+       select DRM_KMS_HELPER
+       select DRM_KMS_CMA_HELPER
+       select DRM_MIPI_DBI
+       select BACKLIGHT_CLASS_DEVICE
+       help
+         DRM driver Sitronix ST7735R with one of the following LCDs:
+         * JD-T18003-T01 1.8" 128x160 TFT
+
+         If M is selected the module will be called st7735r.
diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
new file mode 100644 (file)
index 0000000..896cf31
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_DRM_GM12U320)             += gm12u320.o
+obj-$(CONFIG_TINYDRM_HX8357D)          += hx8357d.o
+obj-$(CONFIG_TINYDRM_ILI9225)          += ili9225.o
+obj-$(CONFIG_TINYDRM_ILI9341)          += ili9341.o
+obj-$(CONFIG_TINYDRM_MI0283QT)         += mi0283qt.o
+obj-$(CONFIG_TINYDRM_REPAPER)          += repaper.o
+obj-$(CONFIG_TINYDRM_ST7586)           += st7586.o
+obj-$(CONFIG_TINYDRM_ST7735R)          += st7735r.o
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
new file mode 100644 (file)
index 0000000..b6f47b8
--- /dev/null
@@ -0,0 +1,814 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Hans de Goede <hdegoede@redhat.com>
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_file.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+
+static bool eco_mode;
+module_param(eco_mode, bool, 0644);
+MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
+
+#define DRIVER_NAME            "gm12u320"
+#define DRIVER_DESC            "Grain Media GM12U320 USB projector display"
+#define DRIVER_DATE            "2019"
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           0
+#define DRIVER_PATCHLEVEL      1
+
+/*
+ * The DLP has an actual width of 854 pixels, but that is not a multiple
+ * of 8, breaking things left and right, so we export a width of 848.
+ */
+#define GM12U320_USER_WIDTH            848
+#define GM12U320_REAL_WIDTH            854
+#define GM12U320_HEIGHT                        480
+
+#define GM12U320_BLOCK_COUNT           20
+
+#define MISC_RCV_EPT                   1
+#define DATA_RCV_EPT                   2
+#define DATA_SND_EPT                   3
+#define MISC_SND_EPT                   4
+
+#define DATA_BLOCK_HEADER_SIZE         84
+#define DATA_BLOCK_CONTENT_SIZE                64512
+#define DATA_BLOCK_FOOTER_SIZE         20
+#define DATA_BLOCK_SIZE                        (DATA_BLOCK_HEADER_SIZE + \
+                                        DATA_BLOCK_CONTENT_SIZE + \
+                                        DATA_BLOCK_FOOTER_SIZE)
+#define DATA_LAST_BLOCK_CONTENT_SIZE   4032
+#define DATA_LAST_BLOCK_SIZE           (DATA_BLOCK_HEADER_SIZE + \
+                                        DATA_LAST_BLOCK_CONTENT_SIZE + \
+                                        DATA_BLOCK_FOOTER_SIZE)
+
+#define CMD_SIZE                       31
+#define READ_STATUS_SIZE               13
+#define MISC_VALUE_SIZE                        4
+
+#define CMD_TIMEOUT                    msecs_to_jiffies(200)
+#define DATA_TIMEOUT                   msecs_to_jiffies(1000)
+#define IDLE_TIMEOUT                   msecs_to_jiffies(2000)
+#define FIRST_FRAME_TIMEOUT            msecs_to_jiffies(2000)
+
+#define MISC_REQ_GET_SET_ECO_A         0xff
+#define MISC_REQ_GET_SET_ECO_B         0x35
+/* Windows driver does once every second, with arg d = 1, other args 0 */
+#define MISC_REQ_UNKNOWN1_A            0xff
+#define MISC_REQ_UNKNOWN1_B            0x38
+/* Windows driver does this on init, with arg a, b = 0, c = 0xa0, d = 4 */
+#define MISC_REQ_UNKNOWN2_A            0xa5
+#define MISC_REQ_UNKNOWN2_B            0x00
+
+struct gm12u320_device {
+       struct drm_device                dev;
+       struct drm_simple_display_pipe   pipe;
+       struct drm_connector             conn;
+       struct usb_device               *udev;
+       unsigned char                   *cmd_buf;
+       unsigned char                   *data_buf[GM12U320_BLOCK_COUNT];
+       bool                             pipe_enabled;
+       struct {
+               bool                     run;
+               struct workqueue_struct *workq;
+               struct work_struct       work;
+               wait_queue_head_t        waitq;
+               struct mutex             lock;
+               struct drm_framebuffer  *fb;
+               struct drm_rect          rect;
+       } fb_update;
+};
+
+static const char cmd_data[CMD_SIZE] = {
+       0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
+       0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff,
+       0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x80, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const char cmd_draw[CMD_SIZE] = {
+       0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
+       0x00, 0x00, 0x00, 0xc0, 0xd1, 0x05, 0x00, 0x40,
+       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const char cmd_misc[CMD_SIZE] = {
+       0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
+       0x04, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0xfd,
+       0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const char data_block_header[DATA_BLOCK_HEADER_SIZE] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x04, 0x15, 0x00, 0x00, 0xfc, 0x00, 0x00,
+       0x01, 0x00, 0x00, 0xdb
+};
+
+static const char data_last_block_header[DATA_BLOCK_HEADER_SIZE] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x2a, 0x00, 0x20, 0x00, 0xc0, 0x0f, 0x00, 0x00,
+       0x01, 0x00, 0x00, 0xd7
+};
+
+static const char data_block_footer[DATA_BLOCK_FOOTER_SIZE] = {
+       0xfb, 0x14, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x80, 0x00, 0x00, 0x4f
+};
+
+static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320)
+{
+       int i, block_size;
+       const char *hdr;
+
+       gm12u320->cmd_buf = kmalloc(CMD_SIZE, GFP_KERNEL);
+       if (!gm12u320->cmd_buf)
+               return -ENOMEM;
+
+       for (i = 0; i < GM12U320_BLOCK_COUNT; i++) {
+               if (i == GM12U320_BLOCK_COUNT - 1) {
+                       block_size = DATA_LAST_BLOCK_SIZE;
+                       hdr = data_last_block_header;
+               } else {
+                       block_size = DATA_BLOCK_SIZE;
+                       hdr = data_block_header;
+               }
+
+               gm12u320->data_buf[i] = kzalloc(block_size, GFP_KERNEL);
+               if (!gm12u320->data_buf[i])
+                       return -ENOMEM;
+
+               memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE);
+               memcpy(gm12u320->data_buf[i] +
+                               (block_size - DATA_BLOCK_FOOTER_SIZE),
+                      data_block_footer, DATA_BLOCK_FOOTER_SIZE);
+       }
+
+       gm12u320->fb_update.workq = create_singlethread_workqueue(DRIVER_NAME);
+       if (!gm12u320->fb_update.workq)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void gm12u320_usb_free(struct gm12u320_device *gm12u320)
+{
+       int i;
+
+       if (gm12u320->fb_update.workq)
+               destroy_workqueue(gm12u320->fb_update.workq);
+
+       for (i = 0; i < GM12U320_BLOCK_COUNT; i++)
+               kfree(gm12u320->data_buf[i]);
+
+       kfree(gm12u320->cmd_buf);
+}
+
+static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
+                                u8 req_a, u8 req_b,
+                                u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
+{
+       int ret, len;
+
+       memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE);
+       gm12u320->cmd_buf[20] = req_a;
+       gm12u320->cmd_buf[21] = req_b;
+       gm12u320->cmd_buf[22] = arg_a;
+       gm12u320->cmd_buf[23] = arg_b;
+       gm12u320->cmd_buf[24] = arg_c;
+       gm12u320->cmd_buf[25] = arg_d;
+
+       /* Send request */
+       ret = usb_bulk_msg(gm12u320->udev,
+                          usb_sndbulkpipe(gm12u320->udev, MISC_SND_EPT),
+                          gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
+       if (ret || len != CMD_SIZE) {
+               dev_err(&gm12u320->udev->dev, "Misc. req. error %d\n", ret);
+               return -EIO;
+       }
+
+       /* Read value */
+       ret = usb_bulk_msg(gm12u320->udev,
+                          usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT),
+                          gm12u320->cmd_buf, MISC_VALUE_SIZE, &len,
+                          DATA_TIMEOUT);
+       if (ret || len != MISC_VALUE_SIZE) {
+               dev_err(&gm12u320->udev->dev, "Misc. value error %d\n", ret);
+               return -EIO;
+       }
+       /* cmd_buf[0] now contains the read value, which we don't use */
+
+       /* Read status */
+       ret = usb_bulk_msg(gm12u320->udev,
+                          usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT),
+                          gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
+                          CMD_TIMEOUT);
+       if (ret || len != READ_STATUS_SIZE) {
+               dev_err(&gm12u320->udev->dev, "Misc. status error %d\n", ret);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len)
+{
+       while (len--) {
+               *dst++ = *src++;
+               *dst++ = *src++;
+               *dst++ = *src++;
+               src++;
+       }
+}
+
+static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
+{
+       int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
+       struct drm_framebuffer *fb;
+       void *vaddr;
+       u8 *src;
+
+       mutex_lock(&gm12u320->fb_update.lock);
+
+       if (!gm12u320->fb_update.fb)
+               goto unlock;
+
+       fb = gm12u320->fb_update.fb;
+       x1 = gm12u320->fb_update.rect.x1;
+       x2 = gm12u320->fb_update.rect.x2;
+       y1 = gm12u320->fb_update.rect.y1;
+       y2 = gm12u320->fb_update.rect.y2;
+
+       vaddr = drm_gem_shmem_vmap(fb->obj[0]);
+       if (IS_ERR(vaddr)) {
+               DRM_ERROR("failed to vmap fb: %ld\n", PTR_ERR(vaddr));
+               goto put_fb;
+       }
+
+       if (fb->obj[0]->import_attach) {
+               ret = dma_buf_begin_cpu_access(
+                       fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE);
+               if (ret) {
+                       DRM_ERROR("dma_buf_begin_cpu_access err: %d\n", ret);
+                       goto vunmap;
+               }
+       }
+
+       src = vaddr + y1 * fb->pitches[0] + x1 * 4;
+
+       x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
+       x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
+
+       for (; y1 < y2; y1++) {
+               remain = 0;
+               len = (x2 - x1) * 3;
+               dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3;
+               block = dst_offset / DATA_BLOCK_CONTENT_SIZE;
+               dst_offset %= DATA_BLOCK_CONTENT_SIZE;
+
+               if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) {
+                       remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE;
+                       len = DATA_BLOCK_CONTENT_SIZE - dst_offset;
+               }
+
+               dst_offset += DATA_BLOCK_HEADER_SIZE;
+               len /= 3;
+
+               gm12u320_32bpp_to_24bpp_packed(
+                       gm12u320->data_buf[block] + dst_offset,
+                       src, len);
+
+               if (remain) {
+                       block++;
+                       dst_offset = DATA_BLOCK_HEADER_SIZE;
+                       gm12u320_32bpp_to_24bpp_packed(
+                               gm12u320->data_buf[block] + dst_offset,
+                               src + len * 4, remain / 3);
+               }
+               src += fb->pitches[0];
+       }
+
+       if (fb->obj[0]->import_attach) {
+               ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf,
+                                            DMA_FROM_DEVICE);
+               if (ret)
+                       DRM_ERROR("dma_buf_end_cpu_access err: %d\n", ret);
+       }
+vunmap:
+       drm_gem_shmem_vunmap(fb->obj[0], vaddr);
+put_fb:
+       drm_framebuffer_put(fb);
+       gm12u320->fb_update.fb = NULL;
+unlock:
+       mutex_unlock(&gm12u320->fb_update.lock);
+}
+
+static int gm12u320_fb_update_ready(struct gm12u320_device *gm12u320)
+{
+       int ret;
+
+       mutex_lock(&gm12u320->fb_update.lock);
+       ret = !gm12u320->fb_update.run || gm12u320->fb_update.fb != NULL;
+       mutex_unlock(&gm12u320->fb_update.lock);
+
+       return ret;
+}
+
+static void gm12u320_fb_update_work(struct work_struct *work)
+{
+       struct gm12u320_device *gm12u320 =
+               container_of(work, struct gm12u320_device, fb_update.work);
+       int draw_status_timeout = FIRST_FRAME_TIMEOUT;
+       int block, block_size, len;
+       int frame = 0;
+       int ret = 0;
+
+       while (gm12u320->fb_update.run) {
+               gm12u320_copy_fb_to_blocks(gm12u320);
+
+               for (block = 0; block < GM12U320_BLOCK_COUNT; block++) {
+                       if (block == GM12U320_BLOCK_COUNT - 1)
+                               block_size = DATA_LAST_BLOCK_SIZE;
+                       else
+                               block_size = DATA_BLOCK_SIZE;
+
+                       /* Send data command to device */
+                       memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE);
+                       gm12u320->cmd_buf[8] = block_size & 0xff;
+                       gm12u320->cmd_buf[9] = block_size >> 8;
+                       gm12u320->cmd_buf[20] = 0xfc - block * 4;
+                       gm12u320->cmd_buf[21] = block | (frame << 7);
+
+                       ret = usb_bulk_msg(gm12u320->udev,
+                               usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
+                               gm12u320->cmd_buf, CMD_SIZE, &len,
+                               CMD_TIMEOUT);
+                       if (ret || len != CMD_SIZE)
+                               goto err;
+
+                       /* Send data block to device */
+                       ret = usb_bulk_msg(gm12u320->udev,
+                               usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
+                               gm12u320->data_buf[block], block_size,
+                               &len, DATA_TIMEOUT);
+                       if (ret || len != block_size)
+                               goto err;
+
+                       /* Read status */
+                       ret = usb_bulk_msg(gm12u320->udev,
+                               usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT),
+                               gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
+                               CMD_TIMEOUT);
+                       if (ret || len != READ_STATUS_SIZE)
+                               goto err;
+               }
+
+               /* Send draw command to device */
+               memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE);
+               ret = usb_bulk_msg(gm12u320->udev,
+                       usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
+                       gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
+               if (ret || len != CMD_SIZE)
+                       goto err;
+
+               /* Read status */
+               ret = usb_bulk_msg(gm12u320->udev,
+                       usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT),
+                       gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
+                       draw_status_timeout);
+               if (ret || len != READ_STATUS_SIZE)
+                       goto err;
+
+               draw_status_timeout = CMD_TIMEOUT;
+               frame = !frame;
+
+               /*
+                * We must draw a frame every 2s otherwise the projector
+                * switches back to showing its logo.
+                */
+               wait_event_timeout(gm12u320->fb_update.waitq,
+                                  gm12u320_fb_update_ready(gm12u320),
+                                  IDLE_TIMEOUT);
+       }
+       return;
+err:
+       /* Do not log errors caused by module unload or device unplug */
+       if (ret != -ECONNRESET && ret != -ESHUTDOWN)
+               dev_err(&gm12u320->udev->dev, "Frame update error: %d\n", ret);
+}
+
+static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb,
+                                  struct drm_rect *dirty)
+{
+       struct gm12u320_device *gm12u320 = fb->dev->dev_private;
+       struct drm_framebuffer *old_fb = NULL;
+       bool wakeup = false;
+
+       mutex_lock(&gm12u320->fb_update.lock);
+
+       if (gm12u320->fb_update.fb != fb) {
+               old_fb = gm12u320->fb_update.fb;
+               drm_framebuffer_get(fb);
+               gm12u320->fb_update.fb = fb;
+               gm12u320->fb_update.rect = *dirty;
+               wakeup = true;
+       } else {
+               struct drm_rect *rect = &gm12u320->fb_update.rect;
+
+               rect->x1 = min(rect->x1, dirty->x1);
+               rect->y1 = min(rect->y1, dirty->y1);
+               rect->x2 = max(rect->x2, dirty->x2);
+               rect->y2 = max(rect->y2, dirty->y2);
+       }
+
+       mutex_unlock(&gm12u320->fb_update.lock);
+
+       if (wakeup)
+               wake_up(&gm12u320->fb_update.waitq);
+
+       if (old_fb)
+               drm_framebuffer_put(old_fb);
+}
+
+static void gm12u320_start_fb_update(struct gm12u320_device *gm12u320)
+{
+       mutex_lock(&gm12u320->fb_update.lock);
+       gm12u320->fb_update.run = true;
+       mutex_unlock(&gm12u320->fb_update.lock);
+
+       queue_work(gm12u320->fb_update.workq, &gm12u320->fb_update.work);
+}
+
+static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320)
+{
+       mutex_lock(&gm12u320->fb_update.lock);
+       gm12u320->fb_update.run = false;
+       mutex_unlock(&gm12u320->fb_update.lock);
+
+       wake_up(&gm12u320->fb_update.waitq);
+       cancel_work_sync(&gm12u320->fb_update.work);
+
+       mutex_lock(&gm12u320->fb_update.lock);
+       if (gm12u320->fb_update.fb) {
+               drm_framebuffer_put(gm12u320->fb_update.fb);
+               gm12u320->fb_update.fb = NULL;
+       }
+       mutex_unlock(&gm12u320->fb_update.lock);
+}
+
+static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320)
+{
+       return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A,
+                                    MISC_REQ_GET_SET_ECO_B, 0x01 /* set */,
+                                    eco_mode ? 0x01 : 0x00, 0x00, 0x01);
+}
+
+/* ------------------------------------------------------------------ */
+/* gm12u320 connector                                                */
+
+/*
+ * We use fake EDID info so that userspace know that it is dealing with
+ * an Acer projector, rather then listing this as an "unknown" monitor.
+ * Note this assumes this driver is only ever used with the Acer C120, if we
+ * add support for other devices the vendor and model should be parameterized.
+ */
+static struct edid gm12u320_edid = {
+       .header         = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 },
+       .mfg_id         = { 0x04, 0x72 },       /* "ACR" */
+       .prod_code      = { 0x20, 0xc1 },       /* C120h */
+       .serial         = 0xaa55aa55,
+       .mfg_week       = 1,
+       .mfg_year       = 16,
+       .version        = 1,                    /* EDID 1.3 */
+       .revision       = 3,                    /* EDID 1.3 */
+       .input          = 0x08,                 /* Analog input */
+       .features       = 0x0a,                 /* Pref timing in DTD 1 */
+       .standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
+                             { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } },
+       .detailed_timings = { {
+               .pixel_clock = 3383,
+               /* hactive = 848, hblank = 256 */
+               .data.pixel_data.hactive_lo = 0x50,
+               .data.pixel_data.hblank_lo = 0x00,
+               .data.pixel_data.hactive_hblank_hi = 0x31,
+               /* vactive = 480, vblank = 28 */
+               .data.pixel_data.vactive_lo = 0xe0,
+               .data.pixel_data.vblank_lo = 0x1c,
+               .data.pixel_data.vactive_vblank_hi = 0x10,
+               /* hsync offset 40 pw 128, vsync offset 1 pw 4 */
+               .data.pixel_data.hsync_offset_lo = 0x28,
+               .data.pixel_data.hsync_pulse_width_lo = 0x80,
+               .data.pixel_data.vsync_offset_pulse_width_lo = 0x14,
+               .data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00,
+               /* Digital separate syncs, hsync+, vsync+ */
+               .data.pixel_data.misc = 0x1e,
+       }, {
+               .pixel_clock = 0,
+               .data.other_data.type = 0xfd, /* Monitor ranges */
+               .data.other_data.data.range.min_vfreq = 59,
+               .data.other_data.data.range.max_vfreq = 61,
+               .data.other_data.data.range.min_hfreq_khz = 29,
+               .data.other_data.data.range.max_hfreq_khz = 32,
+               .data.other_data.data.range.pixel_clock_mhz = 4, /* 40 MHz */
+               .data.other_data.data.range.flags = 0,
+               .data.other_data.data.range.formula.cvt = {
+                       0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
+       }, {
+               .pixel_clock = 0,
+               .data.other_data.type = 0xfc, /* Model string */
+               .data.other_data.data.str.str = {
+                       'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n',
+                       ' ', ' ',  ' ' },
+       }, {
+               .pixel_clock = 0,
+               .data.other_data.type = 0xfe, /* Unspecified text / padding */
+               .data.other_data.data.str.str = {
+                       '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+                       ' ', ' ',  ' ' },
+       } },
+       .checksum = 0x13,
+};
+
+static int gm12u320_conn_get_modes(struct drm_connector *connector)
+{
+       drm_connector_update_edid_property(connector, &gm12u320_edid);
+       return drm_add_edid_modes(connector, &gm12u320_edid);
+}
+
+static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = {
+       .get_modes = gm12u320_conn_get_modes,
+};
+
+static const struct drm_connector_funcs gm12u320_conn_funcs = {
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int gm12u320_conn_init(struct gm12u320_device *gm12u320)
+{
+       drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs);
+       return drm_connector_init(&gm12u320->dev, &gm12u320->conn,
+                                 &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA);
+}
+
+/* ------------------------------------------------------------------ */
+/* gm12u320 (simple) display pipe                                    */
+
+static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
+                                struct drm_crtc_state *crtc_state,
+                                struct drm_plane_state *plane_state)
+{
+       struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private;
+       struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT };
+
+       gm12u320_fb_mark_dirty(plane_state->fb, &rect);
+       gm12u320_start_fb_update(gm12u320);
+       gm12u320->pipe_enabled = true;
+}
+
+static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private;
+
+       gm12u320_stop_fb_update(gm12u320);
+       gm12u320->pipe_enabled = false;
+}
+
+static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
+                                struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               gm12u320_fb_mark_dirty(pipe->plane.state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               crtc->state->event = NULL;
+               spin_unlock_irq(&crtc->dev->event_lock);
+       }
+}
+
+static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
+       .enable     = gm12u320_pipe_enable,
+       .disable    = gm12u320_pipe_disable,
+       .update     = gm12u320_pipe_update,
+};
+
+static const uint32_t gm12u320_pipe_formats[] = {
+       DRM_FORMAT_XRGB8888,
+};
+
+static const uint64_t gm12u320_pipe_modifiers[] = {
+       DRM_FORMAT_MOD_LINEAR,
+       DRM_FORMAT_MOD_INVALID
+};
+
+static void gm12u320_driver_release(struct drm_device *dev)
+{
+       struct gm12u320_device *gm12u320 = dev->dev_private;
+
+       gm12u320_usb_free(gm12u320);
+       drm_mode_config_cleanup(dev);
+       drm_dev_fini(dev);
+       kfree(gm12u320);
+}
+
+DEFINE_DRM_GEM_SHMEM_FOPS(gm12u320_fops);
+
+static struct drm_driver gm12u320_drm_driver = {
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
+
+       .name            = DRIVER_NAME,
+       .desc            = DRIVER_DESC,
+       .date            = DRIVER_DATE,
+       .major           = DRIVER_MAJOR,
+       .minor           = DRIVER_MINOR,
+
+       .release         = gm12u320_driver_release,
+       .fops            = &gm12u320_fops,
+       DRM_GEM_SHMEM_DRIVER_OPS,
+};
+
+static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
+       .fb_create = drm_gem_fb_create_with_dirty,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+};
+
+static int gm12u320_usb_probe(struct usb_interface *interface,
+                             const struct usb_device_id *id)
+{
+       struct gm12u320_device *gm12u320;
+       struct drm_device *dev;
+       int ret;
+
+       /*
+        * The gm12u320 presents itself to the system as 2 usb mass-storage
+        * interfaces, we only care about / need the first one.
+        */
+       if (interface->cur_altsetting->desc.bInterfaceNumber != 0)
+               return -ENODEV;
+
+       gm12u320 = kzalloc(sizeof(*gm12u320), GFP_KERNEL);
+       if (gm12u320 == NULL)
+               return -ENOMEM;
+
+       gm12u320->udev = interface_to_usbdev(interface);
+       INIT_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
+       mutex_init(&gm12u320->fb_update.lock);
+       init_waitqueue_head(&gm12u320->fb_update.waitq);
+
+       dev = &gm12u320->dev;
+       ret = drm_dev_init(dev, &gm12u320_drm_driver, &interface->dev);
+       if (ret) {
+               kfree(gm12u320);
+               return ret;
+       }
+       dev->dev_private = gm12u320;
+
+       drm_mode_config_init(dev);
+       dev->mode_config.min_width = GM12U320_USER_WIDTH;
+       dev->mode_config.max_width = GM12U320_USER_WIDTH;
+       dev->mode_config.min_height = GM12U320_HEIGHT;
+       dev->mode_config.max_height = GM12U320_HEIGHT;
+       dev->mode_config.funcs = &gm12u320_mode_config_funcs;
+
+       ret = gm12u320_usb_alloc(gm12u320);
+       if (ret)
+               goto err_put;
+
+       ret = gm12u320_set_ecomode(gm12u320);
+       if (ret)
+               goto err_put;
+
+       ret = gm12u320_conn_init(gm12u320);
+       if (ret)
+               goto err_put;
+
+       ret = drm_simple_display_pipe_init(&gm12u320->dev,
+                                          &gm12u320->pipe,
+                                          &gm12u320_pipe_funcs,
+                                          gm12u320_pipe_formats,
+                                          ARRAY_SIZE(gm12u320_pipe_formats),
+                                          gm12u320_pipe_modifiers,
+                                          &gm12u320->conn);
+       if (ret)
+               goto err_put;
+
+       drm_mode_config_reset(dev);
+
+       usb_set_intfdata(interface, dev);
+       ret = drm_dev_register(dev, 0);
+       if (ret)
+               goto err_put;
+
+       drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
+
+       return 0;
+
+err_put:
+       drm_dev_put(dev);
+       return ret;
+}
+
+static void gm12u320_usb_disconnect(struct usb_interface *interface)
+{
+       struct drm_device *dev = usb_get_intfdata(interface);
+       struct gm12u320_device *gm12u320 = dev->dev_private;
+
+       gm12u320_stop_fb_update(gm12u320);
+       drm_dev_unplug(dev);
+       drm_dev_put(dev);
+}
+
+#ifdef CONFIG_PM
+static int gm12u320_suspend(struct usb_interface *interface,
+                           pm_message_t message)
+{
+       struct drm_device *dev = usb_get_intfdata(interface);
+       struct gm12u320_device *gm12u320 = dev->dev_private;
+
+       if (gm12u320->pipe_enabled)
+               gm12u320_stop_fb_update(gm12u320);
+
+       return 0;
+}
+
+static int gm12u320_resume(struct usb_interface *interface)
+{
+       struct drm_device *dev = usb_get_intfdata(interface);
+       struct gm12u320_device *gm12u320 = dev->dev_private;
+
+       gm12u320_set_ecomode(gm12u320);
+       if (gm12u320->pipe_enabled)
+               gm12u320_start_fb_update(gm12u320);
+
+       return 0;
+}
+#endif
+
+static const struct usb_device_id id_table[] = {
+       { USB_DEVICE(0x1de1, 0xc102) },
+       {},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver gm12u320_usb_driver = {
+       .name = "gm12u320",
+       .probe = gm12u320_usb_probe,
+       .disconnect = gm12u320_usb_disconnect,
+       .id_table = id_table,
+#ifdef CONFIG_PM
+       .suspend = gm12u320_suspend,
+       .resume = gm12u320_resume,
+       .reset_resume = gm12u320_resume,
+#endif
+};
+
+module_usb_driver(gm12u320_usb_driver);
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
new file mode 100644 (file)
index 0000000..9af8ff8
--- /dev/null
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DRM driver for the HX8357D LCD controller
+ *
+ * Copyright 2018 Broadcom
+ * Copyright 2018 David Lechner <david@lechnology.com>
+ * Copyright 2016 Noralf Trønnes
+ * Copyright (C) 2015 Adafruit Industries
+ * Copyright (C) 2013 Christian Vogelgsang
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modeset_helper.h>
+#include <video/mipi_display.h>
+
+#define HX8357D_SETOSC 0xb0
+#define HX8357D_SETPOWER 0xb1
+#define HX8357D_SETRGB 0xb3
+#define HX8357D_SETCYC 0xb3
+#define HX8357D_SETCOM 0xb6
+#define HX8357D_SETEXTC 0xb9
+#define HX8357D_SETSTBA 0xc0
+#define HX8357D_SETPANEL 0xcc
+#define HX8357D_SETGAMMA 0xe0
+
+#define HX8357D_MADCTL_MY  0x80
+#define HX8357D_MADCTL_MX  0x40
+#define HX8357D_MADCTL_MV  0x20
+#define HX8357D_MADCTL_ML  0x10
+#define HX8357D_MADCTL_RGB 0x00
+#define HX8357D_MADCTL_BGR 0x08
+#define HX8357D_MADCTL_MH  0x04
+
+static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
+                            struct drm_crtc_state *crtc_state,
+                            struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       u8 addr_mode;
+       int ret, idx;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       ret = mipi_dbi_poweron_conditional_reset(dbidev);
+       if (ret < 0)
+               goto out_exit;
+       if (ret == 1)
+               goto out_enable;
+
+       /* setextc */
+       mipi_dbi_command(dbi, HX8357D_SETEXTC, 0xFF, 0x83, 0x57);
+       msleep(150);
+
+       /* setRGB which also enables SDO */
+       mipi_dbi_command(dbi, HX8357D_SETRGB, 0x00, 0x00, 0x06, 0x06);
+
+       /* -1.52V */
+       mipi_dbi_command(dbi, HX8357D_SETCOM, 0x25);
+
+       /* Normal mode 70Hz, Idle mode 55 Hz */
+       mipi_dbi_command(dbi, HX8357D_SETOSC, 0x68);
+
+       /* Set Panel - BGR, Gate direction swapped */
+       mipi_dbi_command(dbi, HX8357D_SETPANEL, 0x05);
+
+       mipi_dbi_command(dbi, HX8357D_SETPOWER,
+                        0x00,  /* Not deep standby */
+                        0x15,  /* BT */
+                        0x1C,  /* VSPR */
+                        0x1C,  /* VSNR */
+                        0x83,  /* AP */
+                        0xAA);  /* FS */
+
+       mipi_dbi_command(dbi, HX8357D_SETSTBA,
+                        0x50,  /* OPON normal */
+                        0x50,  /* OPON idle */
+                        0x01,  /* STBA */
+                        0x3C,  /* STBA */
+                        0x1E,  /* STBA */
+                        0x08);  /* GEN */
+
+       mipi_dbi_command(dbi, HX8357D_SETCYC,
+                        0x02,  /* NW 0x02 */
+                        0x40,  /* RTN */
+                        0x00,  /* DIV */
+                        0x2A,  /* DUM */
+                        0x2A,  /* DUM */
+                        0x0D,  /* GDON */
+                        0x78);  /* GDOFF */
+
+       mipi_dbi_command(dbi, HX8357D_SETGAMMA,
+                        0x02,
+                        0x0A,
+                        0x11,
+                        0x1d,
+                        0x23,
+                        0x35,
+                        0x41,
+                        0x4b,
+                        0x4b,
+                        0x42,
+                        0x3A,
+                        0x27,
+                        0x1B,
+                        0x08,
+                        0x09,
+                        0x03,
+                        0x02,
+                        0x0A,
+                        0x11,
+                        0x1d,
+                        0x23,
+                        0x35,
+                        0x41,
+                        0x4b,
+                        0x4b,
+                        0x42,
+                        0x3A,
+                        0x27,
+                        0x1B,
+                        0x08,
+                        0x09,
+                        0x03,
+                        0x00,
+                        0x01);
+
+       /* 16 bit */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
+                        MIPI_DCS_PIXEL_FMT_16BIT);
+
+       /* TE off */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_ON, 0x00);
+
+       /* tear line */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
+
+       /* Exit Sleep */
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+       msleep(150);
+
+       /* display on */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+       usleep_range(5000, 7000);
+
+out_enable:
+       switch (dbidev->rotation) {
+       default:
+               addr_mode = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY;
+               break;
+       case 90:
+               addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MY;
+               break;
+       case 180:
+               addr_mode = 0;
+               break;
+       case 270:
+               addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX;
+               break;
+       }
+       mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+       mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
+       .enable = yx240qv29_enable,
+       .disable = mipi_dbi_pipe_disable,
+       .update = mipi_dbi_pipe_update,
+       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode yx350hv15_mode = {
+       DRM_SIMPLE_MODE(320, 480, 60, 75),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops);
+
+static struct drm_driver hx8357d_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &hx8357d_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .debugfs_init           = mipi_dbi_debugfs_init,
+       .name                   = "hx8357d",
+       .desc                   = "HX8357D",
+       .date                   = "20181023",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id hx8357d_of_match[] = {
+       { .compatible = "adafruit,yx350hv15" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, hx8357d_of_match);
+
+static const struct spi_device_id hx8357d_id[] = {
+       { "yx350hv15", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, hx8357d_id);
+
+static int hx8357d_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct gpio_desc *dc;
+       u32 rotation = 0;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &hx8357d_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
+       if (IS_ERR(dc)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+               return PTR_ERR(dc);
+       }
+
+       dbidev->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(dbidev->backlight))
+               return PTR_ERR(dbidev->backlight);
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, &dbidev->dbi, dc);
+       if (ret)
+               return ret;
+
+       ret = mipi_dbi_dev_init(dbidev, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int hx8357d_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void hx8357d_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver hx8357d_spi_driver = {
+       .driver = {
+               .name = "hx8357d",
+               .of_match_table = hx8357d_of_match,
+       },
+       .id_table = hx8357d_id,
+       .probe = hx8357d_probe,
+       .remove = hx8357d_remove,
+       .shutdown = hx8357d_shutdown,
+};
+module_spi_driver(hx8357d_spi_driver);
+
+MODULE_DESCRIPTION("HX8357D DRM driver");
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
new file mode 100644 (file)
index 0000000..c66acc5
--- /dev/null
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DRM driver for Ilitek ILI9225 panels
+ *
+ * Copyright 2017 David Lechner <david@lechnology.com>
+ *
+ * Some code copied from mipi-dbi.c
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
+
+#define ILI9225_DRIVER_READ_CODE       0x00
+#define ILI9225_DRIVER_OUTPUT_CONTROL  0x01
+#define ILI9225_LCD_AC_DRIVING_CONTROL 0x02
+#define ILI9225_ENTRY_MODE             0x03
+#define ILI9225_DISPLAY_CONTROL_1      0x07
+#define ILI9225_BLANK_PERIOD_CONTROL_1 0x08
+#define ILI9225_FRAME_CYCLE_CONTROL    0x0b
+#define ILI9225_INTERFACE_CONTROL      0x0c
+#define ILI9225_OSCILLATION_CONTROL    0x0f
+#define ILI9225_POWER_CONTROL_1                0x10
+#define ILI9225_POWER_CONTROL_2                0x11
+#define ILI9225_POWER_CONTROL_3                0x12
+#define ILI9225_POWER_CONTROL_4                0x13
+#define ILI9225_POWER_CONTROL_5                0x14
+#define ILI9225_VCI_RECYCLING          0x15
+#define ILI9225_RAM_ADDRESS_SET_1      0x20
+#define ILI9225_RAM_ADDRESS_SET_2      0x21
+#define ILI9225_WRITE_DATA_TO_GRAM     0x22
+#define ILI9225_SOFTWARE_RESET         0x28
+#define ILI9225_GATE_SCAN_CONTROL      0x30
+#define ILI9225_VERTICAL_SCROLL_1      0x31
+#define ILI9225_VERTICAL_SCROLL_2      0x32
+#define ILI9225_VERTICAL_SCROLL_3      0x33
+#define ILI9225_PARTIAL_DRIVING_POS_1  0x34
+#define ILI9225_PARTIAL_DRIVING_POS_2  0x35
+#define ILI9225_HORIZ_WINDOW_ADDR_1    0x36
+#define ILI9225_HORIZ_WINDOW_ADDR_2    0x37
+#define ILI9225_VERT_WINDOW_ADDR_1     0x38
+#define ILI9225_VERT_WINDOW_ADDR_2     0x39
+#define ILI9225_GAMMA_CONTROL_1                0x50
+#define ILI9225_GAMMA_CONTROL_2                0x51
+#define ILI9225_GAMMA_CONTROL_3                0x52
+#define ILI9225_GAMMA_CONTROL_4                0x53
+#define ILI9225_GAMMA_CONTROL_5                0x54
+#define ILI9225_GAMMA_CONTROL_6                0x55
+#define ILI9225_GAMMA_CONTROL_7                0x56
+#define ILI9225_GAMMA_CONTROL_8                0x57
+#define ILI9225_GAMMA_CONTROL_9                0x58
+#define ILI9225_GAMMA_CONTROL_10       0x59
+
+static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data)
+{
+       u8 par[2] = { data >> 8, data & 0xff };
+
+       return mipi_dbi_command_buf(dbi, cmd, par, 2);
+}
+
+static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+{
+       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
+       unsigned int height = rect->y2 - rect->y1;
+       unsigned int width = rect->x2 - rect->x1;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       bool swap = dbi->swap_bytes;
+       u16 x_start, y_start;
+       u16 x1, x2, y1, y2;
+       int idx, ret = 0;
+       bool full;
+       void *tr;
+
+       if (!dbidev->enabled)
+               return;
+
+       if (!drm_dev_enter(fb->dev, &idx))
+               return;
+
+       full = width == fb->width && height == fb->height;
+
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
+
+       if (!dbi->dc || !full || swap ||
+           fb->format->format == DRM_FORMAT_XRGB8888) {
+               tr = dbidev->tx_buf;
+               ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap);
+               if (ret)
+                       goto err_msg;
+       } else {
+               tr = cma_obj->vaddr;
+       }
+
+       switch (dbidev->rotation) {
+       default:
+               x1 = rect->x1;
+               x2 = rect->x2 - 1;
+               y1 = rect->y1;
+               y2 = rect->y2 - 1;
+               x_start = x1;
+               y_start = y1;
+               break;
+       case 90:
+               x1 = rect->y1;
+               x2 = rect->y2 - 1;
+               y1 = fb->width - rect->x2;
+               y2 = fb->width - rect->x1 - 1;
+               x_start = x1;
+               y_start = y2;
+               break;
+       case 180:
+               x1 = fb->width - rect->x2;
+               x2 = fb->width - rect->x1 - 1;
+               y1 = fb->height - rect->y2;
+               y2 = fb->height - rect->y1 - 1;
+               x_start = x2;
+               y_start = y2;
+               break;
+       case 270:
+               x1 = fb->height - rect->y2;
+               x2 = fb->height - rect->y1 - 1;
+               y1 = rect->x1;
+               y2 = rect->x2 - 1;
+               x_start = x2;
+               y_start = y1;
+               break;
+       }
+
+       ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_1, x2);
+       ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_2, x1);
+       ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_1, y2);
+       ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_2, y1);
+
+       ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, x_start);
+       ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, y_start);
+
+       ret = mipi_dbi_command_buf(dbi, ILI9225_WRITE_DATA_TO_GRAM, tr,
+                                  width * height * 2);
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
+
+       drm_dev_exit(idx);
+}
+
+static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
+                               struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               ili9225_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
+static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
+                               struct drm_crtc_state *crtc_state,
+                               struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct device *dev = pipe->crtc.dev->dev;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
+       int ret, idx;
+       u8 am_id;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       mipi_dbi_hw_reset(dbi);
+
+       /*
+        * There don't seem to be two example init sequences that match, so
+        * using the one from the popular Arduino library for this display.
+        * https://github.com/Nkawu/TFT_22_ILI9225/blob/master/src/TFT_22_ILI9225.cpp
+        */
+
+       ret = ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0000);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
+               goto out_exit;
+       }
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0000);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x0000);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x0000);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x0000);
+
+       msleep(40);
+
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0018);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x6121);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x006f);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x495f);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0800);
+
+       msleep(10);
+
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x103b);
+
+       msleep(50);
+
+       switch (dbidev->rotation) {
+       default:
+               am_id = 0x30;
+               break;
+       case 90:
+               am_id = 0x18;
+               break;
+       case 180:
+               am_id = 0x00;
+               break;
+       case 270:
+               am_id = 0x28;
+               break;
+       }
+       ili9225_command(dbi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c);
+       ili9225_command(dbi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100);
+       ili9225_command(dbi, ILI9225_ENTRY_MODE, 0x1000 | am_id);
+       ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
+       ili9225_command(dbi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808);
+       ili9225_command(dbi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100);
+       ili9225_command(dbi, ILI9225_INTERFACE_CONTROL, 0x0000);
+       ili9225_command(dbi, ILI9225_OSCILLATION_CONTROL, 0x0d01);
+       ili9225_command(dbi, ILI9225_VCI_RECYCLING, 0x0020);
+       ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, 0x0000);
+       ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, 0x0000);
+
+       ili9225_command(dbi, ILI9225_GATE_SCAN_CONTROL, 0x0000);
+       ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_1, 0x00db);
+       ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_2, 0x0000);
+       ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_3, 0x0000);
+       ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db);
+       ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000);
+
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_1, 0x0000);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_2, 0x0808);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_3, 0x080a);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_4, 0x000a);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_5, 0x0a08);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_6, 0x0808);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_7, 0x0000);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_8, 0x0a00);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_9, 0x0710);
+       ili9225_command(dbi, ILI9225_GAMMA_CONTROL_10, 0x0710);
+
+       ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0012);
+
+       msleep(50);
+
+       ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
+
+       dbidev->enabled = true;
+       ili9225_fb_dirty(fb, &rect);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+
+       DRM_DEBUG_KMS("\n");
+
+       /*
+        * This callback is not protected by drm_dev_enter/exit since we want to
+        * turn off the display on regular driver unload. It's highly unlikely
+        * that the underlying SPI controller is gone should this be called after
+        * unplug.
+        */
+
+       if (!dbidev->enabled)
+               return;
+
+       ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
+       msleep(50);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0007);
+       msleep(50);
+       ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0a02);
+
+       dbidev->enabled = false;
+}
+
+static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par,
+                              size_t num)
+{
+       struct spi_device *spi = dbi->spi;
+       unsigned int bpw = 8;
+       u32 speed_hz;
+       int ret;
+
+       gpiod_set_value_cansleep(dbi->dc, 0);
+       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
+       ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1);
+       if (ret || !num)
+               return ret;
+
+       if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !dbi->swap_bytes)
+               bpw = 16;
+
+       gpiod_set_value_cansleep(dbi->dc, 1);
+       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
+
+       return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+}
+
+static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
+       .enable         = ili9225_pipe_enable,
+       .disable        = ili9225_pipe_disable,
+       .update         = ili9225_pipe_update,
+       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode ili9225_mode = {
+       DRM_SIMPLE_MODE(176, 220, 35, 44),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops);
+
+static struct drm_driver ili9225_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &ili9225_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .name                   = "ili9225",
+       .desc                   = "Ilitek ILI9225",
+       .date                   = "20171106",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id ili9225_of_match[] = {
+       { .compatible = "vot,v220hf01a-t" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ili9225_of_match);
+
+static const struct spi_device_id ili9225_id[] = {
+       { "v220hf01a-t", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, ili9225_id);
+
+static int ili9225_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct mipi_dbi *dbi;
+       struct gpio_desc *rs;
+       u32 rotation = 0;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       dbi = &dbidev->dbi;
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &ili9225_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dbi->reset)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return PTR_ERR(dbi->reset);
+       }
+
+       rs = devm_gpiod_get(dev, "rs", GPIOD_OUT_LOW);
+       if (IS_ERR(rs)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'rs'\n");
+               return PTR_ERR(rs);
+       }
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, dbi, rs);
+       if (ret)
+               return ret;
+
+       /* override the command function set in  mipi_dbi_spi_init() */
+       dbi->command = ili9225_dbi_command;
+
+       ret = mipi_dbi_dev_init(dbidev, &ili9225_pipe_funcs, &ili9225_mode, rotation);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int ili9225_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void ili9225_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver ili9225_spi_driver = {
+       .driver = {
+               .name = "ili9225",
+               .owner = THIS_MODULE,
+               .of_match_table = ili9225_of_match,
+       },
+       .id_table = ili9225_id,
+       .probe = ili9225_probe,
+       .remove = ili9225_remove,
+       .shutdown = ili9225_shutdown,
+};
+module_spi_driver(ili9225_spi_driver);
+
+MODULE_DESCRIPTION("Ilitek ILI9225 DRM driver");
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
new file mode 100644 (file)
index 0000000..33b51dc
--- /dev/null
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DRM driver for Ilitek ILI9341 panels
+ *
+ * Copyright 2018 David Lechner <david@lechnology.com>
+ *
+ * Based on mi0283qt.c:
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modeset_helper.h>
+#include <video/mipi_display.h>
+
+#define ILI9341_FRMCTR1                0xb1
+#define ILI9341_DISCTRL                0xb6
+#define ILI9341_ETMOD          0xb7
+
+#define ILI9341_PWCTRL1                0xc0
+#define ILI9341_PWCTRL2                0xc1
+#define ILI9341_VMCTRL1                0xc5
+#define ILI9341_VMCTRL2                0xc7
+#define ILI9341_PWCTRLA                0xcb
+#define ILI9341_PWCTRLB                0xcf
+
+#define ILI9341_PGAMCTRL       0xe0
+#define ILI9341_NGAMCTRL       0xe1
+#define ILI9341_DTCTRLA                0xe8
+#define ILI9341_DTCTRLB                0xea
+#define ILI9341_PWRSEQ         0xed
+
+#define ILI9341_EN3GAM         0xf2
+#define ILI9341_PUMPCTRL       0xf7
+
+#define ILI9341_MADCTL_BGR     BIT(3)
+#define ILI9341_MADCTL_MV      BIT(5)
+#define ILI9341_MADCTL_MX      BIT(6)
+#define ILI9341_MADCTL_MY      BIT(7)
+
+static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
+                            struct drm_crtc_state *crtc_state,
+                            struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       u8 addr_mode;
+       int ret, idx;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       ret = mipi_dbi_poweron_conditional_reset(dbidev);
+       if (ret < 0)
+               goto out_exit;
+       if (ret == 1)
+               goto out_enable;
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+       mipi_dbi_command(dbi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30);
+       mipi_dbi_command(dbi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81);
+       mipi_dbi_command(dbi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78);
+       mipi_dbi_command(dbi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02);
+       mipi_dbi_command(dbi, ILI9341_PUMPCTRL, 0x20);
+       mipi_dbi_command(dbi, ILI9341_DTCTRLB, 0x00, 0x00);
+
+       /* Power Control */
+       mipi_dbi_command(dbi, ILI9341_PWCTRL1, 0x23);
+       mipi_dbi_command(dbi, ILI9341_PWCTRL2, 0x10);
+       /* VCOM */
+       mipi_dbi_command(dbi, ILI9341_VMCTRL1, 0x3e, 0x28);
+       mipi_dbi_command(dbi, ILI9341_VMCTRL2, 0x86);
+
+       /* Memory Access Control */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
+
+       /* Frame Rate */
+       mipi_dbi_command(dbi, ILI9341_FRMCTR1, 0x00, 0x1b);
+
+       /* Gamma */
+       mipi_dbi_command(dbi, ILI9341_EN3GAM, 0x00);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
+       mipi_dbi_command(dbi, ILI9341_PGAMCTRL,
+                        0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
+                        0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
+       mipi_dbi_command(dbi, ILI9341_NGAMCTRL,
+                        0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
+                        0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
+
+       /* DDRAM */
+       mipi_dbi_command(dbi, ILI9341_ETMOD, 0x07);
+
+       /* Display */
+       mipi_dbi_command(dbi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00);
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+       msleep(100);
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+       msleep(100);
+
+out_enable:
+       switch (dbidev->rotation) {
+       default:
+               addr_mode = ILI9341_MADCTL_MX;
+               break;
+       case 90:
+               addr_mode = ILI9341_MADCTL_MV;
+               break;
+       case 180:
+               addr_mode = ILI9341_MADCTL_MY;
+               break;
+       case 270:
+               addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
+                           ILI9341_MADCTL_MX;
+               break;
+       }
+       addr_mode |= ILI9341_MADCTL_BGR;
+       mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+       mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
+       .enable = yx240qv29_enable,
+       .disable = mipi_dbi_pipe_disable,
+       .update = mipi_dbi_pipe_update,
+       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode yx240qv29_mode = {
+       DRM_SIMPLE_MODE(240, 320, 37, 49),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops);
+
+static struct drm_driver ili9341_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &ili9341_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .debugfs_init           = mipi_dbi_debugfs_init,
+       .name                   = "ili9341",
+       .desc                   = "Ilitek ILI9341",
+       .date                   = "20180514",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id ili9341_of_match[] = {
+       { .compatible = "adafruit,yx240qv29" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ili9341_of_match);
+
+static const struct spi_device_id ili9341_id[] = {
+       { "yx240qv29", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, ili9341_id);
+
+static int ili9341_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct mipi_dbi *dbi;
+       struct gpio_desc *dc;
+       u32 rotation = 0;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       dbi = &dbidev->dbi;
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &ili9341_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dbi->reset)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return PTR_ERR(dbi->reset);
+       }
+
+       dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+       if (IS_ERR(dc)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+               return PTR_ERR(dc);
+       }
+
+       dbidev->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(dbidev->backlight))
+               return PTR_ERR(dbidev->backlight);
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, dbi, dc);
+       if (ret)
+               return ret;
+
+       ret = mipi_dbi_dev_init(dbidev, &ili9341_pipe_funcs, &yx240qv29_mode, rotation);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int ili9341_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void ili9341_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver ili9341_spi_driver = {
+       .driver = {
+               .name = "ili9341",
+               .of_match_table = ili9341_of_match,
+       },
+       .id_table = ili9341_id,
+       .probe = ili9341_probe,
+       .remove = ili9341_remove,
+       .shutdown = ili9341_shutdown,
+};
+module_spi_driver(ili9341_spi_driver);
+
+MODULE_DESCRIPTION("Ilitek ILI9341 DRM driver");
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
new file mode 100644 (file)
index 0000000..e2cfd9a
--- /dev/null
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DRM driver for Multi-Inno MI0283QT panels
+ *
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modeset_helper.h>
+#include <video/mipi_display.h>
+
+#define ILI9341_FRMCTR1                0xb1
+#define ILI9341_DISCTRL                0xb6
+#define ILI9341_ETMOD          0xb7
+
+#define ILI9341_PWCTRL1                0xc0
+#define ILI9341_PWCTRL2                0xc1
+#define ILI9341_VMCTRL1                0xc5
+#define ILI9341_VMCTRL2                0xc7
+#define ILI9341_PWCTRLA                0xcb
+#define ILI9341_PWCTRLB                0xcf
+
+#define ILI9341_PGAMCTRL       0xe0
+#define ILI9341_NGAMCTRL       0xe1
+#define ILI9341_DTCTRLA                0xe8
+#define ILI9341_DTCTRLB                0xea
+#define ILI9341_PWRSEQ         0xed
+
+#define ILI9341_EN3GAM         0xf2
+#define ILI9341_PUMPCTRL       0xf7
+
+#define ILI9341_MADCTL_BGR     BIT(3)
+#define ILI9341_MADCTL_MV      BIT(5)
+#define ILI9341_MADCTL_MX      BIT(6)
+#define ILI9341_MADCTL_MY      BIT(7)
+
+static void mi0283qt_enable(struct drm_simple_display_pipe *pipe,
+                           struct drm_crtc_state *crtc_state,
+                           struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       u8 addr_mode;
+       int ret, idx;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       ret = mipi_dbi_poweron_conditional_reset(dbidev);
+       if (ret < 0)
+               goto out_exit;
+       if (ret == 1)
+               goto out_enable;
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+       mipi_dbi_command(dbi, ILI9341_PWCTRLB, 0x00, 0x83, 0x30);
+       mipi_dbi_command(dbi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81);
+       mipi_dbi_command(dbi, ILI9341_DTCTRLA, 0x85, 0x01, 0x79);
+       mipi_dbi_command(dbi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02);
+       mipi_dbi_command(dbi, ILI9341_PUMPCTRL, 0x20);
+       mipi_dbi_command(dbi, ILI9341_DTCTRLB, 0x00, 0x00);
+
+       /* Power Control */
+       mipi_dbi_command(dbi, ILI9341_PWCTRL1, 0x26);
+       mipi_dbi_command(dbi, ILI9341_PWCTRL2, 0x11);
+       /* VCOM */
+       mipi_dbi_command(dbi, ILI9341_VMCTRL1, 0x35, 0x3e);
+       mipi_dbi_command(dbi, ILI9341_VMCTRL2, 0xbe);
+
+       /* Memory Access Control */
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
+
+       /* Frame Rate */
+       mipi_dbi_command(dbi, ILI9341_FRMCTR1, 0x00, 0x1b);
+
+       /* Gamma */
+       mipi_dbi_command(dbi, ILI9341_EN3GAM, 0x08);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
+       mipi_dbi_command(dbi, ILI9341_PGAMCTRL,
+                      0x1f, 0x1a, 0x18, 0x0a, 0x0f, 0x06, 0x45, 0x87,
+                      0x32, 0x0a, 0x07, 0x02, 0x07, 0x05, 0x00);
+       mipi_dbi_command(dbi, ILI9341_NGAMCTRL,
+                      0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3a, 0x78,
+                      0x4d, 0x05, 0x18, 0x0d, 0x38, 0x3a, 0x1f);
+
+       /* DDRAM */
+       mipi_dbi_command(dbi, ILI9341_ETMOD, 0x07);
+
+       /* Display */
+       mipi_dbi_command(dbi, ILI9341_DISCTRL, 0x0a, 0x82, 0x27, 0x00);
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+       msleep(100);
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+       msleep(100);
+
+out_enable:
+       /* The PiTFT (ili9340) has a hardware reset circuit that
+        * resets only on power-on and not on each reboot through
+        * a gpio like the rpi-display does.
+        * As a result, we need to always apply the rotation value
+        * regardless of the display "on/off" state.
+        */
+       switch (dbidev->rotation) {
+       default:
+               addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
+                           ILI9341_MADCTL_MX;
+               break;
+       case 90:
+               addr_mode = ILI9341_MADCTL_MY;
+               break;
+       case 180:
+               addr_mode = ILI9341_MADCTL_MV;
+               break;
+       case 270:
+               addr_mode = ILI9341_MADCTL_MX;
+               break;
+       }
+       addr_mode |= ILI9341_MADCTL_BGR;
+       mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+       mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
+       .enable = mi0283qt_enable,
+       .disable = mipi_dbi_pipe_disable,
+       .update = mipi_dbi_pipe_update,
+       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode mi0283qt_mode = {
+       DRM_SIMPLE_MODE(320, 240, 58, 43),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
+
+static struct drm_driver mi0283qt_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &mi0283qt_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .debugfs_init           = mipi_dbi_debugfs_init,
+       .name                   = "mi0283qt",
+       .desc                   = "Multi-Inno MI0283QT",
+       .date                   = "20160614",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id mi0283qt_of_match[] = {
+       { .compatible = "multi-inno,mi0283qt" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mi0283qt_of_match);
+
+static const struct spi_device_id mi0283qt_id[] = {
+       { "mi0283qt", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, mi0283qt_id);
+
+static int mi0283qt_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct mipi_dbi *dbi;
+       struct gpio_desc *dc;
+       u32 rotation = 0;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       dbi = &dbidev->dbi;
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &mi0283qt_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dbi->reset)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return PTR_ERR(dbi->reset);
+       }
+
+       dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+       if (IS_ERR(dc)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+               return PTR_ERR(dc);
+       }
+
+       dbidev->regulator = devm_regulator_get(dev, "power");
+       if (IS_ERR(dbidev->regulator))
+               return PTR_ERR(dbidev->regulator);
+
+       dbidev->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(dbidev->backlight))
+               return PTR_ERR(dbidev->backlight);
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, dbi, dc);
+       if (ret)
+               return ret;
+
+       ret = mipi_dbi_dev_init(dbidev, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int mi0283qt_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void mi0283qt_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static int __maybe_unused mi0283qt_pm_suspend(struct device *dev)
+{
+       return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
+}
+
+static int __maybe_unused mi0283qt_pm_resume(struct device *dev)
+{
+       drm_mode_config_helper_resume(dev_get_drvdata(dev));
+
+       return 0;
+}
+
+static const struct dev_pm_ops mi0283qt_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(mi0283qt_pm_suspend, mi0283qt_pm_resume)
+};
+
+static struct spi_driver mi0283qt_spi_driver = {
+       .driver = {
+               .name = "mi0283qt",
+               .owner = THIS_MODULE,
+               .of_match_table = mi0283qt_of_match,
+               .pm = &mi0283qt_pm_ops,
+       },
+       .id_table = mi0283qt_id,
+       .probe = mi0283qt_probe,
+       .remove = mi0283qt_remove,
+       .shutdown = mi0283qt_shutdown,
+};
+module_spi_driver(mi0283qt_spi_driver);
+
+MODULE_DESCRIPTION("Multi-Inno MI0283QT DRM driver");
+MODULE_AUTHOR("Noralf Trønnes");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
new file mode 100644 (file)
index 0000000..76d1792
--- /dev/null
@@ -0,0 +1,1212 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DRM driver for Pervasive Displays RePaper branded e-ink panels
+ *
+ * Copyright 2013-2017 Pervasive Displays, Inc.
+ * Copyright 2017 Noralf Trønnes
+ *
+ * The driver supports:
+ * Material Film: Aurora Mb (V231)
+ * Driver IC: G2 (eTC)
+ *
+ * The controller code was taken from the userspace driver:
+ * https://github.com/repaper/gratis
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/sched/clock.h>
+#include <linux/spi/spi.h>
+#include <linux/thermal.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#define REPAPER_RID_G2_COG_ID  0x12
+
+enum repaper_model {
+       E1144CS021 = 1,
+       E1190CS021,
+       E2200CS021,
+       E2271CS021,
+};
+
+enum repaper_stage {         /* Image pixel -> Display pixel */
+       REPAPER_COMPENSATE,  /* B -> W, W -> B (Current Image) */
+       REPAPER_WHITE,       /* B -> N, W -> W (Current Image) */
+       REPAPER_INVERSE,     /* B -> N, W -> B (New Image) */
+       REPAPER_NORMAL       /* B -> B, W -> W (New Image) */
+};
+
+enum repaper_epd_border_byte {
+       REPAPER_BORDER_BYTE_NONE,
+       REPAPER_BORDER_BYTE_ZERO,
+       REPAPER_BORDER_BYTE_SET,
+};
+
+struct repaper_epd {
+       struct drm_device drm;
+       struct drm_simple_display_pipe pipe;
+       const struct drm_display_mode *mode;
+       struct drm_connector connector;
+       struct spi_device *spi;
+
+       struct gpio_desc *panel_on;
+       struct gpio_desc *border;
+       struct gpio_desc *discharge;
+       struct gpio_desc *reset;
+       struct gpio_desc *busy;
+
+       struct thermal_zone_device *thermal;
+
+       unsigned int height;
+       unsigned int width;
+       unsigned int bytes_per_scan;
+       const u8 *channel_select;
+       unsigned int stage_time;
+       unsigned int factored_stage_time;
+       bool middle_scan;
+       bool pre_border_byte;
+       enum repaper_epd_border_byte border_byte;
+
+       u8 *line_buffer;
+       void *current_frame;
+
+       bool enabled;
+       bool cleared;
+       bool partial;
+};
+
+static inline struct repaper_epd *drm_to_epd(struct drm_device *drm)
+{
+       return container_of(drm, struct repaper_epd, drm);
+}
+
+static int repaper_spi_transfer(struct spi_device *spi, u8 header,
+                               const void *tx, void *rx, size_t len)
+{
+       void *txbuf = NULL, *rxbuf = NULL;
+       struct spi_transfer tr[2] = {};
+       u8 *headerbuf;
+       int ret;
+
+       headerbuf = kmalloc(1, GFP_KERNEL);
+       if (!headerbuf)
+               return -ENOMEM;
+
+       headerbuf[0] = header;
+       tr[0].tx_buf = headerbuf;
+       tr[0].len = 1;
+
+       /* Stack allocated tx? */
+       if (tx && len <= 32) {
+               txbuf = kmemdup(tx, len, GFP_KERNEL);
+               if (!txbuf) {
+                       ret = -ENOMEM;
+                       goto out_free;
+               }
+       }
+
+       if (rx) {
+               rxbuf = kmalloc(len, GFP_KERNEL);
+               if (!rxbuf) {
+                       ret = -ENOMEM;
+                       goto out_free;
+               }
+       }
+
+       tr[1].tx_buf = txbuf ? txbuf : tx;
+       tr[1].rx_buf = rxbuf;
+       tr[1].len = len;
+
+       ndelay(80);
+       ret = spi_sync_transfer(spi, tr, 2);
+       if (rx && !ret)
+               memcpy(rx, rxbuf, len);
+
+out_free:
+       kfree(headerbuf);
+       kfree(txbuf);
+       kfree(rxbuf);
+
+       return ret;
+}
+
+static int repaper_write_buf(struct spi_device *spi, u8 reg,
+                            const u8 *buf, size_t len)
+{
+       int ret;
+
+       ret = repaper_spi_transfer(spi, 0x70, &reg, NULL, 1);
+       if (ret)
+               return ret;
+
+       return repaper_spi_transfer(spi, 0x72, buf, NULL, len);
+}
+
+static int repaper_write_val(struct spi_device *spi, u8 reg, u8 val)
+{
+       return repaper_write_buf(spi, reg, &val, 1);
+}
+
+static int repaper_read_val(struct spi_device *spi, u8 reg)
+{
+       int ret;
+       u8 val;
+
+       ret = repaper_spi_transfer(spi, 0x70, &reg, NULL, 1);
+       if (ret)
+               return ret;
+
+       ret = repaper_spi_transfer(spi, 0x73, NULL, &val, 1);
+
+       return ret ? ret : val;
+}
+
+static int repaper_read_id(struct spi_device *spi)
+{
+       int ret;
+       u8 id;
+
+       ret = repaper_spi_transfer(spi, 0x71, NULL, &id, 1);
+
+       return ret ? ret : id;
+}
+
+static void repaper_spi_mosi_low(struct spi_device *spi)
+{
+       const u8 buf[1] = { 0 };
+
+       spi_write(spi, buf, 1);
+}
+
+/* pixels on display are numbered from 1 so even is actually bits 1,3,5,... */
+static void repaper_even_pixels(struct repaper_epd *epd, u8 **pp,
+                               const u8 *data, u8 fixed_value, const u8 *mask,
+                               enum repaper_stage stage)
+{
+       unsigned int b;
+
+       for (b = 0; b < (epd->width / 8); b++) {
+               if (data) {
+                       u8 pixels = data[b] & 0xaa;
+                       u8 pixel_mask = 0xff;
+                       u8 p1, p2, p3, p4;
+
+                       if (mask) {
+                               pixel_mask = (mask[b] ^ pixels) & 0xaa;
+                               pixel_mask |= pixel_mask >> 1;
+                       }
+
+                       switch (stage) {
+                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
+                               pixels = 0xaa | ((pixels ^ 0xaa) >> 1);
+                               break;
+                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
+                               pixels = 0x55 + ((pixels ^ 0xaa) >> 1);
+                               break;
+                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
+                               pixels = 0x55 | (pixels ^ 0xaa);
+                               break;
+                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
+                               pixels = 0xaa | (pixels >> 1);
+                               break;
+                       }
+
+                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55);
+                       p1 = (pixels >> 6) & 0x03;
+                       p2 = (pixels >> 4) & 0x03;
+                       p3 = (pixels >> 2) & 0x03;
+                       p4 = (pixels >> 0) & 0x03;
+                       pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6);
+                       *(*pp)++ = pixels;
+               } else {
+                       *(*pp)++ = fixed_value;
+               }
+       }
+}
+
+/* pixels on display are numbered from 1 so odd is actually bits 0,2,4,... */
+static void repaper_odd_pixels(struct repaper_epd *epd, u8 **pp,
+                              const u8 *data, u8 fixed_value, const u8 *mask,
+                              enum repaper_stage stage)
+{
+       unsigned int b;
+
+       for (b = epd->width / 8; b > 0; b--) {
+               if (data) {
+                       u8 pixels = data[b - 1] & 0x55;
+                       u8 pixel_mask = 0xff;
+
+                       if (mask) {
+                               pixel_mask = (mask[b - 1] ^ pixels) & 0x55;
+                               pixel_mask |= pixel_mask << 1;
+                       }
+
+                       switch (stage) {
+                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
+                               pixels = 0xaa | (pixels ^ 0x55);
+                               break;
+                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
+                               pixels = 0x55 + (pixels ^ 0x55);
+                               break;
+                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
+                               pixels = 0x55 | ((pixels ^ 0x55) << 1);
+                               break;
+                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
+                               pixels = 0xaa | pixels;
+                               break;
+                       }
+
+                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55);
+                       *(*pp)++ = pixels;
+               } else {
+                       *(*pp)++ = fixed_value;
+               }
+       }
+}
+
+/* interleave bits: (byte)76543210 -> (16 bit).7.6.5.4.3.2.1 */
+static inline u16 repaper_interleave_bits(u16 value)
+{
+       value = (value | (value << 4)) & 0x0f0f;
+       value = (value | (value << 2)) & 0x3333;
+       value = (value | (value << 1)) & 0x5555;
+
+       return value;
+}
+
+/* pixels on display are numbered from 1 */
+static void repaper_all_pixels(struct repaper_epd *epd, u8 **pp,
+                              const u8 *data, u8 fixed_value, const u8 *mask,
+                              enum repaper_stage stage)
+{
+       unsigned int b;
+
+       for (b = epd->width / 8; b > 0; b--) {
+               if (data) {
+                       u16 pixels = repaper_interleave_bits(data[b - 1]);
+                       u16 pixel_mask = 0xffff;
+
+                       if (mask) {
+                               pixel_mask = repaper_interleave_bits(mask[b - 1]);
+
+                               pixel_mask = (pixel_mask ^ pixels) & 0x5555;
+                               pixel_mask |= pixel_mask << 1;
+                       }
+
+                       switch (stage) {
+                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
+                               pixels = 0xaaaa | (pixels ^ 0x5555);
+                               break;
+                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
+                               pixels = 0x5555 + (pixels ^ 0x5555);
+                               break;
+                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
+                               pixels = 0x5555 | ((pixels ^ 0x5555) << 1);
+                               break;
+                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
+                               pixels = 0xaaaa | pixels;
+                               break;
+                       }
+
+                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x5555);
+                       *(*pp)++ = pixels >> 8;
+                       *(*pp)++ = pixels;
+               } else {
+                       *(*pp)++ = fixed_value;
+                       *(*pp)++ = fixed_value;
+               }
+       }
+}
+
+/* output one line of scan and data bytes to the display */
+static void repaper_one_line(struct repaper_epd *epd, unsigned int line,
+                            const u8 *data, u8 fixed_value, const u8 *mask,
+                            enum repaper_stage stage)
+{
+       u8 *p = epd->line_buffer;
+       unsigned int b;
+
+       repaper_spi_mosi_low(epd->spi);
+
+       if (epd->pre_border_byte)
+               *p++ = 0x00;
+
+       if (epd->middle_scan) {
+               /* data bytes */
+               repaper_odd_pixels(epd, &p, data, fixed_value, mask, stage);
+
+               /* scan line */
+               for (b = epd->bytes_per_scan; b > 0; b--) {
+                       if (line / 4 == b - 1)
+                               *p++ = 0x03 << (2 * (line & 0x03));
+                       else
+                               *p++ = 0x00;
+               }
+
+               /* data bytes */
+               repaper_even_pixels(epd, &p, data, fixed_value, mask, stage);
+       } else {
+               /*
+                * even scan line, but as lines on display are numbered from 1,
+                * line: 1,3,5,...
+                */
+               for (b = 0; b < epd->bytes_per_scan; b++) {
+                       if (0 != (line & 0x01) && line / 8 == b)
+                               *p++ = 0xc0 >> (line & 0x06);
+                       else
+                               *p++ = 0x00;
+               }
+
+               /* data bytes */
+               repaper_all_pixels(epd, &p, data, fixed_value, mask, stage);
+
+               /*
+                * odd scan line, but as lines on display are numbered from 1,
+                * line: 0,2,4,6,...
+                */
+               for (b = epd->bytes_per_scan; b > 0; b--) {
+                       if (0 == (line & 0x01) && line / 8 == b - 1)
+                               *p++ = 0x03 << (line & 0x06);
+                       else
+                               *p++ = 0x00;
+               }
+       }
+
+       switch (epd->border_byte) {
+       case REPAPER_BORDER_BYTE_NONE:
+               break;
+
+       case REPAPER_BORDER_BYTE_ZERO:
+               *p++ = 0x00;
+               break;
+
+       case REPAPER_BORDER_BYTE_SET:
+               switch (stage) {
+               case REPAPER_COMPENSATE:
+               case REPAPER_WHITE:
+               case REPAPER_INVERSE:
+                       *p++ = 0x00;
+                       break;
+               case REPAPER_NORMAL:
+                       *p++ = 0xaa;
+                       break;
+               }
+               break;
+       }
+
+       repaper_write_buf(epd->spi, 0x0a, epd->line_buffer,
+                         p - epd->line_buffer);
+
+       /* Output data to panel */
+       repaper_write_val(epd->spi, 0x02, 0x07);
+
+       repaper_spi_mosi_low(epd->spi);
+}
+
+static void repaper_frame_fixed(struct repaper_epd *epd, u8 fixed_value,
+                               enum repaper_stage stage)
+{
+       unsigned int line;
+
+       for (line = 0; line < epd->height; line++)
+               repaper_one_line(epd, line, NULL, fixed_value, NULL, stage);
+}
+
+static void repaper_frame_data(struct repaper_epd *epd, const u8 *image,
+                              const u8 *mask, enum repaper_stage stage)
+{
+       unsigned int line;
+
+       if (!mask) {
+               for (line = 0; line < epd->height; line++) {
+                       repaper_one_line(epd, line,
+                                        &image[line * (epd->width / 8)],
+                                        0, NULL, stage);
+               }
+       } else {
+               for (line = 0; line < epd->height; line++) {
+                       size_t n = line * epd->width / 8;
+
+                       repaper_one_line(epd, line, &image[n], 0, &mask[n],
+                                        stage);
+               }
+       }
+}
+
+static void repaper_frame_fixed_repeat(struct repaper_epd *epd, u8 fixed_value,
+                                      enum repaper_stage stage)
+{
+       u64 start = local_clock();
+       u64 end = start + (epd->factored_stage_time * 1000 * 1000);
+
+       do {
+               repaper_frame_fixed(epd, fixed_value, stage);
+       } while (local_clock() < end);
+}
+
+static void repaper_frame_data_repeat(struct repaper_epd *epd, const u8 *image,
+                                     const u8 *mask, enum repaper_stage stage)
+{
+       u64 start = local_clock();
+       u64 end = start + (epd->factored_stage_time * 1000 * 1000);
+
+       do {
+               repaper_frame_data(epd, image, mask, stage);
+       } while (local_clock() < end);
+}
+
+static void repaper_get_temperature(struct repaper_epd *epd)
+{
+       int ret, temperature = 0;
+       unsigned int factor10x;
+
+       if (!epd->thermal)
+               return;
+
+       ret = thermal_zone_get_temp(epd->thermal, &temperature);
+       if (ret) {
+               DRM_DEV_ERROR(&epd->spi->dev, "Failed to get temperature (%d)\n", ret);
+               return;
+       }
+
+       temperature /= 1000;
+
+       if (temperature <= -10)
+               factor10x = 170;
+       else if (temperature <= -5)
+               factor10x = 120;
+       else if (temperature <= 5)
+               factor10x = 80;
+       else if (temperature <= 10)
+               factor10x = 40;
+       else if (temperature <= 15)
+               factor10x = 30;
+       else if (temperature <= 20)
+               factor10x = 20;
+       else if (temperature <= 40)
+               factor10x = 10;
+       else
+               factor10x = 7;
+
+       epd->factored_stage_time = epd->stage_time * factor10x / 10;
+}
+
+static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
+{
+       u8 *gray8 = buf, *mono = buf;
+       int y, xb, i;
+
+       for (y = 0; y < height; y++)
+               for (xb = 0; xb < width / 8; xb++) {
+                       u8 byte = 0x00;
+
+                       for (i = 0; i < 8; i++) {
+                               int x = xb * 8 + i;
+
+                               byte >>= 1;
+                               if (gray8[y * width + x] >> 7)
+                                       byte |= BIT(7);
+                       }
+                       *mono++ = byte;
+               }
+}
+
+static int repaper_fb_dirty(struct drm_framebuffer *fb)
+{
+       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+       struct repaper_epd *epd = drm_to_epd(fb->dev);
+       struct drm_rect clip;
+       int idx, ret = 0;
+       u8 *buf = NULL;
+
+       if (!epd->enabled)
+               return 0;
+
+       if (!drm_dev_enter(fb->dev, &idx))
+               return -ENODEV;
+
+       /* repaper can't do partial updates */
+       clip.x1 = 0;
+       clip.x2 = fb->width;
+       clip.y1 = 0;
+       clip.y2 = fb->height;
+
+       repaper_get_temperature(epd);
+
+       DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id,
+                 epd->factored_stage_time);
+
+       buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto out_exit;
+       }
+
+       if (import_attach) {
+               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
+                                              DMA_FROM_DEVICE);
+               if (ret)
+                       goto out_free;
+       }
+
+       drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
+
+       if (import_attach) {
+               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
+                                            DMA_FROM_DEVICE);
+               if (ret)
+                       goto out_free;
+       }
+
+       repaper_gray8_to_mono_reversed(buf, fb->width, fb->height);
+
+       if (epd->partial) {
+               repaper_frame_data_repeat(epd, buf, epd->current_frame,
+                                         REPAPER_NORMAL);
+       } else if (epd->cleared) {
+               repaper_frame_data_repeat(epd, epd->current_frame, NULL,
+                                         REPAPER_COMPENSATE);
+               repaper_frame_data_repeat(epd, epd->current_frame, NULL,
+                                         REPAPER_WHITE);
+               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE);
+               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL);
+
+               epd->partial = true;
+       } else {
+               /* Clear display (anything -> white) */
+               repaper_frame_fixed_repeat(epd, 0xff, REPAPER_COMPENSATE);
+               repaper_frame_fixed_repeat(epd, 0xff, REPAPER_WHITE);
+               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_INVERSE);
+               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_NORMAL);
+
+               /* Assuming a clear (white) screen output an image */
+               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_COMPENSATE);
+               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_WHITE);
+               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE);
+               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL);
+
+               epd->cleared = true;
+               epd->partial = true;
+       }
+
+       memcpy(epd->current_frame, buf, fb->width * fb->height / 8);
+
+       /*
+        * An extra frame write is needed if pixels are set in the bottom line,
+        * or else grey lines rises up from the pixels
+        */
+       if (epd->pre_border_byte) {
+               unsigned int x;
+
+               for (x = 0; x < (fb->width / 8); x++)
+                       if (buf[x + (fb->width * (fb->height - 1) / 8)]) {
+                               repaper_frame_data_repeat(epd, buf,
+                                                         epd->current_frame,
+                                                         REPAPER_NORMAL);
+                               break;
+                       }
+       }
+
+out_free:
+       kfree(buf);
+out_exit:
+       drm_dev_exit(idx);
+
+       return ret;
+}
+
+static void power_off(struct repaper_epd *epd)
+{
+       /* Turn off power and all signals */
+       gpiod_set_value_cansleep(epd->reset, 0);
+       gpiod_set_value_cansleep(epd->panel_on, 0);
+       if (epd->border)
+               gpiod_set_value_cansleep(epd->border, 0);
+
+       /* Ensure SPI MOSI and CLOCK are Low before CS Low */
+       repaper_spi_mosi_low(epd->spi);
+
+       /* Discharge pulse */
+       gpiod_set_value_cansleep(epd->discharge, 1);
+       msleep(150);
+       gpiod_set_value_cansleep(epd->discharge, 0);
+}
+
+static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe,
+                               struct drm_crtc_state *crtc_state,
+                               struct drm_plane_state *plane_state)
+{
+       struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev);
+       struct spi_device *spi = epd->spi;
+       struct device *dev = &spi->dev;
+       bool dc_ok = false;
+       int i, ret, idx;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       /* Power up sequence */
+       gpiod_set_value_cansleep(epd->reset, 0);
+       gpiod_set_value_cansleep(epd->panel_on, 0);
+       gpiod_set_value_cansleep(epd->discharge, 0);
+       if (epd->border)
+               gpiod_set_value_cansleep(epd->border, 0);
+       repaper_spi_mosi_low(spi);
+       usleep_range(5000, 10000);
+
+       gpiod_set_value_cansleep(epd->panel_on, 1);
+       /*
+        * This delay comes from the repaper.org userspace driver, it's not
+        * mentioned in the datasheet.
+        */
+       usleep_range(10000, 15000);
+       gpiod_set_value_cansleep(epd->reset, 1);
+       if (epd->border)
+               gpiod_set_value_cansleep(epd->border, 1);
+       usleep_range(5000, 10000);
+       gpiod_set_value_cansleep(epd->reset, 0);
+       usleep_range(5000, 10000);
+       gpiod_set_value_cansleep(epd->reset, 1);
+       usleep_range(5000, 10000);
+
+       /* Wait for COG to become ready */
+       for (i = 100; i > 0; i--) {
+               if (!gpiod_get_value_cansleep(epd->busy))
+                       break;
+
+               usleep_range(10, 100);
+       }
+
+       if (!i) {
+               DRM_DEV_ERROR(dev, "timeout waiting for panel to become ready.\n");
+               power_off(epd);
+               goto out_exit;
+       }
+
+       repaper_read_id(spi);
+       ret = repaper_read_id(spi);
+       if (ret != REPAPER_RID_G2_COG_ID) {
+               if (ret < 0)
+                       dev_err(dev, "failed to read chip (%d)\n", ret);
+               else
+                       dev_err(dev, "wrong COG ID 0x%02x\n", ret);
+               power_off(epd);
+               goto out_exit;
+       }
+
+       /* Disable OE */
+       repaper_write_val(spi, 0x02, 0x40);
+
+       ret = repaper_read_val(spi, 0x0f);
+       if (ret < 0 || !(ret & 0x80)) {
+               if (ret < 0)
+                       DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret);
+               else
+                       DRM_DEV_ERROR(dev, "panel is reported broken\n");
+               power_off(epd);
+               goto out_exit;
+       }
+
+       /* Power saving mode */
+       repaper_write_val(spi, 0x0b, 0x02);
+       /* Channel select */
+       repaper_write_buf(spi, 0x01, epd->channel_select, 8);
+       /* High power mode osc */
+       repaper_write_val(spi, 0x07, 0xd1);
+       /* Power setting */
+       repaper_write_val(spi, 0x08, 0x02);
+       /* Vcom level */
+       repaper_write_val(spi, 0x09, 0xc2);
+       /* Power setting */
+       repaper_write_val(spi, 0x04, 0x03);
+       /* Driver latch on */
+       repaper_write_val(spi, 0x03, 0x01);
+       /* Driver latch off */
+       repaper_write_val(spi, 0x03, 0x00);
+       usleep_range(5000, 10000);
+
+       /* Start chargepump */
+       for (i = 0; i < 4; ++i) {
+               /* Charge pump positive voltage on - VGH/VDL on */
+               repaper_write_val(spi, 0x05, 0x01);
+               msleep(240);
+
+               /* Charge pump negative voltage on - VGL/VDL on */
+               repaper_write_val(spi, 0x05, 0x03);
+               msleep(40);
+
+               /* Charge pump Vcom on - Vcom driver on */
+               repaper_write_val(spi, 0x05, 0x0f);
+               msleep(40);
+
+               /* check DC/DC */
+               ret = repaper_read_val(spi, 0x0f);
+               if (ret < 0) {
+                       DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret);
+                       power_off(epd);
+                       goto out_exit;
+               }
+
+               if (ret & 0x40) {
+                       dc_ok = true;
+                       break;
+               }
+       }
+
+       if (!dc_ok) {
+               DRM_DEV_ERROR(dev, "dc/dc failed\n");
+               power_off(epd);
+               goto out_exit;
+       }
+
+       /*
+        * Output enable to disable
+        * The userspace driver sets this to 0x04, but the datasheet says 0x06
+        */
+       repaper_write_val(spi, 0x02, 0x04);
+
+       epd->enabled = true;
+       epd->partial = false;
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev);
+       struct spi_device *spi = epd->spi;
+       unsigned int line;
+
+       /*
+        * This callback is not protected by drm_dev_enter/exit since we want to
+        * turn off the display on regular driver unload. It's highly unlikely
+        * that the underlying SPI controller is gone should this be called after
+        * unplug.
+        */
+
+       if (!epd->enabled)
+               return;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       epd->enabled = false;
+
+       /* Nothing frame */
+       for (line = 0; line < epd->height; line++)
+               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
+                                REPAPER_COMPENSATE);
+
+       /* 2.7" */
+       if (epd->border) {
+               /* Dummy line */
+               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
+                                REPAPER_COMPENSATE);
+               msleep(25);
+               gpiod_set_value_cansleep(epd->border, 0);
+               msleep(200);
+               gpiod_set_value_cansleep(epd->border, 1);
+       } else {
+               /* Border dummy line */
+               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
+                                REPAPER_NORMAL);
+               msleep(200);
+       }
+
+       /* not described in datasheet */
+       repaper_write_val(spi, 0x0b, 0x00);
+       /* Latch reset turn on */
+       repaper_write_val(spi, 0x03, 0x01);
+       /* Power off charge pump Vcom */
+       repaper_write_val(spi, 0x05, 0x03);
+       /* Power off charge pump neg voltage */
+       repaper_write_val(spi, 0x05, 0x01);
+       msleep(120);
+       /* Discharge internal */
+       repaper_write_val(spi, 0x04, 0x80);
+       /* turn off all charge pumps */
+       repaper_write_val(spi, 0x05, 0x00);
+       /* Turn off osc */
+       repaper_write_val(spi, 0x07, 0x01);
+       msleep(50);
+
+       power_off(epd);
+}
+
+static void repaper_pipe_update(struct drm_simple_display_pipe *pipe,
+                               struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               repaper_fb_dirty(state->fb);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
+static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = {
+       .enable = repaper_pipe_enable,
+       .disable = repaper_pipe_disable,
+       .update = repaper_pipe_update,
+       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static int repaper_connector_get_modes(struct drm_connector *connector)
+{
+       struct repaper_epd *epd = drm_to_epd(connector->dev);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, epd->mode);
+       if (!mode) {
+               DRM_ERROR("Failed to duplicate mode\n");
+               return 0;
+       }
+
+       drm_mode_set_name(mode);
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+       drm_mode_probed_add(connector, mode);
+
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+
+       return 1;
+}
+
+static const struct drm_connector_helper_funcs repaper_connector_hfuncs = {
+       .get_modes = repaper_connector_get_modes,
+};
+
+static const struct drm_connector_funcs repaper_connector_funcs = {
+       .reset = drm_atomic_helper_connector_reset,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_mode_config_funcs repaper_mode_config_funcs = {
+       .fb_create = drm_gem_fb_create_with_dirty,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+};
+
+static void repaper_release(struct drm_device *drm)
+{
+       struct repaper_epd *epd = drm_to_epd(drm);
+
+       DRM_DEBUG_DRIVER("\n");
+
+       drm_mode_config_cleanup(drm);
+       drm_dev_fini(drm);
+       kfree(epd);
+}
+
+static const uint32_t repaper_formats[] = {
+       DRM_FORMAT_XRGB8888,
+};
+
+static const struct drm_display_mode repaper_e1144cs021_mode = {
+       DRM_SIMPLE_MODE(128, 96, 29, 22),
+};
+
+static const u8 repaper_e1144cs021_cs[] = { 0x00, 0x00, 0x00, 0x00,
+                                           0x00, 0x0f, 0xff, 0x00 };
+
+static const struct drm_display_mode repaper_e1190cs021_mode = {
+       DRM_SIMPLE_MODE(144, 128, 36, 32),
+};
+
+static const u8 repaper_e1190cs021_cs[] = { 0x00, 0x00, 0x00, 0x03,
+                                           0xfc, 0x00, 0x00, 0xff };
+
+static const struct drm_display_mode repaper_e2200cs021_mode = {
+       DRM_SIMPLE_MODE(200, 96, 46, 22),
+};
+
+static const u8 repaper_e2200cs021_cs[] = { 0x00, 0x00, 0x00, 0x00,
+                                           0x01, 0xff, 0xe0, 0x00 };
+
+static const struct drm_display_mode repaper_e2271cs021_mode = {
+       DRM_SIMPLE_MODE(264, 176, 57, 38),
+};
+
+static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f,
+                                           0xff, 0xfe, 0x00, 0x00 };
+
+DEFINE_DRM_GEM_CMA_FOPS(repaper_fops);
+
+static struct drm_driver repaper_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &repaper_fops,
+       .release                = repaper_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .name                   = "repaper",
+       .desc                   = "Pervasive Displays RePaper e-ink panels",
+       .date                   = "20170405",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id repaper_of_match[] = {
+       { .compatible = "pervasive,e1144cs021", .data = (void *)E1144CS021 },
+       { .compatible = "pervasive,e1190cs021", .data = (void *)E1190CS021 },
+       { .compatible = "pervasive,e2200cs021", .data = (void *)E2200CS021 },
+       { .compatible = "pervasive,e2271cs021", .data = (void *)E2271CS021 },
+       {},
+};
+MODULE_DEVICE_TABLE(of, repaper_of_match);
+
+static const struct spi_device_id repaper_id[] = {
+       { "e1144cs021", E1144CS021 },
+       { "e1190cs021", E1190CS021 },
+       { "e2200cs021", E2200CS021 },
+       { "e2271cs021", E2271CS021 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, repaper_id);
+
+static int repaper_probe(struct spi_device *spi)
+{
+       const struct drm_display_mode *mode;
+       const struct spi_device_id *spi_id;
+       const struct of_device_id *match;
+       struct device *dev = &spi->dev;
+       enum repaper_model model;
+       const char *thermal_zone;
+       struct repaper_epd *epd;
+       size_t line_buffer_size;
+       struct drm_device *drm;
+       int ret;
+
+       match = of_match_device(repaper_of_match, dev);
+       if (match) {
+               model = (enum repaper_model)match->data;
+       } else {
+               spi_id = spi_get_device_id(spi);
+               model = spi_id->driver_data;
+       }
+
+       /* The SPI device is used to allocate dma memory */
+       if (!dev->coherent_dma_mask) {
+               ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+               if (ret) {
+                       dev_warn(dev, "Failed to set dma mask %d\n", ret);
+                       return ret;
+               }
+       }
+
+       epd = kzalloc(sizeof(*epd), GFP_KERNEL);
+       if (!epd)
+               return -ENOMEM;
+
+       drm = &epd->drm;
+
+       ret = devm_drm_dev_init(dev, drm, &repaper_driver);
+       if (ret) {
+               kfree(epd);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+       drm->mode_config.funcs = &repaper_mode_config_funcs;
+
+       epd->spi = spi;
+
+       epd->panel_on = devm_gpiod_get(dev, "panel-on", GPIOD_OUT_LOW);
+       if (IS_ERR(epd->panel_on)) {
+               ret = PTR_ERR(epd->panel_on);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev, "Failed to get gpio 'panel-on'\n");
+               return ret;
+       }
+
+       epd->discharge = devm_gpiod_get(dev, "discharge", GPIOD_OUT_LOW);
+       if (IS_ERR(epd->discharge)) {
+               ret = PTR_ERR(epd->discharge);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev, "Failed to get gpio 'discharge'\n");
+               return ret;
+       }
+
+       epd->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(epd->reset)) {
+               ret = PTR_ERR(epd->reset);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return ret;
+       }
+
+       epd->busy = devm_gpiod_get(dev, "busy", GPIOD_IN);
+       if (IS_ERR(epd->busy)) {
+               ret = PTR_ERR(epd->busy);
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(dev, "Failed to get gpio 'busy'\n");
+               return ret;
+       }
+
+       if (!device_property_read_string(dev, "pervasive,thermal-zone",
+                                        &thermal_zone)) {
+               epd->thermal = thermal_zone_get_zone_by_name(thermal_zone);
+               if (IS_ERR(epd->thermal)) {
+                       DRM_DEV_ERROR(dev, "Failed to get thermal zone: %s\n", thermal_zone);
+                       return PTR_ERR(epd->thermal);
+               }
+       }
+
+       switch (model) {
+       case E1144CS021:
+               mode = &repaper_e1144cs021_mode;
+               epd->channel_select = repaper_e1144cs021_cs;
+               epd->stage_time = 480;
+               epd->bytes_per_scan = 96 / 4;
+               epd->middle_scan = true; /* data-scan-data */
+               epd->pre_border_byte = false;
+               epd->border_byte = REPAPER_BORDER_BYTE_ZERO;
+               break;
+
+       case E1190CS021:
+               mode = &repaper_e1190cs021_mode;
+               epd->channel_select = repaper_e1190cs021_cs;
+               epd->stage_time = 480;
+               epd->bytes_per_scan = 128 / 4 / 2;
+               epd->middle_scan = false; /* scan-data-scan */
+               epd->pre_border_byte = false;
+               epd->border_byte = REPAPER_BORDER_BYTE_SET;
+               break;
+
+       case E2200CS021:
+               mode = &repaper_e2200cs021_mode;
+               epd->channel_select = repaper_e2200cs021_cs;
+               epd->stage_time = 480;
+               epd->bytes_per_scan = 96 / 4;
+               epd->middle_scan = true; /* data-scan-data */
+               epd->pre_border_byte = true;
+               epd->border_byte = REPAPER_BORDER_BYTE_NONE;
+               break;
+
+       case E2271CS021:
+               epd->border = devm_gpiod_get(dev, "border", GPIOD_OUT_LOW);
+               if (IS_ERR(epd->border)) {
+                       ret = PTR_ERR(epd->border);
+                       if (ret != -EPROBE_DEFER)
+                               DRM_DEV_ERROR(dev, "Failed to get gpio 'border'\n");
+                       return ret;
+               }
+
+               mode = &repaper_e2271cs021_mode;
+               epd->channel_select = repaper_e2271cs021_cs;
+               epd->stage_time = 630;
+               epd->bytes_per_scan = 176 / 4;
+               epd->middle_scan = true; /* data-scan-data */
+               epd->pre_border_byte = true;
+               epd->border_byte = REPAPER_BORDER_BYTE_NONE;
+               break;
+
+       default:
+               return -ENODEV;
+       }
+
+       epd->mode = mode;
+       epd->width = mode->hdisplay;
+       epd->height = mode->vdisplay;
+       epd->factored_stage_time = epd->stage_time;
+
+       line_buffer_size = 2 * epd->width / 8 + epd->bytes_per_scan + 2;
+       epd->line_buffer = devm_kzalloc(dev, line_buffer_size, GFP_KERNEL);
+       if (!epd->line_buffer)
+               return -ENOMEM;
+
+       epd->current_frame = devm_kzalloc(dev, epd->width * epd->height / 8,
+                                         GFP_KERNEL);
+       if (!epd->current_frame)
+               return -ENOMEM;
+
+       drm->mode_config.min_width = mode->hdisplay;
+       drm->mode_config.max_width = mode->hdisplay;
+       drm->mode_config.min_height = mode->vdisplay;
+       drm->mode_config.max_height = mode->vdisplay;
+
+       drm_connector_helper_add(&epd->connector, &repaper_connector_hfuncs);
+       ret = drm_connector_init(drm, &epd->connector, &repaper_connector_funcs,
+                                DRM_MODE_CONNECTOR_SPI);
+       if (ret)
+               return ret;
+
+       ret = drm_simple_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs,
+                                          repaper_formats, ARRAY_SIZE(repaper_formats),
+                                          NULL, &epd->connector);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int repaper_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void repaper_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver repaper_spi_driver = {
+       .driver = {
+               .name = "repaper",
+               .owner = THIS_MODULE,
+               .of_match_table = repaper_of_match,
+       },
+       .id_table = repaper_id,
+       .probe = repaper_probe,
+       .remove = repaper_remove,
+       .shutdown = repaper_shutdown,
+};
+module_spi_driver(repaper_spi_driver);
+
+MODULE_DESCRIPTION("Pervasive Displays RePaper DRM driver");
+MODULE_AUTHOR("Noralf Trønnes");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
new file mode 100644 (file)
index 0000000..3cc21a1
--- /dev/null
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DRM driver for Sitronix ST7586 panels
+ *
+ * Copyright 2017 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
+
+/* controller-specific commands */
+#define ST7586_DISP_MODE_GRAY  0x38
+#define ST7586_DISP_MODE_MONO  0x39
+#define ST7586_ENABLE_DDRAM    0x3a
+#define ST7586_SET_DISP_DUTY   0xb0
+#define ST7586_SET_PART_DISP   0xb4
+#define ST7586_SET_NLINE_INV   0xb5
+#define ST7586_SET_VOP         0xc0
+#define ST7586_SET_BIAS_SYSTEM 0xc3
+#define ST7586_SET_BOOST_LEVEL 0xc4
+#define ST7586_SET_VOP_OFFSET  0xc7
+#define ST7586_ENABLE_ANALOG   0xd0
+#define ST7586_AUTO_READ_CTRL  0xd7
+#define ST7586_OTP_RW_CTRL     0xe0
+#define ST7586_OTP_CTRL_OUT    0xe1
+#define ST7586_OTP_READ                0xe3
+
+#define ST7586_DISP_CTRL_MX    BIT(6)
+#define ST7586_DISP_CTRL_MY    BIT(7)
+
+/*
+ * The ST7586 controller has an unusual pixel format where 2bpp grayscale is
+ * packed 3 pixels per byte with the first two pixels using 3 bits and the 3rd
+ * pixel using only 2 bits.
+ *
+ * |  D7  |  D6  |  D5  ||      |      || 2bpp |
+ * | (D4) | (D3) | (D2) ||  D1  |  D0  || GRAY |
+ * +------+------+------++------+------++------+
+ * |  1   |  1   |  1   ||  1   |  1   || 0  0 | black
+ * |  1   |  0   |  0   ||  1   |  0   || 0  1 | dark gray
+ * |  0   |  1   |  0   ||  0   |  1   || 1  0 | light gray
+ * |  0   |  0   |  0   ||  0   |  0   || 1  1 | white
+ */
+
+static const u8 st7586_lookup[] = { 0x7, 0x4, 0x2, 0x0 };
+
+static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
+                                      struct drm_framebuffer *fb,
+                                      struct drm_rect *clip)
+{
+       size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1);
+       unsigned int x, y;
+       u8 *src, *buf, val;
+
+       buf = kmalloc(len, GFP_KERNEL);
+       if (!buf)
+               return;
+
+       drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, clip);
+       src = buf;
+
+       for (y = clip->y1; y < clip->y2; y++) {
+               for (x = clip->x1; x < clip->x2; x += 3) {
+                       val = st7586_lookup[*src++ >> 6] << 5;
+                       val |= st7586_lookup[*src++ >> 6] << 2;
+                       val |= st7586_lookup[*src++ >> 6] >> 1;
+                       *dst++ = val;
+               }
+       }
+
+       kfree(buf);
+}
+
+static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
+                          struct drm_rect *clip)
+{
+       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+       void *src = cma_obj->vaddr;
+       int ret = 0;
+
+       if (import_attach) {
+               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
+                                              DMA_FROM_DEVICE);
+               if (ret)
+                       return ret;
+       }
+
+       st7586_xrgb8888_to_gray332(dst, src, fb, clip);
+
+       if (import_attach)
+               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
+                                            DMA_FROM_DEVICE);
+
+       return ret;
+}
+
+static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       int start, end, idx, ret = 0;
+
+       if (!dbidev->enabled)
+               return;
+
+       if (!drm_dev_enter(fb->dev, &idx))
+               return;
+
+       /* 3 pixels per byte, so grow clip to nearest multiple of 3 */
+       rect->x1 = rounddown(rect->x1, 3);
+       rect->x2 = roundup(rect->x2, 3);
+
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
+
+       ret = st7586_buf_copy(dbidev->tx_buf, fb, rect);
+       if (ret)
+               goto err_msg;
+
+       /* Pixels are packed 3 per byte */
+       start = rect->x1 / 3;
+       end = rect->x2 / 3;
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS,
+                        (start >> 8) & 0xFF, start & 0xFF,
+                        (end >> 8) & 0xFF, (end - 1) & 0xFF);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS,
+                        (rect->y1 >> 8) & 0xFF, rect->y1 & 0xFF,
+                        (rect->y2 >> 8) & 0xFF, (rect->y2 - 1) & 0xFF);
+
+       ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START,
+                                  (u8 *)dbidev->tx_buf,
+                                  (end - start) * (rect->y2 - rect->y1));
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
+
+       drm_dev_exit(idx);
+}
+
+static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
+                              struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               st7586_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
+static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
+                              struct drm_crtc_state *crtc_state,
+                              struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
+       int idx, ret;
+       u8 addr_mode;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       ret = mipi_dbi_poweron_reset(dbidev);
+       if (ret)
+               goto out_exit;
+
+       mipi_dbi_command(dbi, ST7586_AUTO_READ_CTRL, 0x9f);
+       mipi_dbi_command(dbi, ST7586_OTP_RW_CTRL, 0x00);
+
+       msleep(10);
+
+       mipi_dbi_command(dbi, ST7586_OTP_READ);
+
+       msleep(20);
+
+       mipi_dbi_command(dbi, ST7586_OTP_CTRL_OUT);
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+       msleep(50);
+
+       mipi_dbi_command(dbi, ST7586_SET_VOP_OFFSET, 0x00);
+       mipi_dbi_command(dbi, ST7586_SET_VOP, 0xe3, 0x00);
+       mipi_dbi_command(dbi, ST7586_SET_BIAS_SYSTEM, 0x02);
+       mipi_dbi_command(dbi, ST7586_SET_BOOST_LEVEL, 0x04);
+       mipi_dbi_command(dbi, ST7586_ENABLE_ANALOG, 0x1d);
+       mipi_dbi_command(dbi, ST7586_SET_NLINE_INV, 0x00);
+       mipi_dbi_command(dbi, ST7586_DISP_MODE_GRAY);
+       mipi_dbi_command(dbi, ST7586_ENABLE_DDRAM, 0x02);
+
+       switch (dbidev->rotation) {
+       default:
+               addr_mode = 0x00;
+               break;
+       case 90:
+               addr_mode = ST7586_DISP_CTRL_MY;
+               break;
+       case 180:
+               addr_mode = ST7586_DISP_CTRL_MX | ST7586_DISP_CTRL_MY;
+               break;
+       case 270:
+               addr_mode = ST7586_DISP_CTRL_MX;
+               break;
+       }
+       mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+
+       mipi_dbi_command(dbi, ST7586_SET_DISP_DUTY, 0x7f);
+       mipi_dbi_command(dbi, ST7586_SET_PART_DISP, 0xa0);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PARTIAL_AREA, 0x00, 0x00, 0x00, 0x77);
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_INVERT_MODE);
+
+       msleep(100);
+
+       dbidev->enabled = true;
+       st7586_fb_dirty(fb, &rect);
+
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+
+       /*
+        * This callback is not protected by drm_dev_enter/exit since we want to
+        * turn off the display on regular driver unload. It's highly unlikely
+        * that the underlying SPI controller is gone should this be called after
+        * unplug.
+        */
+
+       DRM_DEBUG_KMS("\n");
+
+       if (!dbidev->enabled)
+               return;
+
+       mipi_dbi_command(&dbidev->dbi, MIPI_DCS_SET_DISPLAY_OFF);
+       dbidev->enabled = false;
+}
+
+static const u32 st7586_formats[] = {
+       DRM_FORMAT_XRGB8888,
+};
+
+static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
+       .enable         = st7586_pipe_enable,
+       .disable        = st7586_pipe_disable,
+       .update         = st7586_pipe_update,
+       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode st7586_mode = {
+       DRM_SIMPLE_MODE(178, 128, 37, 27),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(st7586_fops);
+
+static struct drm_driver st7586_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &st7586_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .debugfs_init           = mipi_dbi_debugfs_init,
+       .name                   = "st7586",
+       .desc                   = "Sitronix ST7586",
+       .date                   = "20170801",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id st7586_of_match[] = {
+       { .compatible = "lego,ev3-lcd" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, st7586_of_match);
+
+static const struct spi_device_id st7586_id[] = {
+       { "ev3-lcd", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, st7586_id);
+
+static int st7586_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct mipi_dbi *dbi;
+       struct gpio_desc *a0;
+       u32 rotation = 0;
+       size_t bufsize;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       dbi = &dbidev->dbi;
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &st7586_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       bufsize = (st7586_mode.vdisplay + 2) / 3 * st7586_mode.hdisplay;
+
+       dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dbi->reset)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return PTR_ERR(dbi->reset);
+       }
+
+       a0 = devm_gpiod_get(dev, "a0", GPIOD_OUT_LOW);
+       if (IS_ERR(a0)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'a0'\n");
+               return PTR_ERR(a0);
+       }
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, dbi, a0);
+       if (ret)
+               return ret;
+
+       /* Cannot read from this controller via SPI */
+       dbi->read_commands = NULL;
+
+       ret = mipi_dbi_dev_init_with_formats(dbidev, &st7586_pipe_funcs,
+                                            st7586_formats, ARRAY_SIZE(st7586_formats),
+                                            &st7586_mode, rotation, bufsize);
+       if (ret)
+               return ret;
+
+       /*
+        * we are using 8-bit data, so we are not actually swapping anything,
+        * but setting mipi->swap_bytes makes mipi_dbi_typec3_command() do the
+        * right thing and not use 16-bit transfers (which results in swapped
+        * bytes on little-endian systems and causes out of order data to be
+        * sent to the display).
+        */
+       dbi->swap_bytes = true;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int st7586_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void st7586_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver st7586_spi_driver = {
+       .driver = {
+               .name = "st7586",
+               .owner = THIS_MODULE,
+               .of_match_table = st7586_of_match,
+       },
+       .id_table = st7586_id,
+       .probe = st7586_probe,
+       .remove = st7586_remove,
+       .shutdown = st7586_shutdown,
+};
+module_spi_driver(st7586_spi_driver);
+
+MODULE_DESCRIPTION("Sitronix ST7586 DRM driver");
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
new file mode 100644 (file)
index 0000000..3f4487c
--- /dev/null
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DRM driver for Sitronix ST7735R panels
+ *
+ * Copyright 2017 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+
+#define ST7735R_FRMCTR1                0xb1
+#define ST7735R_FRMCTR2                0xb2
+#define ST7735R_FRMCTR3                0xb3
+#define ST7735R_INVCTR         0xb4
+#define ST7735R_PWCTR1         0xc0
+#define ST7735R_PWCTR2         0xc1
+#define ST7735R_PWCTR3         0xc2
+#define ST7735R_PWCTR4         0xc3
+#define ST7735R_PWCTR5         0xc4
+#define ST7735R_VMCTR1         0xc5
+#define ST7735R_GAMCTRP1       0xe0
+#define ST7735R_GAMCTRN1       0xe1
+
+#define ST7735R_MY     BIT(7)
+#define ST7735R_MX     BIT(6)
+#define ST7735R_MV     BIT(5)
+
+static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
+                                     struct drm_crtc_state *crtc_state,
+                                     struct drm_plane_state *plane_state)
+{
+       struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+       struct mipi_dbi *dbi = &dbidev->dbi;
+       int ret, idx;
+       u8 addr_mode;
+
+       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+               return;
+
+       DRM_DEBUG_KMS("\n");
+
+       ret = mipi_dbi_poweron_reset(dbidev);
+       if (ret)
+               goto out_exit;
+
+       msleep(150);
+
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+       msleep(500);
+
+       mipi_dbi_command(dbi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d);
+       mipi_dbi_command(dbi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d);
+       mipi_dbi_command(dbi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c,
+                        0x2d);
+       mipi_dbi_command(dbi, ST7735R_INVCTR, 0x07);
+       mipi_dbi_command(dbi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84);
+       mipi_dbi_command(dbi, ST7735R_PWCTR2, 0xc5);
+       mipi_dbi_command(dbi, ST7735R_PWCTR3, 0x0a, 0x00);
+       mipi_dbi_command(dbi, ST7735R_PWCTR4, 0x8a, 0x2a);
+       mipi_dbi_command(dbi, ST7735R_PWCTR5, 0x8a, 0xee);
+       mipi_dbi_command(dbi, ST7735R_VMCTR1, 0x0e);
+       mipi_dbi_command(dbi, MIPI_DCS_EXIT_INVERT_MODE);
+       switch (dbidev->rotation) {
+       default:
+               addr_mode = ST7735R_MX | ST7735R_MY;
+               break;
+       case 90:
+               addr_mode = ST7735R_MX | ST7735R_MV;
+               break;
+       case 180:
+               addr_mode = 0;
+               break;
+       case 270:
+               addr_mode = ST7735R_MY | ST7735R_MV;
+               break;
+       }
+       mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
+                        MIPI_DCS_PIXEL_FMT_16BIT);
+       mipi_dbi_command(dbi, ST7735R_GAMCTRP1, 0x02, 0x1c, 0x07, 0x12, 0x37,
+                        0x32, 0x29, 0x2d, 0x29, 0x25, 0x2b, 0x39, 0x00, 0x01,
+                        0x03, 0x10);
+       mipi_dbi_command(dbi, ST7735R_GAMCTRN1, 0x03, 0x1d, 0x07, 0x06, 0x2e,
+                        0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00,
+                        0x02, 0x10);
+       mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+
+       msleep(100);
+
+       mipi_dbi_command(dbi, MIPI_DCS_ENTER_NORMAL_MODE);
+
+       msleep(20);
+
+       mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+out_exit:
+       drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = {
+       .enable         = jd_t18003_t01_pipe_enable,
+       .disable        = mipi_dbi_pipe_disable,
+       .update         = mipi_dbi_pipe_update,
+       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode jd_t18003_t01_mode = {
+       DRM_SIMPLE_MODE(128, 160, 28, 35),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops);
+
+static struct drm_driver st7735r_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops                   = &st7735r_fops,
+       .release                = mipi_dbi_release,
+       DRM_GEM_CMA_VMAP_DRIVER_OPS,
+       .debugfs_init           = mipi_dbi_debugfs_init,
+       .name                   = "st7735r",
+       .desc                   = "Sitronix ST7735R",
+       .date                   = "20171128",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+static const struct of_device_id st7735r_of_match[] = {
+       { .compatible = "jianda,jd-t18003-t01" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, st7735r_of_match);
+
+static const struct spi_device_id st7735r_id[] = {
+       { "jd-t18003-t01", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, st7735r_id);
+
+static int st7735r_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct mipi_dbi_dev *dbidev;
+       struct drm_device *drm;
+       struct mipi_dbi *dbi;
+       struct gpio_desc *dc;
+       u32 rotation = 0;
+       int ret;
+
+       dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+       if (!dbidev)
+               return -ENOMEM;
+
+       dbi = &dbidev->dbi;
+       drm = &dbidev->drm;
+       ret = devm_drm_dev_init(dev, drm, &st7735r_driver);
+       if (ret) {
+               kfree(dbidev);
+               return ret;
+       }
+
+       drm_mode_config_init(drm);
+
+       dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dbi->reset)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+               return PTR_ERR(dbi->reset);
+       }
+
+       dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
+       if (IS_ERR(dc)) {
+               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+               return PTR_ERR(dc);
+       }
+
+       dbidev->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(dbidev->backlight))
+               return PTR_ERR(dbidev->backlight);
+
+       device_property_read_u32(dev, "rotation", &rotation);
+
+       ret = mipi_dbi_spi_init(spi, dbi, dc);
+       if (ret)
+               return ret;
+
+       /* Cannot read from Adafruit 1.8" display via SPI */
+       dbi->read_commands = NULL;
+
+       ret = mipi_dbi_dev_init(dbidev, &jd_t18003_t01_pipe_funcs, &jd_t18003_t01_mode, rotation);
+       if (ret)
+               return ret;
+
+       drm_mode_config_reset(drm);
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               return ret;
+
+       spi_set_drvdata(spi, drm);
+
+       drm_fbdev_generic_setup(drm, 0);
+
+       return 0;
+}
+
+static int st7735r_remove(struct spi_device *spi)
+{
+       struct drm_device *drm = spi_get_drvdata(spi);
+
+       drm_dev_unplug(drm);
+       drm_atomic_helper_shutdown(drm);
+
+       return 0;
+}
+
+static void st7735r_shutdown(struct spi_device *spi)
+{
+       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver st7735r_spi_driver = {
+       .driver = {
+               .name = "st7735r",
+               .owner = THIS_MODULE,
+               .of_match_table = st7735r_of_match,
+       },
+       .id_table = st7735r_id,
+       .probe = st7735r_probe,
+       .remove = st7735r_remove,
+       .shutdown = st7735r_shutdown,
+};
+module_spi_driver(st7735r_spi_driver);
+
+MODULE_DESCRIPTION("Sitronix ST7735R DRM driver");
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig
deleted file mode 100644 (file)
index 87819c8..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig DRM_TINYDRM
-       tristate "Support for simple displays"
-       depends on DRM
-       select DRM_KMS_HELPER
-       select DRM_KMS_CMA_HELPER
-       help
-         Choose this option if you have a tinydrm supported display.
-         If M is selected the module will be called tinydrm.
-
-config TINYDRM_MIPI_DBI
-       tristate
-
-config TINYDRM_HX8357D
-       tristate "DRM support for HX8357D display panels"
-       depends on DRM_TINYDRM && SPI
-       depends on BACKLIGHT_CLASS_DEVICE
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver for the following HX8357D panels:
-         * YX350HV15-T 3.5" 340x350 TFT (Adafruit 3.5")
-
-         If M is selected the module will be called hx8357d.
-
-config TINYDRM_ILI9225
-       tristate "DRM support for ILI9225 display panels"
-       depends on DRM_TINYDRM && SPI
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver for the following Ilitek ILI9225 panels:
-         * No-name 2.2" color screen module
-
-         If M is selected the module will be called ili9225.
-
-config TINYDRM_ILI9341
-       tristate "DRM support for ILI9341 display panels"
-       depends on DRM_TINYDRM && SPI
-       depends on BACKLIGHT_CLASS_DEVICE
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver for the following Ilitek ILI9341 panels:
-         * YX240QV29-T 2.4" 240x320 TFT (Adafruit 2.4")
-
-         If M is selected the module will be called ili9341.
-
-config TINYDRM_MI0283QT
-       tristate "DRM support for MI0283QT"
-       depends on DRM_TINYDRM && SPI
-       depends on BACKLIGHT_CLASS_DEVICE
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver for the Multi-Inno MI0283QT display panel
-         If M is selected the module will be called mi0283qt.
-
-config TINYDRM_REPAPER
-       tristate "DRM support for Pervasive Displays RePaper panels (V231)"
-       depends on DRM_TINYDRM && SPI
-       depends on THERMAL || !THERMAL
-       help
-         DRM driver for the following Pervasive Displays panels:
-         1.44" TFT EPD Panel (E1144CS021)
-         1.90" TFT EPD Panel (E1190CS021)
-         2.00" TFT EPD Panel (E2200CS021)
-         2.71" TFT EPD Panel (E2271CS021)
-
-         If M is selected the module will be called repaper.
-
-config TINYDRM_ST7586
-       tristate "DRM support for Sitronix ST7586 display panels"
-       depends on DRM_TINYDRM && SPI
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver for the following Sitronix ST7586 panels:
-         * LEGO MINDSTORMS EV3
-
-         If M is selected the module will be called st7586.
-
-config TINYDRM_ST7735R
-       tristate "DRM support for Sitronix ST7735R display panels"
-       depends on DRM_TINYDRM && SPI
-       depends on BACKLIGHT_CLASS_DEVICE
-       select TINYDRM_MIPI_DBI
-       help
-         DRM driver Sitronix ST7735R with one of the following LCDs:
-         * JD-T18003-T01 1.8" 128x160 TFT
-
-         If M is selected the module will be called st7735r.
diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tinydrm/Makefile
deleted file mode 100644 (file)
index 48ec8ed..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_DRM_TINYDRM)              += core/
-
-# Controllers
-obj-$(CONFIG_TINYDRM_MIPI_DBI)         += mipi-dbi.o
-
-# Displays
-obj-$(CONFIG_TINYDRM_HX8357D)          += hx8357d.o
-obj-$(CONFIG_TINYDRM_ILI9225)          += ili9225.o
-obj-$(CONFIG_TINYDRM_ILI9341)          += ili9341.o
-obj-$(CONFIG_TINYDRM_MI0283QT)         += mi0283qt.o
-obj-$(CONFIG_TINYDRM_REPAPER)          += repaper.o
-obj-$(CONFIG_TINYDRM_ST7586)           += st7586.o
-obj-$(CONFIG_TINYDRM_ST7735R)          += st7735r.o
diff --git a/drivers/gpu/drm/tinydrm/core/Makefile b/drivers/gpu/drm/tinydrm/core/Makefile
deleted file mode 100644 (file)
index 01065e9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-tinydrm-y := tinydrm-pipe.o tinydrm-helpers.o
-
-obj-$(CONFIG_DRM_TINYDRM) += tinydrm.o
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
deleted file mode 100644 (file)
index dfeafac..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Noralf Trønnes
- */
-
-#include <linux/backlight.h>
-#include <linux/dma-buf.h>
-#include <linux/module.h>
-#include <linux/pm.h>
-#include <linux/spi/spi.h>
-#include <linux/swab.h>
-
-#include <drm/drm_device.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_framebuffer.h>
-#include <drm/drm_print.h>
-#include <drm/drm_rect.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-
-static unsigned int spi_max;
-module_param(spi_max, uint, 0400);
-MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size");
-
-#if IS_ENABLED(CONFIG_SPI)
-
-/**
- * tinydrm_spi_max_transfer_size - Determine max SPI transfer size
- * @spi: SPI device
- * @max_len: Maximum buffer size needed (optional)
- *
- * This function returns the maximum size to use for SPI transfers. It checks
- * the SPI master, the optional @max_len and the module parameter spi_max and
- * returns the smallest.
- *
- * Returns:
- * Maximum size for SPI transfers
- */
-size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len)
-{
-       size_t ret;
-
-       ret = min(spi_max_transfer_size(spi), spi->master->max_dma_len);
-       if (max_len)
-               ret = min(ret, max_len);
-       if (spi_max)
-               ret = min_t(size_t, ret, spi_max);
-       ret &= ~0x3;
-       if (ret < 4)
-               ret = 4;
-
-       return ret;
-}
-EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
-
-/**
- * tinydrm_spi_bpw_supported - Check if bits per word is supported
- * @spi: SPI device
- * @bpw: Bits per word
- *
- * This function checks to see if the SPI master driver supports @bpw.
- *
- * Returns:
- * True if @bpw is supported, false otherwise.
- */
-bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw)
-{
-       u32 bpw_mask = spi->master->bits_per_word_mask;
-
-       if (bpw == 8)
-               return true;
-
-       if (!bpw_mask) {
-               dev_warn_once(&spi->dev,
-                             "bits_per_word_mask not set, assume 8-bit only\n");
-               return false;
-       }
-
-       if (bpw_mask & SPI_BPW_MASK(bpw))
-               return true;
-
-       return false;
-}
-EXPORT_SYMBOL(tinydrm_spi_bpw_supported);
-
-static void
-tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
-                     const void *buf, int idx, bool tx)
-{
-       u32 speed_hz = tr->speed_hz ? tr->speed_hz : spi->max_speed_hz;
-       char linebuf[3 * 32];
-
-       hex_dump_to_buffer(buf, tr->len, 16,
-                          DIV_ROUND_UP(tr->bits_per_word, 8),
-                          linebuf, sizeof(linebuf), false);
-
-       printk(KERN_DEBUG
-              "    tr(%i): speed=%u%s, bpw=%i, len=%u, %s_buf=[%s%s]\n", idx,
-              speed_hz > 1000000 ? speed_hz / 1000000 : speed_hz / 1000,
-              speed_hz > 1000000 ? "MHz" : "kHz", tr->bits_per_word, tr->len,
-              tx ? "tx" : "rx", linebuf, tr->len > 16 ? " ..." : "");
-}
-
-/* called through tinydrm_dbg_spi_message() */
-void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m)
-{
-       struct spi_transfer *tmp;
-       int i = 0;
-
-       list_for_each_entry(tmp, &m->transfers, transfer_list) {
-
-               if (tmp->tx_buf)
-                       tinydrm_dbg_spi_print(spi, tmp, tmp->tx_buf, i, true);
-               if (tmp->rx_buf)
-                       tinydrm_dbg_spi_print(spi, tmp, tmp->rx_buf, i, false);
-               i++;
-       }
-}
-EXPORT_SYMBOL(_tinydrm_dbg_spi_message);
-
-/**
- * tinydrm_spi_transfer - SPI transfer helper
- * @spi: SPI device
- * @speed_hz: Override speed (optional)
- * @header: Optional header transfer
- * @bpw: Bits per word
- * @buf: Buffer to transfer
- * @len: Buffer length
- *
- * This SPI transfer helper breaks up the transfer of @buf into chunks which
- * the SPI master driver can handle. If the machine is Little Endian and the
- * SPI master driver doesn't support 16 bits per word, it swaps the bytes and
- * does a 8-bit transfer.
- * If @header is set, it is prepended to each SPI message.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
-                        struct spi_transfer *header, u8 bpw, const void *buf,
-                        size_t len)
-{
-       struct spi_transfer tr = {
-               .bits_per_word = bpw,
-               .speed_hz = speed_hz,
-       };
-       struct spi_message m;
-       u16 *swap_buf = NULL;
-       size_t max_chunk;
-       size_t chunk;
-       int ret = 0;
-
-       if (WARN_ON_ONCE(bpw != 8 && bpw != 16))
-               return -EINVAL;
-
-       max_chunk = tinydrm_spi_max_transfer_size(spi, 0);
-
-       if (drm_debug & DRM_UT_DRIVER)
-               pr_debug("[drm:%s] bpw=%u, max_chunk=%zu, transfers:\n",
-                        __func__, bpw, max_chunk);
-
-       if (bpw == 16 && !tinydrm_spi_bpw_supported(spi, 16)) {
-               tr.bits_per_word = 8;
-               if (tinydrm_machine_little_endian()) {
-                       swap_buf = kmalloc(min(len, max_chunk), GFP_KERNEL);
-                       if (!swap_buf)
-                               return -ENOMEM;
-               }
-       }
-
-       spi_message_init(&m);
-       if (header)
-               spi_message_add_tail(header, &m);
-       spi_message_add_tail(&tr, &m);
-
-       while (len) {
-               chunk = min(len, max_chunk);
-
-               tr.tx_buf = buf;
-               tr.len = chunk;
-
-               if (swap_buf) {
-                       const u16 *buf16 = buf;
-                       unsigned int i;
-
-                       for (i = 0; i < chunk / 2; i++)
-                               swap_buf[i] = swab16(buf16[i]);
-
-                       tr.tx_buf = swap_buf;
-               }
-
-               buf += chunk;
-               len -= chunk;
-
-               tinydrm_dbg_spi_message(spi, &m);
-               ret = spi_sync(spi, &m);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(tinydrm_spi_transfer);
-
-#endif /* CONFIG_SPI */
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
deleted file mode 100644 (file)
index ed798fd..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Noralf Trønnes
- */
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_modes.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_print.h>
-#include <drm/drm_simple_kms_helper.h>
-
-struct tinydrm_connector {
-       struct drm_connector base;
-       struct drm_display_mode mode;
-};
-
-static inline struct tinydrm_connector *
-to_tinydrm_connector(struct drm_connector *connector)
-{
-       return container_of(connector, struct tinydrm_connector, base);
-}
-
-static int tinydrm_connector_get_modes(struct drm_connector *connector)
-{
-       struct tinydrm_connector *tconn = to_tinydrm_connector(connector);
-       struct drm_display_mode *mode;
-
-       mode = drm_mode_duplicate(connector->dev, &tconn->mode);
-       if (!mode) {
-               DRM_ERROR("Failed to duplicate mode\n");
-               return 0;
-       }
-
-       if (mode->name[0] == '\0')
-               drm_mode_set_name(mode);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-       drm_mode_probed_add(connector, mode);
-
-       if (mode->width_mm) {
-               connector->display_info.width_mm = mode->width_mm;
-               connector->display_info.height_mm = mode->height_mm;
-       }
-
-       return 1;
-}
-
-static const struct drm_connector_helper_funcs tinydrm_connector_hfuncs = {
-       .get_modes = tinydrm_connector_get_modes,
-};
-
-static enum drm_connector_status
-tinydrm_connector_detect(struct drm_connector *connector, bool force)
-{
-       if (drm_dev_is_unplugged(connector->dev))
-               return connector_status_disconnected;
-
-       return connector->status;
-}
-
-static void tinydrm_connector_destroy(struct drm_connector *connector)
-{
-       struct tinydrm_connector *tconn = to_tinydrm_connector(connector);
-
-       drm_connector_cleanup(connector);
-       kfree(tconn);
-}
-
-static const struct drm_connector_funcs tinydrm_connector_funcs = {
-       .reset = drm_atomic_helper_connector_reset,
-       .detect = tinydrm_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = tinydrm_connector_destroy,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-struct drm_connector *
-tinydrm_connector_create(struct drm_device *drm,
-                        const struct drm_display_mode *mode,
-                        int connector_type)
-{
-       struct tinydrm_connector *tconn;
-       struct drm_connector *connector;
-       int ret;
-
-       tconn = kzalloc(sizeof(*tconn), GFP_KERNEL);
-       if (!tconn)
-               return ERR_PTR(-ENOMEM);
-
-       drm_mode_copy(&tconn->mode, mode);
-       connector = &tconn->base;
-
-       drm_connector_helper_add(connector, &tinydrm_connector_hfuncs);
-       ret = drm_connector_init(drm, connector, &tinydrm_connector_funcs,
-                                connector_type);
-       if (ret) {
-               kfree(tconn);
-               return ERR_PTR(ret);
-       }
-
-       connector->status = connector_status_connected;
-
-       return connector;
-}
-
-static int tinydrm_rotate_mode(struct drm_display_mode *mode,
-                              unsigned int rotation)
-{
-       if (rotation == 0 || rotation == 180) {
-               return 0;
-       } else if (rotation == 90 || rotation == 270) {
-               swap(mode->hdisplay, mode->vdisplay);
-               swap(mode->hsync_start, mode->vsync_start);
-               swap(mode->hsync_end, mode->vsync_end);
-               swap(mode->htotal, mode->vtotal);
-               swap(mode->width_mm, mode->height_mm);
-               return 0;
-       } else {
-               return -EINVAL;
-       }
-}
-
-/**
- * tinydrm_display_pipe_init - Initialize display pipe
- * @drm: DRM device
- * @pipe: Display pipe
- * @funcs: Display pipe functions
- * @connector_type: Connector type
- * @formats: Array of supported formats (DRM_FORMAT\_\*)
- * @format_count: Number of elements in @formats
- * @mode: Supported mode
- * @rotation: Initial @mode rotation in degrees Counter Clock Wise
- *
- * This function sets up a &drm_simple_display_pipe with a &drm_connector that
- * has one fixed &drm_display_mode which is rotated according to @rotation.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int tinydrm_display_pipe_init(struct drm_device *drm,
-                             struct drm_simple_display_pipe *pipe,
-                             const struct drm_simple_display_pipe_funcs *funcs,
-                             int connector_type,
-                             const uint32_t *formats,
-                             unsigned int format_count,
-                             const struct drm_display_mode *mode,
-                             unsigned int rotation)
-{
-       struct drm_display_mode mode_copy;
-       struct drm_connector *connector;
-       int ret;
-       static const uint64_t modifiers[] = {
-               DRM_FORMAT_MOD_LINEAR,
-               DRM_FORMAT_MOD_INVALID
-       };
-
-       drm_mode_copy(&mode_copy, mode);
-       ret = tinydrm_rotate_mode(&mode_copy, rotation);
-       if (ret) {
-               DRM_ERROR("Illegal rotation value %u\n", rotation);
-               return -EINVAL;
-       }
-
-       drm->mode_config.min_width = mode_copy.hdisplay;
-       drm->mode_config.max_width = mode_copy.hdisplay;
-       drm->mode_config.min_height = mode_copy.vdisplay;
-       drm->mode_config.max_height = mode_copy.vdisplay;
-
-       connector = tinydrm_connector_create(drm, &mode_copy, connector_type);
-       if (IS_ERR(connector))
-               return PTR_ERR(connector);
-
-       return drm_simple_display_pipe_init(drm, pipe, funcs, formats,
-                                           format_count, modifiers, connector);
-}
-EXPORT_SYMBOL(tinydrm_display_pipe_init);
diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c b/drivers/gpu/drm/tinydrm/hx8357d.c
deleted file mode 100644 (file)
index 5773d0f..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DRM driver for the HX8357D LCD controller
- *
- * Copyright 2018 Broadcom
- * Copyright 2018 David Lechner <david@lechnology.com>
- * Copyright 2016 Noralf Trønnes
- * Copyright (C) 2015 Adafruit Industries
- * Copyright (C) 2013 Christian Vogelgsang
- */
-
-#include <linux/backlight.h>
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/spi/spi.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_modeset_helper.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-#include <video/mipi_display.h>
-
-#define HX8357D_SETOSC 0xb0
-#define HX8357D_SETPOWER 0xb1
-#define HX8357D_SETRGB 0xb3
-#define HX8357D_SETCYC 0xb3
-#define HX8357D_SETCOM 0xb6
-#define HX8357D_SETEXTC 0xb9
-#define HX8357D_SETSTBA 0xc0
-#define HX8357D_SETPANEL 0xcc
-#define HX8357D_SETGAMMA 0xe0
-
-#define HX8357D_MADCTL_MY  0x80
-#define HX8357D_MADCTL_MX  0x40
-#define HX8357D_MADCTL_MV  0x20
-#define HX8357D_MADCTL_ML  0x10
-#define HX8357D_MADCTL_RGB 0x00
-#define HX8357D_MADCTL_BGR 0x08
-#define HX8357D_MADCTL_MH  0x04
-
-static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
-                            struct drm_crtc_state *crtc_state,
-                            struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       u8 addr_mode;
-       int ret, idx;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       ret = mipi_dbi_poweron_conditional_reset(mipi);
-       if (ret < 0)
-               goto out_exit;
-       if (ret == 1)
-               goto out_enable;
-
-       /* setextc */
-       mipi_dbi_command(mipi, HX8357D_SETEXTC, 0xFF, 0x83, 0x57);
-       msleep(150);
-
-       /* setRGB which also enables SDO */
-       mipi_dbi_command(mipi, HX8357D_SETRGB, 0x00, 0x00, 0x06, 0x06);
-
-       /* -1.52V */
-       mipi_dbi_command(mipi, HX8357D_SETCOM, 0x25);
-
-       /* Normal mode 70Hz, Idle mode 55 Hz */
-       mipi_dbi_command(mipi, HX8357D_SETOSC, 0x68);
-
-       /* Set Panel - BGR, Gate direction swapped */
-       mipi_dbi_command(mipi, HX8357D_SETPANEL, 0x05);
-
-       mipi_dbi_command(mipi, HX8357D_SETPOWER,
-                        0x00,  /* Not deep standby */
-                        0x15,  /* BT */
-                        0x1C,  /* VSPR */
-                        0x1C,  /* VSNR */
-                        0x83,  /* AP */
-                        0xAA);  /* FS */
-
-       mipi_dbi_command(mipi, HX8357D_SETSTBA,
-                        0x50,  /* OPON normal */
-                        0x50,  /* OPON idle */
-                        0x01,  /* STBA */
-                        0x3C,  /* STBA */
-                        0x1E,  /* STBA */
-                        0x08);  /* GEN */
-
-       mipi_dbi_command(mipi, HX8357D_SETCYC,
-                        0x02,  /* NW 0x02 */
-                        0x40,  /* RTN */
-                        0x00,  /* DIV */
-                        0x2A,  /* DUM */
-                        0x2A,  /* DUM */
-                        0x0D,  /* GDON */
-                        0x78);  /* GDOFF */
-
-       mipi_dbi_command(mipi, HX8357D_SETGAMMA,
-                        0x02,
-                        0x0A,
-                        0x11,
-                        0x1d,
-                        0x23,
-                        0x35,
-                        0x41,
-                        0x4b,
-                        0x4b,
-                        0x42,
-                        0x3A,
-                        0x27,
-                        0x1B,
-                        0x08,
-                        0x09,
-                        0x03,
-                        0x02,
-                        0x0A,
-                        0x11,
-                        0x1d,
-                        0x23,
-                        0x35,
-                        0x41,
-                        0x4b,
-                        0x4b,
-                        0x42,
-                        0x3A,
-                        0x27,
-                        0x1B,
-                        0x08,
-                        0x09,
-                        0x03,
-                        0x00,
-                        0x01);
-
-       /* 16 bit */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT,
-                        MIPI_DCS_PIXEL_FMT_16BIT);
-
-       /* TE off */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_TEAR_ON, 0x00);
-
-       /* tear line */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
-
-       /* Exit Sleep */
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
-       msleep(150);
-
-       /* display on */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
-       usleep_range(5000, 7000);
-
-out_enable:
-       switch (mipi->rotation) {
-       default:
-               addr_mode = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY;
-               break;
-       case 90:
-               addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MY;
-               break;
-       case 180:
-               addr_mode = 0;
-               break;
-       case 270:
-               addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX;
-               break;
-       }
-       mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
-       .enable = yx240qv29_enable,
-       .disable = mipi_dbi_pipe_disable,
-       .update = mipi_dbi_pipe_update,
-       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_display_mode yx350hv15_mode = {
-       DRM_SIMPLE_MODE(320, 480, 60, 75),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops);
-
-static struct drm_driver hx8357d_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
-       .fops                   = &hx8357d_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .debugfs_init           = mipi_dbi_debugfs_init,
-       .name                   = "hx8357d",
-       .desc                   = "HX8357D",
-       .date                   = "20181023",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id hx8357d_of_match[] = {
-       { .compatible = "adafruit,yx350hv15" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, hx8357d_of_match);
-
-static const struct spi_device_id hx8357d_id[] = {
-       { "yx350hv15", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(spi, hx8357d_id);
-
-static int hx8357d_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *dc;
-       u32 rotation = 0;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &hx8357d_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-
-       dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
-       if (IS_ERR(dc)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
-               return PTR_ERR(dc);
-       }
-
-       mipi->backlight = devm_of_find_backlight(dev);
-       if (IS_ERR(mipi->backlight))
-               return PTR_ERR(mipi->backlight);
-
-       device_property_read_u32(dev, "rotation", &rotation);
-
-       ret = mipi_dbi_spi_init(spi, mipi, dc);
-       if (ret)
-               return ret;
-
-       ret = mipi_dbi_init(mipi, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int hx8357d_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void hx8357d_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver hx8357d_spi_driver = {
-       .driver = {
-               .name = "hx8357d",
-               .of_match_table = hx8357d_of_match,
-       },
-       .id_table = hx8357d_id,
-       .probe = hx8357d_probe,
-       .remove = hx8357d_remove,
-       .shutdown = hx8357d_shutdown,
-};
-module_spi_driver(hx8357d_spi_driver);
-
-MODULE_DESCRIPTION("HX8357D DRM driver");
-MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c
deleted file mode 100644 (file)
index ea69019..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DRM driver for Ilitek ILI9225 panels
- *
- * Copyright 2017 David Lechner <david@lechnology.com>
- *
- * Some code copied from mipi-dbi.c
- * Copyright 2016 Noralf Trønnes
- */
-
-#include <linux/delay.h>
-#include <linux/dma-buf.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/spi/spi.h>
-#include <video/mipi_display.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_rect.h>
-#include <drm/drm_vblank.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-
-#define ILI9225_DRIVER_READ_CODE       0x00
-#define ILI9225_DRIVER_OUTPUT_CONTROL  0x01
-#define ILI9225_LCD_AC_DRIVING_CONTROL 0x02
-#define ILI9225_ENTRY_MODE             0x03
-#define ILI9225_DISPLAY_CONTROL_1      0x07
-#define ILI9225_BLANK_PERIOD_CONTROL_1 0x08
-#define ILI9225_FRAME_CYCLE_CONTROL    0x0b
-#define ILI9225_INTERFACE_CONTROL      0x0c
-#define ILI9225_OSCILLATION_CONTROL    0x0f
-#define ILI9225_POWER_CONTROL_1                0x10
-#define ILI9225_POWER_CONTROL_2                0x11
-#define ILI9225_POWER_CONTROL_3                0x12
-#define ILI9225_POWER_CONTROL_4                0x13
-#define ILI9225_POWER_CONTROL_5                0x14
-#define ILI9225_VCI_RECYCLING          0x15
-#define ILI9225_RAM_ADDRESS_SET_1      0x20
-#define ILI9225_RAM_ADDRESS_SET_2      0x21
-#define ILI9225_WRITE_DATA_TO_GRAM     0x22
-#define ILI9225_SOFTWARE_RESET         0x28
-#define ILI9225_GATE_SCAN_CONTROL      0x30
-#define ILI9225_VERTICAL_SCROLL_1      0x31
-#define ILI9225_VERTICAL_SCROLL_2      0x32
-#define ILI9225_VERTICAL_SCROLL_3      0x33
-#define ILI9225_PARTIAL_DRIVING_POS_1  0x34
-#define ILI9225_PARTIAL_DRIVING_POS_2  0x35
-#define ILI9225_HORIZ_WINDOW_ADDR_1    0x36
-#define ILI9225_HORIZ_WINDOW_ADDR_2    0x37
-#define ILI9225_VERT_WINDOW_ADDR_1     0x38
-#define ILI9225_VERT_WINDOW_ADDR_2     0x39
-#define ILI9225_GAMMA_CONTROL_1                0x50
-#define ILI9225_GAMMA_CONTROL_2                0x51
-#define ILI9225_GAMMA_CONTROL_3                0x52
-#define ILI9225_GAMMA_CONTROL_4                0x53
-#define ILI9225_GAMMA_CONTROL_5                0x54
-#define ILI9225_GAMMA_CONTROL_6                0x55
-#define ILI9225_GAMMA_CONTROL_7                0x56
-#define ILI9225_GAMMA_CONTROL_8                0x57
-#define ILI9225_GAMMA_CONTROL_9                0x58
-#define ILI9225_GAMMA_CONTROL_10       0x59
-
-static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data)
-{
-       u8 par[2] = { data >> 8, data & 0xff };
-
-       return mipi_dbi_command_buf(mipi, cmd, par, 2);
-}
-
-static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
-{
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev);
-       unsigned int height = rect->y2 - rect->y1;
-       unsigned int width = rect->x2 - rect->x1;
-       bool swap = mipi->swap_bytes;
-       u16 x_start, y_start;
-       u16 x1, x2, y1, y2;
-       int idx, ret = 0;
-       bool full;
-       void *tr;
-
-       if (!mipi->enabled)
-               return;
-
-       if (!drm_dev_enter(fb->dev, &idx))
-               return;
-
-       full = width == fb->width && height == fb->height;
-
-       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
-
-       if (!mipi->dc || !full || swap ||
-           fb->format->format == DRM_FORMAT_XRGB8888) {
-               tr = mipi->tx_buf;
-               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
-               if (ret)
-                       goto err_msg;
-       } else {
-               tr = cma_obj->vaddr;
-       }
-
-       switch (mipi->rotation) {
-       default:
-               x1 = rect->x1;
-               x2 = rect->x2 - 1;
-               y1 = rect->y1;
-               y2 = rect->y2 - 1;
-               x_start = x1;
-               y_start = y1;
-               break;
-       case 90:
-               x1 = rect->y1;
-               x2 = rect->y2 - 1;
-               y1 = fb->width - rect->x2;
-               y2 = fb->width - rect->x1 - 1;
-               x_start = x1;
-               y_start = y2;
-               break;
-       case 180:
-               x1 = fb->width - rect->x2;
-               x2 = fb->width - rect->x1 - 1;
-               y1 = fb->height - rect->y2;
-               y2 = fb->height - rect->y1 - 1;
-               x_start = x2;
-               y_start = y2;
-               break;
-       case 270:
-               x1 = fb->height - rect->y2;
-               x2 = fb->height - rect->y1 - 1;
-               y1 = rect->x1;
-               y2 = rect->x2 - 1;
-               x_start = x2;
-               y_start = y1;
-               break;
-       }
-
-       ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_1, x2);
-       ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_2, x1);
-       ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_1, y2);
-       ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_2, y1);
-
-       ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, x_start);
-       ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start);
-
-       ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr,
-                                  width * height * 2);
-err_msg:
-       if (ret)
-               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
-
-       drm_dev_exit(idx);
-}
-
-static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
-                               struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = pipe->plane.state;
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct drm_rect rect;
-
-       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
-               ili9225_fb_dirty(state->fb, &rect);
-
-       if (crtc->state->event) {
-               spin_lock_irq(&crtc->dev->event_lock);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               spin_unlock_irq(&crtc->dev->event_lock);
-               crtc->state->event = NULL;
-       }
-}
-
-static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
-                               struct drm_crtc_state *crtc_state,
-                               struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       struct drm_framebuffer *fb = plane_state->fb;
-       struct device *dev = pipe->crtc.dev->dev;
-       struct drm_rect rect = {
-               .x1 = 0,
-               .x2 = fb->width,
-               .y1 = 0,
-               .y2 = fb->height,
-       };
-       int ret, idx;
-       u8 am_id;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       mipi_dbi_hw_reset(mipi);
-
-       /*
-        * There don't seem to be two example init sequences that match, so
-        * using the one from the popular Arduino library for this display.
-        * https://github.com/Nkawu/TFT_22_ILI9225/blob/master/src/TFT_22_ILI9225.cpp
-        */
-
-       ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000);
-       if (ret) {
-               DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
-               goto out_exit;
-       }
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x0000);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x0000);
-
-       msleep(40);
-
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0018);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x6121);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x006f);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x495f);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0800);
-
-       msleep(10);
-
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x103b);
-
-       msleep(50);
-
-       switch (mipi->rotation) {
-       default:
-               am_id = 0x30;
-               break;
-       case 90:
-               am_id = 0x18;
-               break;
-       case 180:
-               am_id = 0x00;
-               break;
-       case 270:
-               am_id = 0x28;
-               break;
-       }
-       ili9225_command(mipi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c);
-       ili9225_command(mipi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100);
-       ili9225_command(mipi, ILI9225_ENTRY_MODE, 0x1000 | am_id);
-       ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
-       ili9225_command(mipi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808);
-       ili9225_command(mipi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100);
-       ili9225_command(mipi, ILI9225_INTERFACE_CONTROL, 0x0000);
-       ili9225_command(mipi, ILI9225_OSCILLATION_CONTROL, 0x0d01);
-       ili9225_command(mipi, ILI9225_VCI_RECYCLING, 0x0020);
-       ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, 0x0000);
-       ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, 0x0000);
-
-       ili9225_command(mipi, ILI9225_GATE_SCAN_CONTROL, 0x0000);
-       ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_1, 0x00db);
-       ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_2, 0x0000);
-       ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_3, 0x0000);
-       ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db);
-       ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000);
-
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_1, 0x0000);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_2, 0x0808);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_3, 0x080a);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_4, 0x000a);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_5, 0x0a08);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_6, 0x0808);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_7, 0x0000);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_8, 0x0a00);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_9, 0x0710);
-       ili9225_command(mipi, ILI9225_GAMMA_CONTROL_10, 0x0710);
-
-       ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0012);
-
-       msleep(50);
-
-       ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
-
-       mipi->enabled = true;
-       ili9225_fb_dirty(fb, &rect);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-
-       DRM_DEBUG_KMS("\n");
-
-       /*
-        * This callback is not protected by drm_dev_enter/exit since we want to
-        * turn off the display on regular driver unload. It's highly unlikely
-        * that the underlying SPI controller is gone should this be called after
-        * unplug.
-        */
-
-       if (!mipi->enabled)
-               return;
-
-       ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
-       msleep(50);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0007);
-       msleep(50);
-       ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0a02);
-
-       mipi->enabled = false;
-}
-
-static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
-                              size_t num)
-{
-       struct spi_device *spi = mipi->spi;
-       unsigned int bpw = 8;
-       u32 speed_hz;
-       int ret;
-
-       gpiod_set_value_cansleep(mipi->dc, 0);
-       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
-       ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, cmd, 1);
-       if (ret || !num)
-               return ret;
-
-       if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !mipi->swap_bytes)
-               bpw = 16;
-
-       gpiod_set_value_cansleep(mipi->dc, 1);
-       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
-
-       return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num);
-}
-
-static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
-       .enable         = ili9225_pipe_enable,
-       .disable        = ili9225_pipe_disable,
-       .update         = ili9225_pipe_update,
-       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_display_mode ili9225_mode = {
-       DRM_SIMPLE_MODE(176, 220, 35, 44),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops);
-
-static struct drm_driver ili9225_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
-       .fops                   = &ili9225_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .name                   = "ili9225",
-       .desc                   = "Ilitek ILI9225",
-       .date                   = "20171106",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id ili9225_of_match[] = {
-       { .compatible = "vot,v220hf01a-t" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, ili9225_of_match);
-
-static const struct spi_device_id ili9225_id[] = {
-       { "v220hf01a-t", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, ili9225_id);
-
-static int ili9225_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *rs;
-       u32 rotation = 0;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &ili9225_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-
-       mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(mipi->reset)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return PTR_ERR(mipi->reset);
-       }
-
-       rs = devm_gpiod_get(dev, "rs", GPIOD_OUT_LOW);
-       if (IS_ERR(rs)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'rs'\n");
-               return PTR_ERR(rs);
-       }
-
-       device_property_read_u32(dev, "rotation", &rotation);
-
-       ret = mipi_dbi_spi_init(spi, mipi, rs);
-       if (ret)
-               return ret;
-
-       /* override the command function set in  mipi_dbi_spi_init() */
-       mipi->command = ili9225_dbi_command;
-
-       ret = mipi_dbi_init(mipi, &ili9225_pipe_funcs, &ili9225_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int ili9225_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void ili9225_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver ili9225_spi_driver = {
-       .driver = {
-               .name = "ili9225",
-               .owner = THIS_MODULE,
-               .of_match_table = ili9225_of_match,
-       },
-       .id_table = ili9225_id,
-       .probe = ili9225_probe,
-       .remove = ili9225_remove,
-       .shutdown = ili9225_shutdown,
-};
-module_spi_driver(ili9225_spi_driver);
-
-MODULE_DESCRIPTION("Ilitek ILI9225 DRM driver");
-MODULE_AUTHOR("David Lechner <david@lechnology.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c
deleted file mode 100644 (file)
index 4ade9e4..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DRM driver for Ilitek ILI9341 panels
- *
- * Copyright 2018 David Lechner <david@lechnology.com>
- *
- * Based on mi0283qt.c:
- * Copyright 2016 Noralf Trønnes
- */
-
-#include <linux/backlight.h>
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/spi/spi.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_modeset_helper.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-#include <video/mipi_display.h>
-
-#define ILI9341_FRMCTR1                0xb1
-#define ILI9341_DISCTRL                0xb6
-#define ILI9341_ETMOD          0xb7
-
-#define ILI9341_PWCTRL1                0xc0
-#define ILI9341_PWCTRL2                0xc1
-#define ILI9341_VMCTRL1                0xc5
-#define ILI9341_VMCTRL2                0xc7
-#define ILI9341_PWCTRLA                0xcb
-#define ILI9341_PWCTRLB                0xcf
-
-#define ILI9341_PGAMCTRL       0xe0
-#define ILI9341_NGAMCTRL       0xe1
-#define ILI9341_DTCTRLA                0xe8
-#define ILI9341_DTCTRLB                0xea
-#define ILI9341_PWRSEQ         0xed
-
-#define ILI9341_EN3GAM         0xf2
-#define ILI9341_PUMPCTRL       0xf7
-
-#define ILI9341_MADCTL_BGR     BIT(3)
-#define ILI9341_MADCTL_MV      BIT(5)
-#define ILI9341_MADCTL_MX      BIT(6)
-#define ILI9341_MADCTL_MY      BIT(7)
-
-static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
-                            struct drm_crtc_state *crtc_state,
-                            struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       u8 addr_mode;
-       int ret, idx;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       ret = mipi_dbi_poweron_conditional_reset(mipi);
-       if (ret < 0)
-               goto out_exit;
-       if (ret == 1)
-               goto out_enable;
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
-
-       mipi_dbi_command(mipi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30);
-       mipi_dbi_command(mipi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81);
-       mipi_dbi_command(mipi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78);
-       mipi_dbi_command(mipi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02);
-       mipi_dbi_command(mipi, ILI9341_PUMPCTRL, 0x20);
-       mipi_dbi_command(mipi, ILI9341_DTCTRLB, 0x00, 0x00);
-
-       /* Power Control */
-       mipi_dbi_command(mipi, ILI9341_PWCTRL1, 0x23);
-       mipi_dbi_command(mipi, ILI9341_PWCTRL2, 0x10);
-       /* VCOM */
-       mipi_dbi_command(mipi, ILI9341_VMCTRL1, 0x3e, 0x28);
-       mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0x86);
-
-       /* Memory Access Control */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
-
-       /* Frame Rate */
-       mipi_dbi_command(mipi, ILI9341_FRMCTR1, 0x00, 0x1b);
-
-       /* Gamma */
-       mipi_dbi_command(mipi, ILI9341_EN3GAM, 0x00);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
-       mipi_dbi_command(mipi, ILI9341_PGAMCTRL,
-                        0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
-                        0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
-       mipi_dbi_command(mipi, ILI9341_NGAMCTRL,
-                        0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
-                        0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
-
-       /* DDRAM */
-       mipi_dbi_command(mipi, ILI9341_ETMOD, 0x07);
-
-       /* Display */
-       mipi_dbi_command(mipi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00);
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
-       msleep(100);
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
-       msleep(100);
-
-out_enable:
-       switch (mipi->rotation) {
-       default:
-               addr_mode = ILI9341_MADCTL_MX;
-               break;
-       case 90:
-               addr_mode = ILI9341_MADCTL_MV;
-               break;
-       case 180:
-               addr_mode = ILI9341_MADCTL_MY;
-               break;
-       case 270:
-               addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
-                           ILI9341_MADCTL_MX;
-               break;
-       }
-       addr_mode |= ILI9341_MADCTL_BGR;
-       mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
-       .enable = yx240qv29_enable,
-       .disable = mipi_dbi_pipe_disable,
-       .update = mipi_dbi_pipe_update,
-       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_display_mode yx240qv29_mode = {
-       DRM_SIMPLE_MODE(240, 320, 37, 49),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops);
-
-static struct drm_driver ili9341_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
-       .fops                   = &ili9341_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .debugfs_init           = mipi_dbi_debugfs_init,
-       .name                   = "ili9341",
-       .desc                   = "Ilitek ILI9341",
-       .date                   = "20180514",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id ili9341_of_match[] = {
-       { .compatible = "adafruit,yx240qv29" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, ili9341_of_match);
-
-static const struct spi_device_id ili9341_id[] = {
-       { "yx240qv29", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(spi, ili9341_id);
-
-static int ili9341_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *dc;
-       u32 rotation = 0;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &ili9341_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-
-       mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(mipi->reset)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return PTR_ERR(mipi->reset);
-       }
-
-       dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
-       if (IS_ERR(dc)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
-               return PTR_ERR(dc);
-       }
-
-       mipi->backlight = devm_of_find_backlight(dev);
-       if (IS_ERR(mipi->backlight))
-               return PTR_ERR(mipi->backlight);
-
-       device_property_read_u32(dev, "rotation", &rotation);
-
-       ret = mipi_dbi_spi_init(spi, mipi, dc);
-       if (ret)
-               return ret;
-
-       ret = mipi_dbi_init(mipi, &ili9341_pipe_funcs, &yx240qv29_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int ili9341_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void ili9341_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver ili9341_spi_driver = {
-       .driver = {
-               .name = "ili9341",
-               .of_match_table = ili9341_of_match,
-       },
-       .id_table = ili9341_id,
-       .probe = ili9341_probe,
-       .remove = ili9341_remove,
-       .shutdown = ili9341_shutdown,
-};
-module_spi_driver(ili9341_spi_driver);
-
-MODULE_DESCRIPTION("Ilitek ILI9341 DRM driver");
-MODULE_AUTHOR("David Lechner <david@lechnology.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
deleted file mode 100644 (file)
index fdefa53..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DRM driver for Multi-Inno MI0283QT panels
- *
- * Copyright 2016 Noralf Trønnes
- */
-
-#include <linux/backlight.h>
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/regulator/consumer.h>
-#include <linux/spi/spi.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_modeset_helper.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-#include <video/mipi_display.h>
-
-#define ILI9341_FRMCTR1                0xb1
-#define ILI9341_DISCTRL                0xb6
-#define ILI9341_ETMOD          0xb7
-
-#define ILI9341_PWCTRL1                0xc0
-#define ILI9341_PWCTRL2                0xc1
-#define ILI9341_VMCTRL1                0xc5
-#define ILI9341_VMCTRL2                0xc7
-#define ILI9341_PWCTRLA                0xcb
-#define ILI9341_PWCTRLB                0xcf
-
-#define ILI9341_PGAMCTRL       0xe0
-#define ILI9341_NGAMCTRL       0xe1
-#define ILI9341_DTCTRLA                0xe8
-#define ILI9341_DTCTRLB                0xea
-#define ILI9341_PWRSEQ         0xed
-
-#define ILI9341_EN3GAM         0xf2
-#define ILI9341_PUMPCTRL       0xf7
-
-#define ILI9341_MADCTL_BGR     BIT(3)
-#define ILI9341_MADCTL_MV      BIT(5)
-#define ILI9341_MADCTL_MX      BIT(6)
-#define ILI9341_MADCTL_MY      BIT(7)
-
-static void mi0283qt_enable(struct drm_simple_display_pipe *pipe,
-                           struct drm_crtc_state *crtc_state,
-                           struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       u8 addr_mode;
-       int ret, idx;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       ret = mipi_dbi_poweron_conditional_reset(mipi);
-       if (ret < 0)
-               goto out_exit;
-       if (ret == 1)
-               goto out_enable;
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
-
-       mipi_dbi_command(mipi, ILI9341_PWCTRLB, 0x00, 0x83, 0x30);
-       mipi_dbi_command(mipi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81);
-       mipi_dbi_command(mipi, ILI9341_DTCTRLA, 0x85, 0x01, 0x79);
-       mipi_dbi_command(mipi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02);
-       mipi_dbi_command(mipi, ILI9341_PUMPCTRL, 0x20);
-       mipi_dbi_command(mipi, ILI9341_DTCTRLB, 0x00, 0x00);
-
-       /* Power Control */
-       mipi_dbi_command(mipi, ILI9341_PWCTRL1, 0x26);
-       mipi_dbi_command(mipi, ILI9341_PWCTRL2, 0x11);
-       /* VCOM */
-       mipi_dbi_command(mipi, ILI9341_VMCTRL1, 0x35, 0x3e);
-       mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0xbe);
-
-       /* Memory Access Control */
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
-
-       /* Frame Rate */
-       mipi_dbi_command(mipi, ILI9341_FRMCTR1, 0x00, 0x1b);
-
-       /* Gamma */
-       mipi_dbi_command(mipi, ILI9341_EN3GAM, 0x08);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
-       mipi_dbi_command(mipi, ILI9341_PGAMCTRL,
-                      0x1f, 0x1a, 0x18, 0x0a, 0x0f, 0x06, 0x45, 0x87,
-                      0x32, 0x0a, 0x07, 0x02, 0x07, 0x05, 0x00);
-       mipi_dbi_command(mipi, ILI9341_NGAMCTRL,
-                      0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3a, 0x78,
-                      0x4d, 0x05, 0x18, 0x0d, 0x38, 0x3a, 0x1f);
-
-       /* DDRAM */
-       mipi_dbi_command(mipi, ILI9341_ETMOD, 0x07);
-
-       /* Display */
-       mipi_dbi_command(mipi, ILI9341_DISCTRL, 0x0a, 0x82, 0x27, 0x00);
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
-       msleep(100);
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
-       msleep(100);
-
-out_enable:
-       /* The PiTFT (ili9340) has a hardware reset circuit that
-        * resets only on power-on and not on each reboot through
-        * a gpio like the rpi-display does.
-        * As a result, we need to always apply the rotation value
-        * regardless of the display "on/off" state.
-        */
-       switch (mipi->rotation) {
-       default:
-               addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
-                           ILI9341_MADCTL_MX;
-               break;
-       case 90:
-               addr_mode = ILI9341_MADCTL_MY;
-               break;
-       case 180:
-               addr_mode = ILI9341_MADCTL_MV;
-               break;
-       case 270:
-               addr_mode = ILI9341_MADCTL_MX;
-               break;
-       }
-       addr_mode |= ILI9341_MADCTL_BGR;
-       mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
-       .enable = mi0283qt_enable,
-       .disable = mipi_dbi_pipe_disable,
-       .update = mipi_dbi_pipe_update,
-       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_display_mode mi0283qt_mode = {
-       DRM_SIMPLE_MODE(320, 240, 58, 43),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
-
-static struct drm_driver mi0283qt_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
-       .fops                   = &mi0283qt_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .debugfs_init           = mipi_dbi_debugfs_init,
-       .name                   = "mi0283qt",
-       .desc                   = "Multi-Inno MI0283QT",
-       .date                   = "20160614",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id mi0283qt_of_match[] = {
-       { .compatible = "multi-inno,mi0283qt" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, mi0283qt_of_match);
-
-static const struct spi_device_id mi0283qt_id[] = {
-       { "mi0283qt", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, mi0283qt_id);
-
-static int mi0283qt_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *dc;
-       u32 rotation = 0;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &mi0283qt_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-
-       mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(mipi->reset)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return PTR_ERR(mipi->reset);
-       }
-
-       dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
-       if (IS_ERR(dc)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
-               return PTR_ERR(dc);
-       }
-
-       mipi->regulator = devm_regulator_get(dev, "power");
-       if (IS_ERR(mipi->regulator))
-               return PTR_ERR(mipi->regulator);
-
-       mipi->backlight = devm_of_find_backlight(dev);
-       if (IS_ERR(mipi->backlight))
-               return PTR_ERR(mipi->backlight);
-
-       device_property_read_u32(dev, "rotation", &rotation);
-
-       ret = mipi_dbi_spi_init(spi, mipi, dc);
-       if (ret)
-               return ret;
-
-       ret = mipi_dbi_init(mipi, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int mi0283qt_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void mi0283qt_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static int __maybe_unused mi0283qt_pm_suspend(struct device *dev)
-{
-       return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
-}
-
-static int __maybe_unused mi0283qt_pm_resume(struct device *dev)
-{
-       drm_mode_config_helper_resume(dev_get_drvdata(dev));
-
-       return 0;
-}
-
-static const struct dev_pm_ops mi0283qt_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(mi0283qt_pm_suspend, mi0283qt_pm_resume)
-};
-
-static struct spi_driver mi0283qt_spi_driver = {
-       .driver = {
-               .name = "mi0283qt",
-               .owner = THIS_MODULE,
-               .of_match_table = mi0283qt_of_match,
-               .pm = &mi0283qt_pm_ops,
-       },
-       .id_table = mi0283qt_id,
-       .probe = mi0283qt_probe,
-       .remove = mi0283qt_remove,
-       .shutdown = mi0283qt_shutdown,
-};
-module_spi_driver(mi0283qt_spi_driver);
-
-MODULE_DESCRIPTION("Multi-Inno MI0283QT DRM driver");
-MODULE_AUTHOR("Noralf Trønnes");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
deleted file mode 100644 (file)
index ca9da65..0000000
+++ /dev/null
@@ -1,1175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * MIPI Display Bus Interface (DBI) LCD controller support
- *
- * Copyright 2016 Noralf Trønnes
- */
-
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/dma-buf.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/regulator/consumer.h>
-#include <linux/spi/spi.h>
-
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_format_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_vblank.h>
-#include <drm/drm_rect.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-#include <video/mipi_display.h>
-
-#define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */
-
-#define DCS_POWER_MODE_DISPLAY                 BIT(2)
-#define DCS_POWER_MODE_DISPLAY_NORMAL_MODE     BIT(3)
-#define DCS_POWER_MODE_SLEEP_MODE              BIT(4)
-#define DCS_POWER_MODE_PARTIAL_MODE            BIT(5)
-#define DCS_POWER_MODE_IDLE_MODE               BIT(6)
-#define DCS_POWER_MODE_RESERVED_MASK           (BIT(0) | BIT(1) | BIT(7))
-
-/**
- * DOC: overview
- *
- * This library provides helpers for MIPI Display Bus Interface (DBI)
- * compatible display controllers.
- *
- * Many controllers for tiny lcd displays are MIPI compliant and can use this
- * library. If a controller uses registers 0x2A and 0x2B to set the area to
- * update and uses register 0x2C to write to frame memory, it is most likely
- * MIPI compliant.
- *
- * Only MIPI Type 1 displays are supported since a full frame memory is needed.
- *
- * There are 3 MIPI DBI implementation types:
- *
- * A. Motorola 6800 type parallel bus
- *
- * B. Intel 8080 type parallel bus
- *
- * C. SPI type with 3 options:
- *
- *    1. 9-bit with the Data/Command signal as the ninth bit
- *    2. Same as above except it's sent as 16 bits
- *    3. 8-bit with the Data/Command signal as a separate D/CX pin
- *
- * Currently mipi_dbi only supports Type C options 1 and 3 with
- * mipi_dbi_spi_init().
- */
-
-#define MIPI_DBI_DEBUG_COMMAND(cmd, data, len) \
-({ \
-       if (!len) \
-               DRM_DEBUG_DRIVER("cmd=%02x\n", cmd); \
-       else if (len <= 32) \
-               DRM_DEBUG_DRIVER("cmd=%02x, par=%*ph\n", cmd, (int)len, data);\
-       else \
-               DRM_DEBUG_DRIVER("cmd=%02x, len=%zu\n", cmd, len); \
-})
-
-static const u8 mipi_dbi_dcs_read_commands[] = {
-       MIPI_DCS_GET_DISPLAY_ID,
-       MIPI_DCS_GET_RED_CHANNEL,
-       MIPI_DCS_GET_GREEN_CHANNEL,
-       MIPI_DCS_GET_BLUE_CHANNEL,
-       MIPI_DCS_GET_DISPLAY_STATUS,
-       MIPI_DCS_GET_POWER_MODE,
-       MIPI_DCS_GET_ADDRESS_MODE,
-       MIPI_DCS_GET_PIXEL_FORMAT,
-       MIPI_DCS_GET_DISPLAY_MODE,
-       MIPI_DCS_GET_SIGNAL_MODE,
-       MIPI_DCS_GET_DIAGNOSTIC_RESULT,
-       MIPI_DCS_READ_MEMORY_START,
-       MIPI_DCS_READ_MEMORY_CONTINUE,
-       MIPI_DCS_GET_SCANLINE,
-       MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
-       MIPI_DCS_GET_CONTROL_DISPLAY,
-       MIPI_DCS_GET_POWER_SAVE,
-       MIPI_DCS_GET_CABC_MIN_BRIGHTNESS,
-       MIPI_DCS_READ_DDB_START,
-       MIPI_DCS_READ_DDB_CONTINUE,
-       0, /* sentinel */
-};
-
-static bool mipi_dbi_command_is_read(struct mipi_dbi *mipi, u8 cmd)
-{
-       unsigned int i;
-
-       if (!mipi->read_commands)
-               return false;
-
-       for (i = 0; i < 0xff; i++) {
-               if (!mipi->read_commands[i])
-                       return false;
-               if (cmd == mipi->read_commands[i])
-                       return true;
-       }
-
-       return false;
-}
-
-/**
- * mipi_dbi_command_read - MIPI DCS read command
- * @mipi: MIPI structure
- * @cmd: Command
- * @val: Value read
- *
- * Send MIPI DCS read command to the controller.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val)
-{
-       if (!mipi->read_commands)
-               return -EACCES;
-
-       if (!mipi_dbi_command_is_read(mipi, cmd))
-               return -EINVAL;
-
-       return mipi_dbi_command_buf(mipi, cmd, val, 1);
-}
-EXPORT_SYMBOL(mipi_dbi_command_read);
-
-/**
- * mipi_dbi_command_buf - MIPI DCS command with parameter(s) in an array
- * @mipi: MIPI structure
- * @cmd: Command
- * @data: Parameter buffer
- * @len: Buffer length
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len)
-{
-       u8 *cmdbuf;
-       int ret;
-
-       /* SPI requires dma-safe buffers */
-       cmdbuf = kmemdup(&cmd, 1, GFP_KERNEL);
-       if (!cmdbuf)
-               return -ENOMEM;
-
-       mutex_lock(&mipi->cmdlock);
-       ret = mipi->command(mipi, cmdbuf, data, len);
-       mutex_unlock(&mipi->cmdlock);
-
-       kfree(cmdbuf);
-
-       return ret;
-}
-EXPORT_SYMBOL(mipi_dbi_command_buf);
-
-/* This should only be used by mipi_dbi_command() */
-int mipi_dbi_command_stackbuf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len)
-{
-       u8 *buf;
-       int ret;
-
-       buf = kmemdup(data, len, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       ret = mipi_dbi_command_buf(mipi, cmd, buf, len);
-
-       kfree(buf);
-
-       return ret;
-}
-EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
-
-/**
- * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary
- * @dst: The destination buffer
- * @fb: The source framebuffer
- * @clip: Clipping rectangle of the area to be copied
- * @swap: When true, swap MSB/LSB of 16-bit values
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
-                     struct drm_rect *clip, bool swap)
-{
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
-       struct drm_format_name_buf format_name;
-       void *src = cma_obj->vaddr;
-       int ret = 0;
-
-       if (import_attach) {
-               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
-                                              DMA_FROM_DEVICE);
-               if (ret)
-                       return ret;
-       }
-
-       switch (fb->format->format) {
-       case DRM_FORMAT_RGB565:
-               if (swap)
-                       drm_fb_swab16(dst, src, fb, clip);
-               else
-                       drm_fb_memcpy(dst, src, fb, clip);
-               break;
-       case DRM_FORMAT_XRGB8888:
-               drm_fb_xrgb8888_to_rgb565(dst, src, fb, clip, swap);
-               break;
-       default:
-               dev_err_once(fb->dev->dev, "Format is not supported: %s\n",
-                            drm_get_format_name(fb->format->format,
-                                                &format_name));
-               return -EINVAL;
-       }
-
-       if (import_attach)
-               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
-                                            DMA_FROM_DEVICE);
-       return ret;
-}
-EXPORT_SYMBOL(mipi_dbi_buf_copy);
-
-static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
-{
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev);
-       unsigned int height = rect->y2 - rect->y1;
-       unsigned int width = rect->x2 - rect->x1;
-       bool swap = mipi->swap_bytes;
-       int idx, ret = 0;
-       bool full;
-       void *tr;
-
-       if (!mipi->enabled)
-               return;
-
-       if (!drm_dev_enter(fb->dev, &idx))
-               return;
-
-       full = width == fb->width && height == fb->height;
-
-       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
-
-       if (!mipi->dc || !full || swap ||
-           fb->format->format == DRM_FORMAT_XRGB8888) {
-               tr = mipi->tx_buf;
-               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
-               if (ret)
-                       goto err_msg;
-       } else {
-               tr = cma_obj->vaddr;
-       }
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
-                        (rect->x1 >> 8) & 0xff, rect->x1 & 0xff,
-                        ((rect->x2 - 1) >> 8) & 0xff, (rect->x2 - 1) & 0xff);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS,
-                        (rect->y1 >> 8) & 0xff, rect->y1 & 0xff,
-                        ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff);
-
-       ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr,
-                                  width * height * 2);
-err_msg:
-       if (ret)
-               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
-
-       drm_dev_exit(idx);
-}
-
-/**
- * mipi_dbi_pipe_update - Display pipe update helper
- * @pipe: Simple display pipe
- * @old_state: Old plane state
- *
- * This function handles framebuffer flushing and vblank events. Drivers can use
- * this as their &drm_simple_display_pipe_funcs->update callback.
- */
-void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
-                         struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = pipe->plane.state;
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct drm_rect rect;
-
-       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
-               mipi_dbi_fb_dirty(state->fb, &rect);
-
-       if (crtc->state->event) {
-               spin_lock_irq(&crtc->dev->event_lock);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               spin_unlock_irq(&crtc->dev->event_lock);
-               crtc->state->event = NULL;
-       }
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_update);
-
-/**
- * mipi_dbi_enable_flush - MIPI DBI enable helper
- * @mipi: MIPI DBI structure
- * @crtc_state: CRTC state
- * @plane_state: Plane state
- *
- * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and
- * enables the backlight. Drivers can use this in their
- * &drm_simple_display_pipe_funcs->enable callback.
- *
- * Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom
- * framebuffer flushing, can't use this function since they both use the same
- * flushing code.
- */
-void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
-                          struct drm_crtc_state *crtc_state,
-                          struct drm_plane_state *plane_state)
-{
-       struct drm_framebuffer *fb = plane_state->fb;
-       struct drm_rect rect = {
-               .x1 = 0,
-               .x2 = fb->width,
-               .y1 = 0,
-               .y2 = fb->height,
-       };
-       int idx;
-
-       if (!drm_dev_enter(&mipi->drm, &idx))
-               return;
-
-       mipi->enabled = true;
-       mipi_dbi_fb_dirty(fb, &rect);
-       backlight_enable(mipi->backlight);
-
-       drm_dev_exit(idx);
-}
-EXPORT_SYMBOL(mipi_dbi_enable_flush);
-
-static void mipi_dbi_blank(struct mipi_dbi *mipi)
-{
-       struct drm_device *drm = &mipi->drm;
-       u16 height = drm->mode_config.min_height;
-       u16 width = drm->mode_config.min_width;
-       size_t len = width * height * 2;
-       int idx;
-
-       if (!drm_dev_enter(drm, &idx))
-               return;
-
-       memset(mipi->tx_buf, 0, len);
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0,
-                        (width >> 8) & 0xFF, (width - 1) & 0xFF);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0,
-                        (height >> 8) & 0xFF, (height - 1) & 0xFF);
-       mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START,
-                            (u8 *)mipi->tx_buf, len);
-
-       drm_dev_exit(idx);
-}
-
-/**
- * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper
- * @pipe: Display pipe
- *
- * This function disables backlight if present, if not the display memory is
- * blanked. The regulator is disabled if in use. Drivers can use this as their
- * &drm_simple_display_pipe_funcs->disable callback.
- */
-void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-
-       if (!mipi->enabled)
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       mipi->enabled = false;
-
-       if (mipi->backlight)
-               backlight_disable(mipi->backlight);
-       else
-               mipi_dbi_blank(mipi);
-
-       if (mipi->regulator)
-               regulator_disable(mipi->regulator);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_disable);
-
-static const struct drm_mode_config_funcs mipi_dbi_mode_config_funcs = {
-       .fb_create = drm_gem_fb_create_with_dirty,
-       .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = drm_atomic_helper_commit,
-};
-
-static const uint32_t mipi_dbi_formats[] = {
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_XRGB8888,
-};
-
-/**
- * mipi_dbi_init - MIPI DBI initialization
- * @mipi: &mipi_dbi structure to initialize
- * @funcs: Display pipe functions
- * @mode: Display mode
- * @rotation: Initial rotation in degrees Counter Clock Wise
- *
- * This function sets up a &drm_simple_display_pipe with a &drm_connector that
- * has one fixed &drm_display_mode which is rotated according to @rotation.
- * This mode is used to set the mode config min/max width/height properties.
- * Additionally &mipi_dbi.tx_buf is allocated.
- *
- * Supported formats: Native RGB565 and emulated XRGB8888.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_init(struct mipi_dbi *mipi,
-                 const struct drm_simple_display_pipe_funcs *funcs,
-                 const struct drm_display_mode *mode, unsigned int rotation)
-{
-       size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16);
-       struct drm_device *drm = &mipi->drm;
-       int ret;
-
-       if (!mipi->command)
-               return -EINVAL;
-
-       mutex_init(&mipi->cmdlock);
-
-       mipi->tx_buf = devm_kmalloc(drm->dev, bufsize, GFP_KERNEL);
-       if (!mipi->tx_buf)
-               return -ENOMEM;
-
-       /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */
-       ret = tinydrm_display_pipe_init(drm, &mipi->pipe, funcs,
-                                       DRM_MODE_CONNECTOR_VIRTUAL,
-                                       mipi_dbi_formats,
-                                       ARRAY_SIZE(mipi_dbi_formats), mode,
-                                       rotation);
-       if (ret)
-               return ret;
-
-       drm_plane_enable_fb_damage_clips(&mipi->pipe.plane);
-
-       drm->mode_config.funcs = &mipi_dbi_mode_config_funcs;
-       drm->mode_config.preferred_depth = 16;
-       mipi->rotation = rotation;
-
-       DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
-                     drm->mode_config.preferred_depth, rotation);
-
-       return 0;
-}
-EXPORT_SYMBOL(mipi_dbi_init);
-
-/**
- * mipi_dbi_release - DRM driver release helper
- * @drm: DRM device
- *
- * This function finalizes and frees &mipi_dbi.
- *
- * Drivers can use this as their &drm_driver->release callback.
- */
-void mipi_dbi_release(struct drm_device *drm)
-{
-       struct mipi_dbi *dbi = drm_to_mipi_dbi(drm);
-
-       DRM_DEBUG_DRIVER("\n");
-
-       drm_mode_config_cleanup(drm);
-       drm_dev_fini(drm);
-       kfree(dbi);
-}
-EXPORT_SYMBOL(mipi_dbi_release);
-
-/**
- * mipi_dbi_hw_reset - Hardware reset of controller
- * @mipi: MIPI DBI structure
- *
- * Reset controller if the &mipi_dbi->reset gpio is set.
- */
-void mipi_dbi_hw_reset(struct mipi_dbi *mipi)
-{
-       if (!mipi->reset)
-               return;
-
-       gpiod_set_value_cansleep(mipi->reset, 0);
-       usleep_range(20, 1000);
-       gpiod_set_value_cansleep(mipi->reset, 1);
-       msleep(120);
-}
-EXPORT_SYMBOL(mipi_dbi_hw_reset);
-
-/**
- * mipi_dbi_display_is_on - Check if display is on
- * @mipi: MIPI DBI structure
- *
- * This function checks the Power Mode register (if readable) to see if
- * display output is turned on. This can be used to see if the bootloader
- * has already turned on the display avoiding flicker when the pipeline is
- * enabled.
- *
- * Returns:
- * true if the display can be verified to be on, false otherwise.
- */
-bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
-{
-       u8 val;
-
-       if (mipi_dbi_command_read(mipi, MIPI_DCS_GET_POWER_MODE, &val))
-               return false;
-
-       val &= ~DCS_POWER_MODE_RESERVED_MASK;
-
-       /* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
-       if (val != (DCS_POWER_MODE_DISPLAY |
-           DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
-               return false;
-
-       DRM_DEBUG_DRIVER("Display is ON\n");
-
-       return true;
-}
-EXPORT_SYMBOL(mipi_dbi_display_is_on);
-
-static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond)
-{
-       struct device *dev = mipi->drm.dev;
-       int ret;
-
-       if (mipi->regulator) {
-               ret = regulator_enable(mipi->regulator);
-               if (ret) {
-                       DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
-                       return ret;
-               }
-       }
-
-       if (cond && mipi_dbi_display_is_on(mipi))
-               return 1;
-
-       mipi_dbi_hw_reset(mipi);
-       ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
-       if (ret) {
-               DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
-               if (mipi->regulator)
-                       regulator_disable(mipi->regulator);
-               return ret;
-       }
-
-       /*
-        * If we did a hw reset, we know the controller is in Sleep mode and
-        * per MIPI DSC spec should wait 5ms after soft reset. If we didn't,
-        * we assume worst case and wait 120ms.
-        */
-       if (mipi->reset)
-               usleep_range(5000, 20000);
-       else
-               msleep(120);
-
-       return 0;
-}
-
-/**
- * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
- * @mipi: MIPI DBI structure
- *
- * This function enables the regulator if used and does a hardware and software
- * reset.
- *
- * Returns:
- * Zero on success, or a negative error code.
- */
-int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
-{
-       return mipi_dbi_poweron_reset_conditional(mipi, false);
-}
-EXPORT_SYMBOL(mipi_dbi_poweron_reset);
-
-/**
- * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
- * @mipi: MIPI DBI structure
- *
- * This function enables the regulator if used and if the display is off, it
- * does a hardware and software reset. If mipi_dbi_display_is_on() determines
- * that the display is on, no reset is performed.
- *
- * Returns:
- * Zero if the controller was reset, 1 if the display was already on, or a
- * negative error code.
- */
-int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
-{
-       return mipi_dbi_poweron_reset_conditional(mipi, true);
-}
-EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
-
-#if IS_ENABLED(CONFIG_SPI)
-
-/**
- * mipi_dbi_spi_cmd_max_speed - get the maximum SPI bus speed
- * @spi: SPI device
- * @len: The transfer buffer length.
- *
- * Many controllers have a max speed of 10MHz, but can be pushed way beyond
- * that. Increase reliability by running pixel data at max speed and the rest
- * at 10MHz, preventing transfer glitches from messing up the init settings.
- */
-u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len)
-{
-       if (len > 64)
-               return 0; /* use default */
-
-       return min_t(u32, 10000000, spi->max_speed_hz);
-}
-EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
-
-/*
- * MIPI DBI Type C Option 1
- *
- * If the SPI controller doesn't have 9 bits per word support,
- * use blocks of 9 bytes to send 8x 9-bit words using a 8-bit SPI transfer.
- * Pad partial blocks with MIPI_DCS_NOP (zero).
- * This is how the D/C bit (x) is added:
- *     x7654321
- *     0x765432
- *     10x76543
- *     210x7654
- *     3210x765
- *     43210x76
- *     543210x7
- *     6543210x
- *     76543210
- */
-
-static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc,
-                                  const void *buf, size_t len,
-                                  unsigned int bpw)
-{
-       bool swap_bytes = (bpw == 16 && tinydrm_machine_little_endian());
-       size_t chunk, max_chunk = mipi->tx_buf9_len;
-       struct spi_device *spi = mipi->spi;
-       struct spi_transfer tr = {
-               .tx_buf = mipi->tx_buf9,
-               .bits_per_word = 8,
-       };
-       struct spi_message m;
-       const u8 *src = buf;
-       int i, ret;
-       u8 *dst;
-
-       if (drm_debug & DRM_UT_DRIVER)
-               pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
-                        __func__, dc, max_chunk);
-
-       tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len);
-       spi_message_init_with_transfers(&m, &tr, 1);
-
-       if (!dc) {
-               if (WARN_ON_ONCE(len != 1))
-                       return -EINVAL;
-
-               /* Command: pad no-op's (zeroes) at beginning of block */
-               dst = mipi->tx_buf9;
-               memset(dst, 0, 9);
-               dst[8] = *src;
-               tr.len = 9;
-
-               tinydrm_dbg_spi_message(spi, &m);
-
-               return spi_sync(spi, &m);
-       }
-
-       /* max with room for adding one bit per byte */
-       max_chunk = max_chunk / 9 * 8;
-       /* but no bigger than len */
-       max_chunk = min(max_chunk, len);
-       /* 8 byte blocks */
-       max_chunk = max_t(size_t, 8, max_chunk & ~0x7);
-
-       while (len) {
-               size_t added = 0;
-
-               chunk = min(len, max_chunk);
-               len -= chunk;
-               dst = mipi->tx_buf9;
-
-               if (chunk < 8) {
-                       u8 val, carry = 0;
-
-                       /* Data: pad no-op's (zeroes) at end of block */
-                       memset(dst, 0, 9);
-
-                       if (swap_bytes) {
-                               for (i = 1; i < (chunk + 1); i++) {
-                                       val = src[1];
-                                       *dst++ = carry | BIT(8 - i) | (val >> i);
-                                       carry = val << (8 - i);
-                                       i++;
-                                       val = src[0];
-                                       *dst++ = carry | BIT(8 - i) | (val >> i);
-                                       carry = val << (8 - i);
-                                       src += 2;
-                               }
-                               *dst++ = carry;
-                       } else {
-                               for (i = 1; i < (chunk + 1); i++) {
-                                       val = *src++;
-                                       *dst++ = carry | BIT(8 - i) | (val >> i);
-                                       carry = val << (8 - i);
-                               }
-                               *dst++ = carry;
-                       }
-
-                       chunk = 8;
-                       added = 1;
-               } else {
-                       for (i = 0; i < chunk; i += 8) {
-                               if (swap_bytes) {
-                                       *dst++ =                 BIT(7) | (src[1] >> 1);
-                                       *dst++ = (src[1] << 7) | BIT(6) | (src[0] >> 2);
-                                       *dst++ = (src[0] << 6) | BIT(5) | (src[3] >> 3);
-                                       *dst++ = (src[3] << 5) | BIT(4) | (src[2] >> 4);
-                                       *dst++ = (src[2] << 4) | BIT(3) | (src[5] >> 5);
-                                       *dst++ = (src[5] << 3) | BIT(2) | (src[4] >> 6);
-                                       *dst++ = (src[4] << 2) | BIT(1) | (src[7] >> 7);
-                                       *dst++ = (src[7] << 1) | BIT(0);
-                                       *dst++ = src[6];
-                               } else {
-                                       *dst++ =                 BIT(7) | (src[0] >> 1);
-                                       *dst++ = (src[0] << 7) | BIT(6) | (src[1] >> 2);
-                                       *dst++ = (src[1] << 6) | BIT(5) | (src[2] >> 3);
-                                       *dst++ = (src[2] << 5) | BIT(4) | (src[3] >> 4);
-                                       *dst++ = (src[3] << 4) | BIT(3) | (src[4] >> 5);
-                                       *dst++ = (src[4] << 3) | BIT(2) | (src[5] >> 6);
-                                       *dst++ = (src[5] << 2) | BIT(1) | (src[6] >> 7);
-                                       *dst++ = (src[6] << 1) | BIT(0);
-                                       *dst++ = src[7];
-                               }
-
-                               src += 8;
-                               added++;
-                       }
-               }
-
-               tr.len = chunk + added;
-
-               tinydrm_dbg_spi_message(spi, &m);
-               ret = spi_sync(spi, &m);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc,
-                                 const void *buf, size_t len,
-                                 unsigned int bpw)
-{
-       struct spi_device *spi = mipi->spi;
-       struct spi_transfer tr = {
-               .bits_per_word = 9,
-       };
-       const u16 *src16 = buf;
-       const u8 *src8 = buf;
-       struct spi_message m;
-       size_t max_chunk;
-       u16 *dst16;
-       int ret;
-
-       if (!tinydrm_spi_bpw_supported(spi, 9))
-               return mipi_dbi_spi1e_transfer(mipi, dc, buf, len, bpw);
-
-       tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len);
-       max_chunk = mipi->tx_buf9_len;
-       dst16 = mipi->tx_buf9;
-
-       if (drm_debug & DRM_UT_DRIVER)
-               pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
-                        __func__, dc, max_chunk);
-
-       max_chunk = min(max_chunk / 2, len);
-
-       spi_message_init_with_transfers(&m, &tr, 1);
-       tr.tx_buf = dst16;
-
-       while (len) {
-               size_t chunk = min(len, max_chunk);
-               unsigned int i;
-
-               if (bpw == 16 && tinydrm_machine_little_endian()) {
-                       for (i = 0; i < (chunk * 2); i += 2) {
-                               dst16[i]     = *src16 >> 8;
-                               dst16[i + 1] = *src16++ & 0xFF;
-                               if (dc) {
-                                       dst16[i]     |= 0x0100;
-                                       dst16[i + 1] |= 0x0100;
-                               }
-                       }
-               } else {
-                       for (i = 0; i < chunk; i++) {
-                               dst16[i] = *src8++;
-                               if (dc)
-                                       dst16[i] |= 0x0100;
-                       }
-               }
-
-               tr.len = chunk;
-               len -= chunk;
-
-               tinydrm_dbg_spi_message(spi, &m);
-               ret = spi_sync(spi, &m);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int mipi_dbi_typec1_command(struct mipi_dbi *mipi, u8 *cmd,
-                                  u8 *parameters, size_t num)
-{
-       unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8;
-       int ret;
-
-       if (mipi_dbi_command_is_read(mipi, *cmd))
-               return -ENOTSUPP;
-
-       MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num);
-
-       ret = mipi_dbi_spi1_transfer(mipi, 0, cmd, 1, 8);
-       if (ret || !num)
-               return ret;
-
-       return mipi_dbi_spi1_transfer(mipi, 1, parameters, num, bpw);
-}
-
-/* MIPI DBI Type C Option 3 */
-
-static int mipi_dbi_typec3_command_read(struct mipi_dbi *mipi, u8 *cmd,
-                                       u8 *data, size_t len)
-{
-       struct spi_device *spi = mipi->spi;
-       u32 speed_hz = min_t(u32, MIPI_DBI_MAX_SPI_READ_SPEED,
-                            spi->max_speed_hz / 2);
-       struct spi_transfer tr[2] = {
-               {
-                       .speed_hz = speed_hz,
-                       .tx_buf = cmd,
-                       .len = 1,
-               }, {
-                       .speed_hz = speed_hz,
-                       .len = len,
-               },
-       };
-       struct spi_message m;
-       u8 *buf;
-       int ret;
-
-       if (!len)
-               return -EINVAL;
-
-       /*
-        * Support non-standard 24-bit and 32-bit Nokia read commands which
-        * start with a dummy clock, so we need to read an extra byte.
-        */
-       if (*cmd == MIPI_DCS_GET_DISPLAY_ID ||
-           *cmd == MIPI_DCS_GET_DISPLAY_STATUS) {
-               if (!(len == 3 || len == 4))
-                       return -EINVAL;
-
-               tr[1].len = len + 1;
-       }
-
-       buf = kmalloc(tr[1].len, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       tr[1].rx_buf = buf;
-       gpiod_set_value_cansleep(mipi->dc, 0);
-
-       spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr));
-       ret = spi_sync(spi, &m);
-       if (ret)
-               goto err_free;
-
-       tinydrm_dbg_spi_message(spi, &m);
-
-       if (tr[1].len == len) {
-               memcpy(data, buf, len);
-       } else {
-               unsigned int i;
-
-               for (i = 0; i < len; i++)
-                       data[i] = (buf[i] << 1) | !!(buf[i + 1] & BIT(7));
-       }
-
-       MIPI_DBI_DEBUG_COMMAND(*cmd, data, len);
-
-err_free:
-       kfree(buf);
-
-       return ret;
-}
-
-static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, u8 *cmd,
-                                  u8 *par, size_t num)
-{
-       struct spi_device *spi = mipi->spi;
-       unsigned int bpw = 8;
-       u32 speed_hz;
-       int ret;
-
-       if (mipi_dbi_command_is_read(mipi, *cmd))
-               return mipi_dbi_typec3_command_read(mipi, cmd, par, num);
-
-       MIPI_DBI_DEBUG_COMMAND(*cmd, par, num);
-
-       gpiod_set_value_cansleep(mipi->dc, 0);
-       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
-       ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, cmd, 1);
-       if (ret || !num)
-               return ret;
-
-       if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes)
-               bpw = 16;
-
-       gpiod_set_value_cansleep(mipi->dc, 1);
-       speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
-
-       return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num);
-}
-
-/**
- * mipi_dbi_spi_init - Initialize MIPI DBI SPI interfaced controller
- * @spi: SPI device
- * @mipi: &mipi_dbi structure to initialize
- * @dc: D/C gpio (optional)
- *
- * This function sets &mipi_dbi->command, enables &mipi->read_commands for the
- * usual read commands. It should be followed by a call to mipi_dbi_init() or
- * a driver-specific init.
- *
- * If @dc is set, a Type C Option 3 interface is assumed, if not
- * Type C Option 1.
- *
- * If the SPI master driver doesn't support the necessary bits per word,
- * the following transformation is used:
- *
- * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command.
- * - 16-bit: if big endian send as 8-bit, if little endian swap bytes
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi,
-                     struct gpio_desc *dc)
-{
-       size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0);
-       struct device *dev = &spi->dev;
-       int ret;
-
-       if (tx_size < 16) {
-               DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size);
-               return -EINVAL;
-       }
-
-       /*
-        * Even though it's not the SPI device that does DMA (the master does),
-        * the dma mask is necessary for the dma_alloc_wc() in
-        * drm_gem_cma_create(). The dma_addr returned will be a physical
-        * address which might be different from the bus address, but this is
-        * not a problem since the address will not be used.
-        * The virtual address is used in the transfer and the SPI core
-        * re-maps it on the SPI master device using the DMA streaming API
-        * (spi_map_buf()).
-        */
-       if (!dev->coherent_dma_mask) {
-               ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
-               if (ret) {
-                       dev_warn(dev, "Failed to set dma mask %d\n", ret);
-                       return ret;
-               }
-       }
-
-       mipi->spi = spi;
-       mipi->read_commands = mipi_dbi_dcs_read_commands;
-
-       if (dc) {
-               mipi->command = mipi_dbi_typec3_command;
-               mipi->dc = dc;
-               if (tinydrm_machine_little_endian() &&
-                   !tinydrm_spi_bpw_supported(spi, 16))
-                       mipi->swap_bytes = true;
-       } else {
-               mipi->command = mipi_dbi_typec1_command;
-               mipi->tx_buf9_len = tx_size;
-               mipi->tx_buf9 = devm_kmalloc(dev, tx_size, GFP_KERNEL);
-               if (!mipi->tx_buf9)
-                       return -ENOMEM;
-       }
-
-       DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
-
-       return 0;
-}
-EXPORT_SYMBOL(mipi_dbi_spi_init);
-
-#endif /* CONFIG_SPI */
-
-#ifdef CONFIG_DEBUG_FS
-
-static ssize_t mipi_dbi_debugfs_command_write(struct file *file,
-                                             const char __user *ubuf,
-                                             size_t count, loff_t *ppos)
-{
-       struct seq_file *m = file->private_data;
-       struct mipi_dbi *mipi = m->private;
-       u8 val, cmd = 0, parameters[64];
-       char *buf, *pos, *token;
-       unsigned int i;
-       int ret, idx;
-
-       if (!drm_dev_enter(&mipi->drm, &idx))
-               return -ENODEV;
-
-       buf = memdup_user_nul(ubuf, count);
-       if (IS_ERR(buf)) {
-               ret = PTR_ERR(buf);
-               goto err_exit;
-       }
-
-       /* strip trailing whitespace */
-       for (i = count - 1; i > 0; i--)
-               if (isspace(buf[i]))
-                       buf[i] = '\0';
-               else
-                       break;
-       i = 0;
-       pos = buf;
-       while (pos) {
-               token = strsep(&pos, " ");
-               if (!token) {
-                       ret = -EINVAL;
-                       goto err_free;
-               }
-
-               ret = kstrtou8(token, 16, &val);
-               if (ret < 0)
-                       goto err_free;
-
-               if (token == buf)
-                       cmd = val;
-               else
-                       parameters[i++] = val;
-
-               if (i == 64) {
-                       ret = -E2BIG;
-                       goto err_free;
-               }
-       }
-
-       ret = mipi_dbi_command_buf(mipi, cmd, parameters, i);
-
-err_free:
-       kfree(buf);
-err_exit:
-       drm_dev_exit(idx);
-
-       return ret < 0 ? ret : count;
-}
-
-static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused)
-{
-       struct mipi_dbi *mipi = m->private;
-       u8 cmd, val[4];
-       int ret, idx;
-       size_t len;
-
-       if (!drm_dev_enter(&mipi->drm, &idx))
-               return -ENODEV;
-
-       for (cmd = 0; cmd < 255; cmd++) {
-               if (!mipi_dbi_command_is_read(mipi, cmd))
-                       continue;
-
-               switch (cmd) {
-               case MIPI_DCS_READ_MEMORY_START:
-               case MIPI_DCS_READ_MEMORY_CONTINUE:
-                       len = 2;
-                       break;
-               case MIPI_DCS_GET_DISPLAY_ID:
-                       len = 3;
-                       break;
-               case MIPI_DCS_GET_DISPLAY_STATUS:
-                       len = 4;
-                       break;
-               default:
-                       len = 1;
-                       break;
-               }
-
-               seq_printf(m, "%02x: ", cmd);
-               ret = mipi_dbi_command_buf(mipi, cmd, val, len);
-               if (ret) {
-                       seq_puts(m, "XX\n");
-                       continue;
-               }
-               seq_printf(m, "%*phN\n", (int)len, val);
-       }
-
-       drm_dev_exit(idx);
-
-       return 0;
-}
-
-static int mipi_dbi_debugfs_command_open(struct inode *inode,
-                                        struct file *file)
-{
-       return single_open(file, mipi_dbi_debugfs_command_show,
-                          inode->i_private);
-}
-
-static const struct file_operations mipi_dbi_debugfs_command_fops = {
-       .owner = THIS_MODULE,
-       .open = mipi_dbi_debugfs_command_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .write = mipi_dbi_debugfs_command_write,
-};
-
-/**
- * mipi_dbi_debugfs_init - Create debugfs entries
- * @minor: DRM minor
- *
- * This function creates a 'command' debugfs file for sending commands to the
- * controller or getting the read command values.
- * Drivers can use this as their &drm_driver->debugfs_init callback.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_debugfs_init(struct drm_minor *minor)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(minor->dev);
-       umode_t mode = S_IFREG | S_IWUSR;
-
-       if (mipi->read_commands)
-               mode |= S_IRUGO;
-       debugfs_create_file("command", mode, minor->debugfs_root, mipi,
-                           &mipi_dbi_debugfs_command_fops);
-
-       return 0;
-}
-EXPORT_SYMBOL(mipi_dbi_debugfs_init);
-
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
deleted file mode 100644 (file)
index 97a874b..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DRM driver for Pervasive Displays RePaper branded e-ink panels
- *
- * Copyright 2013-2017 Pervasive Displays, Inc.
- * Copyright 2017 Noralf Trønnes
- *
- * The driver supports:
- * Material Film: Aurora Mb (V231)
- * Driver IC: G2 (eTC)
- *
- * The controller code was taken from the userspace driver:
- * https://github.com/repaper/gratis
- */
-
-#include <linux/delay.h>
-#include <linux/dma-buf.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/sched/clock.h>
-#include <linux/spi/spi.h>
-#include <linux/thermal.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_format_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_rect.h>
-#include <drm/drm_vblank.h>
-#include <drm/drm_simple_kms_helper.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-
-#define REPAPER_RID_G2_COG_ID  0x12
-
-enum repaper_model {
-       E1144CS021 = 1,
-       E1190CS021,
-       E2200CS021,
-       E2271CS021,
-};
-
-enum repaper_stage {         /* Image pixel -> Display pixel */
-       REPAPER_COMPENSATE,  /* B -> W, W -> B (Current Image) */
-       REPAPER_WHITE,       /* B -> N, W -> W (Current Image) */
-       REPAPER_INVERSE,     /* B -> N, W -> B (New Image) */
-       REPAPER_NORMAL       /* B -> B, W -> W (New Image) */
-};
-
-enum repaper_epd_border_byte {
-       REPAPER_BORDER_BYTE_NONE,
-       REPAPER_BORDER_BYTE_ZERO,
-       REPAPER_BORDER_BYTE_SET,
-};
-
-struct repaper_epd {
-       struct drm_device drm;
-       struct drm_simple_display_pipe pipe;
-       struct spi_device *spi;
-
-       struct gpio_desc *panel_on;
-       struct gpio_desc *border;
-       struct gpio_desc *discharge;
-       struct gpio_desc *reset;
-       struct gpio_desc *busy;
-
-       struct thermal_zone_device *thermal;
-
-       unsigned int height;
-       unsigned int width;
-       unsigned int bytes_per_scan;
-       const u8 *channel_select;
-       unsigned int stage_time;
-       unsigned int factored_stage_time;
-       bool middle_scan;
-       bool pre_border_byte;
-       enum repaper_epd_border_byte border_byte;
-
-       u8 *line_buffer;
-       void *current_frame;
-
-       bool enabled;
-       bool cleared;
-       bool partial;
-};
-
-static inline struct repaper_epd *drm_to_epd(struct drm_device *drm)
-{
-       return container_of(drm, struct repaper_epd, drm);
-}
-
-static int repaper_spi_transfer(struct spi_device *spi, u8 header,
-                               const void *tx, void *rx, size_t len)
-{
-       void *txbuf = NULL, *rxbuf = NULL;
-       struct spi_transfer tr[2] = {};
-       u8 *headerbuf;
-       int ret;
-
-       headerbuf = kmalloc(1, GFP_KERNEL);
-       if (!headerbuf)
-               return -ENOMEM;
-
-       headerbuf[0] = header;
-       tr[0].tx_buf = headerbuf;
-       tr[0].len = 1;
-
-       /* Stack allocated tx? */
-       if (tx && len <= 32) {
-               txbuf = kmemdup(tx, len, GFP_KERNEL);
-               if (!txbuf) {
-                       ret = -ENOMEM;
-                       goto out_free;
-               }
-       }
-
-       if (rx) {
-               rxbuf = kmalloc(len, GFP_KERNEL);
-               if (!rxbuf) {
-                       ret = -ENOMEM;
-                       goto out_free;
-               }
-       }
-
-       tr[1].tx_buf = txbuf ? txbuf : tx;
-       tr[1].rx_buf = rxbuf;
-       tr[1].len = len;
-
-       ndelay(80);
-       ret = spi_sync_transfer(spi, tr, 2);
-       if (rx && !ret)
-               memcpy(rx, rxbuf, len);
-
-out_free:
-       kfree(headerbuf);
-       kfree(txbuf);
-       kfree(rxbuf);
-
-       return ret;
-}
-
-static int repaper_write_buf(struct spi_device *spi, u8 reg,
-                            const u8 *buf, size_t len)
-{
-       int ret;
-
-       ret = repaper_spi_transfer(spi, 0x70, &reg, NULL, 1);
-       if (ret)
-               return ret;
-
-       return repaper_spi_transfer(spi, 0x72, buf, NULL, len);
-}
-
-static int repaper_write_val(struct spi_device *spi, u8 reg, u8 val)
-{
-       return repaper_write_buf(spi, reg, &val, 1);
-}
-
-static int repaper_read_val(struct spi_device *spi, u8 reg)
-{
-       int ret;
-       u8 val;
-
-       ret = repaper_spi_transfer(spi, 0x70, &reg, NULL, 1);
-       if (ret)
-               return ret;
-
-       ret = repaper_spi_transfer(spi, 0x73, NULL, &val, 1);
-
-       return ret ? ret : val;
-}
-
-static int repaper_read_id(struct spi_device *spi)
-{
-       int ret;
-       u8 id;
-
-       ret = repaper_spi_transfer(spi, 0x71, NULL, &id, 1);
-
-       return ret ? ret : id;
-}
-
-static void repaper_spi_mosi_low(struct spi_device *spi)
-{
-       const u8 buf[1] = { 0 };
-
-       spi_write(spi, buf, 1);
-}
-
-/* pixels on display are numbered from 1 so even is actually bits 1,3,5,... */
-static void repaper_even_pixels(struct repaper_epd *epd, u8 **pp,
-                               const u8 *data, u8 fixed_value, const u8 *mask,
-                               enum repaper_stage stage)
-{
-       unsigned int b;
-
-       for (b = 0; b < (epd->width / 8); b++) {
-               if (data) {
-                       u8 pixels = data[b] & 0xaa;
-                       u8 pixel_mask = 0xff;
-                       u8 p1, p2, p3, p4;
-
-                       if (mask) {
-                               pixel_mask = (mask[b] ^ pixels) & 0xaa;
-                               pixel_mask |= pixel_mask >> 1;
-                       }
-
-                       switch (stage) {
-                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
-                               pixels = 0xaa | ((pixels ^ 0xaa) >> 1);
-                               break;
-                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
-                               pixels = 0x55 + ((pixels ^ 0xaa) >> 1);
-                               break;
-                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
-                               pixels = 0x55 | (pixels ^ 0xaa);
-                               break;
-                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
-                               pixels = 0xaa | (pixels >> 1);
-                               break;
-                       }
-
-                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55);
-                       p1 = (pixels >> 6) & 0x03;
-                       p2 = (pixels >> 4) & 0x03;
-                       p3 = (pixels >> 2) & 0x03;
-                       p4 = (pixels >> 0) & 0x03;
-                       pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6);
-                       *(*pp)++ = pixels;
-               } else {
-                       *(*pp)++ = fixed_value;
-               }
-       }
-}
-
-/* pixels on display are numbered from 1 so odd is actually bits 0,2,4,... */
-static void repaper_odd_pixels(struct repaper_epd *epd, u8 **pp,
-                              const u8 *data, u8 fixed_value, const u8 *mask,
-                              enum repaper_stage stage)
-{
-       unsigned int b;
-
-       for (b = epd->width / 8; b > 0; b--) {
-               if (data) {
-                       u8 pixels = data[b - 1] & 0x55;
-                       u8 pixel_mask = 0xff;
-
-                       if (mask) {
-                               pixel_mask = (mask[b - 1] ^ pixels) & 0x55;
-                               pixel_mask |= pixel_mask << 1;
-                       }
-
-                       switch (stage) {
-                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
-                               pixels = 0xaa | (pixels ^ 0x55);
-                               break;
-                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
-                               pixels = 0x55 + (pixels ^ 0x55);
-                               break;
-                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
-                               pixels = 0x55 | ((pixels ^ 0x55) << 1);
-                               break;
-                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
-                               pixels = 0xaa | pixels;
-                               break;
-                       }
-
-                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55);
-                       *(*pp)++ = pixels;
-               } else {
-                       *(*pp)++ = fixed_value;
-               }
-       }
-}
-
-/* interleave bits: (byte)76543210 -> (16 bit).7.6.5.4.3.2.1 */
-static inline u16 repaper_interleave_bits(u16 value)
-{
-       value = (value | (value << 4)) & 0x0f0f;
-       value = (value | (value << 2)) & 0x3333;
-       value = (value | (value << 1)) & 0x5555;
-
-       return value;
-}
-
-/* pixels on display are numbered from 1 */
-static void repaper_all_pixels(struct repaper_epd *epd, u8 **pp,
-                              const u8 *data, u8 fixed_value, const u8 *mask,
-                              enum repaper_stage stage)
-{
-       unsigned int b;
-
-       for (b = epd->width / 8; b > 0; b--) {
-               if (data) {
-                       u16 pixels = repaper_interleave_bits(data[b - 1]);
-                       u16 pixel_mask = 0xffff;
-
-                       if (mask) {
-                               pixel_mask = repaper_interleave_bits(mask[b - 1]);
-
-                               pixel_mask = (pixel_mask ^ pixels) & 0x5555;
-                               pixel_mask |= pixel_mask << 1;
-                       }
-
-                       switch (stage) {
-                       case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */
-                               pixels = 0xaaaa | (pixels ^ 0x5555);
-                               break;
-                       case REPAPER_WHITE:      /* B -> N, W -> W (Current) */
-                               pixels = 0x5555 + (pixels ^ 0x5555);
-                               break;
-                       case REPAPER_INVERSE:    /* B -> N, W -> B (New) */
-                               pixels = 0x5555 | ((pixels ^ 0x5555) << 1);
-                               break;
-                       case REPAPER_NORMAL:     /* B -> B, W -> W (New) */
-                               pixels = 0xaaaa | pixels;
-                               break;
-                       }
-
-                       pixels = (pixels & pixel_mask) | (~pixel_mask & 0x5555);
-                       *(*pp)++ = pixels >> 8;
-                       *(*pp)++ = pixels;
-               } else {
-                       *(*pp)++ = fixed_value;
-                       *(*pp)++ = fixed_value;
-               }
-       }
-}
-
-/* output one line of scan and data bytes to the display */
-static void repaper_one_line(struct repaper_epd *epd, unsigned int line,
-                            const u8 *data, u8 fixed_value, const u8 *mask,
-                            enum repaper_stage stage)
-{
-       u8 *p = epd->line_buffer;
-       unsigned int b;
-
-       repaper_spi_mosi_low(epd->spi);
-
-       if (epd->pre_border_byte)
-               *p++ = 0x00;
-
-       if (epd->middle_scan) {
-               /* data bytes */
-               repaper_odd_pixels(epd, &p, data, fixed_value, mask, stage);
-
-               /* scan line */
-               for (b = epd->bytes_per_scan; b > 0; b--) {
-                       if (line / 4 == b - 1)
-                               *p++ = 0x03 << (2 * (line & 0x03));
-                       else
-                               *p++ = 0x00;
-               }
-
-               /* data bytes */
-               repaper_even_pixels(epd, &p, data, fixed_value, mask, stage);
-       } else {
-               /*
-                * even scan line, but as lines on display are numbered from 1,
-                * line: 1,3,5,...
-                */
-               for (b = 0; b < epd->bytes_per_scan; b++) {
-                       if (0 != (line & 0x01) && line / 8 == b)
-                               *p++ = 0xc0 >> (line & 0x06);
-                       else
-                               *p++ = 0x00;
-               }
-
-               /* data bytes */
-               repaper_all_pixels(epd, &p, data, fixed_value, mask, stage);
-
-               /*
-                * odd scan line, but as lines on display are numbered from 1,
-                * line: 0,2,4,6,...
-                */
-               for (b = epd->bytes_per_scan; b > 0; b--) {
-                       if (0 == (line & 0x01) && line / 8 == b - 1)
-                               *p++ = 0x03 << (line & 0x06);
-                       else
-                               *p++ = 0x00;
-               }
-       }
-
-       switch (epd->border_byte) {
-       case REPAPER_BORDER_BYTE_NONE:
-               break;
-
-       case REPAPER_BORDER_BYTE_ZERO:
-               *p++ = 0x00;
-               break;
-
-       case REPAPER_BORDER_BYTE_SET:
-               switch (stage) {
-               case REPAPER_COMPENSATE:
-               case REPAPER_WHITE:
-               case REPAPER_INVERSE:
-                       *p++ = 0x00;
-                       break;
-               case REPAPER_NORMAL:
-                       *p++ = 0xaa;
-                       break;
-               }
-               break;
-       }
-
-       repaper_write_buf(epd->spi, 0x0a, epd->line_buffer,
-                         p - epd->line_buffer);
-
-       /* Output data to panel */
-       repaper_write_val(epd->spi, 0x02, 0x07);
-
-       repaper_spi_mosi_low(epd->spi);
-}
-
-static void repaper_frame_fixed(struct repaper_epd *epd, u8 fixed_value,
-                               enum repaper_stage stage)
-{
-       unsigned int line;
-
-       for (line = 0; line < epd->height; line++)
-               repaper_one_line(epd, line, NULL, fixed_value, NULL, stage);
-}
-
-static void repaper_frame_data(struct repaper_epd *epd, const u8 *image,
-                              const u8 *mask, enum repaper_stage stage)
-{
-       unsigned int line;
-
-       if (!mask) {
-               for (line = 0; line < epd->height; line++) {
-                       repaper_one_line(epd, line,
-                                        &image[line * (epd->width / 8)],
-                                        0, NULL, stage);
-               }
-       } else {
-               for (line = 0; line < epd->height; line++) {
-                       size_t n = line * epd->width / 8;
-
-                       repaper_one_line(epd, line, &image[n], 0, &mask[n],
-                                        stage);
-               }
-       }
-}
-
-static void repaper_frame_fixed_repeat(struct repaper_epd *epd, u8 fixed_value,
-                                      enum repaper_stage stage)
-{
-       u64 start = local_clock();
-       u64 end = start + (epd->factored_stage_time * 1000 * 1000);
-
-       do {
-               repaper_frame_fixed(epd, fixed_value, stage);
-       } while (local_clock() < end);
-}
-
-static void repaper_frame_data_repeat(struct repaper_epd *epd, const u8 *image,
-                                     const u8 *mask, enum repaper_stage stage)
-{
-       u64 start = local_clock();
-       u64 end = start + (epd->factored_stage_time * 1000 * 1000);
-
-       do {
-               repaper_frame_data(epd, image, mask, stage);
-       } while (local_clock() < end);
-}
-
-static void repaper_get_temperature(struct repaper_epd *epd)
-{
-       int ret, temperature = 0;
-       unsigned int factor10x;
-
-       if (!epd->thermal)
-               return;
-
-       ret = thermal_zone_get_temp(epd->thermal, &temperature);
-       if (ret) {
-               DRM_DEV_ERROR(&epd->spi->dev, "Failed to get temperature (%d)\n", ret);
-               return;
-       }
-
-       temperature /= 1000;
-
-       if (temperature <= -10)
-               factor10x = 170;
-       else if (temperature <= -5)
-               factor10x = 120;
-       else if (temperature <= 5)
-               factor10x = 80;
-       else if (temperature <= 10)
-               factor10x = 40;
-       else if (temperature <= 15)
-               factor10x = 30;
-       else if (temperature <= 20)
-               factor10x = 20;
-       else if (temperature <= 40)
-               factor10x = 10;
-       else
-               factor10x = 7;
-
-       epd->factored_stage_time = epd->stage_time * factor10x / 10;
-}
-
-static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
-{
-       u8 *gray8 = buf, *mono = buf;
-       int y, xb, i;
-
-       for (y = 0; y < height; y++)
-               for (xb = 0; xb < width / 8; xb++) {
-                       u8 byte = 0x00;
-
-                       for (i = 0; i < 8; i++) {
-                               int x = xb * 8 + i;
-
-                               byte >>= 1;
-                               if (gray8[y * width + x] >> 7)
-                                       byte |= BIT(7);
-                       }
-                       *mono++ = byte;
-               }
-}
-
-static int repaper_fb_dirty(struct drm_framebuffer *fb)
-{
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
-       struct repaper_epd *epd = drm_to_epd(fb->dev);
-       struct drm_rect clip;
-       int idx, ret = 0;
-       u8 *buf = NULL;
-
-       if (!epd->enabled)
-               return 0;
-
-       if (!drm_dev_enter(fb->dev, &idx))
-               return -ENODEV;
-
-       /* repaper can't do partial updates */
-       clip.x1 = 0;
-       clip.x2 = fb->width;
-       clip.y1 = 0;
-       clip.y2 = fb->height;
-
-       repaper_get_temperature(epd);
-
-       DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id,
-                 epd->factored_stage_time);
-
-       buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL);
-       if (!buf) {
-               ret = -ENOMEM;
-               goto out_exit;
-       }
-
-       if (import_attach) {
-               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
-                                              DMA_FROM_DEVICE);
-               if (ret)
-                       goto out_free;
-       }
-
-       drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
-
-       if (import_attach) {
-               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
-                                            DMA_FROM_DEVICE);
-               if (ret)
-                       goto out_free;
-       }
-
-       repaper_gray8_to_mono_reversed(buf, fb->width, fb->height);
-
-       if (epd->partial) {
-               repaper_frame_data_repeat(epd, buf, epd->current_frame,
-                                         REPAPER_NORMAL);
-       } else if (epd->cleared) {
-               repaper_frame_data_repeat(epd, epd->current_frame, NULL,
-                                         REPAPER_COMPENSATE);
-               repaper_frame_data_repeat(epd, epd->current_frame, NULL,
-                                         REPAPER_WHITE);
-               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE);
-               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL);
-
-               epd->partial = true;
-       } else {
-               /* Clear display (anything -> white) */
-               repaper_frame_fixed_repeat(epd, 0xff, REPAPER_COMPENSATE);
-               repaper_frame_fixed_repeat(epd, 0xff, REPAPER_WHITE);
-               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_INVERSE);
-               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_NORMAL);
-
-               /* Assuming a clear (white) screen output an image */
-               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_COMPENSATE);
-               repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_WHITE);
-               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE);
-               repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL);
-
-               epd->cleared = true;
-               epd->partial = true;
-       }
-
-       memcpy(epd->current_frame, buf, fb->width * fb->height / 8);
-
-       /*
-        * An extra frame write is needed if pixels are set in the bottom line,
-        * or else grey lines rises up from the pixels
-        */
-       if (epd->pre_border_byte) {
-               unsigned int x;
-
-               for (x = 0; x < (fb->width / 8); x++)
-                       if (buf[x + (fb->width * (fb->height - 1) / 8)]) {
-                               repaper_frame_data_repeat(epd, buf,
-                                                         epd->current_frame,
-                                                         REPAPER_NORMAL);
-                               break;
-                       }
-       }
-
-out_free:
-       kfree(buf);
-out_exit:
-       drm_dev_exit(idx);
-
-       return ret;
-}
-
-static void power_off(struct repaper_epd *epd)
-{
-       /* Turn off power and all signals */
-       gpiod_set_value_cansleep(epd->reset, 0);
-       gpiod_set_value_cansleep(epd->panel_on, 0);
-       if (epd->border)
-               gpiod_set_value_cansleep(epd->border, 0);
-
-       /* Ensure SPI MOSI and CLOCK are Low before CS Low */
-       repaper_spi_mosi_low(epd->spi);
-
-       /* Discharge pulse */
-       gpiod_set_value_cansleep(epd->discharge, 1);
-       msleep(150);
-       gpiod_set_value_cansleep(epd->discharge, 0);
-}
-
-static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe,
-                               struct drm_crtc_state *crtc_state,
-                               struct drm_plane_state *plane_state)
-{
-       struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev);
-       struct spi_device *spi = epd->spi;
-       struct device *dev = &spi->dev;
-       bool dc_ok = false;
-       int i, ret, idx;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       /* Power up sequence */
-       gpiod_set_value_cansleep(epd->reset, 0);
-       gpiod_set_value_cansleep(epd->panel_on, 0);
-       gpiod_set_value_cansleep(epd->discharge, 0);
-       if (epd->border)
-               gpiod_set_value_cansleep(epd->border, 0);
-       repaper_spi_mosi_low(spi);
-       usleep_range(5000, 10000);
-
-       gpiod_set_value_cansleep(epd->panel_on, 1);
-       /*
-        * This delay comes from the repaper.org userspace driver, it's not
-        * mentioned in the datasheet.
-        */
-       usleep_range(10000, 15000);
-       gpiod_set_value_cansleep(epd->reset, 1);
-       if (epd->border)
-               gpiod_set_value_cansleep(epd->border, 1);
-       usleep_range(5000, 10000);
-       gpiod_set_value_cansleep(epd->reset, 0);
-       usleep_range(5000, 10000);
-       gpiod_set_value_cansleep(epd->reset, 1);
-       usleep_range(5000, 10000);
-
-       /* Wait for COG to become ready */
-       for (i = 100; i > 0; i--) {
-               if (!gpiod_get_value_cansleep(epd->busy))
-                       break;
-
-               usleep_range(10, 100);
-       }
-
-       if (!i) {
-               DRM_DEV_ERROR(dev, "timeout waiting for panel to become ready.\n");
-               power_off(epd);
-               goto out_exit;
-       }
-
-       repaper_read_id(spi);
-       ret = repaper_read_id(spi);
-       if (ret != REPAPER_RID_G2_COG_ID) {
-               if (ret < 0)
-                       dev_err(dev, "failed to read chip (%d)\n", ret);
-               else
-                       dev_err(dev, "wrong COG ID 0x%02x\n", ret);
-               power_off(epd);
-               goto out_exit;
-       }
-
-       /* Disable OE */
-       repaper_write_val(spi, 0x02, 0x40);
-
-       ret = repaper_read_val(spi, 0x0f);
-       if (ret < 0 || !(ret & 0x80)) {
-               if (ret < 0)
-                       DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret);
-               else
-                       DRM_DEV_ERROR(dev, "panel is reported broken\n");
-               power_off(epd);
-               goto out_exit;
-       }
-
-       /* Power saving mode */
-       repaper_write_val(spi, 0x0b, 0x02);
-       /* Channel select */
-       repaper_write_buf(spi, 0x01, epd->channel_select, 8);
-       /* High power mode osc */
-       repaper_write_val(spi, 0x07, 0xd1);
-       /* Power setting */
-       repaper_write_val(spi, 0x08, 0x02);
-       /* Vcom level */
-       repaper_write_val(spi, 0x09, 0xc2);
-       /* Power setting */
-       repaper_write_val(spi, 0x04, 0x03);
-       /* Driver latch on */
-       repaper_write_val(spi, 0x03, 0x01);
-       /* Driver latch off */
-       repaper_write_val(spi, 0x03, 0x00);
-       usleep_range(5000, 10000);
-
-       /* Start chargepump */
-       for (i = 0; i < 4; ++i) {
-               /* Charge pump positive voltage on - VGH/VDL on */
-               repaper_write_val(spi, 0x05, 0x01);
-               msleep(240);
-
-               /* Charge pump negative voltage on - VGL/VDL on */
-               repaper_write_val(spi, 0x05, 0x03);
-               msleep(40);
-
-               /* Charge pump Vcom on - Vcom driver on */
-               repaper_write_val(spi, 0x05, 0x0f);
-               msleep(40);
-
-               /* check DC/DC */
-               ret = repaper_read_val(spi, 0x0f);
-               if (ret < 0) {
-                       DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret);
-                       power_off(epd);
-                       goto out_exit;
-               }
-
-               if (ret & 0x40) {
-                       dc_ok = true;
-                       break;
-               }
-       }
-
-       if (!dc_ok) {
-               DRM_DEV_ERROR(dev, "dc/dc failed\n");
-               power_off(epd);
-               goto out_exit;
-       }
-
-       /*
-        * Output enable to disable
-        * The userspace driver sets this to 0x04, but the datasheet says 0x06
-        */
-       repaper_write_val(spi, 0x02, 0x04);
-
-       epd->enabled = true;
-       epd->partial = false;
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
-       struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev);
-       struct spi_device *spi = epd->spi;
-       unsigned int line;
-
-       /*
-        * This callback is not protected by drm_dev_enter/exit since we want to
-        * turn off the display on regular driver unload. It's highly unlikely
-        * that the underlying SPI controller is gone should this be called after
-        * unplug.
-        */
-
-       if (!epd->enabled)
-               return;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       epd->enabled = false;
-
-       /* Nothing frame */
-       for (line = 0; line < epd->height; line++)
-               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
-                                REPAPER_COMPENSATE);
-
-       /* 2.7" */
-       if (epd->border) {
-               /* Dummy line */
-               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
-                                REPAPER_COMPENSATE);
-               msleep(25);
-               gpiod_set_value_cansleep(epd->border, 0);
-               msleep(200);
-               gpiod_set_value_cansleep(epd->border, 1);
-       } else {
-               /* Border dummy line */
-               repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL,
-                                REPAPER_NORMAL);
-               msleep(200);
-       }
-
-       /* not described in datasheet */
-       repaper_write_val(spi, 0x0b, 0x00);
-       /* Latch reset turn on */
-       repaper_write_val(spi, 0x03, 0x01);
-       /* Power off charge pump Vcom */
-       repaper_write_val(spi, 0x05, 0x03);
-       /* Power off charge pump neg voltage */
-       repaper_write_val(spi, 0x05, 0x01);
-       msleep(120);
-       /* Discharge internal */
-       repaper_write_val(spi, 0x04, 0x80);
-       /* turn off all charge pumps */
-       repaper_write_val(spi, 0x05, 0x00);
-       /* Turn off osc */
-       repaper_write_val(spi, 0x07, 0x01);
-       msleep(50);
-
-       power_off(epd);
-}
-
-static void repaper_pipe_update(struct drm_simple_display_pipe *pipe,
-                               struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = pipe->plane.state;
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct drm_rect rect;
-
-       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
-               repaper_fb_dirty(state->fb);
-
-       if (crtc->state->event) {
-               spin_lock_irq(&crtc->dev->event_lock);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               spin_unlock_irq(&crtc->dev->event_lock);
-               crtc->state->event = NULL;
-       }
-}
-
-static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = {
-       .enable = repaper_pipe_enable,
-       .disable = repaper_pipe_disable,
-       .update = repaper_pipe_update,
-       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_mode_config_funcs repaper_mode_config_funcs = {
-       .fb_create = drm_gem_fb_create_with_dirty,
-       .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = drm_atomic_helper_commit,
-};
-
-static void repaper_release(struct drm_device *drm)
-{
-       struct repaper_epd *epd = drm_to_epd(drm);
-
-       DRM_DEBUG_DRIVER("\n");
-
-       drm_mode_config_cleanup(drm);
-       drm_dev_fini(drm);
-       kfree(epd);
-}
-
-static const uint32_t repaper_formats[] = {
-       DRM_FORMAT_XRGB8888,
-};
-
-static const struct drm_display_mode repaper_e1144cs021_mode = {
-       DRM_SIMPLE_MODE(128, 96, 29, 22),
-};
-
-static const u8 repaper_e1144cs021_cs[] = { 0x00, 0x00, 0x00, 0x00,
-                                           0x00, 0x0f, 0xff, 0x00 };
-
-static const struct drm_display_mode repaper_e1190cs021_mode = {
-       DRM_SIMPLE_MODE(144, 128, 36, 32),
-};
-
-static const u8 repaper_e1190cs021_cs[] = { 0x00, 0x00, 0x00, 0x03,
-                                           0xfc, 0x00, 0x00, 0xff };
-
-static const struct drm_display_mode repaper_e2200cs021_mode = {
-       DRM_SIMPLE_MODE(200, 96, 46, 22),
-};
-
-static const u8 repaper_e2200cs021_cs[] = { 0x00, 0x00, 0x00, 0x00,
-                                           0x01, 0xff, 0xe0, 0x00 };
-
-static const struct drm_display_mode repaper_e2271cs021_mode = {
-       DRM_SIMPLE_MODE(264, 176, 57, 38),
-};
-
-static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f,
-                                           0xff, 0xfe, 0x00, 0x00 };
-
-DEFINE_DRM_GEM_CMA_FOPS(repaper_fops);
-
-static struct drm_driver repaper_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
-       .fops                   = &repaper_fops,
-       .release                = repaper_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .name                   = "repaper",
-       .desc                   = "Pervasive Displays RePaper e-ink panels",
-       .date                   = "20170405",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id repaper_of_match[] = {
-       { .compatible = "pervasive,e1144cs021", .data = (void *)E1144CS021 },
-       { .compatible = "pervasive,e1190cs021", .data = (void *)E1190CS021 },
-       { .compatible = "pervasive,e2200cs021", .data = (void *)E2200CS021 },
-       { .compatible = "pervasive,e2271cs021", .data = (void *)E2271CS021 },
-       {},
-};
-MODULE_DEVICE_TABLE(of, repaper_of_match);
-
-static const struct spi_device_id repaper_id[] = {
-       { "e1144cs021", E1144CS021 },
-       { "e1190cs021", E1190CS021 },
-       { "e2200cs021", E2200CS021 },
-       { "e2271cs021", E2271CS021 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, repaper_id);
-
-static int repaper_probe(struct spi_device *spi)
-{
-       const struct drm_display_mode *mode;
-       const struct spi_device_id *spi_id;
-       const struct of_device_id *match;
-       struct device *dev = &spi->dev;
-       enum repaper_model model;
-       const char *thermal_zone;
-       struct repaper_epd *epd;
-       size_t line_buffer_size;
-       struct drm_device *drm;
-       int ret;
-
-       match = of_match_device(repaper_of_match, dev);
-       if (match) {
-               model = (enum repaper_model)match->data;
-       } else {
-               spi_id = spi_get_device_id(spi);
-               model = spi_id->driver_data;
-       }
-
-       /* The SPI device is used to allocate dma memory */
-       if (!dev->coherent_dma_mask) {
-               ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
-               if (ret) {
-                       dev_warn(dev, "Failed to set dma mask %d\n", ret);
-                       return ret;
-               }
-       }
-
-       epd = kzalloc(sizeof(*epd), GFP_KERNEL);
-       if (!epd)
-               return -ENOMEM;
-
-       drm = &epd->drm;
-
-       ret = devm_drm_dev_init(dev, drm, &repaper_driver);
-       if (ret) {
-               kfree(epd);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-       drm->mode_config.funcs = &repaper_mode_config_funcs;
-
-       epd->spi = spi;
-
-       epd->panel_on = devm_gpiod_get(dev, "panel-on", GPIOD_OUT_LOW);
-       if (IS_ERR(epd->panel_on)) {
-               ret = PTR_ERR(epd->panel_on);
-               if (ret != -EPROBE_DEFER)
-                       DRM_DEV_ERROR(dev, "Failed to get gpio 'panel-on'\n");
-               return ret;
-       }
-
-       epd->discharge = devm_gpiod_get(dev, "discharge", GPIOD_OUT_LOW);
-       if (IS_ERR(epd->discharge)) {
-               ret = PTR_ERR(epd->discharge);
-               if (ret != -EPROBE_DEFER)
-                       DRM_DEV_ERROR(dev, "Failed to get gpio 'discharge'\n");
-               return ret;
-       }
-
-       epd->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
-       if (IS_ERR(epd->reset)) {
-               ret = PTR_ERR(epd->reset);
-               if (ret != -EPROBE_DEFER)
-                       DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return ret;
-       }
-
-       epd->busy = devm_gpiod_get(dev, "busy", GPIOD_IN);
-       if (IS_ERR(epd->busy)) {
-               ret = PTR_ERR(epd->busy);
-               if (ret != -EPROBE_DEFER)
-                       DRM_DEV_ERROR(dev, "Failed to get gpio 'busy'\n");
-               return ret;
-       }
-
-       if (!device_property_read_string(dev, "pervasive,thermal-zone",
-                                        &thermal_zone)) {
-               epd->thermal = thermal_zone_get_zone_by_name(thermal_zone);
-               if (IS_ERR(epd->thermal)) {
-                       DRM_DEV_ERROR(dev, "Failed to get thermal zone: %s\n", thermal_zone);
-                       return PTR_ERR(epd->thermal);
-               }
-       }
-
-       switch (model) {
-       case E1144CS021:
-               mode = &repaper_e1144cs021_mode;
-               epd->channel_select = repaper_e1144cs021_cs;
-               epd->stage_time = 480;
-               epd->bytes_per_scan = 96 / 4;
-               epd->middle_scan = true; /* data-scan-data */
-               epd->pre_border_byte = false;
-               epd->border_byte = REPAPER_BORDER_BYTE_ZERO;
-               break;
-
-       case E1190CS021:
-               mode = &repaper_e1190cs021_mode;
-               epd->channel_select = repaper_e1190cs021_cs;
-               epd->stage_time = 480;
-               epd->bytes_per_scan = 128 / 4 / 2;
-               epd->middle_scan = false; /* scan-data-scan */
-               epd->pre_border_byte = false;
-               epd->border_byte = REPAPER_BORDER_BYTE_SET;
-               break;
-
-       case E2200CS021:
-               mode = &repaper_e2200cs021_mode;
-               epd->channel_select = repaper_e2200cs021_cs;
-               epd->stage_time = 480;
-               epd->bytes_per_scan = 96 / 4;
-               epd->middle_scan = true; /* data-scan-data */
-               epd->pre_border_byte = true;
-               epd->border_byte = REPAPER_BORDER_BYTE_NONE;
-               break;
-
-       case E2271CS021:
-               epd->border = devm_gpiod_get(dev, "border", GPIOD_OUT_LOW);
-               if (IS_ERR(epd->border)) {
-                       ret = PTR_ERR(epd->border);
-                       if (ret != -EPROBE_DEFER)
-                               DRM_DEV_ERROR(dev, "Failed to get gpio 'border'\n");
-                       return ret;
-               }
-
-               mode = &repaper_e2271cs021_mode;
-               epd->channel_select = repaper_e2271cs021_cs;
-               epd->stage_time = 630;
-               epd->bytes_per_scan = 176 / 4;
-               epd->middle_scan = true; /* data-scan-data */
-               epd->pre_border_byte = true;
-               epd->border_byte = REPAPER_BORDER_BYTE_NONE;
-               break;
-
-       default:
-               return -ENODEV;
-       }
-
-       epd->width = mode->hdisplay;
-       epd->height = mode->vdisplay;
-       epd->factored_stage_time = epd->stage_time;
-
-       line_buffer_size = 2 * epd->width / 8 + epd->bytes_per_scan + 2;
-       epd->line_buffer = devm_kzalloc(dev, line_buffer_size, GFP_KERNEL);
-       if (!epd->line_buffer)
-               return -ENOMEM;
-
-       epd->current_frame = devm_kzalloc(dev, epd->width * epd->height / 8,
-                                         GFP_KERNEL);
-       if (!epd->current_frame)
-               return -ENOMEM;
-
-       ret = tinydrm_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs,
-                                       DRM_MODE_CONNECTOR_VIRTUAL,
-                                       repaper_formats,
-                                       ARRAY_SIZE(repaper_formats), mode, 0);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int repaper_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void repaper_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver repaper_spi_driver = {
-       .driver = {
-               .name = "repaper",
-               .owner = THIS_MODULE,
-               .of_match_table = repaper_of_match,
-       },
-       .id_table = repaper_id,
-       .probe = repaper_probe,
-       .remove = repaper_remove,
-       .shutdown = repaper_shutdown,
-};
-module_spi_driver(repaper_spi_driver);
-
-MODULE_DESCRIPTION("Pervasive Displays RePaper DRM driver");
-MODULE_AUTHOR("Noralf Trønnes");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
deleted file mode 100644 (file)
index 9ac6262..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DRM driver for Sitronix ST7586 panels
- *
- * Copyright 2017 David Lechner <david@lechnology.com>
- */
-
-#include <linux/delay.h>
-#include <linux/dma-buf.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/spi/spi.h>
-#include <video/mipi_display.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_format_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_rect.h>
-#include <drm/drm_vblank.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-
-/* controller-specific commands */
-#define ST7586_DISP_MODE_GRAY  0x38
-#define ST7586_DISP_MODE_MONO  0x39
-#define ST7586_ENABLE_DDRAM    0x3a
-#define ST7586_SET_DISP_DUTY   0xb0
-#define ST7586_SET_PART_DISP   0xb4
-#define ST7586_SET_NLINE_INV   0xb5
-#define ST7586_SET_VOP         0xc0
-#define ST7586_SET_BIAS_SYSTEM 0xc3
-#define ST7586_SET_BOOST_LEVEL 0xc4
-#define ST7586_SET_VOP_OFFSET  0xc7
-#define ST7586_ENABLE_ANALOG   0xd0
-#define ST7586_AUTO_READ_CTRL  0xd7
-#define ST7586_OTP_RW_CTRL     0xe0
-#define ST7586_OTP_CTRL_OUT    0xe1
-#define ST7586_OTP_READ                0xe3
-
-#define ST7586_DISP_CTRL_MX    BIT(6)
-#define ST7586_DISP_CTRL_MY    BIT(7)
-
-/*
- * The ST7586 controller has an unusual pixel format where 2bpp grayscale is
- * packed 3 pixels per byte with the first two pixels using 3 bits and the 3rd
- * pixel using only 2 bits.
- *
- * |  D7  |  D6  |  D5  ||      |      || 2bpp |
- * | (D4) | (D3) | (D2) ||  D1  |  D0  || GRAY |
- * +------+------+------++------+------++------+
- * |  1   |  1   |  1   ||  1   |  1   || 0  0 | black
- * |  1   |  0   |  0   ||  1   |  0   || 0  1 | dark gray
- * |  0   |  1   |  0   ||  0   |  1   || 1  0 | light gray
- * |  0   |  0   |  0   ||  0   |  0   || 1  1 | white
- */
-
-static const u8 st7586_lookup[] = { 0x7, 0x4, 0x2, 0x0 };
-
-static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
-                                      struct drm_framebuffer *fb,
-                                      struct drm_rect *clip)
-{
-       size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1);
-       unsigned int x, y;
-       u8 *src, *buf, val;
-
-       buf = kmalloc(len, GFP_KERNEL);
-       if (!buf)
-               return;
-
-       drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, clip);
-       src = buf;
-
-       for (y = clip->y1; y < clip->y2; y++) {
-               for (x = clip->x1; x < clip->x2; x += 3) {
-                       val = st7586_lookup[*src++ >> 6] << 5;
-                       val |= st7586_lookup[*src++ >> 6] << 2;
-                       val |= st7586_lookup[*src++ >> 6] >> 1;
-                       *dst++ = val;
-               }
-       }
-
-       kfree(buf);
-}
-
-static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
-                          struct drm_rect *clip)
-{
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
-       void *src = cma_obj->vaddr;
-       int ret = 0;
-
-       if (import_attach) {
-               ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
-                                              DMA_FROM_DEVICE);
-               if (ret)
-                       return ret;
-       }
-
-       st7586_xrgb8888_to_gray332(dst, src, fb, clip);
-
-       if (import_attach)
-               ret = dma_buf_end_cpu_access(import_attach->dmabuf,
-                                            DMA_FROM_DEVICE);
-
-       return ret;
-}
-
-static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev);
-       int start, end, idx, ret = 0;
-
-       if (!mipi->enabled)
-               return;
-
-       if (!drm_dev_enter(fb->dev, &idx))
-               return;
-
-       /* 3 pixels per byte, so grow clip to nearest multiple of 3 */
-       rect->x1 = rounddown(rect->x1, 3);
-       rect->x2 = roundup(rect->x2, 3);
-
-       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
-
-       ret = st7586_buf_copy(mipi->tx_buf, fb, rect);
-       if (ret)
-               goto err_msg;
-
-       /* Pixels are packed 3 per byte */
-       start = rect->x1 / 3;
-       end = rect->x2 / 3;
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
-                        (start >> 8) & 0xFF, start & 0xFF,
-                        (end >> 8) & 0xFF, (end - 1) & 0xFF);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS,
-                        (rect->y1 >> 8) & 0xFF, rect->y1 & 0xFF,
-                        (rect->y2 >> 8) & 0xFF, (rect->y2 - 1) & 0xFF);
-
-       ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START,
-                                  (u8 *)mipi->tx_buf,
-                                  (end - start) * (rect->y2 - rect->y1));
-err_msg:
-       if (ret)
-               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
-
-       drm_dev_exit(idx);
-}
-
-static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
-                              struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = pipe->plane.state;
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct drm_rect rect;
-
-       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
-               st7586_fb_dirty(state->fb, &rect);
-
-       if (crtc->state->event) {
-               spin_lock_irq(&crtc->dev->event_lock);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               spin_unlock_irq(&crtc->dev->event_lock);
-               crtc->state->event = NULL;
-       }
-}
-
-static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
-                              struct drm_crtc_state *crtc_state,
-                              struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       struct drm_framebuffer *fb = plane_state->fb;
-       struct drm_rect rect = {
-               .x1 = 0,
-               .x2 = fb->width,
-               .y1 = 0,
-               .y2 = fb->height,
-       };
-       int idx, ret;
-       u8 addr_mode;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       ret = mipi_dbi_poweron_reset(mipi);
-       if (ret)
-               goto out_exit;
-
-       mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
-       mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
-
-       msleep(10);
-
-       mipi_dbi_command(mipi, ST7586_OTP_READ);
-
-       msleep(20);
-
-       mipi_dbi_command(mipi, ST7586_OTP_CTRL_OUT);
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
-
-       msleep(50);
-
-       mipi_dbi_command(mipi, ST7586_SET_VOP_OFFSET, 0x00);
-       mipi_dbi_command(mipi, ST7586_SET_VOP, 0xe3, 0x00);
-       mipi_dbi_command(mipi, ST7586_SET_BIAS_SYSTEM, 0x02);
-       mipi_dbi_command(mipi, ST7586_SET_BOOST_LEVEL, 0x04);
-       mipi_dbi_command(mipi, ST7586_ENABLE_ANALOG, 0x1d);
-       mipi_dbi_command(mipi, ST7586_SET_NLINE_INV, 0x00);
-       mipi_dbi_command(mipi, ST7586_DISP_MODE_GRAY);
-       mipi_dbi_command(mipi, ST7586_ENABLE_DDRAM, 0x02);
-
-       switch (mipi->rotation) {
-       default:
-               addr_mode = 0x00;
-               break;
-       case 90:
-               addr_mode = ST7586_DISP_CTRL_MY;
-               break;
-       case 180:
-               addr_mode = ST7586_DISP_CTRL_MX | ST7586_DISP_CTRL_MY;
-               break;
-       case 270:
-               addr_mode = ST7586_DISP_CTRL_MX;
-               break;
-       }
-       mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
-
-       mipi_dbi_command(mipi, ST7586_SET_DISP_DUTY, 0x7f);
-       mipi_dbi_command(mipi, ST7586_SET_PART_DISP, 0xa0);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PARTIAL_AREA, 0x00, 0x00, 0x00, 0x77);
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE);
-
-       msleep(100);
-
-       mipi->enabled = true;
-       st7586_fb_dirty(fb, &rect);
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-
-       /*
-        * This callback is not protected by drm_dev_enter/exit since we want to
-        * turn off the display on regular driver unload. It's highly unlikely
-        * that the underlying SPI controller is gone should this be called after
-        * unplug.
-        */
-
-       DRM_DEBUG_KMS("\n");
-
-       if (!mipi->enabled)
-               return;
-
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
-       mipi->enabled = false;
-}
-
-static const u32 st7586_formats[] = {
-       DRM_FORMAT_XRGB8888,
-};
-
-static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
-       .enable         = st7586_pipe_enable,
-       .disable        = st7586_pipe_disable,
-       .update         = st7586_pipe_update,
-       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_mode_config_funcs st7586_mode_config_funcs = {
-       .fb_create = drm_gem_fb_create_with_dirty,
-       .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = drm_atomic_helper_commit,
-};
-
-static const struct drm_display_mode st7586_mode = {
-       DRM_SIMPLE_MODE(178, 128, 37, 27),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(st7586_fops);
-
-static struct drm_driver st7586_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
-       .fops                   = &st7586_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .debugfs_init           = mipi_dbi_debugfs_init,
-       .name                   = "st7586",
-       .desc                   = "Sitronix ST7586",
-       .date                   = "20170801",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id st7586_of_match[] = {
-       { .compatible = "lego,ev3-lcd" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, st7586_of_match);
-
-static const struct spi_device_id st7586_id[] = {
-       { "ev3-lcd", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, st7586_id);
-
-static int st7586_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *a0;
-       u32 rotation = 0;
-       size_t bufsize;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &st7586_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-       drm->mode_config.preferred_depth = 32;
-       drm->mode_config.funcs = &st7586_mode_config_funcs;
-
-       mutex_init(&mipi->cmdlock);
-
-       bufsize = (st7586_mode.vdisplay + 2) / 3 * st7586_mode.hdisplay;
-       mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL);
-       if (!mipi->tx_buf)
-               return -ENOMEM;
-
-       mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(mipi->reset)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return PTR_ERR(mipi->reset);
-       }
-
-       a0 = devm_gpiod_get(dev, "a0", GPIOD_OUT_LOW);
-       if (IS_ERR(a0)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'a0'\n");
-               return PTR_ERR(a0);
-       }
-
-       device_property_read_u32(dev, "rotation", &rotation);
-       mipi->rotation = rotation;
-
-       ret = mipi_dbi_spi_init(spi, mipi, a0);
-       if (ret)
-               return ret;
-
-       /* Cannot read from this controller via SPI */
-       mipi->read_commands = NULL;
-
-       /*
-        * we are using 8-bit data, so we are not actually swapping anything,
-        * but setting mipi->swap_bytes makes mipi_dbi_typec3_command() do the
-        * right thing and not use 16-bit transfers (which results in swapped
-        * bytes on little-endian systems and causes out of order data to be
-        * sent to the display).
-        */
-       mipi->swap_bytes = true;
-
-       ret = tinydrm_display_pipe_init(drm, &mipi->pipe, &st7586_pipe_funcs,
-                                       DRM_MODE_CONNECTOR_VIRTUAL,
-                                       st7586_formats, ARRAY_SIZE(st7586_formats),
-                                       &st7586_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_plane_enable_fb_damage_clips(&mipi->pipe.plane);
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
-                     drm->mode_config.preferred_depth, rotation);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int st7586_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void st7586_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver st7586_spi_driver = {
-       .driver = {
-               .name = "st7586",
-               .owner = THIS_MODULE,
-               .of_match_table = st7586_of_match,
-       },
-       .id_table = st7586_id,
-       .probe = st7586_probe,
-       .remove = st7586_remove,
-       .shutdown = st7586_shutdown,
-};
-module_spi_driver(st7586_spi_driver);
-
-MODULE_DESCRIPTION("Sitronix ST7586 DRM driver");
-MODULE_AUTHOR("David Lechner <david@lechnology.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
deleted file mode 100644 (file)
index ce9109e..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DRM driver for Sitronix ST7735R panels
- *
- * Copyright 2017 David Lechner <david@lechnology.com>
- */
-
-#include <linux/backlight.h>
-#include <linux/delay.h>
-#include <linux/dma-buf.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/property.h>
-#include <linux/spi/spi.h>
-#include <video/mipi_display.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/tinydrm/mipi-dbi.h>
-#include <drm/tinydrm/tinydrm-helpers.h>
-
-#define ST7735R_FRMCTR1                0xb1
-#define ST7735R_FRMCTR2                0xb2
-#define ST7735R_FRMCTR3                0xb3
-#define ST7735R_INVCTR         0xb4
-#define ST7735R_PWCTR1         0xc0
-#define ST7735R_PWCTR2         0xc1
-#define ST7735R_PWCTR3         0xc2
-#define ST7735R_PWCTR4         0xc3
-#define ST7735R_PWCTR5         0xc4
-#define ST7735R_VMCTR1         0xc5
-#define ST7735R_GAMCTRP1       0xe0
-#define ST7735R_GAMCTRN1       0xe1
-
-#define ST7735R_MY     BIT(7)
-#define ST7735R_MX     BIT(6)
-#define ST7735R_MV     BIT(5)
-
-static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
-                                     struct drm_crtc_state *crtc_state,
-                                     struct drm_plane_state *plane_state)
-{
-       struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
-       int ret, idx;
-       u8 addr_mode;
-
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
-               return;
-
-       DRM_DEBUG_KMS("\n");
-
-       ret = mipi_dbi_poweron_reset(mipi);
-       if (ret)
-               goto out_exit;
-
-       msleep(150);
-
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
-       msleep(500);
-
-       mipi_dbi_command(mipi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d);
-       mipi_dbi_command(mipi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d);
-       mipi_dbi_command(mipi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c,
-                        0x2d);
-       mipi_dbi_command(mipi, ST7735R_INVCTR, 0x07);
-       mipi_dbi_command(mipi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84);
-       mipi_dbi_command(mipi, ST7735R_PWCTR2, 0xc5);
-       mipi_dbi_command(mipi, ST7735R_PWCTR3, 0x0a, 0x00);
-       mipi_dbi_command(mipi, ST7735R_PWCTR4, 0x8a, 0x2a);
-       mipi_dbi_command(mipi, ST7735R_PWCTR5, 0x8a, 0xee);
-       mipi_dbi_command(mipi, ST7735R_VMCTR1, 0x0e);
-       mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE);
-       switch (mipi->rotation) {
-       default:
-               addr_mode = ST7735R_MX | ST7735R_MY;
-               break;
-       case 90:
-               addr_mode = ST7735R_MX | ST7735R_MV;
-               break;
-       case 180:
-               addr_mode = 0;
-               break;
-       case 270:
-               addr_mode = ST7735R_MY | ST7735R_MV;
-               break;
-       }
-       mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT,
-                        MIPI_DCS_PIXEL_FMT_16BIT);
-       mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x02, 0x1c, 0x07, 0x12, 0x37,
-                        0x32, 0x29, 0x2d, 0x29, 0x25, 0x2b, 0x39, 0x00, 0x01,
-                        0x03, 0x10);
-       mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x03, 0x1d, 0x07, 0x06, 0x2e,
-                        0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00,
-                        0x02, 0x10);
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
-
-       msleep(100);
-
-       mipi_dbi_command(mipi, MIPI_DCS_ENTER_NORMAL_MODE);
-
-       msleep(20);
-
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
-out_exit:
-       drm_dev_exit(idx);
-}
-
-static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = {
-       .enable         = jd_t18003_t01_pipe_enable,
-       .disable        = mipi_dbi_pipe_disable,
-       .update         = mipi_dbi_pipe_update,
-       .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
-};
-
-static const struct drm_display_mode jd_t18003_t01_mode = {
-       DRM_SIMPLE_MODE(128, 160, 28, 35),
-};
-
-DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops);
-
-static struct drm_driver st7735r_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                                 DRIVER_ATOMIC,
-       .fops                   = &st7735r_fops,
-       .release                = mipi_dbi_release,
-       DRM_GEM_CMA_VMAP_DRIVER_OPS,
-       .debugfs_init           = mipi_dbi_debugfs_init,
-       .name                   = "st7735r",
-       .desc                   = "Sitronix ST7735R",
-       .date                   = "20171128",
-       .major                  = 1,
-       .minor                  = 0,
-};
-
-static const struct of_device_id st7735r_of_match[] = {
-       { .compatible = "jianda,jd-t18003-t01" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, st7735r_of_match);
-
-static const struct spi_device_id st7735r_id[] = {
-       { "jd-t18003-t01", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, st7735r_id);
-
-static int st7735r_probe(struct spi_device *spi)
-{
-       struct device *dev = &spi->dev;
-       struct drm_device *drm;
-       struct mipi_dbi *mipi;
-       struct gpio_desc *dc;
-       u32 rotation = 0;
-       int ret;
-
-       mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-       if (!mipi)
-               return -ENOMEM;
-
-       drm = &mipi->drm;
-       ret = devm_drm_dev_init(dev, drm, &st7735r_driver);
-       if (ret) {
-               kfree(mipi);
-               return ret;
-       }
-
-       drm_mode_config_init(drm);
-
-       mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(mipi->reset)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
-               return PTR_ERR(mipi->reset);
-       }
-
-       dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
-       if (IS_ERR(dc)) {
-               DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
-               return PTR_ERR(dc);
-       }
-
-       mipi->backlight = devm_of_find_backlight(dev);
-       if (IS_ERR(mipi->backlight))
-               return PTR_ERR(mipi->backlight);
-
-       device_property_read_u32(dev, "rotation", &rotation);
-
-       ret = mipi_dbi_spi_init(spi, mipi, dc);
-       if (ret)
-               return ret;
-
-       /* Cannot read from Adafruit 1.8" display via SPI */
-       mipi->read_commands = NULL;
-
-       ret = mipi_dbi_init(mipi, &jd_t18003_t01_pipe_funcs, &jd_t18003_t01_mode, rotation);
-       if (ret)
-               return ret;
-
-       drm_mode_config_reset(drm);
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               return ret;
-
-       spi_set_drvdata(spi, drm);
-
-       drm_fbdev_generic_setup(drm, 0);
-
-       return 0;
-}
-
-static int st7735r_remove(struct spi_device *spi)
-{
-       struct drm_device *drm = spi_get_drvdata(spi);
-
-       drm_dev_unplug(drm);
-       drm_atomic_helper_shutdown(drm);
-
-       return 0;
-}
-
-static void st7735r_shutdown(struct spi_device *spi)
-{
-       drm_atomic_helper_shutdown(spi_get_drvdata(spi));
-}
-
-static struct spi_driver st7735r_spi_driver = {
-       .driver = {
-               .name = "st7735r",
-               .owner = THIS_MODULE,
-               .of_match_table = st7735r_of_match,
-       },
-       .id_table = st7735r_id,
-       .probe = st7735r_probe,
-       .remove = st7735r_remove,
-       .shutdown = st7735r_shutdown,
-};
-module_spi_driver(st7735r_spi_driver);
-
-MODULE_DESCRIPTION("Sitronix ST7735R DRM driver");
-MODULE_AUTHOR("David Lechner <david@lechnology.com>");
-MODULE_LICENSE("GPL");
index 58c403e..10a861a 100644 (file)
@@ -160,7 +160,8 @@ static void ttm_bo_release_list(struct kref *list_kref)
        ttm_tt_destroy(bo->ttm);
        atomic_dec(&bo->bdev->glob->bo_count);
        dma_fence_put(bo->moving);
-       reservation_object_fini(&bo->ttm_resv);
+       if (!ttm_bo_uses_embedded_gem_object(bo))
+               reservation_object_fini(&bo->base._resv);
        mutex_destroy(&bo->wu_mutex);
        bo->destroy(bo);
        ttm_mem_global_free(bdev->glob->mem_glob, acc_size);
@@ -172,7 +173,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo,
        struct ttm_bo_device *bdev = bo->bdev;
        struct ttm_mem_type_manager *man;
 
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
 
        if (!list_empty(&bo->lru))
                return;
@@ -243,7 +244,7 @@ static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos,
 void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,
                             struct ttm_lru_bulk_move *bulk)
 {
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
 
        ttm_bo_del_from_lru(bo);
        ttm_bo_add_to_lru(bo);
@@ -276,8 +277,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
                if (!pos->first)
                        continue;
 
-               reservation_object_assert_held(pos->first->resv);
-               reservation_object_assert_held(pos->last->resv);
+               reservation_object_assert_held(pos->first->base.resv);
+               reservation_object_assert_held(pos->last->base.resv);
 
                man = &pos->first->bdev->man[TTM_PL_TT];
                list_bulk_move_tail(&man->lru[i], &pos->first->lru,
@@ -291,8 +292,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
                if (!pos->first)
                        continue;
 
-               reservation_object_assert_held(pos->first->resv);
-               reservation_object_assert_held(pos->last->resv);
+               reservation_object_assert_held(pos->first->base.resv);
+               reservation_object_assert_held(pos->last->base.resv);
 
                man = &pos->first->bdev->man[TTM_PL_VRAM];
                list_bulk_move_tail(&man->lru[i], &pos->first->lru,
@@ -306,8 +307,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
                if (!pos->first)
                        continue;
 
-               reservation_object_assert_held(pos->first->resv);
-               reservation_object_assert_held(pos->last->resv);
+               reservation_object_assert_held(pos->first->base.resv);
+               reservation_object_assert_held(pos->last->base.resv);
 
                lru = &pos->first->bdev->glob->swap_lru[i];
                list_bulk_move_tail(lru, &pos->first->swap, &pos->last->swap);
@@ -438,14 +439,14 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
 {
        int r;
 
-       if (bo->resv == &bo->ttm_resv)
+       if (bo->base.resv == &bo->base._resv)
                return 0;
 
-       BUG_ON(!reservation_object_trylock(&bo->ttm_resv));
+       BUG_ON(!reservation_object_trylock(&bo->base._resv));
 
-       r = reservation_object_copy_fences(&bo->ttm_resv, bo->resv);
+       r = reservation_object_copy_fences(&bo->base._resv, bo->base.resv);
        if (r)
-               reservation_object_unlock(&bo->ttm_resv);
+               reservation_object_unlock(&bo->base._resv);
 
        return r;
 }
@@ -456,14 +457,14 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
        struct dma_fence *fence;
        int i;
 
-       fobj = reservation_object_get_list(&bo->ttm_resv);
-       fence = reservation_object_get_excl(&bo->ttm_resv);
+       fobj = reservation_object_get_list(&bo->base._resv);
+       fence = reservation_object_get_excl(&bo->base._resv);
        if (fence && !fence->ops->signaled)
                dma_fence_enable_sw_signaling(fence);
 
        for (i = 0; fobj && i < fobj->shared_count; ++i) {
                fence = rcu_dereference_protected(fobj->shared[i],
-                                       reservation_object_held(bo->resv));
+                                       reservation_object_held(bo->base.resv));
 
                if (!fence->ops->signaled)
                        dma_fence_enable_sw_signaling(fence);
@@ -481,23 +482,23 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
                /* Last resort, if we fail to allocate memory for the
                 * fences block for the BO to become idle
                 */
-               reservation_object_wait_timeout_rcu(bo->resv, true, false,
+               reservation_object_wait_timeout_rcu(bo->base.resv, true, false,
                                                    30 * HZ);
                spin_lock(&glob->lru_lock);
                goto error;
        }
 
        spin_lock(&glob->lru_lock);
-       ret = reservation_object_trylock(bo->resv) ? 0 : -EBUSY;
+       ret = reservation_object_trylock(bo->base.resv) ? 0 : -EBUSY;
        if (!ret) {
-               if (reservation_object_test_signaled_rcu(&bo->ttm_resv, true)) {
+               if (reservation_object_test_signaled_rcu(&bo->base._resv, true)) {
                        ttm_bo_del_from_lru(bo);
                        spin_unlock(&glob->lru_lock);
-                       if (bo->resv != &bo->ttm_resv)
-                               reservation_object_unlock(&bo->ttm_resv);
+                       if (bo->base.resv != &bo->base._resv)
+                               reservation_object_unlock(&bo->base._resv);
 
                        ttm_bo_cleanup_memtype_use(bo);
-                       reservation_object_unlock(bo->resv);
+                       reservation_object_unlock(bo->base.resv);
                        return;
                }
 
@@ -513,10 +514,10 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
                        ttm_bo_add_to_lru(bo);
                }
 
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        }
-       if (bo->resv != &bo->ttm_resv)
-               reservation_object_unlock(&bo->ttm_resv);
+       if (bo->base.resv != &bo->base._resv)
+               reservation_object_unlock(&bo->base._resv);
 
 error:
        kref_get(&bo->list_kref);
@@ -549,9 +550,9 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
        int ret;
 
        if (unlikely(list_empty(&bo->ddestroy)))
-               resv = bo->resv;
+               resv = bo->base.resv;
        else
-               resv = &bo->ttm_resv;
+               resv = &bo->base._resv;
 
        if (reservation_object_test_signaled_rcu(resv, true))
                ret = 0;
@@ -562,7 +563,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
                long lret;
 
                if (unlock_resv)
-                       reservation_object_unlock(bo->resv);
+                       reservation_object_unlock(bo->base.resv);
                spin_unlock(&glob->lru_lock);
 
                lret = reservation_object_wait_timeout_rcu(resv, true,
@@ -575,7 +576,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
                        return -EBUSY;
 
                spin_lock(&glob->lru_lock);
-               if (unlock_resv && !reservation_object_trylock(bo->resv)) {
+               if (unlock_resv && !reservation_object_trylock(bo->base.resv)) {
                        /*
                         * We raced, and lost, someone else holds the reservation now,
                         * and is probably busy in ttm_bo_cleanup_memtype_use.
@@ -592,7 +593,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
 
        if (ret || unlikely(list_empty(&bo->ddestroy))) {
                if (unlock_resv)
-                       reservation_object_unlock(bo->resv);
+                       reservation_object_unlock(bo->base.resv);
                spin_unlock(&glob->lru_lock);
                return ret;
        }
@@ -605,7 +606,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
        ttm_bo_cleanup_memtype_use(bo);
 
        if (unlock_resv)
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
 
        return 0;
 }
@@ -631,14 +632,14 @@ static bool ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
                kref_get(&bo->list_kref);
                list_move_tail(&bo->ddestroy, &removed);
 
-               if (remove_all || bo->resv != &bo->ttm_resv) {
+               if (remove_all || bo->base.resv != &bo->base._resv) {
                        spin_unlock(&glob->lru_lock);
-                       reservation_object_lock(bo->resv, NULL);
+                       reservation_object_lock(bo->base.resv, NULL);
 
                        spin_lock(&glob->lru_lock);
                        ttm_bo_cleanup_refs(bo, false, !remove_all, true);
 
-               } else if (reservation_object_trylock(bo->resv)) {
+               } else if (reservation_object_trylock(bo->base.resv)) {
                        ttm_bo_cleanup_refs(bo, false, !remove_all, true);
                } else {
                        spin_unlock(&glob->lru_lock);
@@ -671,7 +672,7 @@ static void ttm_bo_release(struct kref *kref)
        struct ttm_bo_device *bdev = bo->bdev;
        struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
 
-       drm_vma_offset_remove(&bdev->vma_manager, &bo->vma_node);
+       drm_vma_offset_remove(&bdev->vma_manager, &bo->base.vma_node);
        ttm_mem_io_lock(man, false);
        ttm_mem_io_free_vm(bo);
        ttm_mem_io_unlock(man);
@@ -707,7 +708,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
        struct ttm_placement placement;
        int ret = 0;
 
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
 
        placement.num_placement = 0;
        placement.num_busy_placement = 0;
@@ -777,8 +778,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
 {
        bool ret = false;
 
-       if (bo->resv == ctx->resv) {
-               reservation_object_assert_held(bo->resv);
+       if (bo->base.resv == ctx->resv) {
+               reservation_object_assert_held(bo->base.resv);
                if (ctx->flags & TTM_OPT_FLAG_ALLOW_RES_EVICT
                    || !list_empty(&bo->ddestroy))
                        ret = true;
@@ -786,7 +787,7 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
                if (busy)
                        *busy = false;
        } else {
-               ret = reservation_object_trylock(bo->resv);
+               ret = reservation_object_trylock(bo->base.resv);
                *locked = ret;
                if (busy)
                        *busy = !ret;
@@ -814,10 +815,10 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo,
                return -EBUSY;
 
        if (ctx->interruptible)
-               r = reservation_object_lock_interruptible(busy_bo->resv,
+               r = reservation_object_lock_interruptible(busy_bo->base.resv,
                                                          ticket);
        else
-               r = reservation_object_lock(busy_bo->resv, ticket);
+               r = reservation_object_lock(busy_bo->base.resv, ticket);
 
        /*
         * TODO: It would be better to keep the BO locked until allocation is at
@@ -825,7 +826,7 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo,
         * of TTM.
         */
        if (!r)
-               reservation_object_unlock(busy_bo->resv);
+               reservation_object_unlock(busy_bo->base.resv);
 
        return r == -EDEADLK ? -EBUSY : r;
 }
@@ -850,8 +851,8 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
 
                        if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked,
                                                            &busy)) {
-                               if (busy && !busy_bo &&
-                                   bo->resv->lock.ctx != ticket)
+                               if (busy && !busy_bo && ticket !=
+                                   reservation_object_locking_ctx(bo->base.resv))
                                        busy_bo = bo;
                                continue;
                        }
@@ -859,7 +860,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
                        if (place && !bdev->driver->eviction_valuable(bo,
                                                                      place)) {
                                if (locked)
-                                       reservation_object_unlock(bo->resv);
+                                       reservation_object_unlock(bo->base.resv);
                                continue;
                        }
                        break;
@@ -931,9 +932,9 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
        spin_unlock(&man->move_lock);
 
        if (fence) {
-               reservation_object_add_shared_fence(bo->resv, fence);
+               reservation_object_add_shared_fence(bo->base.resv, fence);
 
-               ret = reservation_object_reserve_shared(bo->resv, 1);
+               ret = reservation_object_reserve_shared(bo->base.resv, 1);
                if (unlikely(ret)) {
                        dma_fence_put(fence);
                        return ret;
@@ -957,8 +958,10 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
 {
        struct ttm_bo_device *bdev = bo->bdev;
        struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+       struct ww_acquire_ctx *ticket;
        int ret;
 
+       ticket = reservation_object_locking_ctx(bo->base.resv);
        do {
                ret = (*man->func->get_node)(man, bo, place, mem);
                if (unlikely(ret != 0))
@@ -966,7 +969,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
                if (mem->mm_node)
                        break;
                ret = ttm_mem_evict_first(bdev, mem->mem_type, place, ctx,
-                                         bo->resv->lock.ctx);
+                                         ticket);
                if (unlikely(ret != 0))
                        return ret;
        } while (1);
@@ -1088,7 +1091,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
        bool type_found = false;
        int i, ret;
 
-       ret = reservation_object_reserve_shared(bo->resv, 1);
+       ret = reservation_object_reserve_shared(bo->base.resv, 1);
        if (unlikely(ret))
                return ret;
 
@@ -1169,7 +1172,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
        int ret = 0;
        struct ttm_mem_reg mem;
 
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
 
        mem.num_pages = bo->num_pages;
        mem.size = mem.num_pages << PAGE_SHIFT;
@@ -1239,7 +1242,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
        int ret;
        uint32_t new_flags;
 
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
        /*
         * Check whether we need to move buffer.
         */
@@ -1329,14 +1332,20 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
        bo->acc_size = acc_size;
        bo->sg = sg;
        if (resv) {
-               bo->resv = resv;
-               reservation_object_assert_held(bo->resv);
+               bo->base.resv = resv;
+               reservation_object_assert_held(bo->base.resv);
        } else {
-               bo->resv = &bo->ttm_resv;
+               bo->base.resv = &bo->base._resv;
+       }
+       if (!ttm_bo_uses_embedded_gem_object(bo)) {
+               /*
+                * bo.gem is not initialized, so we have to setup the
+                * struct elements we want use regardless.
+                */
+               reservation_object_init(&bo->base._resv);
+               drm_vma_node_reset(&bo->base.vma_node);
        }
-       reservation_object_init(&bo->ttm_resv);
        atomic_inc(&bo->bdev->glob->bo_count);
-       drm_vma_node_reset(&bo->vma_node);
 
        /*
         * For ttm_bo_type_device buffers, allocate
@@ -1344,14 +1353,14 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
         */
        if (bo->type == ttm_bo_type_device ||
            bo->type == ttm_bo_type_sg)
-               ret = drm_vma_offset_add(&bdev->vma_manager, &bo->vma_node,
+               ret = drm_vma_offset_add(&bdev->vma_manager, &bo->base.vma_node,
                                         bo->mem.num_pages);
 
        /* passed reservation objects should already be locked,
         * since otherwise lockdep will be angered in radeon.
         */
        if (!resv) {
-               locked = reservation_object_trylock(bo->resv);
+               locked = reservation_object_trylock(bo->base.resv);
                WARN_ON(!locked);
        }
 
@@ -1772,7 +1781,7 @@ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo)
 {
        struct ttm_bo_device *bdev = bo->bdev;
 
-       drm_vma_node_unmap(&bo->vma_node, bdev->dev_mapping);
+       drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping);
        ttm_mem_io_free_vm(bo);
 }
 
@@ -1795,13 +1804,13 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
        long timeout = 15 * HZ;
 
        if (no_wait) {
-               if (reservation_object_test_signaled_rcu(bo->resv, true))
+               if (reservation_object_test_signaled_rcu(bo->base.resv, true))
                        return 0;
                else
                        return -EBUSY;
        }
 
-       timeout = reservation_object_wait_timeout_rcu(bo->resv, true,
+       timeout = reservation_object_wait_timeout_rcu(bo->base.resv, true,
                                                      interruptible, timeout);
        if (timeout < 0)
                return timeout;
@@ -1809,7 +1818,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
        if (timeout == 0)
                return -EBUSY;
 
-       reservation_object_add_excl_fence(bo->resv, NULL);
+       reservation_object_add_excl_fence(bo->base.resv, NULL);
        return 0;
 }
 EXPORT_SYMBOL(ttm_bo_wait);
@@ -1925,7 +1934,7 @@ out:
         * already swapped buffer.
         */
        if (locked)
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        kref_put(&bo->list_kref, ttm_bo_release_list);
        return ret;
 }
@@ -1963,14 +1972,14 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo)
        ret = mutex_lock_interruptible(&bo->wu_mutex);
        if (unlikely(ret != 0))
                return -ERESTARTSYS;
-       if (!ww_mutex_is_locked(&bo->resv->lock))
+       if (!reservation_object_is_locked(bo->base.resv))
                goto out_unlock;
-       ret = reservation_object_lock_interruptible(bo->resv, NULL);
+       ret = reservation_object_lock_interruptible(bo->base.resv, NULL);
        if (ret == -EINTR)
                ret = -ERESTARTSYS;
        if (unlikely(ret != 0))
                goto out_unlock;
-       reservation_object_unlock(bo->resv);
+       reservation_object_unlock(bo->base.resv);
 
 out_unlock:
        mutex_unlock(&bo->wu_mutex);
index 9f918b9..425a6d6 100644 (file)
@@ -510,16 +510,16 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        INIT_LIST_HEAD(&fbo->base.io_reserve_lru);
        mutex_init(&fbo->base.wu_mutex);
        fbo->base.moving = NULL;
-       drm_vma_node_reset(&fbo->base.vma_node);
+       drm_vma_node_reset(&fbo->base.base.vma_node);
        atomic_set(&fbo->base.cpu_writers, 0);
 
        kref_init(&fbo->base.list_kref);
        kref_init(&fbo->base.kref);
        fbo->base.destroy = &ttm_transfered_destroy;
        fbo->base.acc_size = 0;
-       fbo->base.resv = &fbo->base.ttm_resv;
-       reservation_object_init(fbo->base.resv);
-       ret = reservation_object_trylock(fbo->base.resv);
+       fbo->base.base.resv = &fbo->base.base._resv;
+       reservation_object_init(fbo->base.base.resv);
+       ret = reservation_object_trylock(fbo->base.base.resv);
        WARN_ON(!ret);
 
        *new_obj = &fbo->base;
@@ -689,7 +689,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
        int ret;
        struct ttm_buffer_object *ghost_obj;
 
-       reservation_object_add_excl_fence(bo->resv, fence);
+       reservation_object_add_excl_fence(bo->base.resv, fence);
        if (evict) {
                ret = ttm_bo_wait(bo, false, false);
                if (ret)
@@ -716,7 +716,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
                if (ret)
                        return ret;
 
-               reservation_object_add_excl_fence(ghost_obj->resv, fence);
+               reservation_object_add_excl_fence(ghost_obj->base.resv, fence);
 
                /**
                 * If we're not moving to fixed memory, the TTM object
@@ -752,7 +752,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
 
        int ret;
 
-       reservation_object_add_excl_fence(bo->resv, fence);
+       reservation_object_add_excl_fence(bo->base.resv, fence);
 
        if (!evict) {
                struct ttm_buffer_object *ghost_obj;
@@ -772,7 +772,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
                if (ret)
                        return ret;
 
-               reservation_object_add_excl_fence(ghost_obj->resv, fence);
+               reservation_object_add_excl_fence(ghost_obj->base.resv, fence);
 
                /**
                 * If we're not moving to fixed memory, the TTM object
@@ -841,7 +841,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo)
        if (ret)
                return ret;
 
-       ret = reservation_object_copy_fences(ghost->resv, bo->resv);
+       ret = reservation_object_copy_fences(ghost->base.resv, bo->base.resv);
        /* Last resort, wait for the BO to be idle when we are OOM */
        if (ret)
                ttm_bo_wait(bo, false, false);
index 6dacff4..85f5bcb 100644 (file)
@@ -71,7 +71,7 @@ static vm_fault_t ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
                ttm_bo_get(bo);
                up_read(&vmf->vma->vm_mm->mmap_sem);
                (void) dma_fence_wait(bo->moving, true);
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
                ttm_bo_put(bo);
                goto out_unlock;
        }
@@ -131,7 +131,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
         * for reserve, and if it fails, retry the fault after waiting
         * for the buffer to become unreserved.
         */
-       if (unlikely(!reservation_object_trylock(bo->resv))) {
+       if (unlikely(!reservation_object_trylock(bo->base.resv))) {
                if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
                        if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
                                ttm_bo_get(bo);
@@ -211,9 +211,9 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
        }
 
        page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
-               vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+               vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node);
        page_last = vma_pages(vma) + vma->vm_pgoff -
-               drm_vma_node_start(&bo->vma_node);
+               drm_vma_node_start(&bo->base.vma_node);
 
        if (unlikely(page_offset >= bo->num_pages)) {
                ret = VM_FAULT_SIGBUS;
@@ -267,7 +267,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
                        } else if (unlikely(!page)) {
                                break;
                        }
-                       page->index = drm_vma_node_start(&bo->vma_node) +
+                       page->index = drm_vma_node_start(&bo->base.vma_node) +
                                page_offset;
                        pfn = page_to_pfn(page);
                }
@@ -296,7 +296,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
 out_io_unlock:
        ttm_mem_io_unlock(man);
 out_unlock:
-       reservation_object_unlock(bo->resv);
+       reservation_object_unlock(bo->base.resv);
        return ret;
 }
 
@@ -413,7 +413,8 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev,
 
        node = drm_vma_offset_lookup_locked(&bdev->vma_manager, offset, pages);
        if (likely(node)) {
-               bo = container_of(node, struct ttm_buffer_object, vma_node);
+               bo = container_of(node, struct ttm_buffer_object,
+                                 base.vma_node);
                bo = ttm_bo_get_unless_zero(bo);
        }
 
index 957ec37..3aefe72 100644 (file)
@@ -39,7 +39,7 @@ static void ttm_eu_backoff_reservation_reverse(struct list_head *list,
        list_for_each_entry_continue_reverse(entry, list, head) {
                struct ttm_buffer_object *bo = entry->bo;
 
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        }
 }
 
@@ -71,7 +71,7 @@ void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
 
                if (list_empty(&bo->lru))
                        ttm_bo_add_to_lru(bo);
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        }
        spin_unlock(&glob->lru_lock);
 
@@ -114,7 +114,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
 
                ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket);
                if (!ret && unlikely(atomic_read(&bo->cpu_writers) > 0)) {
-                       reservation_object_unlock(bo->resv);
+                       reservation_object_unlock(bo->base.resv);
 
                        ret = -EBUSY;
 
@@ -130,7 +130,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
                        if (!entry->num_shared)
                                continue;
 
-                       ret = reservation_object_reserve_shared(bo->resv,
+                       ret = reservation_object_reserve_shared(bo->base.resv,
                                                                entry->num_shared);
                        if (!ret)
                                continue;
@@ -144,16 +144,16 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
 
                if (ret == -EDEADLK) {
                        if (intr) {
-                               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
-                                                                      ticket);
+                               ret = reservation_object_lock_slow_interruptible(bo->base.resv,
+                                                                                ticket);
                        } else {
-                               ww_mutex_lock_slow(&bo->resv->lock, ticket);
+                               reservation_object_lock_slow(bo->base.resv, ticket);
                                ret = 0;
                        }
                }
 
                if (!ret && entry->num_shared)
-                       ret = reservation_object_reserve_shared(bo->resv,
+                       ret = reservation_object_reserve_shared(bo->base.resv,
                                                                entry->num_shared);
 
                if (unlikely(ret != 0)) {
@@ -201,14 +201,14 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
        list_for_each_entry(entry, list, head) {
                bo = entry->bo;
                if (entry->num_shared)
-                       reservation_object_add_shared_fence(bo->resv, fence);
+                       reservation_object_add_shared_fence(bo->base.resv, fence);
                else
-                       reservation_object_add_excl_fence(bo->resv, fence);
+                       reservation_object_add_excl_fence(bo->base.resv, fence);
                if (list_empty(&bo->lru))
                        ttm_bo_add_to_lru(bo);
                else
                        ttm_bo_move_to_lru_tail(bo, NULL);
-               reservation_object_unlock(bo->resv);
+               reservation_object_unlock(bo->base.resv);
        }
        spin_unlock(&glob->lru_lock);
        if (ticket)
index e3a0691..00b4a33 100644 (file)
@@ -48,7 +48,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
        struct ttm_bo_device *bdev = bo->bdev;
        uint32_t page_flags = 0;
 
-       reservation_object_assert_held(bo->resv);
+       reservation_object_assert_held(bo->base.resv);
 
        if (bdev->need_dma32)
                page_flags |= TTM_PAGE_FLAG_DMA32;
index 58fd310..d733bbc 100644 (file)
@@ -9,16 +9,18 @@
  * Copyright (C) 2011 Texas Instruments
  * Copyright (C) 2017 Eric Anholt
  */
+
 #include <linux/clk.h>
 #include <linux/version.h>
 #include <linux/dma-buf.h>
 #include <linux/of_graph.h>
 
-#include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_vblank.h>
 
 #include "tve200_drm.h"
 
index 62061b5..5420b52 100644 (file)
 #ifndef _TVE200_DRM_H_
 #define _TVE200_DRM_H_
 
+#include <linux/irqreturn.h>
+
+#include <drm/drm_simple_kms_helper.h>
+
+struct clk;
+struct drm_bridge;
+struct drm_connector;
+struct drm_device;
+struct drm_file;
+struct drm_mode_create_dumb;
+struct drm_panel;
+
 /* Bits 2-31 are valid physical base addresses */
 #define TVE200_Y_FRAME_BASE_ADDR       0x00
 #define TVE200_U_FRAME_BASE_ADDR       0x04
 #define TVE200_CTRL_4                  0x24
 #define TVE200_CTRL_4_RESET            BIT(0) /* triggers reset of TVE200 */
 
-#include <drm/drm_gem.h>
-#include <drm/drm_simple_kms_helper.h>
-
 struct tve200_drm_dev_private {
        struct drm_device *drm;
 
index 6e695fb..416f248 100644 (file)
@@ -37,9 +37,9 @@
 #include <linux/slab.h>
 #include <linux/version.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
@@ -47,6 +47,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "tve200_drm.h"
 
@@ -137,8 +138,7 @@ finish:
 DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
 
 static struct drm_driver tve200_drm_driver = {
-       .driver_features =
-               DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .ioctls = NULL,
        .fops = &drm_fops,
        .name = "tve200",
@@ -153,8 +153,6 @@ static struct drm_driver tve200_drm_driver = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_import = drm_gem_prime_import,
-       .gem_prime_export = drm_gem_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index 9215618..ddb61a6 100644 (file)
@@ -7,11 +7,9 @@
  * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_probe_helper.h>
+
 #include "udl_connector.h"
 #include "udl_drv.h"
 
index 0fb0db5..7f2d392 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <drm/drm_crtc.h>
 
+struct edid;
+
 struct udl_drm_connector {
        struct drm_connector connector;
        /* last udl_detect edid */
index a288921..3108e9a 100644 (file)
@@ -5,11 +5,13 @@
  * Copyright (c) 2014 The Chromium OS Authors
  */
 
-#include <drm/drmP.h>
-#include "udl_drv.h"
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 
+#include <drm/drm_prime.h>
+
+#include "udl_drv.h"
+
 struct udl_drm_dmabuf_attachment {
        struct sg_table sgt;
        enum dma_data_direction dir;
@@ -170,8 +172,7 @@ static const struct dma_buf_ops udl_dmabuf_ops = {
        .release                = drm_gem_dmabuf_release,
 };
 
-struct dma_buf *udl_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj, int flags)
+struct dma_buf *udl_gem_prime_export(struct drm_gem_object *obj, int flags)
 {
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
@@ -180,7 +181,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev,
        exp_info.flags = flags;
        exp_info.priv = obj;
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       return drm_gem_dmabuf_export(obj->dev, &exp_info);
 }
 
 static int udl_prime_create(struct drm_device *dev,
index 4a49fac..8426669 100644 (file)
@@ -4,9 +4,14 @@
  */
 
 #include <linux/module.h>
-#include <drm/drmP.h>
+
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
+
 #include "udl_drv.h"
 
 static int udl_usb_suspend(struct usb_interface *interface,
@@ -54,7 +59,7 @@ static void udl_driver_release(struct drm_device *dev)
 }
 
 static struct drm_driver driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .release = udl_driver_release,
 
        /* gem hooks */
index a928801..12a970f 100644 (file)
 #ifndef UDL_DRV_H
 #define UDL_DRV_H
 
+#include <linux/mm_types.h>
 #include <linux/usb.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_framebuffer.h>
 #include <drm/drm_gem.h>
-#include <linux/mm_types.h>
+
+struct drm_encoder;
+struct drm_mode_create_dumb;
 
 #define DRIVER_NAME            "udl"
 #define DRIVER_DESC            "DisplayLink"
@@ -126,8 +132,7 @@ int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev,
 void udl_gem_free_object(struct drm_gem_object *gem_obj);
 struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
                                            size_t size);
-struct dma_buf *udl_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj, int flags);
+struct dma_buf *udl_gem_prime_export(struct drm_gem_object *obj, int flags);
 struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
                                struct dma_buf *dma_buf);
 
index f87989e..203f041 100644 (file)
@@ -7,9 +7,9 @@
  * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
+
 #include "udl_drv.h"
 
 /* dummy encoder */
index e1116bf..ef3504d 100644 (file)
@@ -7,18 +7,17 @@
  * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
  * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
  */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
+
+#include <linux/moduleparam.h>
 #include <linux/dma-buf.h>
-#include <linux/mem_encrypt.h>
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include "udl_drv.h"
-
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_modeset_helper.h>
+
+#include "udl_drv.h"
 
 #define DL_DEFIO_WRITE_DELAY    (HZ/20) /* fb_deferred_io.delay in jiffies */
 
index c6ca2c0..b23a5c2 100644 (file)
@@ -3,10 +3,13 @@
  * Copyright (C) 2012 Red Hat
  */
 
-#include <drm/drmP.h>
-#include "udl_drv.h"
-#include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_mode.h>
+#include <drm/drm_prime.h>
+
+#include "udl_drv.h"
 
 struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
                                            size_t size)
index 1a99c76..4e854e0 100644 (file)
@@ -7,9 +7,11 @@
  * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
  * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
  */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
+
+#include <drm/drm.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
+
 #include "udl_drv.h"
 
 /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
index 793722d..bc1ab60 100644 (file)
@@ -9,10 +9,10 @@
 
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_vblank.h>
+
 #include "udl_drv.h"
 
 /*
index 6837f59..1973a4c 100644 (file)
@@ -7,12 +7,8 @@
  * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
  */
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
 #include <asm/unaligned.h>
 
-#include <drm/drmP.h>
 #include "udl_drv.h"
 
 #define MAX_CMD_PIXELS         255
index 78a7893..9e953ce 100644 (file)
@@ -6,7 +6,8 @@
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_debugfs.h>
 
 #include "v3d_drv.h"
 #include "v3d_regs.h"
index fea597f..3506ae2 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
+
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <uapi/drm/v3d_drm.h>
 
-#include "uapi/drm/v3d_drm.h"
 #include "v3d_drv.h"
 #include "v3d_regs.h"
 
@@ -188,7 +191,6 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
 static struct drm_driver v3d_drm_driver = {
        .driver_features = (DRIVER_GEM |
                            DRIVER_RENDER |
-                           DRIVER_PRIME |
                            DRIVER_SYNCOBJ),
 
        .open = v3d_open,
index 9aad9da..9a35c55 100644 (file)
@@ -1,14 +1,23 @@
 // SPDX-License-Identifier: GPL-2.0+
 /* Copyright (C) 2015-2018 Broadcom */
 
-#include <linux/mm_types.h>
-#include <drm/drmP.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
+#include <linux/workqueue.h>
+
 #include <drm/drm_encoder.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/gpu_scheduler.h>
+
 #include "uapi/drm/v3d_drm.h"
 
+struct clk;
+struct device;
+struct platform_device;
+struct reset_control;
+
 #define GMP_GRANULARITY (128 * 1024)
 
 /* Enum for each of the V3D queues. */
index 27e0f87..7974413 100644 (file)
@@ -1,17 +1,19 @@
 // SPDX-License-Identifier: GPL-2.0+
 /* Copyright (C) 2014-2018 Broadcom */
 
-#include <drm/drmP.h>
-#include <drm/drm_syncobj.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
-#include <linux/device.h>
-#include <linux/io.h>
 #include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_syncobj.h>
+#include <uapi/drm/v3d_drm.h>
 
-#include "uapi/drm/v3d_drm.h"
 #include "v3d_drv.h"
 #include "v3d_regs.h"
 #include "v3d_trace.h"
index 268d8a8..662e672 100644 (file)
@@ -13,6 +13,8 @@
  * current job can make progress.
  */
 
+#include <linux/platform_device.h>
+
 #include "v3d_drv.h"
 #include "v3d_regs.h"
 #include "v3d_trace.h"
index 1224f31..55d798c 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 vboxvideo-y :=  hgsmi_base.o modesetting.o vbva_base.o \
                vbox_drv.o vbox_fb.o vbox_hgsmi.o vbox_irq.o vbox_main.o \
-               vbox_mode.o vbox_prime.o vbox_ttm.o
+               vbox_mode.o vbox_ttm.o
 
 obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo.o
index 02537ab..6189ea8 100644 (file)
@@ -196,7 +196,7 @@ static const struct file_operations vbox_fops = {
 
 static struct drm_driver driver = {
        .driver_features =
-           DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+           DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 
        .lastclose = drm_fb_helper_lastclose,
 
@@ -210,17 +210,6 @@ static struct drm_driver driver = {
        .patchlevel = DRIVER_PATCHLEVEL,
 
        DRM_GEM_VRAM_DRIVER,
-       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
-       .gem_prime_pin = vbox_gem_prime_pin,
-       .gem_prime_unpin = vbox_gem_prime_unpin,
-       .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
-       .gem_prime_vmap = vbox_gem_prime_vmap,
-       .gem_prime_vunmap = vbox_gem_prime_vunmap,
-       .gem_prime_mmap = vbox_gem_prime_mmap,
 };
 
 static int __init vbox_init(void)
index 9028f94..e8cb9ef 100644 (file)
@@ -167,18 +167,6 @@ void vbox_mm_fini(struct vbox_private *vbox);
 int vbox_gem_create(struct vbox_private *vbox,
                    u32 size, bool iskernel, struct drm_gem_object **obj);
 
-/* vbox_prime.c */
-int vbox_gem_prime_pin(struct drm_gem_object *obj);
-void vbox_gem_prime_unpin(struct drm_gem_object *obj);
-struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *vbox_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table);
-void *vbox_gem_prime_vmap(struct drm_gem_object *obj);
-void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
-int vbox_gem_prime_mmap(struct drm_gem_object *obj,
-                       struct vm_area_struct *area);
-
 /* vbox_irq.c */
 int vbox_irq_init(struct vbox_private *vbox);
 void vbox_irq_fini(struct vbox_private *vbox);
index 18693e2..02fa827 100644 (file)
@@ -292,7 +292,7 @@ int vbox_gem_create(struct vbox_private *vbox,
                return ret;
        }
 
-       *obj = &gbo->gem;
+       *obj = &gbo->bo.base;
 
        return 0;
 }
diff --git a/drivers/gpu/drm/vboxvideo/vbox_prime.c b/drivers/gpu/drm/vboxvideo/vbox_prime.c
deleted file mode 100644 (file)
index 702b1aa..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright (C) 2017 Oracle Corporation
- * Copyright 2017 Canonical
- * Authors: Andreas Pokorny
- */
-
-#include "vbox_drv.h"
-
-/*
- * Based on qxl_prime.c:
- * Empty Implementations as there should not be any other driver for a virtual
- * device that might share buffers with vboxvideo
- */
-
-int vbox_gem_prime_pin(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return -ENODEV;
-}
-
-void vbox_gem_prime_unpin(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-}
-
-struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-struct drm_gem_object *vbox_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-void *vbox_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       WARN_ONCE(1, "not implemented");
-}
-
-int vbox_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *area)
-{
-       WARN_ONCE(1, "not implemented");
-       return -ENODEV;
-}
index a75a2f9..72d30d9 100644 (file)
@@ -655,8 +655,7 @@ static void vc4_bo_cache_time_timer(struct timer_list *t)
        schedule_work(&vc4->bo_cache.time_work);
 }
 
-struct dma_buf *
-vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags)
+struct dma_buf * vc4_prime_export(struct drm_gem_object *obj, int flags)
 {
        struct vc4_bo *bo = to_vc4_bo(obj);
        struct dma_buf *dmabuf;
@@ -678,7 +677,7 @@ vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags)
                return ERR_PTR(ret);
        }
 
-       dmabuf = drm_gem_prime_export(dev, obj, flags);
+       dmabuf = drm_gem_prime_export(obj, flags);
        if (IS_ERR(dmabuf))
                vc4_bo_dec_usecnt(bo);
 
@@ -791,8 +790,6 @@ vc4_prime_import_sg_table(struct drm_device *dev,
        if (IS_ERR(obj))
                return obj;
 
-       obj->resv = attach->dmabuf->resv;
-
        return obj;
 }
 
index 5ea8db7..f1f0a7c 100644 (file)
  * ones that set the clock.
  */
 
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
-#include <linux/clk.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <linux/component.h>
-#include <linux/of_device.h>
+#include <drm/drm_vblank.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index 4829a00..b61b2d3 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/circ_buf.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
-#include <drm/drmP.h>
 
 #include "vc4_drv.h"
 #include "vc4_regs.h"
index bf11930..048c70a 100644 (file)
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_atomic_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "uapi/drm/vc4_drm.h"
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
@@ -177,7 +182,6 @@ static struct drm_driver vc4_drm_driver = {
                            DRIVER_ATOMIC |
                            DRIVER_GEM |
                            DRIVER_RENDER |
-                           DRIVER_PRIME |
                            DRIVER_SYNCOBJ),
        .open = vc4_open,
        .postclose = vc4_close,
@@ -199,7 +203,6 @@ static struct drm_driver vc4_drm_driver = {
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_export = vc4_prime_export,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = vc4_prime_import_sg_table,
index 616c011..6627b20 100644 (file)
@@ -3,16 +3,23 @@
  * Copyright (C) 2015 Broadcom
  */
 
-#include <linux/mm_types.h>
-#include <drm/drmP.h>
-#include <drm/drm_util.h>
+#include <linux/delay.h>
+#include <linux/refcount.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_device.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_syncobj.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_modeset_lock.h>
 
 #include "uapi/drm/vc4_drm.h"
 
+struct drm_device;
+struct drm_gem_object;
+
 /* Don't forget to update vc4_bo.c: bo_type_names[] when adding to
  * this.
  */
@@ -705,8 +712,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size,
 int vc4_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args);
-struct dma_buf *vc4_prime_export(struct drm_device *dev,
-                                struct drm_gem_object *obj, int flags);
+struct dma_buf *vc4_prime_export(struct drm_gem_object *obj, int flags);
 int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
index 1db39b5..c78fa81 100644 (file)
  * hopefully present.
  */
 
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/component.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index 84795d9..b72b760 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/sched/signal.h>
 #include <linux/dma-fence-array.h>
 
+#include <drm/drm_syncobj.h>
+
 #include "uapi/drm/vc4_drm.h"
 #include "vc4_drv.h"
 #include "vc4_regs.h"
index 0f633be..9936b15 100644 (file)
  * each CRTC.
  */
 
-#include <drm/drm_atomic_helper.h>
 #include <linux/component.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_atomic_helper.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index 70d079b..78d4fb0 100644 (file)
  * crtc, HDMI encoder).
  */
 
-#include <drm/drm_crtc.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index 0a0207c..5e5f908 100644 (file)
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
-#include <drm/drm_atomic_uapi.h>
 
 #include "uapi/drm/vc4_drm.h"
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
@@ -1123,7 +1126,6 @@ static int vc4_prepare_fb(struct drm_plane *plane,
                          struct drm_plane_state *state)
 {
        struct vc4_bo *bo;
-       struct dma_fence *fence;
        int ret;
 
        if (!state->fb)
@@ -1131,8 +1133,7 @@ static int vc4_prepare_fb(struct drm_plane *plane,
 
        bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base);
 
-       fence = reservation_object_get_excl_rcu(bo->base.base.resv);
-       drm_atomic_set_fence_for_plane(state, fence);
+       drm_gem_fb_prepare_fb(plane, state);
 
        if (plane->state->fb == state->fb)
                return 0;
index 96f91c1..1ce4d71 100644 (file)
@@ -7,18 +7,20 @@
  *     Boris Brezillon <boris.brezillon@bootlin.com>
  */
 
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_writeback.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/of_graph.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_writeback.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index fee4f90..cea77a2 100644 (file)
@@ -7,7 +7,11 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+
+#include <drm/drm_irq.h>
+
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
index 11a8f99..5bd60de 100644 (file)
  * software renderer and the X server for efficient buffer sharing.
  */
 
+#include <linux/dma-buf.h>
 #include <linux/module.h>
-#include <linux/ramfs.h>
+#include <linux/platform_device.h>
 #include <linux/shmem_fs.h>
-#include <linux/dma-buf.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_prime.h>
+
 #include "vgem_drv.h"
 
 #define DRIVER_NAME    "vgem"
@@ -214,7 +221,7 @@ static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
        args->size = gem_object->size;
        args->pitch = pitch;
 
-       DRM_DEBUG_DRIVER("Created object of size %lld\n", size);
+       DRM_DEBUG("Created object of size %lld\n", size);
 
        return 0;
 }
@@ -246,8 +253,8 @@ unref:
 }
 
 static struct drm_ioctl_desc vgem_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),
 };
 
 static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -427,8 +434,7 @@ static void vgem_release(struct drm_device *dev)
 }
 
 static struct drm_driver vgem_driver = {
-       .driver_features                = DRIVER_GEM | DRIVER_PRIME |
-                                         DRIVER_RENDER,
+       .driver_features                = DRIVER_GEM | DRIVER_RENDER,
        .release                        = vgem_release,
        .open                           = vgem_open,
        .postclose                      = vgem_postclose,
@@ -446,7 +452,6 @@ static struct drm_driver vgem_driver = {
        .gem_prime_pin = vgem_prime_pin,
        .gem_prime_unpin = vgem_prime_unpin,
        .gem_prime_import = vgem_prime_import,
-       .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import_sg_table = vgem_prime_import_sg_table,
        .gem_prime_get_sg_table = vgem_prime_get_sg_table,
        .gem_prime_vmap = vgem_prime_vmap,
index 5c8f6d6..0ed3003 100644 (file)
@@ -29,7 +29,6 @@
 #ifndef _VGEM_DRV_H_
 #define _VGEM_DRV_H_
 
-#include <drm/drmP.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_cache.h>
 
index eb17c0c..d863046 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/dma-buf.h>
 #include <linux/reservation.h>
 
+#include <drm/drm_file.h>
+
 #include "vgem_drv.h"
 
 #define VGEM_FENCE_TIMEOUT (10*HZ)
@@ -100,22 +102,6 @@ static struct dma_fence *vgem_fence_create(struct vgem_file *vfile,
        return &fence->base;
 }
 
-static int attach_dmabuf(struct drm_device *dev,
-                        struct drm_gem_object *obj)
-{
-       struct dma_buf *dmabuf;
-
-       if (obj->dma_buf)
-               return 0;
-
-       dmabuf = dev->driver->gem_prime_export(dev, obj, 0);
-       if (IS_ERR(dmabuf))
-               return PTR_ERR(dmabuf);
-
-       obj->dma_buf = dmabuf;
-       return 0;
-}
-
 /*
  * vgem_fence_attach_ioctl (DRM_IOCTL_VGEM_FENCE_ATTACH):
  *
@@ -157,10 +143,6 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
        if (!obj)
                return -ENOENT;
 
-       ret = attach_dmabuf(dev, obj);
-       if (ret)
-               goto err;
-
        fence = vgem_fence_create(vfile, arg->flags);
        if (!fence) {
                ret = -ENOMEM;
@@ -168,7 +150,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
        }
 
        /* Check for a conflicting fence */
-       resv = obj->dma_buf->resv;
+       resv = obj->resv;
        if (!reservation_object_test_signaled_rcu(resv,
                                                  arg->flags & VGEM_FENCE_WRITE)) {
                ret = -EBUSY;
index d17d8f2..1208445 100644 (file)
  *    Thomas Hellstrom.
  */
 
-#include <drm/drmP.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm.h>
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 #include "via_3d_reg.h"
 
@@ -430,14 +437,14 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
        diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
        count = 10000000;
        while (diff == 0 && count--) {
-               paused = (VIA_READ(0x41c) & 0x80000000);
+               paused = (via_read(dev_priv, 0x41c) & 0x80000000);
                if (paused)
                        break;
                reader = *(dev_priv->hw_addr_ptr);
                diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
        }
 
-       paused = VIA_READ(0x41c) & 0x80000000;
+       paused = via_read(dev_priv, 0x41c) & 0x80000000;
 
        if (paused && !no_pci_fire) {
                reader = *(dev_priv->hw_addr_ptr);
@@ -454,10 +461,10 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
                         * doesn't make a difference.
                         */
 
-                       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
-                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-                       VIA_READ(VIA_REG_TRANSPACE);
+                       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
+                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
+                       via_read(dev_priv, VIA_REG_TRANSPACE);
                }
        }
        return paused;
@@ -467,10 +474,10 @@ static int via_wait_idle(drm_via_private_t *dev_priv)
 {
        int count = 10000000;
 
-       while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count)
+       while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count)
                ;
 
-       while (count && (VIA_READ(VIA_REG_STATUS) &
+       while (count && (via_read(dev_priv, VIA_REG_STATUS) &
                           (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
                            VIA_3D_ENG_BUSY)))
                --count;
@@ -536,21 +543,21 @@ static void via_cmdbuf_start(drm_via_private_t *dev_priv)
        via_flush_write_combine();
        (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
 
-       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-       VIA_WRITE(VIA_REG_TRANSPACE, command);
-       VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
-       VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
+       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+       via_write(dev_priv, VIA_REG_TRANSPACE, command);
+       via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo);
+       via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo);
 
-       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
-       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
+       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
        wmb();
-       VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
-       VIA_READ(VIA_REG_TRANSPACE);
+       via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+       via_read(dev_priv, VIA_REG_TRANSPACE);
 
        dev_priv->dma_diff = 0;
 
        count = 10000000;
-       while (!(VIA_READ(0x41c) & 0x80000000) && count--);
+       while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--);
 
        reader = *(dev_priv->hw_addr_ptr);
        ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
index 0620674..feaa538 100644 (file)
  * the same DMA mappings?
  */
 
-#include <drm/drmP.h>
-#include <drm/via_drm.h>
-#include "via_drv.h"
-#include "via_dmablit.h"
-
 #include <linux/pagemap.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_pci.h>
+#include <drm/via_drm.h>
+
+#include "via_dmablit.h"
+#include "via_drv.h"
 
 #define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
 #define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
@@ -214,16 +217,16 @@ via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
-       VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
+       via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
                  VIA_DMA_CSR_DE);
-       VIA_WRITE(VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
-       VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
+       via_write(dev_priv, VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
+       via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
        wmb();
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
-       VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
+       via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04);
 }
 
 /*
@@ -291,7 +294,7 @@ via_abort_dmablit(struct drm_device *dev, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
 }
 
 static void
@@ -299,7 +302,7 @@ via_dmablit_engine_off(struct drm_device *dev, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
 }
 
 
@@ -330,7 +333,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
                spin_lock_irqsave(&blitq->blit_lock, irqsave);
 
        done_transfer = blitq->is_active &&
-         ((status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
+         ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
        done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE));
 
        cur = blitq->cur;
@@ -349,7 +352,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
                 * Clear transfer done flag.
                 */
 
-               VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
+               via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
 
                blitq->is_active = 0;
                blitq->aborting = 0;
@@ -436,7 +439,7 @@ via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
        int ret = 0;
 
        if (via_dmablit_active(blitq, engine, handle, &queue)) {
-               DRM_WAIT_ON(ret, *queue, 3 * HZ,
+               VIA_WAIT_ON(ret, *queue, 3 * HZ,
                            !via_dmablit_active(blitq, engine, handle, NULL));
        }
        DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
@@ -687,7 +690,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
        while (blitq->num_free == 0) {
                spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
 
-               DRM_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
+               VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
                if (ret)
                        return (-EINTR == ret) ? -EAGAIN : ret;
 
index af6a12d..666a16d 100644 (file)
 
 #include <linux/module.h>
 
-#include <drm/drmP.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_pciids.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 
-#include <drm/drm_pciids.h>
 
 static int via_driver_open(struct drm_device *dev, struct drm_file *file)
 {
index 6d1ae83..d5ad1b0 100644 (file)
 #ifndef _VIA_DRV_H_
 #define _VIA_DRV_H_
 
-#include <drm/drm_mm.h>
+#include <linux/irqreturn.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/wait.h>
+
+#include <drm/drm_ioctl.h>
 #include <drm/drm_legacy.h>
+#include <drm/drm_mm.h>
+#include <drm/via_drm.h>
 
 #define DRIVER_AUTHOR  "Various"
 
@@ -113,12 +121,67 @@ enum via_family {
 };
 
 /* VIA MMIO register access */
-#define VIA_BASE ((dev_priv->mmio))
+static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg)
+{
+       return readl((void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write(struct drm_via_private *dev_priv, u32 reg,
+                            u32 val)
+{
+       writel(val, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write8(struct drm_via_private *dev_priv, u32 reg,
+                             u32 val)
+{
+       writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write8_mask(struct drm_via_private *dev_priv,
+                                  u32 reg, u32 mask, u32 val)
+{
+       u32 tmp;
+
+       tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg));
+       tmp = (tmp & ~mask) | (val & mask);
+       writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
 
-#define VIA_READ(reg)          DRM_READ32(VIA_BASE, reg)
-#define VIA_WRITE(reg, val)    DRM_WRITE32(VIA_BASE, reg, val)
-#define VIA_READ8(reg)         DRM_READ8(VIA_BASE, reg)
-#define VIA_WRITE8(reg, val)   DRM_WRITE8(VIA_BASE, reg, val)
+/*
+ * Poll in a loop waiting for 'contidition' to be true.
+ * Note: A direct replacement with wait_event_interruptible_timeout()
+ *       will not work unless driver is updated to emit wake_up()
+ *       in relevant places that can impact the 'condition'
+ *
+ * Returns:
+ *   ret keeps current value if 'condition' becomes true
+ *   ret = -BUSY if timeout happens
+ *   ret = -EINTR if a signal interrupted the waiting period
+ */
+#define VIA_WAIT_ON( ret, queue, timeout, condition )          \
+do {                                                           \
+       DECLARE_WAITQUEUE(entry, current);                      \
+       unsigned long end = jiffies + (timeout);                \
+       add_wait_queue(&(queue), &entry);                       \
+                                                               \
+       for (;;) {                                              \
+               __set_current_state(TASK_INTERRUPTIBLE);        \
+               if (condition)                                  \
+                       break;                                  \
+               if (time_after_eq(jiffies, end)) {              \
+                       ret = -EBUSY;                           \
+                       break;                                  \
+               }                                               \
+               schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);    \
+               if (signal_pending(current)) {                  \
+                       ret = -EINTR;                           \
+                       break;                                  \
+               }                                               \
+       }                                                       \
+       __set_current_state(TASK_RUNNING);                      \
+       remove_wait_queue(&(queue), &entry);                    \
+} while (0)
 
 extern const struct drm_ioctl_desc via_ioctls[];
 extern int via_max_ioctl;
index c96830c..24cc445 100644 (file)
  * The refresh rate is also calculated for video playback sync purposes.
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_device.h>
+#include <drm/drm_vblank.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 
 #define VIA_REG_INTERRUPT       0x200
@@ -108,7 +110,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
        drm_via_irq_t *cur_irq = dev_priv->via_irqs;
        int i;
 
-       status = VIA_READ(VIA_REG_INTERRUPT);
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
        if (status & VIA_IRQ_VBLANK_PENDING) {
                atomic_inc(&dev_priv->vbl_received);
                if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
@@ -143,7 +145,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
        }
 
        /* Acknowledge interrupts */
-       VIA_WRITE(VIA_REG_INTERRUPT, status);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status);
 
 
        if (handled)
@@ -158,8 +160,8 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
 
        if (dev_priv) {
                /* Acknowledge interrupts */
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status |
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status |
                          dev_priv->irq_pending_mask);
        }
 }
@@ -174,11 +176,11 @@ int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
                return -EINVAL;
        }
 
-       status = VIA_READ(VIA_REG_INTERRUPT);
-       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
 
-       VIA_WRITE8(0x83d4, 0x11);
-       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
 
        return 0;
 }
@@ -188,11 +190,11 @@ void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
        drm_via_private_t *dev_priv = dev->dev_private;
        u32 status;
 
-       status = VIA_READ(VIA_REG_INTERRUPT);
-       VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
 
-       VIA_WRITE8(0x83d4, 0x11);
-       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
 
        if (pipe != 0)
                DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
@@ -233,12 +235,12 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence
        cur_irq = dev_priv->via_irqs + real_irq;
 
        if (masks[real_irq][2] && !force_sequence) {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
-                           ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
+               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
+                           ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) ==
                             masks[irq][4]));
                cur_irq_sequence = atomic_read(&cur_irq->irq_received);
        } else {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
+               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
                            (((cur_irq_sequence =
                               atomic_read(&cur_irq->irq_received)) -
                              *sequence) <= (1 << 23)));
@@ -292,8 +294,8 @@ void via_driver_irq_preinstall(struct drm_device *dev)
                dev_priv->last_vblank_valid = 0;
 
                /* Clear VSync interrupt regs */
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status &
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status &
                          ~(dev_priv->irq_enable_mask));
 
                /* Clear bits if they're already high */
@@ -310,13 +312,13 @@ int via_driver_irq_postinstall(struct drm_device *dev)
        if (!dev_priv)
                return -EINVAL;
 
-       status = VIA_READ(VIA_REG_INTERRUPT);
-       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
                  | dev_priv->irq_enable_mask);
 
        /* Some magic, oh for some data sheets ! */
-       VIA_WRITE8(0x83d4, 0x11);
-       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
 
        return 0;
 }
@@ -331,11 +333,11 @@ void via_driver_irq_uninstall(struct drm_device *dev)
 
                /* Some more magic, oh for some data sheets ! */
 
-               VIA_WRITE8(0x83d4, 0x11);
-               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+               via_write8(dev_priv, 0x83d4, 0x11);
+               via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
 
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status &
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status &
                          ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
        }
 }
index 2ad8658..431c150 100644 (file)
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-#include <drm/drmP.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_vblank.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 
 static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init)
index 4217d66..45cc9e9 100644 (file)
  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
  */
 
-#include <drm/drmP.h>
+#include <linux/slab.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/drm_irq.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 
 #define VIA_MM_ALIGN_SHIFT 4
index fb26094..8d8135f 100644 (file)
  * be very slow.
  */
 
-#include "via_3d_reg.h"
-#include <drm/drmP.h>
-#include <drm/via_drm.h>
+#include <drm/drm_device.h>
 #include <drm/drm_legacy.h>
-#include "via_verifier.h"
+#include <drm/via_drm.h>
+
+#include "via_3d_reg.h"
 #include "via_drv.h"
-#include <linux/kernel.h>
+#include "via_verifier.h"
 
 typedef enum {
        state_command,
@@ -725,14 +725,14 @@ via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
        next_fire = dev_priv->fire_offsets[*fire_count];
        buf++;
        cmd = (*buf & 0xFFFF0000) >> 16;
-       VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
+       via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
        switch (cmd) {
        case HC_ParaType_CmdVdata:
                while ((buf < buf_end) &&
                       (*fire_count < dev_priv->num_fire_offsets) &&
                       (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
                        while (buf <= next_fire) {
-                               VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                               via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
                                          (burst & 63), *buf++);
                                burst += 4;
                        }
@@ -753,7 +753,7 @@ via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
                            (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
                                break;
 
-                       VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                       via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
                                  (burst & 63), *buf++);
                        burst += 4;
                }
@@ -843,7 +843,7 @@ via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,
                cmd = *buf;
                if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
                        break;
-               VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+               via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
                buf++;
        }
        *buffer = buf;
@@ -894,7 +894,7 @@ via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,
        i = count = *buf;
        buf += 3;
        while (i--)
-               VIA_WRITE(addr, *buf++);
+               via_write(dev_priv, addr, *buf++);
        if (count & 3)
                buf += 4 - (count & 3);
        *buffer = buf;
@@ -950,7 +950,7 @@ via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer,
        buf += 3;
        while (i--) {
                addr = *buf++;
-               VIA_WRITE(addr, *buf++);
+               via_write(dev_priv, addr, *buf++);
        }
        count <<= 1;
        if (count & 3)
index a9ffbad..53b1f58 100644 (file)
@@ -25,8 +25,9 @@
  * Video and XvMC related functions.
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_device.h>
 #include <drm/via_drm.h>
+
 #include "via_drv.h"
 
 void via_init_futex(drm_via_private_t *dev_priv)
@@ -82,7 +83,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_
 
        switch (fx->func) {
        case VIA_FUTEX_WAIT:
-               DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
+               VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
                            (fx->ms / 10) * (HZ / 100), *lock != fx->val);
                return ret;
        case VIA_FUTEX_WAKE:
index ed0fcda..5156e6b 100644 (file)
@@ -23,8 +23,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <linux/debugfs.h>
-#include <drm/drmP.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_file.h>
 
 #include "virtgpu_drv.h"
 
index ba16e8c..e622485 100644 (file)
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "virtgpu_drv.h"
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_damage_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "virtgpu_drv.h"
 
 #define XRES_MIN    32
 #define YRES_MIN    32
index c508687..0fc32fa 100644 (file)
 #include <linux/module.h>
 #include <linux/console.h>
 #include <linux/pci.h>
-#include <drm/drmP.h>
+
 #include <drm/drm.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
 
 #include "virtgpu_drv.h"
+
 static struct drm_driver driver;
 
 static int virtio_gpu_modeset = -1;
@@ -195,7 +198,7 @@ static const struct file_operations virtio_gpu_driver_fops = {
 };
 
 static struct drm_driver driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
        .open = virtio_gpu_driver_open,
        .postclose = virtio_gpu_driver_postclose,
 
@@ -207,8 +210,6 @@ static struct drm_driver driver = {
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
        .gem_prime_vmap = virtgpu_gem_prime_vmap,
index 9e2d306..e288296 100644 (file)
 #include <linux/virtio_config.h>
 #include <linux/virtio_gpu.h>
 
-#include <drm/drmP.h>
-#include <drm/drm_gem.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_module.h>
+#include <drm/ttm/ttm_placement.h>
 
 #define DRIVER_NAME "virtio_gpu"
 #define DRIVER_DESC "virtio GPU"
@@ -396,7 +396,7 @@ static inline void virtio_gpu_object_unref(struct virtio_gpu_object **bo)
 
 static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo)
 {
-       return drm_vma_node_offset_addr(&bo->tbo.vma_node);
+       return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
 static inline int virtio_gpu_object_reserve(struct virtio_gpu_object *bo,
index 70d6c43..a0514f5 100644 (file)
@@ -23,8 +23,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
 #include <trace/events/dma_fence.h>
+
 #include "virtgpu_drv.h"
 
 static const char *virtio_get_driver_name(struct dma_fence *f)
index 1e49e08..2925661 100644 (file)
@@ -23,7 +23,9 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
+
 #include "virtgpu_drv.h"
 
 void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj)
index ac60be9..3c430dd 100644 (file)
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
-#include <drm/virtgpu_drm.h>
-#include <drm/ttm/ttm_execbuf_util.h>
+#include <linux/file.h>
 #include <linux/sync_file.h>
 
+#include <drm/drm_file.h>
+#include <drm/ttm/ttm_execbuf_util.h>
+#include <drm/virtgpu_drm.h>
+
 #include "virtgpu_drv.h"
 
 static void convert_to_hw_box(struct virtio_gpu_box *dst,
@@ -394,7 +396,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
                (vgdev, qobj->hw_res_handle,
                 vfpriv->ctx_id, offset, args->level,
                 &box, fence);
-       reservation_object_add_excl_fence(qobj->tbo.resv,
+       reservation_object_add_excl_fence(qobj->tbo.base.resv,
                                          &fence->f);
 
        dma_fence_put(&fence->f);
@@ -448,7 +450,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
                        (vgdev, qobj,
                         vfpriv ? vfpriv->ctx_id : 0, offset,
                         args->level, &box, fence);
-               reservation_object_add_excl_fence(qobj->tbo.resv,
+               reservation_object_add_excl_fence(qobj->tbo.base.resv,
                                                  &fence->f);
                dma_fence_put(&fence->f);
        }
@@ -553,34 +555,34 @@ copy_exit:
 
 struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
        DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
                          virtio_gpu_resource_create_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        /* make transfer async to the main ring? - no sure, can we
         * thread these in the underlying GL
         */
        DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
                          virtio_gpu_transfer_from_host_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
                          virtio_gpu_transfer_to_host_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 
        DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
-                         DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_RENDER_ALLOW),
 };
index 84b6a6b..c190702 100644 (file)
@@ -25,7 +25,9 @@
 
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_file.h>
+
 #include "virtgpu_drv.h"
 
 static void virtio_gpu_config_changed_work_func(struct work_struct *work)
index 024c2aa..3dc08f9 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "virtgpu_drv.h"
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane_helper.h>
+
+#include "virtgpu_drv.h"
 
 static const uint32_t virtio_gpu_formats[] = {
        DRM_FORMAT_HOST_XRGB8888,
@@ -210,7 +212,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
                         0, 0, vgfb->fence);
                ret = virtio_gpu_object_reserve(bo, false);
                if (!ret) {
-                       reservation_object_add_excl_fence(bo->tbo.resv,
+                       reservation_object_add_excl_fence(bo->tbo.base.resv,
                                                          &vgfb->fence->f);
                        dma_fence_put(&vgfb->fence->f);
                        vgfb->fence = NULL;
index 8fbf71b..dc642a8 100644 (file)
@@ -22,6 +22,8 @@
  * Authors: Andreas Pokorny
  */
 
+#include <drm/drm_prime.h>
+
 #include "virtgpu_drv.h"
 
 /* Empty Implementations as there should not be any other driver for a virtual
@@ -66,8 +68,5 @@ void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
 int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
                           struct vm_area_struct *vma)
 {
-       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
-
-       bo->gem_base.vma_node.vm_node.start = bo->tbo.vma_node.vm_node.start;
        return drm_gem_prime_mmap(obj, vma);
 }
index 300ef3a..f879036 100644 (file)
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/delay.h>
+
+#include <drm/drm.h>
+#include <drm/drm_file.h>
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_placement.h>
-#include <drm/ttm/ttm_page_alloc.h>
 #include <drm/ttm/ttm_module.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
+#include <drm/ttm/ttm_page_alloc.h>
+#include <drm/ttm/ttm_placement.h>
 #include <drm/virtgpu_drm.h>
-#include "virtgpu_drv.h"
 
-#include <linux/delay.h>
+#include "virtgpu_drv.h"
 
 static struct
 virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev)
index 981ee16..7ac2049 100644 (file)
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
-#include "virtgpu_drv.h"
-#include "virtgpu_trace.h"
+#include <linux/dma-mapping.h>
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
 
+#include "virtgpu_drv.h"
+#include "virtgpu_trace.h"
+
 #define MAX_INLINE_CMD_SIZE   96
 #define MAX_INLINE_RESP_SIZE  24
 #define VBUFFER_SIZE          (sizeof(struct virtio_gpu_vbuffer) \
index 89f09be..0b767d7 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_crc.o
+vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_composer.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
new file mode 100644 (file)
index 0000000..d558569
--- /dev/null
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/crc32.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "vkms_drv.h"
+
+/**
+ * compute_crc - Compute CRC value on output frame
+ *
+ * @vaddr_out: address to final framebuffer
+ * @composer: framebuffer's metadata
+ *
+ * returns CRC value computed using crc32 on the visible portion of
+ * the final framebuffer at vaddr_out
+ */
+static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer)
+{
+       int i, j, src_offset;
+       int x_src = composer->src.x1 >> 16;
+       int y_src = composer->src.y1 >> 16;
+       int h_src = drm_rect_height(&composer->src) >> 16;
+       int w_src = drm_rect_width(&composer->src) >> 16;
+       u32 crc = 0;
+
+       for (i = y_src; i < y_src + h_src; ++i) {
+               for (j = x_src; j < x_src + w_src; ++j) {
+                       src_offset = composer->offset
+                                    + (i * composer->pitch)
+                                    + (j * composer->cpp);
+                       /* XRGB format ignores Alpha channel */
+                       memset(vaddr_out + src_offset + 24, 0,  8);
+                       crc = crc32_le(crc, vaddr_out + src_offset,
+                                      sizeof(u32));
+               }
+       }
+
+       return crc;
+}
+
+/**
+ * blend - belnd value at vaddr_src with value at vaddr_dst
+ * @vaddr_dst: destination address
+ * @vaddr_src: source address
+ * @dest_composer: destination framebuffer's metadata
+ * @src_composer: source framebuffer's metadata
+ *
+ * Blend value at vaddr_src with value at vaddr_dst.
+ * Currently, this function write value at vaddr_src on value
+ * at vaddr_dst using buffer's metadata to locate the new values
+ * from vaddr_src and their distenation at vaddr_dst.
+ *
+ * Todo: Use the alpha value to blend vaddr_src with vaddr_dst
+ *      instead of overwriting it.
+ */
+static void blend(void *vaddr_dst, void *vaddr_src,
+                 struct vkms_composer *dest_composer,
+                 struct vkms_composer *src_composer)
+{
+       int i, j, j_dst, i_dst;
+       int offset_src, offset_dst;
+
+       int x_src = src_composer->src.x1 >> 16;
+       int y_src = src_composer->src.y1 >> 16;
+
+       int x_dst = src_composer->dst.x1;
+       int y_dst = src_composer->dst.y1;
+       int h_dst = drm_rect_height(&src_composer->dst);
+       int w_dst = drm_rect_width(&src_composer->dst);
+
+       int y_limit = y_src + h_dst;
+       int x_limit = x_src + w_dst;
+
+       for (i = y_src, i_dst = y_dst; i < y_limit; ++i) {
+               for (j = x_src, j_dst = x_dst; j < x_limit; ++j) {
+                       offset_dst = dest_composer->offset
+                                    + (i_dst * dest_composer->pitch)
+                                    + (j_dst++ * dest_composer->cpp);
+                       offset_src = src_composer->offset
+                                    + (i * src_composer->pitch)
+                                    + (j * src_composer->cpp);
+
+                       memcpy(vaddr_dst + offset_dst,
+                              vaddr_src + offset_src, sizeof(u32));
+               }
+               i_dst++;
+       }
+}
+
+static void compose_cursor(struct vkms_composer *cursor_composer,
+                          struct vkms_composer *primary_composer,
+                          void *vaddr_out)
+{
+       struct drm_gem_object *cursor_obj;
+       struct vkms_gem_object *cursor_vkms_obj;
+
+       cursor_obj = drm_gem_fb_get_obj(&cursor_composer->fb, 0);
+       cursor_vkms_obj = drm_gem_to_vkms_gem(cursor_obj);
+
+       if (WARN_ON(!cursor_vkms_obj->vaddr))
+               return;
+
+       blend(vaddr_out, cursor_vkms_obj->vaddr,
+             primary_composer, cursor_composer);
+}
+
+static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer,
+                             struct vkms_composer *cursor_composer)
+{
+       struct drm_framebuffer *fb = &primary_composer->fb;
+       struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
+       struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
+       void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
+       u32 crc = 0;
+
+       if (!vaddr_out) {
+               DRM_ERROR("Failed to allocate memory for output frame.");
+               return 0;
+       }
+
+       if (WARN_ON(!vkms_obj->vaddr)) {
+               kfree(vaddr_out);
+               return crc;
+       }
+
+       memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
+
+       if (cursor_composer)
+               compose_cursor(cursor_composer, primary_composer, vaddr_out);
+
+       crc = compute_crc(vaddr_out, primary_composer);
+
+       kfree(vaddr_out);
+
+       return crc;
+}
+
+/**
+ * vkms_composer_worker - ordered work_struct to compute CRC
+ *
+ * @work: work_struct
+ *
+ * Work handler for composing and computing CRCs. work_struct scheduled in
+ * an ordered workqueue that's periodically scheduled to run by
+ * _vblank_handle() and flushed at vkms_atomic_crtc_destroy_state().
+ */
+void vkms_composer_worker(struct work_struct *work)
+{
+       struct vkms_crtc_state *crtc_state = container_of(work,
+                                               struct vkms_crtc_state,
+                                               composer_work);
+       struct drm_crtc *crtc = crtc_state->base.crtc;
+       struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
+       struct vkms_composer *primary_composer = NULL;
+       struct vkms_composer *cursor_composer = NULL;
+       u32 crc32 = 0;
+       u64 frame_start, frame_end;
+       bool crc_pending;
+
+       spin_lock_irq(&out->composer_lock);
+       frame_start = crtc_state->frame_start;
+       frame_end = crtc_state->frame_end;
+       crc_pending = crtc_state->crc_pending;
+       crtc_state->frame_start = 0;
+       crtc_state->frame_end = 0;
+       crtc_state->crc_pending = false;
+       spin_unlock_irq(&out->composer_lock);
+
+       /*
+        * We raced with the vblank hrtimer and previous work already computed
+        * the crc, nothing to do.
+        */
+       if (!crc_pending)
+               return;
+
+       if (crtc_state->num_active_planes >= 1)
+               primary_composer = crtc_state->active_planes[0]->composer;
+
+       if (crtc_state->num_active_planes == 2)
+               cursor_composer = crtc_state->active_planes[1]->composer;
+
+       if (primary_composer)
+               crc32 = _vkms_get_crc(primary_composer, cursor_composer);
+
+       /*
+        * The worker can fall behind the vblank hrtimer, make sure we catch up.
+        */
+       while (frame_start <= frame_end)
+               drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32);
+}
+
+static const char * const pipe_crc_sources[] = {"auto"};
+
+const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
+                                       size_t *count)
+{
+       *count = ARRAY_SIZE(pipe_crc_sources);
+       return pipe_crc_sources;
+}
+
+static int vkms_crc_parse_source(const char *src_name, bool *enabled)
+{
+       int ret = 0;
+
+       if (!src_name) {
+               *enabled = false;
+       } else if (strcmp(src_name, "auto") == 0) {
+               *enabled = true;
+       } else {
+               *enabled = false;
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
+                          size_t *values_cnt)
+{
+       bool enabled;
+
+       if (vkms_crc_parse_source(src_name, &enabled) < 0) {
+               DRM_DEBUG_DRIVER("unknown source %s\n", src_name);
+               return -EINVAL;
+       }
+
+       *values_cnt = 1;
+
+       return 0;
+}
+
+int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+{
+       struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
+       bool enabled = false;
+       int ret = 0;
+
+       ret = vkms_crc_parse_source(src_name, &enabled);
+
+       spin_lock_irq(&out->lock);
+       out->composer_enabled = enabled;
+       spin_unlock_irq(&out->lock);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
deleted file mode 100644 (file)
index e66ff25..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include "vkms_drv.h"
-#include <linux/crc32.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-
-/**
- * compute_crc - Compute CRC value on output frame
- *
- * @vaddr_out: address to final framebuffer
- * @crc_out: framebuffer's metadata
- *
- * returns CRC value computed using crc32 on the visible portion of
- * the final framebuffer at vaddr_out
- */
-static uint32_t compute_crc(void *vaddr_out, struct vkms_crc_data *crc_out)
-{
-       int i, j, src_offset;
-       int x_src = crc_out->src.x1 >> 16;
-       int y_src = crc_out->src.y1 >> 16;
-       int h_src = drm_rect_height(&crc_out->src) >> 16;
-       int w_src = drm_rect_width(&crc_out->src) >> 16;
-       u32 crc = 0;
-
-       for (i = y_src; i < y_src + h_src; ++i) {
-               for (j = x_src; j < x_src + w_src; ++j) {
-                       src_offset = crc_out->offset
-                                    + (i * crc_out->pitch)
-                                    + (j * crc_out->cpp);
-                       /* XRGB format ignores Alpha channel */
-                       memset(vaddr_out + src_offset + 24, 0,  8);
-                       crc = crc32_le(crc, vaddr_out + src_offset,
-                                      sizeof(u32));
-               }
-       }
-
-       return crc;
-}
-
-/**
- * blend - belnd value at vaddr_src with value at vaddr_dst
- * @vaddr_dst: destination address
- * @vaddr_src: source address
- * @crc_dst: destination framebuffer's metadata
- * @crc_src: source framebuffer's metadata
- *
- * Blend value at vaddr_src with value at vaddr_dst.
- * Currently, this function write value at vaddr_src on value
- * at vaddr_dst using buffer's metadata to locate the new values
- * from vaddr_src and their distenation at vaddr_dst.
- *
- * Todo: Use the alpha value to blend vaddr_src with vaddr_dst
- *      instead of overwriting it.
- */
-static void blend(void *vaddr_dst, void *vaddr_src,
-                 struct vkms_crc_data *crc_dst,
-                 struct vkms_crc_data *crc_src)
-{
-       int i, j, j_dst, i_dst;
-       int offset_src, offset_dst;
-
-       int x_src = crc_src->src.x1 >> 16;
-       int y_src = crc_src->src.y1 >> 16;
-
-       int x_dst = crc_src->dst.x1;
-       int y_dst = crc_src->dst.y1;
-       int h_dst = drm_rect_height(&crc_src->dst);
-       int w_dst = drm_rect_width(&crc_src->dst);
-
-       int y_limit = y_src + h_dst;
-       int x_limit = x_src + w_dst;
-
-       for (i = y_src, i_dst = y_dst; i < y_limit; ++i) {
-               for (j = x_src, j_dst = x_dst; j < x_limit; ++j) {
-                       offset_dst = crc_dst->offset
-                                    + (i_dst * crc_dst->pitch)
-                                    + (j_dst++ * crc_dst->cpp);
-                       offset_src = crc_src->offset
-                                    + (i * crc_src->pitch)
-                                    + (j * crc_src->cpp);
-
-                       memcpy(vaddr_dst + offset_dst,
-                              vaddr_src + offset_src, sizeof(u32));
-               }
-               i_dst++;
-       }
-}
-
-static void compose_cursor(struct vkms_crc_data *cursor_crc,
-                          struct vkms_crc_data *primary_crc, void *vaddr_out)
-{
-       struct drm_gem_object *cursor_obj;
-       struct vkms_gem_object *cursor_vkms_obj;
-
-       cursor_obj = drm_gem_fb_get_obj(&cursor_crc->fb, 0);
-       cursor_vkms_obj = drm_gem_to_vkms_gem(cursor_obj);
-
-       mutex_lock(&cursor_vkms_obj->pages_lock);
-       if (!cursor_vkms_obj->vaddr) {
-               DRM_WARN("cursor plane vaddr is NULL");
-               goto out;
-       }
-
-       blend(vaddr_out, cursor_vkms_obj->vaddr, primary_crc, cursor_crc);
-
-out:
-       mutex_unlock(&cursor_vkms_obj->pages_lock);
-}
-
-static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc,
-                             struct vkms_crc_data *cursor_crc)
-{
-       struct drm_framebuffer *fb = &primary_crc->fb;
-       struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
-       struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
-       void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
-       u32 crc = 0;
-
-       if (!vaddr_out) {
-               DRM_ERROR("Failed to allocate memory for output frame.");
-               return 0;
-       }
-
-       mutex_lock(&vkms_obj->pages_lock);
-       if (WARN_ON(!vkms_obj->vaddr)) {
-               mutex_unlock(&vkms_obj->pages_lock);
-               kfree(vaddr_out);
-               return crc;
-       }
-
-       memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
-       mutex_unlock(&vkms_obj->pages_lock);
-
-       if (cursor_crc)
-               compose_cursor(cursor_crc, primary_crc, vaddr_out);
-
-       crc = compute_crc(vaddr_out, primary_crc);
-
-       kfree(vaddr_out);
-
-       return crc;
-}
-
-/**
- * vkms_crc_work_handle - ordered work_struct to compute CRC
- *
- * @work: work_struct
- *
- * Work handler for computing CRCs. work_struct scheduled in
- * an ordered workqueue that's periodically scheduled to run by
- * _vblank_handle() and flushed at vkms_atomic_crtc_destroy_state().
- */
-void vkms_crc_work_handle(struct work_struct *work)
-{
-       struct vkms_crtc_state *crtc_state = container_of(work,
-                                               struct vkms_crtc_state,
-                                               crc_work);
-       struct drm_crtc *crtc = crtc_state->base.crtc;
-       struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
-       struct vkms_device *vdev = container_of(out, struct vkms_device,
-                                               output);
-       struct vkms_crc_data *primary_crc = NULL;
-       struct vkms_crc_data *cursor_crc = NULL;
-       struct drm_plane *plane;
-       u32 crc32 = 0;
-       u64 frame_start, frame_end;
-       unsigned long flags;
-
-       spin_lock_irqsave(&out->state_lock, flags);
-       frame_start = crtc_state->frame_start;
-       frame_end = crtc_state->frame_end;
-       spin_unlock_irqrestore(&out->state_lock, flags);
-
-       /* _vblank_handle() hasn't updated frame_start yet */
-       if (!frame_start || frame_start == frame_end)
-               goto out;
-
-       drm_for_each_plane(plane, &vdev->drm) {
-               struct vkms_plane_state *vplane_state;
-               struct vkms_crc_data *crc_data;
-
-               vplane_state = to_vkms_plane_state(plane->state);
-               crc_data = vplane_state->crc_data;
-
-               if (drm_framebuffer_read_refcount(&crc_data->fb) == 0)
-                       continue;
-
-               if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-                       primary_crc = crc_data;
-               else
-                       cursor_crc = crc_data;
-       }
-
-       if (primary_crc)
-               crc32 = _vkms_get_crc(primary_crc, cursor_crc);
-
-       frame_end = drm_crtc_accurate_vblank_count(crtc);
-
-       /* queue_work can fail to schedule crc_work; add crc for
-        * missing frames
-        */
-       while (frame_start <= frame_end)
-               drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32);
-
-out:
-       /* to avoid using the same value for frame number again */
-       spin_lock_irqsave(&out->state_lock, flags);
-       crtc_state->frame_end = frame_end;
-       crtc_state->frame_start = 0;
-       spin_unlock_irqrestore(&out->state_lock, flags);
-}
-
-static const char * const pipe_crc_sources[] = {"auto"};
-
-const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
-                                       size_t *count)
-{
-       *count = ARRAY_SIZE(pipe_crc_sources);
-       return pipe_crc_sources;
-}
-
-static int vkms_crc_parse_source(const char *src_name, bool *enabled)
-{
-       int ret = 0;
-
-       if (!src_name) {
-               *enabled = false;
-       } else if (strcmp(src_name, "auto") == 0) {
-               *enabled = true;
-       } else {
-               *enabled = false;
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
-                          size_t *values_cnt)
-{
-       bool enabled;
-
-       if (vkms_crc_parse_source(src_name, &enabled) < 0) {
-               DRM_DEBUG_DRIVER("unknown source %s\n", src_name);
-               return -EINVAL;
-       }
-
-       *values_cnt = 1;
-
-       return 0;
-}
-
-int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name)
-{
-       struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
-       bool enabled = false;
-       unsigned long flags;
-       int ret = 0;
-
-       ret = vkms_crc_parse_source(src_name, &enabled);
-
-       /* make sure nothing is scheduled on crtc workq */
-       flush_workqueue(out->crc_workq);
-
-       spin_lock_irqsave(&out->lock, flags);
-       out->crc_enabled = enabled;
-       spin_unlock_irqrestore(&out->lock, flags);
-
-       return ret;
-}
index 4d11292..927dafa 100644 (file)
@@ -1,15 +1,18 @@
 // SPDX-License-Identifier: GPL-2.0+
 
-#include "vkms_drv.h"
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "vkms_drv.h"
 
 static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
 {
        struct vkms_output *output = container_of(timer, struct vkms_output,
                                                  vblank_hrtimer);
        struct drm_crtc *crtc = &output->crtc;
-       struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state);
+       struct vkms_crtc_state *state;
        u64 ret_overrun;
        bool ret;
 
@@ -23,20 +26,26 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
        if (!ret)
                DRM_ERROR("vkms failure on handling vblank");
 
-       if (state && output->crc_enabled) {
+       state = output->composer_state;
+       if (state && output->composer_enabled) {
                u64 frame = drm_crtc_accurate_vblank_count(crtc);
 
-               /* update frame_start only if a queued vkms_crc_work_handle()
+               /* update frame_start only if a queued vkms_composer_worker()
                 * has read the data
                 */
-               spin_lock(&output->state_lock);
-               if (!state->frame_start)
+               spin_lock(&output->composer_lock);
+               if (!state->crc_pending)
                        state->frame_start = frame;
-               spin_unlock(&output->state_lock);
+               else
+                       DRM_DEBUG_DRIVER("crc worker falling behind, frame_start: %llu, frame_end: %llu\n",
+                                        state->frame_start, frame);
+               state->frame_end = frame;
+               state->crc_pending = true;
+               spin_unlock(&output->composer_lock);
 
-               ret = queue_work(output->crc_workq, &state->crc_work);
+               ret = queue_work(output->composer_workq, &state->composer_work);
                if (!ret)
-                       DRM_WARN("failed to queue vkms_crc_work_handle");
+                       DRM_DEBUG_DRIVER("Composer worker already queued\n");
        }
 
        spin_unlock(&output->lock);
@@ -107,7 +116,7 @@ vkms_atomic_crtc_duplicate_state(struct drm_crtc *crtc)
 
        __drm_atomic_helper_crtc_duplicate_state(crtc, &vkms_state->base);
 
-       INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle);
+       INIT_WORK(&vkms_state->composer_work, vkms_composer_worker);
 
        return &vkms_state->base;
 }
@@ -119,10 +128,9 @@ static void vkms_atomic_crtc_destroy_state(struct drm_crtc *crtc,
 
        __drm_atomic_helper_crtc_destroy_state(state);
 
-       if (vkms_state) {
-               flush_work(&vkms_state->crc_work);
-               kfree(vkms_state);
-       }
+       WARN_ON(work_pending(&vkms_state->composer_work));
+       kfree(vkms_state->active_planes);
+       kfree(vkms_state);
 }
 
 static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)
@@ -135,7 +143,7 @@ static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)
 
        __drm_atomic_helper_crtc_reset(crtc, &vkms_state->base);
        if (vkms_state)
-               INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle);
+               INIT_WORK(&vkms_state->composer_work, vkms_composer_worker);
 }
 
 static const struct drm_crtc_funcs vkms_crtc_funcs = {
@@ -152,6 +160,52 @@ static const struct drm_crtc_funcs vkms_crtc_funcs = {
        .verify_crc_source      = vkms_verify_crc_source,
 };
 
+static int vkms_crtc_atomic_check(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *state)
+{
+       struct vkms_crtc_state *vkms_state = to_vkms_crtc_state(state);
+       struct drm_plane *plane;
+       struct drm_plane_state *plane_state;
+       int i = 0, ret;
+
+       if (vkms_state->active_planes)
+               return 0;
+
+       ret = drm_atomic_add_affected_planes(state->state, crtc);
+       if (ret < 0)
+               return ret;
+
+       drm_for_each_plane_mask(plane, crtc->dev, state->plane_mask) {
+               plane_state = drm_atomic_get_existing_plane_state(state->state,
+                                                                 plane);
+               WARN_ON(!plane_state);
+
+               if (!plane_state->visible)
+                       continue;
+
+               i++;
+       }
+
+       vkms_state->active_planes = kcalloc(i, sizeof(plane), GFP_KERNEL);
+       if (!vkms_state->active_planes)
+               return -ENOMEM;
+       vkms_state->num_active_planes = i;
+
+       i = 0;
+       drm_for_each_plane_mask(plane, crtc->dev, state->plane_mask) {
+               plane_state = drm_atomic_get_existing_plane_state(state->state,
+                                                                 plane);
+
+               if (!plane_state->visible)
+                       continue;
+
+               vkms_state->active_planes[i++] =
+                       to_vkms_plane_state(plane_state);
+       }
+
+       return 0;
+}
+
 static void vkms_crtc_atomic_enable(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
@@ -170,7 +224,7 @@ static void vkms_crtc_atomic_begin(struct drm_crtc *crtc,
        struct vkms_output *vkms_output = drm_crtc_to_vkms_output(crtc);
 
        /* This lock is held across the atomic commit to block vblank timer
-        * from scheduling vkms_crc_work_handle until the crc_data is updated
+        * from scheduling vkms_composer_worker until the composer is updated
         */
        spin_lock_irq(&vkms_output->lock);
 }
@@ -179,25 +233,27 @@ static void vkms_crtc_atomic_flush(struct drm_crtc *crtc,
                                   struct drm_crtc_state *old_crtc_state)
 {
        struct vkms_output *vkms_output = drm_crtc_to_vkms_output(crtc);
-       unsigned long flags;
 
        if (crtc->state->event) {
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
+               spin_lock(&crtc->dev->event_lock);
 
                if (drm_crtc_vblank_get(crtc) != 0)
                        drm_crtc_send_vblank_event(crtc, crtc->state->event);
                else
                        drm_crtc_arm_vblank_event(crtc, crtc->state->event);
 
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+               spin_unlock(&crtc->dev->event_lock);
 
                crtc->state->event = NULL;
        }
 
+       vkms_output->composer_state = to_vkms_crtc_state(crtc->state);
+
        spin_unlock_irq(&vkms_output->lock);
 }
 
 static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = {
+       .atomic_check   = vkms_crtc_atomic_check,
        .atomic_begin   = vkms_crtc_atomic_begin,
        .atomic_flush   = vkms_crtc_atomic_flush,
        .atomic_enable  = vkms_crtc_atomic_enable,
@@ -220,10 +276,10 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
        drm_crtc_helper_add(crtc, &vkms_crtc_helper_funcs);
 
        spin_lock_init(&vkms_out->lock);
-       spin_lock_init(&vkms_out->state_lock);
+       spin_lock_init(&vkms_out->composer_lock);
 
-       vkms_out->crc_workq = alloc_ordered_workqueue("vkms_crc_workq", 0);
-       if (!vkms_out->crc_workq)
+       vkms_out->composer_workq = alloc_ordered_workqueue("vkms_composer", 0);
+       if (!vkms_out->composer_workq)
                return -ENOMEM;
 
        return ret;
index 738dd62..44ab9f8 100644 (file)
  */
 
 #include <linux/module.h>
-#include <drm/drm_gem.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
 #include "vkms_drv.h"
 
 #define DRIVER_NAME    "vkms"
@@ -55,7 +63,36 @@ static void vkms_release(struct drm_device *dev)
        drm_atomic_helper_shutdown(&vkms->drm);
        drm_mode_config_cleanup(&vkms->drm);
        drm_dev_fini(&vkms->drm);
-       destroy_workqueue(vkms->output.crc_workq);
+       destroy_workqueue(vkms->output.composer_workq);
+}
+
+static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = old_state->dev;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state;
+       int i;
+
+       drm_atomic_helper_commit_modeset_disables(dev, old_state);
+
+       drm_atomic_helper_commit_planes(dev, old_state, 0);
+
+       drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+       drm_atomic_helper_fake_vblank(old_state);
+
+       drm_atomic_helper_commit_hw_done(old_state);
+
+       drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+       for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+               struct vkms_crtc_state *vkms_state =
+                       to_vkms_crtc_state(old_crtc_state);
+
+               flush_work(&vkms_state->composer_work);
+       }
+
+       drm_atomic_helper_cleanup_planes(dev, old_state);
 }
 
 static struct drm_driver vkms_driver = {
@@ -80,6 +117,10 @@ static const struct drm_mode_config_funcs vkms_mode_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
+static const struct drm_mode_config_helper_funcs vkms_mode_config_helpers = {
+       .atomic_commit_tail = vkms_atomic_commit_tail,
+};
+
 static int vkms_modeset_init(struct vkms_device *vkmsdev)
 {
        struct drm_device *dev = &vkmsdev->drm;
@@ -91,8 +132,9 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev)
        dev->mode_config.max_width = XRES_MAX;
        dev->mode_config.max_height = YRES_MAX;
        dev->mode_config.preferred_depth = 24;
+       dev->mode_config.helper_private = &vkms_mode_config_helpers;
 
-       return vkms_output_init(vkmsdev);
+       return vkms_output_init(vkmsdev, 0);
 }
 
 static int __init vkms_init(void)
index b92c30c..5a95100 100644 (file)
@@ -3,11 +3,11 @@
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
-#include <drm/drmP.h>
+#include <linux/hrtimer.h>
+
 #include <drm/drm.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_encoder.h>
-#include <linux/hrtimer.h>
 
 #define XRES_MIN    20
 #define YRES_MIN    20
@@ -20,7 +20,7 @@
 
 extern bool enable_cursor;
 
-struct vkms_crc_data {
+struct vkms_composer {
        struct drm_framebuffer fb;
        struct drm_rect src, dst;
        unsigned int offset;
@@ -31,23 +31,30 @@ struct vkms_crc_data {
 /**
  * vkms_plane_state - Driver specific plane state
  * @base: base plane state
- * @crc_data: data required for CRC computation
+ * @composer: data required for composing computation
  */
 struct vkms_plane_state {
        struct drm_plane_state base;
-       struct vkms_crc_data *crc_data;
+       struct vkms_composer *composer;
 };
 
 /**
  * vkms_crtc_state - Driver specific CRTC state
  * @base: base CRTC state
- * @crc_work: work struct to compute and add CRC entries
+ * @composer_work: work struct to compose and add CRC entries
  * @n_frame_start: start frame number for computed CRC
  * @n_frame_end: end frame number for computed CRC
  */
 struct vkms_crtc_state {
        struct drm_crtc_state base;
-       struct work_struct crc_work;
+       struct work_struct composer_work;
+
+       int num_active_planes;
+       /* stack of active planes for crc computation, should be in z order */
+       struct vkms_plane_state **active_planes;
+
+       /* below three are protected by vkms_output.composer_lock */
+       bool crc_pending;
        u64 frame_start;
        u64 frame_end;
 };
@@ -59,13 +66,16 @@ struct vkms_output {
        struct hrtimer vblank_hrtimer;
        ktime_t period_ns;
        struct drm_pending_vblank_event *event;
-       bool crc_enabled;
-       /* ordered wq for crc_work */
-       struct workqueue_struct *crc_workq;
-       /* protects concurrent access to crc_data */
+       /* ordered wq for composer_work */
+       struct workqueue_struct *composer_workq;
+       /* protects concurrent access to composer */
        spinlock_t lock;
-       /* protects concurrent access to crtc_state */
-       spinlock_t state_lock;
+
+       /* protected by @lock */
+       bool composer_enabled;
+       struct vkms_crtc_state *composer_state;
+
+       spinlock_t composer_lock;
 };
 
 struct vkms_device {
@@ -105,10 +115,10 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
                               int *max_error, ktime_t *vblank_time,
                               bool in_vblank_irq);
 
-int vkms_output_init(struct vkms_device *vkmsdev);
+int vkms_output_init(struct vkms_device *vkmsdev, int index);
 
 struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
-                                 enum drm_plane_type type);
+                                 enum drm_plane_type type, int index);
 
 /* Gem stuff */
 struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
@@ -133,6 +143,8 @@ const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
 int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name);
 int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
                           size_t *values_cnt);
-void vkms_crc_work_handle(struct work_struct *work);
+
+/* Composer Support */
+void vkms_composer_worker(struct work_struct *work);
 
 #endif /* _VKMS_DRV_H_ */
index 69048e7..6489bfe 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include <linux/shmem_fs.h>
+#include <linux/vmalloc.h>
 
 #include "vkms_drv.h"
 
index 56fb5c2..fb1941a 100644 (file)
@@ -35,7 +35,7 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
        .get_modes    = vkms_conn_get_modes,
 };
 
-int vkms_output_init(struct vkms_device *vkmsdev)
+int vkms_output_init(struct vkms_device *vkmsdev, int index)
 {
        struct vkms_output *output = &vkmsdev->output;
        struct drm_device *dev = &vkmsdev->drm;
@@ -45,12 +45,12 @@ int vkms_output_init(struct vkms_device *vkmsdev)
        struct drm_plane *primary, *cursor = NULL;
        int ret;
 
-       primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY);
+       primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
        if (IS_ERR(primary))
                return PTR_ERR(primary);
 
        if (enable_cursor) {
-               cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR);
+               cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
                if (IS_ERR(cursor)) {
                        ret = PTR_ERR(cursor);
                        goto err_cursor;
index 0fceb62..5fc8f85 100644 (file)
@@ -1,10 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0+
 
-#include "vkms_drv.h"
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "vkms_drv.h"
 
 static const u32 vkms_formats[] = {
        DRM_FORMAT_XRGB8888,
@@ -18,20 +20,20 @@ static struct drm_plane_state *
 vkms_plane_duplicate_state(struct drm_plane *plane)
 {
        struct vkms_plane_state *vkms_state;
-       struct vkms_crc_data *crc_data;
+       struct vkms_composer *composer;
 
        vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
        if (!vkms_state)
                return NULL;
 
-       crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL);
-       if (!crc_data) {
-               DRM_DEBUG_KMS("Couldn't allocate crc_data\n");
+       composer = kzalloc(sizeof(*composer), GFP_KERNEL);
+       if (!composer) {
+               DRM_DEBUG_KMS("Couldn't allocate composer\n");
                kfree(vkms_state);
                return NULL;
        }
 
-       vkms_state->crc_data = crc_data;
+       vkms_state->composer = composer;
 
        __drm_atomic_helper_plane_duplicate_state(plane,
                                                  &vkms_state->base);
@@ -49,12 +51,12 @@ static void vkms_plane_destroy_state(struct drm_plane *plane,
                /* dropping the reference we acquired in
                 * vkms_primary_plane_update()
                 */
-               if (drm_framebuffer_read_refcount(&vkms_state->crc_data->fb))
-                       drm_framebuffer_put(&vkms_state->crc_data->fb);
+               if (drm_framebuffer_read_refcount(&vkms_state->composer->fb))
+                       drm_framebuffer_put(&vkms_state->composer->fb);
        }
 
-       kfree(vkms_state->crc_data);
-       vkms_state->crc_data = NULL;
+       kfree(vkms_state->composer);
+       vkms_state->composer = NULL;
 
        __drm_atomic_helper_plane_destroy_state(old_state);
        kfree(vkms_state);
@@ -91,21 +93,21 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
 {
        struct vkms_plane_state *vkms_plane_state;
        struct drm_framebuffer *fb = plane->state->fb;
-       struct vkms_crc_data *crc_data;
+       struct vkms_composer *composer;
 
        if (!plane->state->crtc || !fb)
                return;
 
        vkms_plane_state = to_vkms_plane_state(plane->state);
 
-       crc_data = vkms_plane_state->crc_data;
-       memcpy(&crc_data->src, &plane->state->src, sizeof(struct drm_rect));
-       memcpy(&crc_data->dst, &plane->state->dst, sizeof(struct drm_rect));
-       memcpy(&crc_data->fb, fb, sizeof(struct drm_framebuffer));
-       drm_framebuffer_get(&crc_data->fb);
-       crc_data->offset = fb->offsets[0];
-       crc_data->pitch = fb->pitches[0];
-       crc_data->cpp = fb->format->cpp[0];
+       composer = vkms_plane_state->composer;
+       memcpy(&composer->src, &plane->state->src, sizeof(struct drm_rect));
+       memcpy(&composer->dst, &plane->state->dst, sizeof(struct drm_rect));
+       memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));
+       drm_framebuffer_get(&composer->fb);
+       composer->offset = fb->offsets[0];
+       composer->pitch = fb->pitches[0];
+       composer->cpp = fb->format->cpp[0];
 }
 
 static int vkms_plane_atomic_check(struct drm_plane *plane,
@@ -176,7 +178,7 @@ static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
 };
 
 struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
-                                 enum drm_plane_type type)
+                                 enum drm_plane_type type, int index)
 {
        struct drm_device *dev = &vkmsdev->drm;
        const struct drm_plane_helper_funcs *funcs;
@@ -198,7 +200,7 @@ struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
                funcs = &vkms_primary_helper_funcs;
        }
 
-       ret = drm_universal_plane_init(dev, plane, 0,
+       ret = drm_universal_plane_init(dev, plane, 1 << index,
                                       &vkms_plane_funcs,
                                       formats, nformats,
                                       NULL, type, NULL);
index fc6673c..6c01ad2 100644 (file)
@@ -459,9 +459,9 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
 
        /* Buffer objects need to be either pinned or reserved: */
        if (!(dst->mem.placement & TTM_PL_FLAG_NO_EVICT))
-               lockdep_assert_held(&dst->resv->lock.base);
+               reservation_object_assert_held(dst->base.resv);
        if (!(src->mem.placement & TTM_PL_FLAG_NO_EVICT))
-               lockdep_assert_held(&src->resv->lock.base);
+               reservation_object_assert_held(src->base.resv);
 
        if (dst->ttm->state == tt_unpopulated) {
                ret = dst->ttm->bdev->driver->ttm_tt_populate(dst->ttm, &ctx);
index 5d5c2bc..369034c 100644 (file)
@@ -342,7 +342,7 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin)
        uint32_t old_mem_type = bo->mem.mem_type;
        int ret;
 
-       lockdep_assert_held(&bo->resv->lock.base);
+       reservation_object_assert_held(bo->base.resv);
 
        if (pin) {
                if (vbo->pin_count++ > 0)
@@ -690,7 +690,7 @@ static int vmw_user_bo_synccpu_grab(struct vmw_user_buffer_object *user_bo,
                long lret;
 
                lret = reservation_object_wait_timeout_rcu
-                       (bo->resv, true, true,
+                       (bo->base.resv, true, true,
                         nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
                if (!lret)
                        return -EBUSY;
@@ -835,7 +835,7 @@ int vmw_bo_alloc_ioctl(struct drm_device *dev, void *data,
                goto out_no_bo;
 
        rep->handle = handle;
-       rep->map_handle = drm_vma_node_offset_addr(&vbo->base.vma_node);
+       rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node);
        rep->cur_gmr_id = handle;
        rep->cur_gmr_offset = 0;
 
@@ -1007,10 +1007,10 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo,
 
        if (fence == NULL) {
                vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
-               reservation_object_add_excl_fence(bo->resv, &fence->base);
+               reservation_object_add_excl_fence(bo->base.resv, &fence->base);
                dma_fence_put(&fence->base);
        } else
-               reservation_object_add_excl_fence(bo->resv, &fence->base);
+               reservation_object_add_excl_fence(bo->base.resv, &fence->base);
 }
 
 
@@ -1077,7 +1077,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
        if (ret != 0)
                return -EINVAL;
 
-       *offset = drm_vma_node_offset_addr(&out_buf->base.vma_node);
+       *offset = drm_vma_node_offset_addr(&out_buf->base.base.vma_node);
        vmw_bo_unreference(&out_buf);
        return 0;
 }
index b4f6e12..7984f17 100644 (file)
@@ -169,7 +169,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res)
        } *cmd;
 
        WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB);
-       lockdep_assert_held(&bo->resv->lock.base);
+       reservation_object_assert_held(bo->base.resv);
 
        cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
        if (!cmd)
@@ -311,7 +311,7 @@ static int vmw_cotable_unbind(struct vmw_resource *res,
                return 0;
 
        WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB);
-       lockdep_assert_held(&bo->resv->lock.base);
+       reservation_object_assert_held(bo->base.resv);
 
        mutex_lock(&dev_priv->binding_mutex);
        if (!vcotbl->scrubbed)
index 9506190..cd0d49d 100644 (file)
@@ -186,7 +186,7 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
                      DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
                      DRM_AUTH | DRM_RENDER_ALLOW),
-       VMW_IOCTL_DEF(VMW_EXECBUF, NULL, DRM_AUTH |
+       VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl, DRM_AUTH |
                      DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
                      DRM_RENDER_ALLOW),
@@ -641,7 +641,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                INIT_LIST_HEAD(&dev_priv->res_lru[i]);
        }
 
-       mutex_init(&dev_priv->init_mutex);
        init_waitqueue_head(&dev_priv->fence_queue);
        init_waitqueue_head(&dev_priv->fifo_queue);
        dev_priv->fence_queue_waiters = 0;
@@ -1121,15 +1120,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
                        &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
                if (nr == DRM_COMMAND_BASE + DRM_VMW_EXECBUF) {
-                       ret = (long) drm_ioctl_permit(ioctl->flags, file_priv);
-                       if (unlikely(ret != 0))
-                               return ret;
-
-                       if (unlikely((cmd & (IOC_IN | IOC_OUT)) != IOC_IN))
-                               goto out_io_encoding;
-
-                       return (long) vmw_execbuf_ioctl(dev, arg, file_priv,
-                                                       _IOC_SIZE(cmd));
+                       return ioctl_func(filp, cmd, arg);
                } else if (nr == DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT) {
                        if (!drm_is_current_master(file_priv) &&
                            !capable(CAP_SYS_ADMIN))
@@ -1180,10 +1171,6 @@ static long vmw_compat_ioctl(struct file *filp, unsigned int cmd,
 }
 #endif
 
-static void vmw_lastclose(struct drm_device *dev)
-{
-}
-
 static void vmw_master_init(struct vmw_master *vmaster)
 {
        ttm_lock_init(&vmaster->lock);
@@ -1551,10 +1538,9 @@ static const struct file_operations vmwgfx_driver_fops = {
 
 static struct drm_driver driver = {
        .driver_features =
-       DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
+       DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC,
        .load = vmw_driver_load,
        .unload = vmw_driver_unload,
-       .lastclose = vmw_lastclose,
        .get_vblank_counter = vmw_get_vblank_counter,
        .enable_vblank = vmw_enable_vblank,
        .disable_vblank = vmw_disable_vblank,
index 366dcfc..dbb04db 100644 (file)
@@ -484,11 +484,6 @@ struct vmw_private {
 
        spinlock_t resource_lock;
        struct idr res_idr[vmw_res_max];
-       /*
-        * Block lastclose from racing with firstopen.
-        */
-
-       struct mutex init_mutex;
 
        /*
         * A resource manager for kernel-only surfaces and
@@ -915,8 +910,8 @@ static inline struct page *vmw_piter_page(struct vmw_piter *viter)
  * Command submission - vmwgfx_execbuf.c
  */
 
-extern int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
-                            struct drm_file *file_priv, size_t size);
+extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
 extern int vmw_execbuf_process(struct drm_file *file_priv,
                               struct vmw_private *dev_priv,
                               void __user *user_commands,
index 33533d1..ff86d49 100644 (file)
@@ -3995,54 +3995,40 @@ void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv)
        mutex_unlock(&dev_priv->cmdbuf_mutex);
 }
 
-int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
-                     struct drm_file *file_priv, size_t size)
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
-       struct drm_vmw_execbuf_arg arg;
+       struct drm_vmw_execbuf_arg *arg = data;
        int ret;
-       static const size_t copy_offset[] = {
-               offsetof(struct drm_vmw_execbuf_arg, context_handle),
-               sizeof(struct drm_vmw_execbuf_arg)};
        struct dma_fence *in_fence = NULL;
 
-       if (unlikely(size < copy_offset[0])) {
-               VMW_DEBUG_USER("Invalid command size, ioctl %d\n",
-                              DRM_VMW_EXECBUF);
-               return -EINVAL;
-       }
-
-       if (copy_from_user(&arg, (void __user *) data, copy_offset[0]) != 0)
-               return -EFAULT;
-
        /*
         * Extend the ioctl argument while maintaining backwards compatibility:
-        * We take different code paths depending on the value of arg.version.
+        * We take different code paths depending on the value of arg->version.
+        *
+        * Note: The ioctl argument is extended and zeropadded by core DRM.
         */
-       if (unlikely(arg.version > DRM_VMW_EXECBUF_VERSION ||
-                    arg.version == 0)) {
+       if (unlikely(arg->version > DRM_VMW_EXECBUF_VERSION ||
+                    arg->version == 0)) {
                VMW_DEBUG_USER("Incorrect execbuf version.\n");
                return -EINVAL;
        }
 
-       if (arg.version > 1 &&
-           copy_from_user(&arg.context_handle,
-                          (void __user *) (data + copy_offset[0]),
-                          copy_offset[arg.version - 1] - copy_offset[0]) != 0)
-               return -EFAULT;
-
-       switch (arg.version) {
+       switch (arg->version) {
        case 1:
-               arg.context_handle = (uint32_t) -1;
+               /* For v1 core DRM have extended + zeropadded the data */
+               arg->context_handle = (uint32_t) -1;
                break;
        case 2:
        default:
+               /* For v2 and later core DRM would have correctly copied it */
                break;
        }
 
        /* If imported a fence FD from elsewhere, then wait on it */
-       if (arg.flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) {
-               in_fence = sync_file_get_fence(arg.imported_fence_fd);
+       if (arg->flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) {
+               in_fence = sync_file_get_fence(arg->imported_fence_fd);
 
                if (!in_fence) {
                        VMW_DEBUG_USER("Cannot get imported fence\n");
@@ -4059,11 +4045,11 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
                return ret;
 
        ret = vmw_execbuf_process(file_priv, dev_priv,
-                                 (void __user *)(unsigned long)arg.commands,
-                                 NULL, arg.command_size, arg.throttle_us,
-                                 arg.context_handle,
-                                 (void __user *)(unsigned long)arg.fence_rep,
-                                 NULL, arg.flags);
+                                 (void __user *)(unsigned long)arg->commands,
+                                 NULL, arg->command_size, arg->throttle_us,
+                                 arg->context_handle,
+                                 (void __user *)(unsigned long)arg->fence_rep,
+                                 NULL, arg->flags);
 
        ttm_read_unlock(&dev_priv->reservation_sem);
        if (unlikely(ret != 0))
index b97bc8e..34284f0 100644 (file)
@@ -1704,14 +1704,6 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev,
        if (ret)
                return ret;
 
-       if (!state->allow_modeset)
-               return ret;
-
-       /*
-        * Legacy path do not set allow_modeset properly like
-        * @drm_atomic_helper_update_plane, This will result in unnecessary call
-        * to vmw_kms_check_topology. So extra set of check.
-        */
        for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                if (drm_atomic_crtc_needs_modeset(crtc_state))
                        need_modeset = true;
index 1d38a8b..701643b 100644 (file)
@@ -402,14 +402,14 @@ void vmw_resource_unreserve(struct vmw_resource *res,
 
        if (switch_backup && new_backup != res->backup) {
                if (res->backup) {
-                       lockdep_assert_held(&res->backup->base.resv->lock.base);
+                       reservation_object_assert_held(res->backup->base.base.resv);
                        list_del_init(&res->mob_head);
                        vmw_bo_unreference(&res->backup);
                }
 
                if (new_backup) {
                        res->backup = vmw_bo_reference(new_backup);
-                       lockdep_assert_held(&new_backup->base.resv->lock.base);
+                       reservation_object_assert_held(new_backup->base.base.resv);
                        list_add_tail(&res->mob_head, &new_backup->res_list);
                } else {
                        res->backup = NULL;
@@ -691,7 +691,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo)
                .num_shared = 0
        };
 
-       lockdep_assert_held(&vbo->base.resv->lock.base);
+       reservation_object_assert_held(vbo->base.base.resv);
        list_for_each_entry_safe(res, next, &vbo->res_list, mob_head) {
                if (!res->func->unbind)
                        continue;
index 2194719..3a6da3b 100644 (file)
@@ -1669,7 +1669,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
        rep->backup_size = res->backup_size;
        if (res->backup) {
                rep->buffer_map_handle =
-                       drm_vma_node_offset_addr(&res->backup->base.vma_node);
+                       drm_vma_node_offset_addr(&res->backup->base.base.vma_node);
                rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
                rep->buffer_handle = backup_handle;
        } else {
@@ -1745,7 +1745,7 @@ vmw_gb_surface_reference_internal(struct drm_device *dev,
        rep->crep.backup_size = srf->res.backup_size;
        rep->crep.buffer_handle = backup_handle;
        rep->crep.buffer_map_handle =
-               drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
+               drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node);
        rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
 
        rep->creq.version = drm_vmw_gb_surface_v1;
index 84aa4d6..ba1828a 100644 (file)
@@ -8,13 +8,18 @@
  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  */
 
-#include <drm/drmP.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_file.h>
 #include <drm/drm_gem.h>
 
-#include <linux/of_device.h>
-
 #include <xen/platform_pci.h>
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -485,15 +490,12 @@ static const struct vm_operations_struct xen_drm_drv_vm_ops = {
 };
 
 static struct drm_driver xen_drm_driver = {
-       .driver_features           = DRIVER_GEM | DRIVER_MODESET |
-                                    DRIVER_PRIME | DRIVER_ATOMIC,
+       .driver_features           = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .release                   = xen_drm_drv_release,
        .gem_vm_ops                = &xen_drm_drv_vm_ops,
        .gem_free_object_unlocked  = xen_drm_drv_free_object_unlocked,
        .prime_handle_to_fd        = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle        = drm_gem_prime_fd_to_handle,
-       .gem_prime_import          = drm_gem_prime_import,
-       .gem_prime_export          = drm_gem_prime_export,
        .gem_prime_import_sg_table = xen_drm_front_gem_import_sg_table,
        .gem_prime_get_sg_table    = xen_drm_front_gem_get_sg_table,
        .gem_prime_vmap            = xen_drm_front_gem_prime_vmap,
index 5693b4a..f92c258 100644 (file)
 #ifndef __XEN_DRM_FRONT_H_
 #define __XEN_DRM_FRONT_H_
 
-#include <drm/drmP.h>
-#include <drm/drm_simple_kms_helper.h>
-
 #include <linux/scatterlist.h>
 
+#include <drm/drm_connector.h>
+#include <drm/drm_simple_kms_helper.h>
+
 #include "xen_drm_front_cfg.h"
 
+struct drm_device;
+struct drm_framebuffer;
+struct drm_gem_object;
+struct drm_pending_vblank_event;
+
 /**
  * DOC: Driver modes of operation in terms of display buffers used
  *
index 5baf2b9..ec53b9c 100644 (file)
@@ -8,10 +8,10 @@
  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  */
 
-#include <drm/drmP.h>
-
 #include <linux/device.h>
 
+#include <drm/drm_print.h>
+
 #include <xen/interface/io/displif.h>
 #include <xen/xenbus.h>
 
index 9f5f31f..459702f 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_probe_helper.h>
 
 #include <video/videomode.h>
index 39de7cf..3adacba 100644 (file)
 #ifndef __XEN_DRM_FRONT_CONN_H_
 #define __XEN_DRM_FRONT_CONN_H_
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_encoder.h>
+#include <linux/types.h>
 
-#include <linux/wait.h>
+struct drm_connector;
+struct xen_drm_front_drm_info;
 
 struct xen_drm_front_drm_info;
 
index 945226a..e10d95d 100644 (file)
@@ -8,11 +8,11 @@
  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  */
 
-#include <drm/drmP.h>
-
 #include <linux/errno.h>
 #include <linux/irq.h>
 
+#include <drm/drm_print.h>
+
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/grant_table.h>
index a245484..f0b85e0 100644 (file)
@@ -8,20 +8,19 @@
  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  */
 
-#include "xen_drm_front_gem.h"
+#include <linux/dma-buf.h>
+#include <linux/scatterlist.h>
+#include <linux/shmem_fs.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_prime.h>
 #include <drm/drm_probe_helper.h>
 
-#include <linux/dma-buf.h>
-#include <linux/scatterlist.h>
-#include <linux/shmem_fs.h>
-
 #include <xen/balloon.h>
 
 #include "xen_drm_front.h"
+#include "xen_drm_front_gem.h"
 
 struct xen_gem_object {
        struct drm_gem_object base;
index d5ab734..a39675f 100644 (file)
 #ifndef __XEN_DRM_FRONT_GEM_H
 #define __XEN_DRM_FRONT_GEM_H
 
-#include <drm/drmP.h>
+struct dma_buf_attachment;
+struct drm_device;
+struct drm_gem_object;
+struct file;
+struct sg_table;
+struct vm_area_struct;
 
 struct drm_gem_object *xen_drm_front_gem_create(struct drm_device *dev,
                                                size_t size);
index c2955d3..de99003 100644 (file)
@@ -8,17 +8,18 @@
  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  */
 
-#include "xen_drm_front_kms.h"
-
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "xen_drm_front.h"
 #include "xen_drm_front_conn.h"
+#include "xen_drm_front_kms.h"
 
 /*
  * Timeout in ms to wait for frame done event from the backend:
index 520d736..1141c1e 100644 (file)
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
+#include <drm/drm_vblank.h>
 
 #include "zx_drm_drv.h"
 #include "zx_vou.h"
@@ -34,15 +35,12 @@ static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
 DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops);
 
 static struct drm_driver zx_drm_driver = {
-       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                          DRIVER_ATOMIC,
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
        .gem_prime_vmap = drm_gem_cma_prime_vmap,
index bfe918b..a50f5a1 100644 (file)
@@ -19,7 +19,7 @@
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
+#include <drm/drm_print.h>
 
 #include <sound/hdmi-codec.h>
 
index 6b812aa..086c50f 100644 (file)
@@ -7,10 +7,10 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
 
 #include "zx_common_regs.h"
 #include "zx_drm_drv.h"
index a768c56..c598b7d 100644 (file)
@@ -7,11 +7,13 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
 
 #include "zx_drm_drv.h"
 #include "zx_tvenc_regs.h"
index 1634a08..9b67e41 100644 (file)
@@ -7,11 +7,13 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
 
 #include "zx_drm_drv.h"
 #include "zx_vga_regs.h"
index 81b4cf1..5259ff2 100644 (file)
@@ -6,7 +6,10 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
+
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
@@ -17,7 +20,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
+#include <drm/drm_vblank.h>
 
 #include "zx_common_regs.h"
 #include "zx_drm_drv.h"
index d6b653a..78b0333 100644 (file)
@@ -39,14 +39,6 @@ static int fb_notifier_callback(struct notifier_block *self,
                if (event == FB_EVENT_BLANK) {
                        if (ld->ops->set_power)
                                ld->ops->set_power(ld, *(int *)evdata->data);
-               } else if (event == FB_EARLY_EVENT_BLANK) {
-                       if (ld->ops->early_set_power)
-                               ld->ops->early_set_power(ld,
-                                               *(int *)evdata->data);
-               } else if (event == FB_R_EARLY_EVENT_BLANK) {
-                       if (ld->ops->r_early_set_power)
-                               ld->ops->r_early_set_power(ld,
-                                               *(int *)evdata->data);
                } else {
                        if (ld->ops->set_mode)
                                ld->ops->set_mode(ld, evdata->data);
index 89324e4..7de43be 100644 (file)
@@ -561,8 +561,10 @@ static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
        struct videomode video;
 
        err = of_get_display_timing(node, "panel-timing", &timing);
-       if (err)
+       if (err) {
+               pr_err("%pOF: problems parsing panel-timing (%d)\n", node, err);
                return err;
+       }
 
        videomode_from_timing(&timing, &video);
 
index 26caffb..265d3b4 100644 (file)
@@ -1234,7 +1234,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
        struct au1200fb_device *fbdev = info->par;
 
        return dma_mmap_attrs(fbdev->dev, vma, fbdev->fb_mem, fbdev->fb_phys,
-                       fbdev->fb_len, DMA_ATTR_NON_CONSISTENT);
+                       fbdev->fb_len, 0);
 }
 
 static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
@@ -1692,8 +1692,7 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 
                fbdev->fb_mem = dmam_alloc_attrs(&dev->dev,
                                PAGE_ALIGN(fbdev->fb_len),
-                               &fbdev->fb_phys, GFP_KERNEL,
-                               DMA_ATTR_NON_CONSISTENT);
+                               &fbdev->fb_phys, GFP_KERNEL, 0);
                if (!fbdev->fb_mem) {
                        print_err("fail to allocate framebuffer (size: %dK))",
                                  fbdev->fb_len / 1024);
index 64dd732..e6a1c80 100644 (file)
@@ -1058,7 +1058,7 @@ int
 fb_blank(struct fb_info *info, int blank)
 {      
        struct fb_event event;
-       int ret = -EINVAL, early_ret;
+       int ret = -EINVAL;
 
        if (blank > FB_BLANK_POWERDOWN)
                blank = FB_BLANK_POWERDOWN;
@@ -1066,21 +1066,11 @@ fb_blank(struct fb_info *info, int blank)
        event.info = info;
        event.data = &blank;
 
-       early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
-
        if (info->fbops->fb_blank)
                ret = info->fbops->fb_blank(blank, info);
 
        if (!ret)
                fb_notifier_call_chain(FB_EVENT_BLANK, &event);
-       else {
-               /*
-                * if fb_blank is failed then revert effects of
-                * the early blank event.
-                */
-               if (!early_ret)
-                       fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
-       }
 
        return ret;
 }
@@ -1957,7 +1947,7 @@ int fb_new_modelist(struct fb_info *info)
        struct list_head *pos, *n;
        struct fb_modelist *modelist;
        struct fb_videomode *m, mode;
-       int err = 1;
+       int err;
 
        list_for_each_safe(pos, n, &info->modelist) {
                modelist = list_entry(pos, struct fb_modelist, list);
index 3558a70..8e2e19f 100644 (file)
@@ -999,98 +999,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
        DPRINTK("========================================\n");
 }
 
-/**
- * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
- * @edid:      128 byte array with an E-EDID block
- * @spacs:     monitor specs to be extended
- */
-void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-       unsigned char *block;
-       struct fb_videomode *m;
-       int num = 0, i;
-       u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
-       u8 pos = 4, svd_n = 0;
-
-       if (!edid)
-               return;
-
-       if (!edid_checksum(edid))
-               return;
-
-       if (edid[0] != 0x2 ||
-           edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
-               return;
-
-       DPRINTK("  Short Video Descriptors\n");
-
-       while (pos < edid[2]) {
-               u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
-               pr_debug("Data block %u of %u bytes\n", type, len);
-               if (type == 2) {
-                       for (i = pos; i < pos + len; i++) {
-                               u8 idx = edid[pos + i] & 0x7f;
-                               svd[svd_n++] = idx;
-                               pr_debug("N%sative mode #%d\n",
-                                        edid[pos + i] & 0x80 ? "" : "on-n", idx);
-                       }
-               } else if (type == 3 && len >= 3) {
-                       /* Check Vendor Specific Data Block.  For HDMI,
-                          it is always 00-0C-03 for HDMI Licensing, LLC. */
-                       if (edid[pos + 1] == 3 && edid[pos + 2] == 0xc &&
-                           edid[pos + 3] == 0)
-                               specs->misc |= FB_MISC_HDMI;
-               }
-               pos += len + 1;
-       }
-
-       block = edid + edid[2];
-
-       DPRINTK("  Extended Detailed Timings\n");
-
-       for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
-            i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
-               if (PIXEL_CLOCK != 0)
-                       edt[num++] = block - edid;
-
-       /* Yikes, EDID data is totally useless */
-       if (!(num + svd_n))
-               return;
-
-       m = kcalloc(specs->modedb_len + num + svd_n,
-                   sizeof(struct fb_videomode),
-                   GFP_KERNEL);
-
-       if (!m)
-               return;
-
-       memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
-
-       for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
-               get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
-               if (i == specs->modedb_len)
-                       m[i].flag |= FB_MODE_IS_FIRST;
-               pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
-       }
-
-       for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
-               int idx = svd[i - specs->modedb_len - num];
-               if (!idx || idx >= ARRAY_SIZE(cea_modes)) {
-                       pr_warn("Reserved SVD code %d\n", idx);
-               } else if (!cea_modes[idx].xres) {
-                       pr_warn("Unimplemented SVD code %d\n", idx);
-               } else {
-                       memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
-                       pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
-                                m[i].xres, m[i].yres, m[i].refresh);
-               }
-       }
-
-       kfree(specs->modedb);
-       specs->modedb = m;
-       specs->modedb_len = specs->modedb_len + num + svd_n;
-}
-
 /*
  * VESA Generalized Timing Formula (GTF)
  */
@@ -1500,9 +1408,6 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 {
 }
-void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-}
 void fb_destroy_modedb(struct fb_videomode *modedb)
 {
 }
@@ -1610,7 +1515,6 @@ EXPORT_SYMBOL(fb_firmware_edid);
 
 EXPORT_SYMBOL(fb_parse_edid);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(fb_edid_add_monspecs);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
 EXPORT_SYMBOL(fb_destroy_modedb);
index ac04987..6473e0d 100644 (file)
@@ -289,63 +289,6 @@ static const struct fb_videomode modedb[] = {
 };
 
 #ifdef CONFIG_FB_MODE_HELPERS
-const struct fb_videomode cea_modes[65] = {
-       /* #1: 640x480p@59.94/60Hz */
-       [1] = {
-               NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #3: 720x480p@59.94/60Hz */
-       [3] = {
-               NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #5: 1920x1080i@59.94/60Hz */
-       [5] = {
-               NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
-               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_INTERLACED, 0,
-       },
-       /* #7: 720(1440)x480iH@59.94/60Hz */
-       [7] = {
-               NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
-               FB_VMODE_INTERLACED, 0,
-       },
-       /* #9: 720(1440)x240pH@59.94/60Hz */
-       [9] = {
-               NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #18: 720x576pH@50Hz */
-       [18] = {
-               NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #19: 1280x720p@50Hz */
-       [19] = {
-               NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
-               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #20: 1920x1080i@50Hz */
-       [20] = {
-               NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
-               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_INTERLACED, 0,
-       },
-       /* #32: 1920x1080p@23.98/24Hz */
-       [32] = {
-               NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
-               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-       /* #35: (2880)x480p4x@59.94/60Hz */
-       [35] = {
-               NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
-               FB_VMODE_NONINTERLACED, 0,
-       },
-};
-
 const struct fb_videomode vesa_modes[] = {
        /* 0 640x350-85 VESA */
        { NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
index e5b56f2..47bc7c5 100644 (file)
@@ -612,7 +612,6 @@ static int mmpfb_probe(struct platform_device *pdev)
                ret = -ENOMEM;
                goto failed_destroy_mutex;
        }
-       memset(fbi->fb_start, 0, fbi->fb_size);
        dev_info(fbi->dev, "fb %dk allocated\n", fbi->fb_size/1024);
 
        /* fb power on */
index e705a78..2ce5352 100644 (file)
@@ -123,8 +123,6 @@ void nvidia_bl_init(struct nvidia_par *par)
 
        printk("nvidia: Backlight initialized (%s)\n", name);
 
-       return;
-
 error:
        return;
 }
index b17acd2..2fa6866 100644 (file)
@@ -119,34 +119,10 @@ u8 NVReadMiscOut(struct nvidia_par *par)
 {
        return (VGA_RD08(par->PVIO, VGA_MIS_R));
 }
-#if 0
-void NVEnablePalette(struct nvidia_par *par)
-{
-       volatile u8 tmp;
-
-       tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-       VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
-       par->paletteEnabled = 1;
-}
-void NVDisablePalette(struct nvidia_par *par)
-{
-       volatile u8 tmp;
-
-       tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-       VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
-       par->paletteEnabled = 0;
-}
-#endif  /*  0  */
 void NVWriteDacMask(struct nvidia_par *par, u8 value)
 {
        VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
 }
-#if 0
-u8 NVReadDacMask(struct nvidia_par *par)
-{
-       return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
-}
-#endif  /*  0  */
 void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
 {
        VGA_WR08(par->PDIO, VGA_PEL_IR, value);
index b674948..78ca7ff 100644 (file)
@@ -28,6 +28,7 @@
 #define SSD1307FB_SET_COL_RANGE                0x21
 #define SSD1307FB_SET_PAGE_RANGE       0x22
 #define SSD1307FB_CONTRAST             0x81
+#define SSD1307FB_SET_LOOKUP_TABLE     0x91
 #define        SSD1307FB_CHARGE_PUMP           0x8d
 #define SSD1307FB_SEG_REMAP_ON         0xa1
 #define SSD1307FB_DISPLAY_OFF          0xae
@@ -36,6 +37,7 @@
 #define SSD1307FB_START_PAGE_ADDRESS   0xb0
 #define SSD1307FB_SET_DISPLAY_OFFSET   0xd3
 #define        SSD1307FB_SET_CLOCK_FREQ        0xd5
+#define        SSD1307FB_SET_AREA_COLOR_MODE   0xd8
 #define        SSD1307FB_SET_PRECHARGE_PERIOD  0xd9
 #define        SSD1307FB_SET_COM_PINS_CONFIG   0xda
 #define        SSD1307FB_SET_VCOMH             0xdb
@@ -58,10 +60,14 @@ struct ssd1307fb_deviceinfo {
 };
 
 struct ssd1307fb_par {
-       u32 com_invdir;
-       u32 com_lrremap;
+       unsigned area_color_enable : 1;
+       unsigned com_invdir : 1;
+       unsigned com_lrremap : 1;
+       unsigned com_seq : 1;
+       unsigned lookup_table_set : 1;
+       unsigned low_power : 1;
+       unsigned seg_remap : 1;
        u32 com_offset;
-       u32 com_seq;
        u32 contrast;
        u32 dclk_div;
        u32 dclk_frq;
@@ -69,6 +75,7 @@ struct ssd1307fb_par {
        struct i2c_client *client;
        u32 height;
        struct fb_info *info;
+       u8 lookup_table[4];
        u32 page_offset;
        u32 prechargep1;
        u32 prechargep2;
@@ -76,7 +83,6 @@ struct ssd1307fb_par {
        u32 pwm_period;
        struct gpio_desc *reset;
        struct regulator *vbat_reg;
-       u32 seg_remap;
        u32 vcomh;
        u32 width;
 };
@@ -98,6 +104,9 @@ static const struct fb_fix_screeninfo ssd1307fb_fix = {
 
 static const struct fb_var_screeninfo ssd1307fb_var = {
        .bits_per_pixel = 1,
+       .red = { .length = 1 },
+       .green = { .length = 1 },
+       .blue = { .length = 1 },
 };
 
 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
@@ -149,11 +158,12 @@ static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
 static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 {
        struct ssd1307fb_array *array;
-       u8 *vmem = par->info->screen_base;
+       u8 *vmem = par->info->screen_buffer;
+       unsigned int line_length = par->info->fix.line_length;
+       unsigned int pages = DIV_ROUND_UP(par->height, 8);
        int i, j, k;
 
-       array = ssd1307fb_alloc_array(par->width * par->height / 8,
-                                     SSD1307FB_DATA);
+       array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA);
        if (!array)
                return;
 
@@ -186,22 +196,24 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
         *  (5) A4 B4 C4 D4 E4 F4 G4 H4
         */
 
-       for (i = 0; i < (par->height / 8); i++) {
+       for (i = 0; i < pages; i++) {
                for (j = 0; j < par->width; j++) {
+                       int m = 8;
                        u32 array_idx = i * par->width + j;
                        array->data[array_idx] = 0;
-                       for (k = 0; k < 8; k++) {
-                               u32 page_length = par->width * i;
-                               u32 index = page_length + (par->width * k + j) / 8;
-                               u8 byte = *(vmem + index);
-                               u8 bit = byte & (1 << (j % 8));
-                               bit = bit >> (j % 8);
+                       /* Last page may be partial */
+                       if (i + 1 == pages && par->height % 8)
+                               m = par->height % 8;
+                       for (k = 0; k < m; k++) {
+                               u8 byte = vmem[(8 * i + k) * line_length +
+                                              j / 8];
+                               u8 bit = (byte >> (j % 8)) & 1;
                                array->data[array_idx] |= bit << k;
                        }
                }
        }
 
-       ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
+       ssd1307fb_write_array(par->client, array, par->width * pages);
        kfree(array);
 }
 
@@ -212,7 +224,7 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
        struct ssd1307fb_par *par = info->par;
        unsigned long total_size;
        unsigned long p = *ppos;
-       u8 __iomem *dst;
+       void *dst;
 
        total_size = info->fix.smem_len;
 
@@ -225,7 +237,7 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
        if (!count)
                return -EINVAL;
 
-       dst = (void __force *) (info->screen_base + p);
+       dst = info->screen_buffer + p;
 
        if (copy_from_user(dst, buf, count))
                return -EFAULT;
@@ -312,7 +324,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 
                dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
                        par->pwm->pwm, par->pwm_period);
-       };
+       }
 
        /* Set initial contrast */
        ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
@@ -328,10 +340,10 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
                ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
                if (ret < 0)
                        return ret;
-       };
+       }
 
        /* Set COM direction */
-       com_invdir = 0xc0 | (par->com_invdir & 0x1) << 3;
+       com_invdir = 0xc0 | par->com_invdir << 3;
        ret = ssd1307fb_write_cmd(par->client,  com_invdir);
        if (ret < 0)
                return ret;
@@ -364,6 +376,22 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
+       /* Set Set Area Color Mode ON/OFF & Low Power Display Mode */
+       if (par->area_color_enable || par->low_power) {
+               u32 mode;
+
+               ret = ssd1307fb_write_cmd(par->client,
+                                         SSD1307FB_SET_AREA_COLOR_MODE);
+               if (ret < 0)
+                       return ret;
+
+               mode = (par->area_color_enable ? 0x30 : 0) |
+                       (par->low_power ? 5 : 0);
+               ret = ssd1307fb_write_cmd(par->client, mode);
+               if (ret < 0)
+                       return ret;
+       }
+
        /* Set precharge period in number of ticks from the internal clock */
        ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
        if (ret < 0)
@@ -379,8 +407,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
-       compins = 0x02 | !(par->com_seq & 0x1) << 4
-                                  | (par->com_lrremap & 0x1) << 5;
+       compins = 0x02 | !par->com_seq << 4 | par->com_lrremap << 5;
        ret = ssd1307fb_write_cmd(par->client, compins);
        if (ret < 0)
                return ret;
@@ -404,6 +431,28 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
+       /* Set lookup table */
+       if (par->lookup_table_set) {
+               int i;
+
+               ret = ssd1307fb_write_cmd(par->client,
+                                         SSD1307FB_SET_LOOKUP_TABLE);
+               if (ret < 0)
+                       return ret;
+
+               for (i = 0; i < ARRAY_SIZE(par->lookup_table); ++i) {
+                       u8 val = par->lookup_table[i];
+
+                       if (val < 31 || val > 63)
+                               dev_warn(&par->client->dev,
+                                        "lookup table index %d value out of range 31 <= %d <= 63\n",
+                                        i, val);
+                       ret = ssd1307fb_write_cmd(par->client, val);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        /* Switch to horizontal addressing mode */
        ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
        if (ret < 0)
@@ -432,12 +481,13 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
-       ret = ssd1307fb_write_cmd(par->client, 0x0);
+       ret = ssd1307fb_write_cmd(par->client, par->page_offset);
        if (ret < 0)
                return ret;
 
        ret = ssd1307fb_write_cmd(par->client,
-                                 par->page_offset + (par->height / 8) - 1);
+                                 par->page_offset +
+                                 DIV_ROUND_UP(par->height, 8) - 1);
        if (ret < 0)
                return ret;
 
@@ -546,7 +596,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
        struct fb_deferred_io *ssd1307fb_defio;
        u32 vmem_size;
        struct ssd1307fb_par *par;
-       u8 *vmem;
+       void *vmem;
        int ret;
 
        if (!node) {
@@ -603,19 +653,29 @@ static int ssd1307fb_probe(struct i2c_client *client,
        if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
                par->prechargep2 = 2;
 
+       if (!of_property_read_u8_array(node, "solomon,lookup-table",
+                                      par->lookup_table,
+                                      ARRAY_SIZE(par->lookup_table)))
+               par->lookup_table_set = 1;
+
        par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
        par->com_seq = of_property_read_bool(node, "solomon,com-seq");
        par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
        par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+       par->area_color_enable =
+               of_property_read_bool(node, "solomon,area-color-enable");
+       par->low_power = of_property_read_bool(node, "solomon,low-power");
 
        par->contrast = 127;
        par->vcomh = par->device_info->default_vcomh;
 
        /* Setup display timing */
-       par->dclk_div = par->device_info->default_dclk_div;
-       par->dclk_frq = par->device_info->default_dclk_frq;
+       if (of_property_read_u32(node, "solomon,dclk-div", &par->dclk_div))
+               par->dclk_div = par->device_info->default_dclk_div;
+       if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
+               par->dclk_frq = par->device_info->default_dclk_frq;
 
-       vmem_size = par->width * par->height / 8;
+       vmem_size = DIV_ROUND_UP(par->width, 8) * par->height;
 
        vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(vmem_size));
@@ -638,7 +698,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
        info->fbops = &ssd1307fb_ops;
        info->fix = ssd1307fb_fix;
-       info->fix.line_length = par->width / 8;
+       info->fix.line_length = DIV_ROUND_UP(par->width, 8);
        info->fbdefio = ssd1307fb_defio;
 
        info->var = ssd1307fb_var;
@@ -647,14 +707,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
        info->var.yres = par->height;
        info->var.yres_virtual = par->height;
 
-       info->var.red.length = 1;
-       info->var.red.offset = 0;
-       info->var.green.length = 1;
-       info->var.green.offset = 0;
-       info->var.blue.length = 1;
-       info->var.blue.offset = 0;
-
-       info->screen_base = (u8 __force __iomem *)vmem;
+       info->screen_buffer = vmem;
        info->fix.smem_start = __pa(vmem);
        info->fix.smem_len = vmem_size;
 
@@ -713,7 +766,7 @@ panel_init_error:
        if (par->device_info->need_pwm) {
                pwm_disable(par->pwm);
                pwm_put(par->pwm);
-       };
+       }
 regulator_enable_error:
        if (par->vbat_reg)
                regulator_disable(par->vbat_reg);
@@ -737,7 +790,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
        if (par->device_info->need_pwm) {
                pwm_disable(par->pwm);
                pwm_put(par->pwm);
-       };
+       }
        fb_deferred_io_cleanup(info);
        __free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
        framebuffer_release(info);
index f5c1c46..abc9ada 100644 (file)
@@ -119,17 +119,20 @@ int of_get_display_timing(const struct device_node *np, const char *name,
                struct display_timing *dt)
 {
        struct device_node *timing_np;
+       int ret;
 
        if (!np)
                return -EINVAL;
 
        timing_np = of_get_child_by_name(np, name);
-       if (!timing_np) {
-               pr_err("%pOF: could not find node '%s'\n", np, name);
+       if (!timing_np)
                return -ENOENT;
-       }
 
-       return of_parse_display_timing(timing_np, dt);
+       ret = of_parse_display_timing(timing_np, dt);
+
+       of_node_put(timing_np);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(of_get_display_timing);
 
index e56046c..7aa2f93 100644 (file)
@@ -38,10 +38,6 @@ struct analogix_dp_plat_data {
                         struct drm_connector *);
 };
 
-int analogix_dp_psr_enabled(struct analogix_dp_device *dp);
-int analogix_dp_enable_psr(struct analogix_dp_device *dp);
-int analogix_dp_disable_psr(struct analogix_dp_device *dp);
-
 int analogix_dp_resume(struct analogix_dp_device *dp);
 int analogix_dp_suspend(struct analogix_dp_device *dp);
 
index b05e462..664e120 100644 (file)
@@ -31,11 +31,6 @@ struct drm_agp_head {
 void drm_free_agp(struct agp_memory * handle, int pages);
 int drm_bind_agp(struct agp_memory * handle, unsigned int start);
 int drm_unbind_agp(struct agp_memory * handle);
-struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
-                               struct page **pages,
-                               unsigned long num_pages,
-                               uint32_t gtt_offset,
-                               uint32_t type);
 
 struct drm_agp_head *drm_agp_init(struct drm_device *dev);
 void drm_legacy_agp_clear(struct drm_device *dev);
@@ -80,15 +75,6 @@ static inline int drm_unbind_agp(struct agp_memory * handle)
        return -ENODEV;
 }
 
-static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
-                                             struct page **pages,
-                                             unsigned long num_pages,
-                                             uint32_t gtt_offset,
-                                             uint32_t type)
-{
-       return NULL;
-}
-
 static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
        return NULL;
index ca745d9..0b9997e 100644 (file)
@@ -41,6 +41,7 @@ struct drm_property;
 struct drm_property_blob;
 struct drm_printer;
 struct edid;
+struct i2c_adapter;
 
 enum drm_connector_force {
        DRM_FORCE_UNSPECIFIED,
@@ -323,6 +324,8 @@ enum drm_panel_orientation {
  *                                     edge of the pixel clock
  * @DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE:  Sync signals are sampled on the falling
  *                                     edge of the pixel clock
+ * @DRM_BUS_FLAG_SHARP_SIGNALS:                Set if the Sharp-specific signals
+ *                                     (SPL, CLS, PS, REV) must be used
  */
 enum drm_bus_flags {
        DRM_BUS_FLAG_DE_LOW = BIT(0),
@@ -341,6 +344,7 @@ enum drm_bus_flags {
        DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE = DRM_BUS_FLAG_SYNC_NEGEDGE,
        DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE = DRM_BUS_FLAG_SYNC_NEGEDGE,
        DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE = DRM_BUS_FLAG_SYNC_POSEDGE,
+       DRM_BUS_FLAG_SHARP_SIGNALS = BIT(8),
 };
 
 /**
@@ -598,6 +602,12 @@ struct drm_connector_state {
         */
        unsigned int content_type;
 
+       /**
+        * @hdcp_content_type: Connector property to pass the type of
+        * protected content. This is most commonly used for HDCP.
+        */
+       unsigned int hdcp_content_type;
+
        /**
         * @scaling_mode: Connector property to control the
         * upscaling, mostly used for built-in panels.
@@ -1308,6 +1318,18 @@ struct drm_connector {
         * [0]: progressive, [1]: interlaced
         */
        int audio_latency[2];
+
+       /**
+        * @ddc: associated ddc adapter.
+        * A connector usually has its associated ddc adapter. If a driver uses
+        * this field, then an appropriate symbolic link is created in connector
+        * sysfs directory to make it easy for the user to tell which i2c
+        * adapter is for a particular display.
+        *
+        * The field should be set by calling drm_connector_init_with_ddc().
+        */
+       struct i2c_adapter *ddc;
+
        /**
         * @null_edid_counter: track sinks that give us all zeros for the EDID.
         * Needed to workaround some HW bugs where we get all 0s
@@ -1396,6 +1418,11 @@ int drm_connector_init(struct drm_device *dev,
                       struct drm_connector *connector,
                       const struct drm_connector_funcs *funcs,
                       int connector_type);
+int drm_connector_init_with_ddc(struct drm_device *dev,
+                               struct drm_connector *connector,
+                               const struct drm_connector_funcs *funcs,
+                               int connector_type,
+                               struct i2c_adapter *ddc);
 void drm_connector_attach_edid_property(struct drm_connector *connector);
 int drm_connector_register(struct drm_connector *connector);
 void drm_connector_unregister(struct drm_connector *connector);
@@ -1481,6 +1508,7 @@ const char *drm_get_dvi_i_select_name(int val);
 const char *drm_get_tv_subconnector_name(int val);
 const char *drm_get_tv_select_name(int val);
 const char *drm_get_content_protection_name(int val);
+const char *drm_get_hdcp_content_type_name(int val);
 
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 int drm_mode_create_tv_margin_properties(struct drm_device *dev);
index 128d8b2..7d14c11 100644 (file)
@@ -756,6 +756,9 @@ struct drm_crtc_funcs {
         * provided from the configured source. Drivers must accept an "auto"
         * source name that will select a default source for this CRTC.
         *
+        * This may trigger an atomic modeset commit if necessary, to enable CRC
+        * generation.
+        *
         * Note that "auto" can depend upon the current modeset configuration,
         * e.g. it could pick an encoder or output specific CRC sampling point.
         *
@@ -767,6 +770,7 @@ struct drm_crtc_funcs {
         * 0 on success or a negative error code on failure.
         */
        int (*set_crc_source)(struct drm_crtc *crtc, const char *source);
+
        /**
         * @verify_crc_source:
         *
index 397896b..8364502 100644 (file)
@@ -1309,6 +1309,10 @@ struct drm_dp_aux {
         * @cec: struct containing fields used for CEC-Tunneling-over-AUX.
         */
        struct drm_dp_aux_cec cec;
+       /**
+        * @is_remote: Is this AUX CH actually using sideband messaging.
+        */
+       bool is_remote;
 };
 
 ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
index 8c97a5f..2ba6253 100644 (file)
@@ -643,6 +643,17 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int __must_check
 drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+                            unsigned int offset, void *buffer, size_t size);
+ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
+                             unsigned int offset, void *buffer, size_t size);
+
+int drm_dp_mst_connector_late_register(struct drm_connector *connector,
+                                      struct drm_dp_mst_port *port);
+void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
+                                          struct drm_dp_mst_port *port);
+
 struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
                                                                    struct drm_dp_mst_topology_mgr *mgr);
 int __must_check
index 68ca736..8976afe 100644 (file)
@@ -61,12 +61,6 @@ enum drm_driver_feature {
         * Driver supports mode setting interfaces (KMS).
         */
        DRIVER_MODESET                  = BIT(1),
-       /**
-        * @DRIVER_PRIME:
-        *
-        * Driver implements DRM PRIME buffer sharing.
-        */
-       DRIVER_PRIME                    = BIT(2),
        /**
         * @DRIVER_RENDER:
         *
@@ -502,21 +496,25 @@ struct drm_driver {
         * @gem_free_object: deconstructor for drm_gem_objects
         *
         * This is deprecated and should not be used by new drivers. Use
-        * @gem_free_object_unlocked instead.
+        * &drm_gem_object_funcs.free instead.
         */
        void (*gem_free_object) (struct drm_gem_object *obj);
 
        /**
         * @gem_free_object_unlocked: deconstructor for drm_gem_objects
         *
-        * This is for drivers which are not encumbered with &drm_device.struct_mutex
-        * legacy locking schemes. Use this hook instead of @gem_free_object.
+        * This is deprecated and should not be used by new drivers. Use
+        * &drm_gem_object_funcs.free instead.
+        * Compared to @gem_free_object this is not encumbered with
+        * &drm_device.struct_mutex legacy locking schemes.
         */
        void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
        /**
         * @gem_open_object:
         *
+        * This callback is deprecated in favour of &drm_gem_object_funcs.open.
+        *
         * Driver hook called upon gem handle creation
         */
        int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
@@ -524,6 +522,8 @@ struct drm_driver {
        /**
         * @gem_close_object:
         *
+        * This callback is deprecated in favour of &drm_gem_object_funcs.close.
+        *
         * Driver hook called upon gem handle release
         */
        void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
@@ -531,6 +531,9 @@ struct drm_driver {
        /**
         * @gem_print_info:
         *
+        * This callback is deprecated in favour of
+        * &drm_gem_object_funcs.print_info.
+        *
         * If driver subclasses struct &drm_gem_object, it can implement this
         * optional hook for printing additional driver specific info.
         *
@@ -545,56 +548,108 @@ struct drm_driver {
        /**
         * @gem_create_object: constructor for gem objects
         *
-        * Hook for allocating the GEM object struct, for use by core
-        * helpers.
+        * Hook for allocating the GEM object struct, for use by the CMA and
+        * SHMEM GEM helpers.
         */
        struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
                                                    size_t size);
-
-       /* prime: */
        /**
         * @prime_handle_to_fd:
         *
-        * export handle -> fd (see drm_gem_prime_handle_to_fd() helper)
+        * Main PRIME export function. Should be implemented with
+        * drm_gem_prime_handle_to_fd() for GEM based drivers.
+        *
+        * For an in-depth discussion see :ref:`PRIME buffer sharing
+        * documentation <prime_buffer_sharing>`.
         */
        int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
                                uint32_t handle, uint32_t flags, int *prime_fd);
        /**
         * @prime_fd_to_handle:
         *
-        * import fd -> handle (see drm_gem_prime_fd_to_handle() helper)
+        * Main PRIME import function. Should be implemented with
+        * drm_gem_prime_fd_to_handle() for GEM based drivers.
+        *
+        * For an in-depth discussion see :ref:`PRIME buffer sharing
+        * documentation <prime_buffer_sharing>`.
         */
        int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
                                int prime_fd, uint32_t *handle);
        /**
         * @gem_prime_export:
         *
-        * export GEM -> dmabuf
-        *
-        * This defaults to drm_gem_prime_export() if not set.
+        * Export hook for GEM drivers. Deprecated in favour of
+        * &drm_gem_object_funcs.export.
         */
-       struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
-                               struct drm_gem_object *obj, int flags);
+       struct dma_buf * (*gem_prime_export)(struct drm_gem_object *obj,
+                                            int flags);
        /**
         * @gem_prime_import:
         *
-        * import dmabuf -> GEM
+        * Import hook for GEM drivers.
         *
         * This defaults to drm_gem_prime_import() if not set.
         */
        struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
                                struct dma_buf *dma_buf);
+
+       /**
+        * @gem_prime_pin:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.pin.
+        */
        int (*gem_prime_pin)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_unpin:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.unpin.
+        */
        void (*gem_prime_unpin)(struct drm_gem_object *obj);
-       struct reservation_object * (*gem_prime_res_obj)(
-                               struct drm_gem_object *obj);
+
+
+       /**
+        * @gem_prime_get_sg_table:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.get_sg_table.
+        */
        struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_import_sg_table:
+        *
+        * Optional hook used by the PRIME helper functions
+        * drm_gem_prime_import() respectively drm_gem_prime_import_dev().
+        */
        struct drm_gem_object *(*gem_prime_import_sg_table)(
                                struct drm_device *dev,
                                struct dma_buf_attachment *attach,
                                struct sg_table *sgt);
+       /**
+        * @gem_prime_vmap:
+        *
+        * Deprecated vmap hook for GEM drivers. Please use
+        * &drm_gem_object_funcs.vmap instead.
+        */
        void *(*gem_prime_vmap)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_vunmap:
+        *
+        * Deprecated vunmap hook for GEM drivers. Please use
+        * &drm_gem_object_funcs.vunmap instead.
+        */
        void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
+
+       /**
+        * @gem_prime_mmap:
+        *
+        * mmap hook for GEM drivers, used to implement dma-buf mmap in the
+        * PRIME helpers.
+        *
+        * FIXME: There's way too much duplication going on here, and also moved
+        * to &drm_gem_object_funcs.
+        */
        int (*gem_prime_mmap)(struct drm_gem_object *obj,
                                struct vm_area_struct *vma);
 
@@ -662,6 +717,9 @@ struct drm_driver {
 
        /**
         * @gem_vm_ops: Driver private ops for this object
+        *
+        * For GEM drivers this is deprecated in favour of
+        * &drm_gem_object_funcs.vm_ops.
         */
        const struct vm_operations_struct *gem_vm_ops;
 
index a9121fe..ae693c0 100644 (file)
@@ -101,7 +101,7 @@ struct drm_gem_object_funcs {
        /**
         * @pin:
         *
-        * Pin backing buffer in memory.
+        * Pin backing buffer in memory. Used by the drm_gem_map_attach() helper.
         *
         * This callback is optional.
         */
@@ -110,7 +110,7 @@ struct drm_gem_object_funcs {
        /**
         * @unpin:
         *
-        * Unpin backing buffer.
+        * Unpin backing buffer. Used by the drm_gem_map_detach() helper.
         *
         * This callback is optional.
         */
@@ -120,16 +120,21 @@ struct drm_gem_object_funcs {
         * @get_sg_table:
         *
         * Returns a Scatter-Gather table representation of the buffer.
-        * Used when exporting a buffer.
+        * Used when exporting a buffer by the drm_gem_map_dma_buf() helper.
+        * Releasing is done by calling dma_unmap_sg_attrs() and sg_free_table()
+        * in drm_gem_unmap_buf(), therefore these helpers and this callback
+        * here cannot be used for sg tables pointing at driver private memory
+        * ranges.
         *
-        * This callback is mandatory if buffer export is supported.
+        * See also drm_prime_pages_to_sg().
         */
        struct sg_table *(*get_sg_table)(struct drm_gem_object *obj);
 
        /**
         * @vmap:
         *
-        * Returns a virtual address for the buffer.
+        * Returns a virtual address for the buffer. Used by the
+        * drm_gem_dmabuf_vmap() helper.
         *
         * This callback is optional.
         */
@@ -138,7 +143,8 @@ struct drm_gem_object_funcs {
        /**
         * @vunmap:
         *
-        * Releases the the address previously returned by @vmap.
+        * Releases the the address previously returned by @vmap. Used by the
+        * drm_gem_dmabuf_vunmap() helper.
         *
         * This callback is optional.
         */
index 7f307e8..d9f13fd 100644 (file)
@@ -33,11 +33,4 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane,
                          struct drm_plane_state *state);
 int drm_gem_fb_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
                                              struct drm_plane_state *plane_state);
-
-struct drm_framebuffer *
-drm_gem_fbdev_fb_create(struct drm_device *dev,
-                       struct drm_fb_helper_surface_size *sizes,
-                       unsigned int pitch_align, struct drm_gem_object *obj,
-                       const struct drm_framebuffer_funcs *funcs);
-
 #endif
index 9581ea0..ac217d7 100644 (file)
@@ -36,7 +36,6 @@ struct vm_area_struct;
  * video memory becomes scarce.
  */
 struct drm_gem_vram_object {
-       struct drm_gem_object gem;
        struct ttm_buffer_object bo;
        struct ttm_bo_kmap_obj kmap;
 
@@ -68,7 +67,7 @@ static inline struct drm_gem_vram_object *drm_gem_vram_of_bo(
 static inline struct drm_gem_vram_object *drm_gem_vram_of_gem(
        struct drm_gem_object *gem)
 {
-       return container_of(gem, struct drm_gem_vram_object, gem);
+       return container_of(gem, struct drm_gem_vram_object, bo.base);
 }
 
 struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
@@ -108,7 +107,6 @@ extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs;
  * Helpers for struct drm_driver
  */
 
-void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem);
 int drm_gem_vram_driver_dumb_create(struct drm_file *file,
                                    struct drm_device *dev,
                                    struct drm_mode_create_dumb *args);
@@ -124,30 +122,8 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
  * &struct drm_driver with default functions.
  */
 #define DRM_GEM_VRAM_DRIVER \
-       .gem_free_object_unlocked = \
-               drm_gem_vram_driver_gem_free_object_unlocked, \
        .dumb_create              = drm_gem_vram_driver_dumb_create, \
-       .dumb_map_offset          = drm_gem_vram_driver_dumb_mmap_offset
-
-/*
- * PRIME helpers for struct drm_driver
- */
-
-int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *obj);
-void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *obj);
-void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *obj);
-void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *obj,
-                                         void *vaddr);
-int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *obj,
-                                      struct vm_area_struct *vma);
-
-#define DRM_GEM_VRAM_DRIVER_PRIME \
-       .gem_prime_export = drm_gem_prime_export, \
-       .gem_prime_import = drm_gem_prime_import, \
-       .gem_prime_pin    = drm_gem_vram_driver_gem_prime_pin, \
-       .gem_prime_unpin  = drm_gem_vram_driver_gem_prime_unpin, \
-       .gem_prime_vmap   = drm_gem_vram_driver_gem_prime_vmap, \
-       .gem_prime_vunmap = drm_gem_vram_driver_gem_prime_vunmap, \
-       .gem_prime_mmap   = drm_gem_vram_driver_gem_prime_mmap
+       .dumb_map_offset          = drm_gem_vram_driver_dumb_mmap_offset, \
+       .gem_prime_mmap           = drm_gem_prime_mmap
 
 #endif
index 13771a4..06a1120 100644 (file)
@@ -291,5 +291,12 @@ struct drm_connector;
 bool drm_hdcp_check_ksvs_revoked(struct drm_device *dev,
                                 u8 *ksvs, u32 ksv_count);
 int drm_connector_attach_content_protection_property(
-               struct drm_connector *connector);
+               struct drm_connector *connector, bool hdcp_content_type);
+void drm_hdcp_update_content_protection(struct drm_connector *connector,
+                                       u64 val);
+
+/* Content Type classification for HDCP2.2 vs others */
+#define DRM_MODE_HDCP_CONTENT_TYPE0            0
+#define DRM_MODE_HDCP_CONTENT_TYPE1            1
+
 #endif
index fafb6f5..10100a4 100644 (file)
@@ -114,6 +114,9 @@ enum drm_ioctl_flags {
         * Whether &drm_ioctl_desc.func should be called with the DRM BKL held
         * or not. Enforced as the default for all modern drivers, hence there
         * should never be a need to set this flag.
+        *
+        * Do not use anywhere else than for the VBLANK_WAIT IOCTL, which is the
+        * only legacy IOCTL which needs this.
         */
        DRM_UNLOCKED            = BIT(4),
        /**
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
new file mode 100644 (file)
index 0000000..67c66f5
--- /dev/null
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * MIPI Display Bus Interface (DBI) LCD controller support
+ *
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#ifndef __LINUX_MIPI_DBI_H
+#define __LINUX_MIPI_DBI_H
+
+#include <linux/mutex.h>
+#include <drm/drm_device.h>
+#include <drm/drm_simple_kms_helper.h>
+
+struct drm_rect;
+struct spi_device;
+struct gpio_desc;
+struct regulator;
+
+/**
+ * struct mipi_dbi - MIPI DBI interface
+ */
+struct mipi_dbi {
+       /**
+        * @cmdlock: Command lock
+        */
+       struct mutex cmdlock;
+
+       /**
+        * @command: Bus specific callback executing commands.
+        */
+       int (*command)(struct mipi_dbi *dbi, u8 *cmd, u8 *param, size_t num);
+
+       /**
+        * @read_commands: Array of read commands terminated by a zero entry.
+        *                 Reading is disabled if this is NULL.
+        */
+       const u8 *read_commands;
+
+       /**
+        * @swap_bytes: Swap bytes in buffer before transfer
+        */
+       bool swap_bytes;
+
+       /**
+        * @reset: Optional reset gpio
+        */
+       struct gpio_desc *reset;
+
+       /* Type C specific */
+
+       /**
+        * @spi: SPI device
+        */
+       struct spi_device *spi;
+
+       /**
+        * @dc: Optional D/C gpio.
+        */
+       struct gpio_desc *dc;
+
+       /**
+        * @tx_buf9: Buffer used for Option 1 9-bit conversion
+        */
+       void *tx_buf9;
+
+       /**
+        * @tx_buf9_len: Size of tx_buf9.
+        */
+       size_t tx_buf9_len;
+};
+
+/**
+ * struct mipi_dbi_dev - MIPI DBI device
+ */
+struct mipi_dbi_dev {
+       /**
+        * @drm: DRM device
+        */
+       struct drm_device drm;
+
+       /**
+        * @pipe: Display pipe structure
+        */
+       struct drm_simple_display_pipe pipe;
+
+       /**
+        * @connector: Connector
+        */
+       struct drm_connector connector;
+
+       /**
+        * @mode: Fixed display mode
+        */
+       struct drm_display_mode mode;
+
+       /**
+        * @enabled: Pipeline is enabled
+        */
+       bool enabled;
+
+       /**
+        * @tx_buf: Buffer used for transfer (copy clip rect area)
+        */
+       u16 *tx_buf;
+
+       /**
+        * @rotation: initial rotation in degrees Counter Clock Wise
+        */
+       unsigned int rotation;
+
+       /**
+        * @backlight: backlight device (optional)
+        */
+       struct backlight_device *backlight;
+
+       /**
+        * @regulator: power regulator (optional)
+        */
+       struct regulator *regulator;
+
+       /**
+        * @dbi: MIPI DBI interface
+        */
+       struct mipi_dbi dbi;
+};
+
+static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm)
+{
+       return container_of(drm, struct mipi_dbi_dev, drm);
+}
+
+int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
+                     struct gpio_desc *dc);
+int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
+                                  const struct drm_simple_display_pipe_funcs *funcs,
+                                  const uint32_t *formats, unsigned int format_count,
+                                  const struct drm_display_mode *mode,
+                                  unsigned int rotation, size_t tx_buf_size);
+int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev,
+                     const struct drm_simple_display_pipe_funcs *funcs,
+                     const struct drm_display_mode *mode, unsigned int rotation);
+void mipi_dbi_release(struct drm_device *drm);
+void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
+                         struct drm_plane_state *old_state);
+void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
+                          struct drm_crtc_state *crtc_state,
+                          struct drm_plane_state *plan_state);
+void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
+void mipi_dbi_hw_reset(struct mipi_dbi *dbi);
+bool mipi_dbi_display_is_on(struct mipi_dbi *dbi);
+int mipi_dbi_poweron_reset(struct mipi_dbi_dev *dbidev);
+int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev);
+
+u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
+int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
+                         u8 bpw, const void *buf, size_t len);
+
+int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val);
+int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len);
+int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len);
+int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
+                     struct drm_rect *clip, bool swap);
+/**
+ * mipi_dbi_command - MIPI DCS command with optional parameter(s)
+ * @dbi: MIPI DBI structure
+ * @cmd: Command
+ * @seq...: Optional parameter(s)
+ *
+ * Send MIPI DCS command to the controller. Use mipi_dbi_command_read() for
+ * get/read.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+#define mipi_dbi_command(dbi, cmd, seq...) \
+({ \
+       u8 d[] = { seq }; \
+       mipi_dbi_command_stackbuf(dbi, cmd, d, ARRAY_SIZE(d)); \
+})
+
+#ifdef CONFIG_DEBUG_FS
+int mipi_dbi_debugfs_init(struct drm_minor *minor);
+#else
+#define mipi_dbi_debugfs_init          NULL
+#endif
+
+#endif /* __LINUX_MIPI_DBI_H */
index f57eea0..3bcbe30 100644 (file)
@@ -849,6 +849,12 @@ struct drm_mode_config {
         */
        struct drm_property *content_protection_property;
 
+       /**
+        * @hdcp_content_type_property: DRM ENUM property for type of
+        * Protected Content.
+        */
+       struct drm_property *hdcp_content_type_property;
+
        /* dumb ioctl parameters */
        uint32_t preferred_depth, prefer_shadow;
 
index 8c738c0..2637783 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef __DRM_PANEL_H__
 #define __DRM_PANEL_H__
 
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 
index b03731a..d89311b 100644 (file)
@@ -42,7 +42,6 @@
  * This just contains the internal &struct dma_buf and handle caches for each
  * &struct drm_file used by the PRIME core code.
  */
-
 struct drm_prime_file_private {
 /* private: */
        struct mutex lock;
@@ -64,25 +63,18 @@ struct drm_file;
 
 struct device;
 
-struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj,
-                                    int flags);
+/* core prime functions */
+struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
+                                     struct dma_buf_export_info *exp_info);
+void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+                              struct drm_file *file_priv, int prime_fd, uint32_t *handle);
 int drm_gem_prime_handle_to_fd(struct drm_device *dev,
                               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
                               int *prime_fd);
-int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
-struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
-                                           struct dma_buf *dma_buf);
 
-struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
-                                               struct dma_buf *dma_buf,
-                                               struct device *attach_dev);
-
-int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-                              struct drm_file *file_priv, int prime_fd, uint32_t *handle);
-struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
-                                     struct dma_buf_export_info *exp_info);
-void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+/* helper functions for exporting */
 int drm_gem_map_attach(struct dma_buf *dma_buf,
                       struct dma_buf_attachment *attach);
 void drm_gem_map_detach(struct dma_buf *dma_buf,
@@ -94,12 +86,25 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
                           enum dma_data_direction dir);
 void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
 void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
+
+int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
 int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma);
 
-int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
-                                    dma_addr_t *addrs, int max_pages);
 struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
+struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
+                                    int flags);
+
+/* helper functions for importing */
+struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
+                                               struct dma_buf *dma_buf,
+                                               struct device *attach_dev);
+struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
+                                           struct dma_buf *dma_buf);
+
 void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
 
+int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
+                                    dma_addr_t *addrs, int max_pages);
+
 
 #endif /* __DRM_PRIME_H__ */
index 4f311e8..d454ef6 100644 (file)
@@ -4,10 +4,13 @@
 
 struct drm_device;
 struct device;
+struct drm_connector;
+struct drm_property;
 
 int drm_class_device_register(struct device *dev);
 void drm_class_device_unregister(struct device *dev);
 
 void drm_sysfs_hotplug_event(struct drm_device *dev);
-
+void drm_sysfs_connector_status_event(struct drm_connector *connector,
+                                     struct drm_property *property);
 #endif
index e528bb2..9fe4ba8 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <drm/drm_file.h>
 #include <drm/drm_modes.h>
-#include <uapi/drm/drm.h>
 
 struct drm_device;
 struct drm_crtc;
index a8ffd85..2aacfb1 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef DRM_VRAM_MM_HELPER_H
 #define DRM_VRAM_MM_HELPER_H
 
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
 #include <drm/ttm/ttm_bo_driver.h>
 
 struct drm_device;
diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
deleted file mode 100644 (file)
index 51fc667..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * MIPI Display Bus Interface (DBI) LCD controller support
- *
- * Copyright 2016 Noralf Trønnes
- */
-
-#ifndef __LINUX_MIPI_DBI_H
-#define __LINUX_MIPI_DBI_H
-
-#include <linux/mutex.h>
-#include <drm/drm_device.h>
-#include <drm/drm_simple_kms_helper.h>
-
-struct drm_rect;
-struct spi_device;
-struct gpio_desc;
-struct regulator;
-
-/**
- * struct mipi_dbi - MIPI DBI controller
- * @spi: SPI device
- * @enabled: Pipeline is enabled
- * @cmdlock: Command lock
- * @command: Bus specific callback executing commands.
- * @read_commands: Array of read commands terminated by a zero entry.
- *                 Reading is disabled if this is NULL.
- * @dc: Optional D/C gpio.
- * @tx_buf: Buffer used for transfer (copy clip rect area)
- * @tx_buf9: Buffer used for Option 1 9-bit conversion
- * @tx_buf9_len: Size of tx_buf9.
- * @swap_bytes: Swap bytes in buffer before transfer
- * @reset: Optional reset gpio
- * @rotation: initial rotation in degrees Counter Clock Wise
- * @backlight: backlight device (optional)
- * @regulator: power regulator (optional)
- */
-struct mipi_dbi {
-       /**
-        * @drm: DRM device
-        */
-       struct drm_device drm;
-
-       /**
-        * @pipe: Display pipe structure
-        */
-       struct drm_simple_display_pipe pipe;
-
-       struct spi_device *spi;
-       bool enabled;
-       struct mutex cmdlock;
-       int (*command)(struct mipi_dbi *mipi, u8 *cmd, u8 *param, size_t num);
-       const u8 *read_commands;
-       struct gpio_desc *dc;
-       u16 *tx_buf;
-       void *tx_buf9;
-       size_t tx_buf9_len;
-       bool swap_bytes;
-       struct gpio_desc *reset;
-       unsigned int rotation;
-       struct backlight_device *backlight;
-       struct regulator *regulator;
-};
-
-static inline struct mipi_dbi *drm_to_mipi_dbi(struct drm_device *drm)
-{
-       return container_of(drm, struct mipi_dbi, drm);
-}
-
-int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi,
-                     struct gpio_desc *dc);
-int mipi_dbi_init(struct mipi_dbi *mipi,
-                 const struct drm_simple_display_pipe_funcs *funcs,
-                 const struct drm_display_mode *mode, unsigned int rotation);
-void mipi_dbi_release(struct drm_device *drm);
-void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
-                         struct drm_plane_state *old_state);
-void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
-                          struct drm_crtc_state *crtc_state,
-                          struct drm_plane_state *plan_state);
-void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
-void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
-bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
-int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
-int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
-u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
-
-int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
-int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len);
-int mipi_dbi_command_stackbuf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len);
-int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
-                     struct drm_rect *clip, bool swap);
-/**
- * mipi_dbi_command - MIPI DCS command with optional parameter(s)
- * @mipi: MIPI structure
- * @cmd: Command
- * @seq...: Optional parameter(s)
- *
- * Send MIPI DCS command to the controller. Use mipi_dbi_command_read() for
- * get/read.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-#define mipi_dbi_command(mipi, cmd, seq...) \
-({ \
-       u8 d[] = { seq }; \
-       mipi_dbi_command_stackbuf(mipi, cmd, d, ARRAY_SIZE(d)); \
-})
-
-#ifdef CONFIG_DEBUG_FS
-int mipi_dbi_debugfs_init(struct drm_minor *minor);
-#else
-#define mipi_dbi_debugfs_init          NULL
-#endif
-
-#endif /* __LINUX_MIPI_DBI_H */
diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h
deleted file mode 100644 (file)
index f8bcadf..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Noralf Trønnes
- */
-
-#ifndef __LINUX_TINYDRM_HELPERS_H
-#define __LINUX_TINYDRM_HELPERS_H
-
-struct backlight_device;
-struct drm_device;
-struct drm_display_mode;
-struct drm_framebuffer;
-struct drm_rect;
-struct drm_simple_display_pipe;
-struct drm_simple_display_pipe_funcs;
-struct spi_transfer;
-struct spi_message;
-struct spi_device;
-struct device;
-
-/**
- * tinydrm_machine_little_endian - Machine is little endian
- *
- * Returns:
- * true if *defined(__LITTLE_ENDIAN)*, false otherwise
- */
-static inline bool tinydrm_machine_little_endian(void)
-{
-#if defined(__LITTLE_ENDIAN)
-       return true;
-#else
-       return false;
-#endif
-}
-
-int tinydrm_display_pipe_init(struct drm_device *drm,
-                             struct drm_simple_display_pipe *pipe,
-                             const struct drm_simple_display_pipe_funcs *funcs,
-                             int connector_type,
-                             const uint32_t *formats,
-                             unsigned int format_count,
-                             const struct drm_display_mode *mode,
-                             unsigned int rotation);
-
-size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len);
-bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw);
-int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
-                        struct spi_transfer *header, u8 bpw, const void *buf,
-                        size_t len);
-void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m);
-
-#ifdef DEBUG
-/**
- * tinydrm_dbg_spi_message - Dump SPI message
- * @spi: SPI device
- * @m: SPI message
- *
- * Dumps info about the transfers in a SPI message including buffer content.
- * DEBUG has to be defined for this function to be enabled alongside setting
- * the DRM_UT_DRIVER bit of &drm_debug.
- */
-static inline void tinydrm_dbg_spi_message(struct spi_device *spi,
-                                          struct spi_message *m)
-{
-       if (drm_debug & DRM_UT_DRIVER)
-               _tinydrm_dbg_spi_message(spi, m);
-}
-#else
-static inline void tinydrm_dbg_spi_message(struct spi_device *spi,
-                                          struct spi_message *m)
-{
-}
-#endif /* DEBUG */
-
-#endif /* __LINUX_TINYDRM_HELPERS_H */
index 49d9cdf..65ef537 100644 (file)
@@ -31,6 +31,7 @@
 #ifndef _TTM_BO_API_H_
 #define _TTM_BO_API_H_
 
+#include <drm/drm_gem.h>
 #include <drm/drm_hashtab.h>
 #include <drm/drm_vma_manager.h>
 #include <linux/kref.h>
@@ -127,6 +128,7 @@ struct ttm_tt;
 /**
  * struct ttm_buffer_object
  *
+ * @base: drm_gem_object superclass data.
  * @bdev: Pointer to the buffer object device structure.
  * @type: The bo type.
  * @destroy: Destruction function. If NULL, kfree is used.
@@ -150,7 +152,6 @@ struct ttm_tt;
  * @ddestroy: List head for the delayed destroy list.
  * @swap: List head for swap LRU list.
  * @moving: Fence set when BO is moving
- * @vma_node: Address space manager node.
  * @offset: The current GPU offset, which can have different meanings
  * depending on the memory type. For SYSTEM type memory, it should be 0.
  * @cur_placement: Hint of current placement.
@@ -169,6 +170,8 @@ struct ttm_tt;
  */
 
 struct ttm_buffer_object {
+       struct drm_gem_object base;
+
        /**
         * Members constant at init.
         */
@@ -215,9 +218,6 @@ struct ttm_buffer_object {
         */
 
        struct dma_fence *moving;
-
-       struct drm_vma_offset_node vma_node;
-
        unsigned priority;
 
        /**
@@ -230,8 +230,6 @@ struct ttm_buffer_object {
 
        struct sg_table *sg;
 
-       struct reservation_object *resv;
-       struct reservation_object ttm_resv;
        struct mutex wu_mutex;
 };
 
@@ -768,4 +766,23 @@ int ttm_bo_swapout(struct ttm_bo_global *glob,
                        struct ttm_operation_ctx *ctx);
 void ttm_bo_swapout_all(struct ttm_bo_device *bdev);
 int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo);
+
+/**
+ * ttm_bo_uses_embedded_gem_object - check if the given bo uses the
+ * embedded drm_gem_object.
+ *
+ * Most ttm drivers are using gem too, so the embedded
+ * ttm_buffer_object.base will be initialized by the driver (before
+ * calling ttm_bo_init).  It is also possible to use ttm without gem
+ * though (vmwgfx does that).
+ *
+ * This helper will figure whenever a given ttm bo is a gem object too
+ * or not.
+ *
+ * @bo: The bo to check.
+ */
+static inline bool ttm_bo_uses_embedded_gem_object(struct ttm_buffer_object *bo)
+{
+       return bo->base.dev != NULL;
+}
 #endif
index c9b8ba4..3f1935c 100644 (file)
@@ -654,14 +654,14 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
                if (WARN_ON(ticket))
                        return -EBUSY;
 
-               success = reservation_object_trylock(bo->resv);
+               success = reservation_object_trylock(bo->base.resv);
                return success ? 0 : -EBUSY;
        }
 
        if (interruptible)
-               ret = reservation_object_lock_interruptible(bo->resv, ticket);
+               ret = reservation_object_lock_interruptible(bo->base.resv, ticket);
        else
-               ret = reservation_object_lock(bo->resv, ticket);
+               ret = reservation_object_lock(bo->base.resv, ticket);
        if (ret == -EINTR)
                return -ERESTARTSYS;
        return ret;
@@ -745,10 +745,10 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
        WARN_ON(!kref_read(&bo->kref));
 
        if (interruptible)
-               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
-                                                      ticket);
+               ret = reservation_object_lock_slow_interruptible(bo->base.resv,
+                                                                ticket);
        else
-               ww_mutex_lock_slow(&bo->resv->lock, ticket);
+               reservation_object_lock_slow(bo->base.resv, ticket);
 
        if (likely(ret == 0))
                ttm_bo_del_sub_from_lru(bo);
@@ -773,7 +773,7 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo)
        else
                ttm_bo_move_to_lru_tail(bo, NULL);
        spin_unlock(&bo->bdev->glob->lru_lock);
-       reservation_object_unlock(bo->resv);
+       reservation_object_unlock(bo->base.resv);
 }
 
 /*
index 3037712..756706b 100644 (file)
@@ -135,10 +135,6 @@ struct fb_cursor_user {
 
 /*      A display blank is requested       */
 #define FB_EVENT_BLANK                  0x09
-/*      A hardware display blank early change occurred */
-#define FB_EARLY_EVENT_BLANK           0x10
-/*      A hardware display blank revert early change occurred */
-#define FB_R_EARLY_EVENT_BLANK         0x11
 
 struct fb_event {
        struct fb_info *info;
@@ -721,8 +717,6 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
 extern const unsigned char *fb_firmware_edid(struct device *device);
 extern void fb_edid_to_monspecs(unsigned char *edid,
                                struct fb_monspecs *specs);
-extern void fb_edid_add_monspecs(unsigned char *edid,
-                                struct fb_monspecs *specs);
 extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
@@ -796,7 +790,6 @@ struct dmt_videomode {
 
 extern const char *fb_mode_option;
 extern const struct fb_videomode vesa_modes[];
-extern const struct fb_videomode cea_modes[65];
 extern const struct dmt_videomode dmt_modes[];
 
 struct fb_modelist {
index 851eee8..238fb1d 100644 (file)
@@ -41,16 +41,6 @@ struct lcd_ops {
        /* Get the LCD panel power status (0: full on, 1..3: controller
           power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
        int (*get_power)(struct lcd_device *);
-       /*
-        * Enable or disable power to the LCD(0: on; 4: off, see FB_BLANK_XXX)
-        * and this callback would be called proir to fb driver's callback.
-        *
-        * P.S. note that if early_set_power is not NULL then early fb notifier
-        *      would be registered.
-        */
-       int (*early_set_power)(struct lcd_device *, int power);
-       /* revert the effects of the early blank event. */
-       int (*r_early_set_power)(struct lcd_device *, int power);
        /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
        int (*set_power)(struct lcd_device *, int power);
        /* Get the current contrast setting (0-max_contrast) */
index 644a22d..56b782f 100644 (file)
@@ -81,50 +81,6 @@ struct reservation_object {
 #define reservation_object_assert_held(obj) \
        lockdep_assert_held(&(obj)->lock.base)
 
-/**
- * reservation_object_init - initialize a reservation object
- * @obj: the reservation object
- */
-static inline void
-reservation_object_init(struct reservation_object *obj)
-{
-       ww_mutex_init(&obj->lock, &reservation_ww_class);
-
-       __seqcount_init(&obj->seq, reservation_seqcount_string, &reservation_seqcount_class);
-       RCU_INIT_POINTER(obj->fence, NULL);
-       RCU_INIT_POINTER(obj->fence_excl, NULL);
-}
-
-/**
- * reservation_object_fini - destroys a reservation object
- * @obj: the reservation object
- */
-static inline void
-reservation_object_fini(struct reservation_object *obj)
-{
-       int i;
-       struct reservation_object_list *fobj;
-       struct dma_fence *excl;
-
-       /*
-        * This object should be dead and all references must have
-        * been released to it, so no need to be protected with rcu.
-        */
-       excl = rcu_dereference_protected(obj->fence_excl, 1);
-       if (excl)
-               dma_fence_put(excl);
-
-       fobj = rcu_dereference_protected(obj->fence, 1);
-       if (fobj) {
-               for (i = 0; i < fobj->shared_count; ++i)
-                       dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1));
-
-               kfree(fobj);
-       }
-
-       ww_mutex_destroy(&obj->lock);
-}
-
 /**
  * reservation_object_get_list - get the reservation object's
  * shared fence list, with update-side lock held
@@ -184,6 +140,38 @@ reservation_object_lock_interruptible(struct reservation_object *obj,
        return ww_mutex_lock_interruptible(&obj->lock, ctx);
 }
 
+/**
+ * reservation_object_lock_slow - slowpath lock the reservation object
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Acquires the reservation object after a die case. This function
+ * will sleep until the lock becomes available. See reservation_object_lock() as
+ * well.
+ */
+static inline void
+reservation_object_lock_slow(struct reservation_object *obj,
+                            struct ww_acquire_ctx *ctx)
+{
+       ww_mutex_lock_slow(&obj->lock, ctx);
+}
+
+/**
+ * reservation_object_lock_slow_interruptible - slowpath lock the reservation
+ * object, interruptible
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Acquires the reservation object interruptible after a die case. This function
+ * will sleep until the lock becomes available. See
+ * reservation_object_lock_interruptible() as well.
+ */
+static inline int
+reservation_object_lock_slow_interruptible(struct reservation_object *obj,
+                                          struct ww_acquire_ctx *ctx)
+{
+       return ww_mutex_lock_slow_interruptible(&obj->lock, ctx);
+}
 
 /**
  * reservation_object_trylock - trylock the reservation object
@@ -205,6 +193,31 @@ reservation_object_trylock(struct reservation_object *obj)
        return ww_mutex_trylock(&obj->lock);
 }
 
+/**
+ * reservation_object_is_locked - is the reservation object locked
+ * @obj: the reservation object
+ *
+ * Returns true if the mutex is locked, false if unlocked.
+ */
+static inline bool
+reservation_object_is_locked(struct reservation_object *obj)
+{
+       return ww_mutex_is_locked(&obj->lock);
+}
+
+/**
+ * reservation_object_locking_ctx - returns the context used to lock the object
+ * @obj: the reservation object
+ *
+ * Returns the context used to lock a reservation object or NULL if no context
+ * was used or the object is not locked at all.
+ */
+static inline struct ww_acquire_ctx *
+reservation_object_locking_ctx(struct reservation_object *obj)
+{
+       return READ_ONCE(obj->lock.ctx);
+}
+
 /**
  * reservation_object_unlock - unlock the reservation object
  * @obj: the reservation object
@@ -271,6 +284,8 @@ reservation_object_get_excl_rcu(struct reservation_object *obj)
        return fence;
 }
 
+void reservation_object_init(struct reservation_object *obj);
+void reservation_object_fini(struct reservation_object *obj);
 int reservation_object_reserve_shared(struct reservation_object *obj,
                                      unsigned int num_fences);
 void reservation_object_add_shared_fence(struct reservation_object *obj,
index b4dde2f..0cb2a60 100644 (file)
@@ -20,6 +20,7 @@
 #define MESON_CANVAS_ENDIAN_SWAP64     0x7
 #define MESON_CANVAS_ENDIAN_SWAP128    0xf
 
+struct device;
 struct meson_canvas;
 
 /**
index 5ab331e..735c8cf 100644 (file)
@@ -361,6 +361,7 @@ enum drm_mode_subconnector {
 #define DRM_MODE_CONNECTOR_DSI         16
 #define DRM_MODE_CONNECTOR_DPI         17
 #define DRM_MODE_CONNECTOR_WRITEBACK   18
+#define DRM_MODE_CONNECTOR_SPI         19
 
 struct drm_mode_get_connector {
 
index b5d3706..cb577fb 100644 (file)
@@ -127,6 +127,45 @@ struct drm_panfrost_mmap_bo {
 
 enum drm_panfrost_param {
        DRM_PANFROST_PARAM_GPU_PROD_ID,
+       DRM_PANFROST_PARAM_GPU_REVISION,
+       DRM_PANFROST_PARAM_SHADER_PRESENT,
+       DRM_PANFROST_PARAM_TILER_PRESENT,
+       DRM_PANFROST_PARAM_L2_PRESENT,
+       DRM_PANFROST_PARAM_STACK_PRESENT,
+       DRM_PANFROST_PARAM_AS_PRESENT,
+       DRM_PANFROST_PARAM_JS_PRESENT,
+       DRM_PANFROST_PARAM_L2_FEATURES,
+       DRM_PANFROST_PARAM_CORE_FEATURES,
+       DRM_PANFROST_PARAM_TILER_FEATURES,
+       DRM_PANFROST_PARAM_MEM_FEATURES,
+       DRM_PANFROST_PARAM_MMU_FEATURES,
+       DRM_PANFROST_PARAM_THREAD_FEATURES,
+       DRM_PANFROST_PARAM_MAX_THREADS,
+       DRM_PANFROST_PARAM_THREAD_MAX_WORKGROUP_SZ,
+       DRM_PANFROST_PARAM_THREAD_MAX_BARRIER_SZ,
+       DRM_PANFROST_PARAM_COHERENCY_FEATURES,
+       DRM_PANFROST_PARAM_TEXTURE_FEATURES0,
+       DRM_PANFROST_PARAM_TEXTURE_FEATURES1,
+       DRM_PANFROST_PARAM_TEXTURE_FEATURES2,
+       DRM_PANFROST_PARAM_TEXTURE_FEATURES3,
+       DRM_PANFROST_PARAM_JS_FEATURES0,
+       DRM_PANFROST_PARAM_JS_FEATURES1,
+       DRM_PANFROST_PARAM_JS_FEATURES2,
+       DRM_PANFROST_PARAM_JS_FEATURES3,
+       DRM_PANFROST_PARAM_JS_FEATURES4,
+       DRM_PANFROST_PARAM_JS_FEATURES5,
+       DRM_PANFROST_PARAM_JS_FEATURES6,
+       DRM_PANFROST_PARAM_JS_FEATURES7,
+       DRM_PANFROST_PARAM_JS_FEATURES8,
+       DRM_PANFROST_PARAM_JS_FEATURES9,
+       DRM_PANFROST_PARAM_JS_FEATURES10,
+       DRM_PANFROST_PARAM_JS_FEATURES11,
+       DRM_PANFROST_PARAM_JS_FEATURES12,
+       DRM_PANFROST_PARAM_JS_FEATURES13,
+       DRM_PANFROST_PARAM_JS_FEATURES14,
+       DRM_PANFROST_PARAM_JS_FEATURES15,
+       DRM_PANFROST_PARAM_NR_CORE_GROUPS,
+       DRM_PANFROST_PARAM_THREAD_TLS_ALLOC,
 };
 
 struct drm_panfrost_get_param {
index 2a6b253..16c1fa2 100644 (file)
@@ -34,7 +34,7 @@
 
 #define MEDIA_BUS_FMT_FIXED                    0x0001
 
-/* RGB - next is       0x101c */
+/* RGB - next is       0x101d */
 #define MEDIA_BUS_FMT_RGB444_1X12              0x1016
 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE      0x1001
 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE      0x1002
@@ -55,6 +55,7 @@
 #define MEDIA_BUS_FMT_RGB888_1X24              0x100a
 #define MEDIA_BUS_FMT_RGB888_2X12_BE           0x100b
 #define MEDIA_BUS_FMT_RGB888_2X12_LE           0x100c
+#define MEDIA_BUS_FMT_RGB888_3X8               0x101c
 #define MEDIA_BUS_FMT_RGB888_1X7X4_SPWG                0x1011
 #define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA       0x1012
 #define MEDIA_BUS_FMT_ARGB8888_1X32            0x100d