Merge branch 'drm-next-4.19' of git://people.freedesktop.org/~agd5f/linux into drm...
authorDave Airlie <airlied@redhat.com>
Fri, 20 Jul 2018 04:30:18 +0000 (14:30 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 20 Jul 2018 04:54:31 +0000 (14:54 +1000)
More features for 4.19:
- Map processes to vmids for debugging GPUVM faults
- Raven gfxoff fixes
- Initial gfxoff support for vega12
- Use defines for interrupt sources rather than magic numbers
- DC aux fixes
- Finish DC logging TODO
- Add more DC debugfs interfaces for conformance testing
- Add CRC support for DCN
- Scheduler rework in preparation for load balancing
- Unify common smu9 code
- Clean up UVD instancing support
- ttm cleanups
- Misc fixes and cleanups

Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180719194001.3488-1-alexander.deucher@amd.com
363 files changed:
Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
Documentation/devicetree/bindings/display/panel/boe,hv070wsa-100.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/dataimage,scf0700c48ggu18.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/edt,et-series.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/edt,et070080dh6.txt [deleted file]
Documentation/devicetree/bindings/display/panel/edt,etm0700g0dh6.txt [deleted file]
Documentation/devicetree/bindings/display/panel/innolux,g070y2-l01.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/kingdisplay,kd097d04.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/newhaven,nhd-4.3-480272ef-atxl.txt [moved from Documentation/devicetree/bindings/display/panel/edt,et057090dhu.txt with 55% similarity]
Documentation/devicetree/bindings/display/panel/rocktech,rk070er9427.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/sharp,lq035q7db03.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpu/drm-client.rst [new file with mode: 0644]
Documentation/gpu/drm-kms-helpers.rst
Documentation/gpu/drm-kms.rst
Documentation/gpu/index.rst
Documentation/gpu/v3d.rst [new file with mode: 0644]
arch/arm/mm/dma-mapping.c
arch/x86/kernel/early-quirks.c
drivers/dma-buf/reservation.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.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_sim.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/analogix-anx78xx.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/cdns-dsi.c
drivers/gpu/drm/bridge/dumb-vga-dac.c
drivers/gpu/drm/bridge/lvds-encoder.c
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
drivers/gpu/drm/bridge/nxp-ptn3460.c
drivers/gpu/drm/bridge/panel.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/tc358767.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/cirrus/cirrus_mode.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_client.c [new file with mode: 0644]
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_internal.h
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_debugfs_crc.c
drivers/gpu/drm/drm_dp_cec.c [new file with mode: 0644]
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_fb_cma_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/drm_fourcc.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_mode_object.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_of.c
drivers/gpu/drm/drm_panel.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/drm_writeback.c
drivers/gpu/drm/exynos/exynos_dp.c
drivers/gpu/drm/exynos/exynos_drm_dpi.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
drivers/gpu/drm/gma500/cdv_intel_dp.c
drivers/gpu/drm/gma500/cdv_intel_hdmi.c
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/intel_bios.h
drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
drivers/gpu/drm/gma500/oaktrail_hdmi.c
drivers/gpu/drm/gma500/oaktrail_lvds.c
drivers/gpu/drm/gma500/psb_intel_modes.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/Kconfig.debug
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gtt.h
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem.h
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h
drivers/gpu/drm/i915/i915_gem_object.h
drivers/gpu/drm/i915/i915_gem_render_state.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_request.h
drivers/gpu/drm/i915/i915_selftest.h
drivers/gpu/drm/i915/i915_timeline.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/i915_vma.h
drivers/gpu/drm/i915/icl_dsi.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_breadcrumbs.c
drivers/gpu/drm/i915/intel_cdclk.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_device_info.c
drivers/gpu/drm/i915/intel_device_info.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_display.h
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_dpll_mgr.h
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_vbt.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_guc.c
drivers/gpu/drm/i915/intel_guc.h
drivers/gpu/drm/i915/intel_guc_submission.c
drivers/gpu/drm/i915/intel_gvt.c
drivers/gpu/drm/i915/intel_hotplug.c
drivers/gpu/drm/i915/intel_huc.c
drivers/gpu/drm/i915/intel_huc.h
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pipe_crc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/i915/intel_uc.c
drivers/gpu/drm/i915/selftests/huge_pages.c
drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
drivers/gpu/drm/i915/selftests/i915_gem_context.c
drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
drivers/gpu/drm/i915/selftests/i915_gem_evict.c
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
drivers/gpu/drm/i915/selftests/i915_gem_object.c
drivers/gpu/drm/i915/selftests/i915_request.c
drivers/gpu/drm/i915/selftests/i915_selftest.c
drivers/gpu/drm/i915/selftests/i915_vma.c
drivers/gpu/drm/i915/selftests/igt_flush_test.c
drivers/gpu/drm/i915/selftests/igt_wedge_me.h [new file with mode: 0644]
drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
drivers/gpu/drm/i915/selftests/intel_guc.c
drivers/gpu/drm/i915/selftests/intel_hangcheck.c
drivers/gpu/drm/i915/selftests/intel_lrc.c
drivers/gpu/drm/i915/selftests/intel_workarounds.c
drivers/gpu/drm/i915/selftests/mock_engine.c
drivers/gpu/drm/i915/selftests/mock_gem_device.c
drivers/gpu/drm/i915/selftests/mock_gtt.c
drivers/gpu/drm/i915/vlv_dsi.c [moved from drivers/gpu/drm/i915/intel_dsi.c with 97% similarity]
drivers/gpu/drm/i915/vlv_dsi_pll.c [moved from drivers/gpu/drm/i915/intel_dsi_pll.c with 84% similarity]
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/imx-tve.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_drv.h
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
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/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/msm/edp/edp_connector.c
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/dac.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/include/nvif/object.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_debugfs.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_hwmon.c
drivers/gpu/drm/nouveau/nouveau_platform.c
drivers/gpu/drm/nouveau/nvkm/core/engine.c
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b. [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
drivers/gpu/drm/panel/panel-innolux-p079zca.c
drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/rcar-du/rcar_lvds.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/dw-mipi-dsi.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sti/sti_dvo.c
drivers/gpu/drm/sti/sti_hda.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/stm/drv.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/stm/ltdc.h
drivers/gpu/drm/sun4i/Kconfig
drivers/gpu/drm/sun4i/Makefile
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.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_dw_hdmi.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_mixer.h
drivers/gpu/drm/sun4i/sun8i_tcon_top.c
drivers/gpu/drm/sun4i/sun8i_tcon_top.h
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tegra/dsi.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/tilcdc/tilcdc_external.c
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
drivers/gpu/drm/tinydrm/Kconfig
drivers/gpu/drm/tinydrm/core/tinydrm-core.c
drivers/gpu/drm/tinydrm/ili9225.c
drivers/gpu/drm/tinydrm/ili9341.c
drivers/gpu/drm/tinydrm/mi0283qt.c
drivers/gpu/drm/tinydrm/mipi-dbi.c
drivers/gpu/drm/tinydrm/st7586.c
drivers/gpu/drm/tinydrm/st7735r.c
drivers/gpu/drm/udl/udl_connector.c
drivers/gpu/drm/v3d/v3d_bo.c
drivers/gpu/drm/v3d/v3d_drv.h
drivers/gpu/drm/v3d/v3d_fence.c
drivers/gpu/drm/v3d/v3d_regs.h
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/vc4/Makefile
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_hdmi.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_txp.c [new file with mode: 0644]
drivers/gpu/drm/vc4/vc4_vec.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/vkms/Makefile [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_crtc.c [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_drv.c [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_drv.h [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_gem.c [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_output.c [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_plane.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/zte/zx_hdmi.c
drivers/gpu/drm/zte/zx_tvenc.c
drivers/gpu/drm/zte/zx_vga.c
drivers/staging/vboxvideo/vbox_mode.c
include/drm/drmP.h
include/drm/drm_atomic_helper.h
include/drm/drm_client.h [new file with mode: 0644]
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_debugfs_crc.h
include/drm/drm_device.h
include/drm/drm_dp_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_modes.h
include/drm/drm_modeset_helper_vtables.h
include/drm/drm_panel.h
include/drm/drm_plane.h
include/drm/drm_print.h
include/drm/drm_property.h
include/drm/drm_vma_manager.h
include/drm/drm_writeback.h
include/drm/i915_drm.h
include/drm/tinydrm/tinydrm.h
include/uapi/drm/drm_fourcc.h

index 284e2b14cfbe0a291416973ce429ee4b9aa05300..26649b4c4dd8de41ab16a6f76f8e73dcac2525a1 100644 (file)
@@ -74,6 +74,12 @@ Required properties for DSI:
                The 3 clocks output from the DSI analog PHY: dsi[01]_byte,
                dsi[01]_ddr2, and dsi[01]_ddr
 
+Required properties for the TXP (writeback) block:
+- compatible:  Should be "brcm,bcm2835-txp"
+- reg:         Physical base address and length of the TXP block's registers
+- interrupts:  The interrupt number
+                 See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+
 [1] Documentation/devicetree/bindings/media/video-interfaces.txt
 
 Example:
index 383183a89164de7310ca5d2e241d80e14f991fca..8469de510001b25cc173b4ab2f44d1e27e9acc21 100644 (file)
@@ -40,7 +40,7 @@ Required properties (all function blocks):
        "mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
        "mediatek,<chip>-disp-mutex" - display mutex
        "mediatek,<chip>-disp-od"    - overdrive
-  the supported chips are mt2701 and mt8173.
+  the supported chips are mt2701, mt2712 and mt8173.
 - reg: Physical base address and length of the function block register space
 - interrupts: The interrupt signal from the function block (required, except for
   merge and split function blocks).
diff --git a/Documentation/devicetree/bindings/display/panel/boe,hv070wsa-100.txt b/Documentation/devicetree/bindings/display/panel/boe,hv070wsa-100.txt
new file mode 100644 (file)
index 0000000..55183d3
--- /dev/null
@@ -0,0 +1,28 @@
+BOE HV070WSA-100 7.01" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "boe,hv070wsa-100"
+- power-supply: regulator to provide the VCC supply voltage (3.3 volts)
+- enable-gpios: GPIO pin to enable and disable panel (active high)
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
+
+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 = "boe,hv070wsa-100";
+               power-supply = <&vcc_3v3_reg>;
+               enable-gpios = <&gpd1 3 GPIO_ACTIVE_HIGH>;
+               port {
+                       panel_ep: endpoint {
+                               remote-endpoint = <&bridge_out_ep>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/dataimage,scf0700c48ggu18.txt b/Documentation/devicetree/bindings/display/panel/dataimage,scf0700c48ggu18.txt
new file mode 100644 (file)
index 0000000..897085e
--- /dev/null
@@ -0,0 +1,8 @@
+DataImage, Inc. 7" WVGA (800x480) TFT LCD panel with 24-bit parallel interface.
+
+Required properties:
+- compatible: should be "dataimage,scf0700c48ggu18"
+- power-supply: 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/dlc,dlc0700yzg-1.txt b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt
new file mode 100644 (file)
index 0000000..bf06bb0
--- /dev/null
@@ -0,0 +1,13 @@
+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/edt,et-series.txt b/Documentation/devicetree/bindings/display/panel/edt,et-series.txt
new file mode 100644 (file)
index 0000000..f56b99e
--- /dev/null
@@ -0,0 +1,39 @@
+Emerging Display Technology Corp. Displays
+==========================================
+
+
+Display bindings for EDT Display Technology Corp. Displays which are
+compatible with the simple-panel binding, which is specified in
+simple-panel.txt
+
+
+5,7" WVGA TFT Panels
+--------------------
+
++-----------------+---------------------+-------------------------------------+
+| Identifier      | compatbile          | description                         |
++=================+=====================+=====================================+
+| ET057090DHU     | edt,et057090dhu     | 5.7" VGA TFT LCD panel              |
++-----------------+---------------------+-------------------------------------+
+
+
+7,0" WVGA TFT Panels
+--------------------
+
++-----------------+---------------------+-------------------------------------+
+| Identifier      | compatbile          | description                         |
++=================+=====================+=====================================+
+| ETM0700G0DH6    | edt,etm070080dh6    | WVGA TFT Display with capacitive    |
+|                 |                     | Touchscreen                         |
++-----------------+---------------------+-------------------------------------+
+| ETM0700G0BDH6   | edt,etm070080bdh6   | Same as ETM0700G0DH6 but with       |
+|                 |                     | inverted pixel clock.               |
++-----------------+---------------------+-------------------------------------+
+| ETM0700G0EDH6   | edt,etm070080edh6   | Same display as the ETM0700G0BDH6,  |
+|                 |                     | but with changed Hardware for the   |
+|                 |                     | backlight and the touch interface   |
++-----------------+---------------------+-------------------------------------+
+| ET070080DH6     | edt,etm070080dh6    | Same timings as the ETM0700G0DH6,   |
+|                 |                     | but with resistive touch.           |
++-----------------+---------------------+-------------------------------------+
+
diff --git a/Documentation/devicetree/bindings/display/panel/edt,et070080dh6.txt b/Documentation/devicetree/bindings/display/panel/edt,et070080dh6.txt
deleted file mode 100644 (file)
index 20cb38e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Emerging Display Technology Corp. ET070080DH6 7.0" WVGA TFT LCD panel
-
-Required properties:
-- compatible: should be "edt,et070080dh6"
-
-This panel is the same as ETM0700G0DH6 except for the touchscreen.
-ET070080DH6 is the model with resistive touch.
-
-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/edt,etm0700g0dh6.txt b/Documentation/devicetree/bindings/display/panel/edt,etm0700g0dh6.txt
deleted file mode 100644 (file)
index ee4b180..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Emerging Display Technology Corp. ETM0700G0DH6 7.0" WVGA TFT LCD panel
-
-Required properties:
-- compatible: should be "edt,etm0700g0dh6"
-
-This panel is the same as ET070080DH6 except for the touchscreen.
-ETM0700G0DH6 is the model with capacitive multitouch.
-
-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,g070y2-l01.txt b/Documentation/devicetree/bindings/display/panel/innolux,g070y2-l01.txt
new file mode 100644 (file)
index 0000000..7c234cf
--- /dev/null
@@ -0,0 +1,12 @@
+Innolux G070Y2-L01 7" WVGA (800x480) TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,g070y2-l01"
+- 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,p097pfg.txt b/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt
new file mode 100644 (file)
index 0000000..595d9df
--- /dev/null
@@ -0,0 +1,24 @@
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p097pfg"
+- reg: DSI virtual channel of the peripheral
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+       &mipi_dsi {
+               panel {
+                       compatible = "innolux,p079zca";
+                       reg = <0>;
+                       avdd-supply = <...>;
+                       avee-supply = <...>;
+                       backlight = <&backlight>;
+                       enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd097d04.txt b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd097d04.txt
new file mode 100644 (file)
index 0000000..164a5fa
--- /dev/null
@@ -0,0 +1,22 @@
+Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
+
+Required properties:
+- compatible: should be "kingdisplay,kd097d04"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+       &mipi_dsi {
+               panel {
+                       compatible = "kingdisplay,kd097d04";
+                       reg = <0>;
+                       power-supply = <...>;
+                       backlight = <&backlight>;
+                       enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               };
+       };
similarity index 55%
rename from Documentation/devicetree/bindings/display/panel/edt,et057090dhu.txt
rename to Documentation/devicetree/bindings/display/panel/newhaven,nhd-4.3-480272ef-atxl.txt
index 4903d7b1d947fc1a79079504b913b4636d900d2e..e78292b1a131e3d96aa85a7ffd77134e7a8a73ba 100644 (file)
@@ -1,7 +1,7 @@
-Emerging Display Technology Corp. 5.7" VGA TFT LCD panel
+Newhaven Display International 480 x 272 TFT LCD panel
 
 Required properties:
-- compatible: should be "edt,et057090dhu"
+- compatible: should be "newhaven,nhd-4.3-480272ef-atxl"
 
 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/rocktech,rk070er9427.txt b/Documentation/devicetree/bindings/display/panel/rocktech,rk070er9427.txt
new file mode 100644 (file)
index 0000000..eb1fb9f
--- /dev/null
@@ -0,0 +1,25 @@
+Rocktech Display Ltd. RK070ER9427 800(RGB)x480 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 "rocktech,rk070er9427"
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Optional nodes:
+- Video port for LCD panel input.
+
+Example:
+       panel {
+               compatible = "rocktech,rk070er9427";
+               backlight = <&backlight_lcd>;
+
+               port {
+                       lcd_panel_in: endpoint {
+                               remote-endpoint = <&lcd_display_out>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,lq035q7db03.txt b/Documentation/devicetree/bindings/display/panel/sharp,lq035q7db03.txt
new file mode 100644 (file)
index 0000000..0753f69
--- /dev/null
@@ -0,0 +1,12 @@
+Sharp LQ035Q7DB03 3.5" QVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,lq035q7db03"
+- power-supply: phandle of the regulator that provides the supply voltage
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- 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.
index 5a9319ad8861c3d0138280ceb4b81fd231fa1d39..f8773ecb75252f91ea1e80cc47574b9781888de2 100644 (file)
@@ -101,9 +101,9 @@ DWC HDMI PHY
 
 Required properties:
   - compatible: value must be one of:
-    * allwinner,sun50i-a64-hdmi-phy
     * allwinner,sun8i-a83t-hdmi-phy
     * allwinner,sun8i-h3-hdmi-phy
+    * allwinner,sun50i-a64-hdmi-phy
   - reg: base address and size of memory-mapped region
   - clocks: phandles to the clocks feeding the HDMI PHY
     * bus: the HDMI PHY interface clock
@@ -147,6 +147,7 @@ Required properties:
    * allwinner,sun8i-a33-tcon
    * allwinner,sun8i-a83t-tcon-lcd
    * allwinner,sun8i-a83t-tcon-tv
+   * allwinner,sun8i-r40-tcon-tv
    * allwinner,sun8i-v3s-tcon
    * allwinner,sun9i-a80-tcon-lcd
    * allwinner,sun9i-a80-tcon-tv
@@ -181,7 +182,7 @@ For TCONs with channel 0, there is one more clock required:
 For TCONs with channel 1, there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
-When TCON support LVDS (all TCONs except TV TCON on A83T and those found
+When TCON support LVDS (all TCONs except TV TCONs on A83T, R40 and those found
 in A13, H3, H5 and V3s SoCs), you need one more reset line:
    - 'lvds': The reset line driving the LVDS logic
 
@@ -399,6 +400,7 @@ Required properties:
     * allwinner,sun8i-a33-display-engine
     * allwinner,sun8i-a83t-display-engine
     * allwinner,sun8i-h3-display-engine
+    * allwinner,sun8i-r40-display-engine
     * allwinner,sun8i-v3s-display-engine
     * allwinner,sun9i-a80-display-engine
 
index 6984539437895e5b1ff459aa51c0b87c4b00c2fb..2afaa633ffc893e4e994d84876033d858ef4d1cd 100644 (file)
@@ -86,6 +86,7 @@ cubietech     Cubietech, Ltd.
 cypress        Cypress Semiconductor Corporation
 cznic  CZ.NIC, z.s.p.o.
 dallas Maxim Integrated Products (formerly Dallas Semiconductor)
+dataimage      DataImage, Inc.
 davicom        DAVICOM Semiconductor, Inc.
 delta  Delta Electronics, Inc.
 denx   Denx Software Engineering
@@ -94,6 +95,7 @@ dh    DH electronics GmbH
 digi   Digi International Inc.
 digilent       Diglent, Inc.
 dioo   Dioo Microcircuit Co., Ltd
+dlc    DLC Display Co., Ltd.
 dlg    Dialog Semiconductor
 dlink  D-Link Corporation
 dmo    Data Modul AG
@@ -189,6 +191,7 @@ keymile     Keymile GmbH
 khadas Khadas
 kiebackpeter    Kieback & Peter GmbH
 kinetic Kinetic Technologies
+kingdisplay    King & Display Technology Co., Ltd.
 kingnovel      Kingnovel Technology Co., Ltd.
 koe    Kaohsiung Opto-Electronics Inc.
 kosagi Sutajio Ko-Usagi PTE Ltd.
diff --git a/Documentation/gpu/drm-client.rst b/Documentation/gpu/drm-client.rst
new file mode 100644 (file)
index 0000000..7e67206
--- /dev/null
@@ -0,0 +1,12 @@
+=================
+Kernel clients
+=================
+
+.. kernel-doc:: drivers/gpu/drm/drm_client.c
+   :doc: overview
+
+.. kernel-doc:: include/drm/drm_client.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_client.c
+   :export:
index e37557b30f620604dfddffa2f00e1d303e147f7d..f9cfcdcdf024fc88cbf8edf82d7c2fc1c4f4c8a7 100644 (file)
@@ -109,6 +109,15 @@ Framebuffer CMA Helper Functions Reference
 
 .. _drm_bridges:
 
+Framebuffer GEM Helper Reference
+================================
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+   :export:
+
 Bridges
 =======
 
@@ -169,6 +178,15 @@ Display Port Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
    :export:
 
+Display Port CEC Helper Functions Reference
+===========================================
+
+.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
+   :doc: dp cec helpers
+
+.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
+   :export:
+
 Display Port Dual Mode Adaptor Helper Functions Reference
 =========================================================
 
@@ -282,13 +300,13 @@ Auxiliary Modeset Helpers
 .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
    :export:
 
-Framebuffer GEM Helper Reference
-================================
+OF/DT Helpers
+=============
 
-.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_of.c
    :doc: overview
 
-.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_of.c
    :export:
 
 Legacy Plane Helper Reference
index 514939433004a3d5b718da21b2cf50c9406b3048..5dee6b8a4c12511f16bb9e540ec7e1eb854e88cb 100644 (file)
@@ -56,11 +56,12 @@ Overview
 
 The basic object structure KMS presents to userspace is fairly simple.
 Framebuffers (represented by :c:type:`struct drm_framebuffer <drm_framebuffer>`,
-see `Frame Buffer Abstraction`_) feed into planes. One or more (or even no)
-planes feed their pixel data into a CRTC (represented by :c:type:`struct
-drm_crtc <drm_crtc>`, see `CRTC Abstraction`_) for blending. The precise
-blending step is explained in more detail in `Plane Composition Properties`_ and
-related chapters.
+see `Frame Buffer Abstraction`_) feed into planes. Planes are represented by
+:c:type:`struct drm_plane <drm_plane>`, see `Plane Abstraction`_ for more
+details. One or more (or even no) planes feed their pixel data into a CRTC
+(represented by :c:type:`struct drm_crtc <drm_crtc>`, see `CRTC Abstraction`_)
+for blending. The precise blending step is explained in more detail in `Plane
+Composition Properties`_ and related chapters.
 
 For the output routing the first step is encoders (represented by
 :c:type:`struct drm_encoder <drm_encoder>`, see `Encoder Abstraction`_). Those
@@ -466,7 +467,7 @@ Output discovery and initialization example
         drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
                  DRM_MODE_ENCODER_DAC);
 
-        drm_mode_connector_attach_encoder(&intel_output->base,
+        drm_connector_attach_encoder(&intel_output->base,
                           &intel_output->enc);
 
         /* Set up the DDC bus. */
index 00288f34c5a6322835877770fb86c2cd8d380a22..1fcf8e851e1540f1b85b53fba24994f26338a6d9 100644 (file)
@@ -10,6 +10,7 @@ Linux GPU Driver Developer's Guide
    drm-kms
    drm-kms-helpers
    drm-uapi
+   drm-client
    drivers
    vga-switcheroo
    vgaarbiter
diff --git a/Documentation/gpu/v3d.rst b/Documentation/gpu/v3d.rst
new file mode 100644 (file)
index 0000000..543f7fb
--- /dev/null
@@ -0,0 +1,28 @@
+=====================================
+ drm/v3d Broadcom V3D Graphics Driver
+=====================================
+
+.. kernel-doc:: drivers/gpu/drm/v3d/v3d_drv.c
+   :doc: Broadcom V3D Graphics Driver
+
+GPU buffer object (BO) management
+---------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/v3d/v3d_bo.c
+   :doc: V3D GEM BO management support
+
+Address space management
+===========================================
+.. kernel-doc:: drivers/gpu/drm/v3d/v3d_mmu.c
+   :doc: Broadcom V3D MMU
+
+GPU Scheduling
+===========================================
+.. kernel-doc:: drivers/gpu/drm/v3d/v3d_sched.c
+   :doc: Broadcom V3D scheduling
+
+Interrupts
+--------------
+
+.. kernel-doc:: drivers/gpu/drm/v3d/v3d_irq.c
+   :doc: Interrupt management for the V3D engine
index be0fa7e39c2621ea4a9a83744e513f4d62d246c4..ba0e786c952e70a1989ccb93043bb08e4d721d28 100644 (file)
@@ -1151,6 +1151,11 @@ int arm_dma_supported(struct device *dev, u64 mask)
        return __dma_supported(dev, mask, false);
 }
 
+static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
+{
+       return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
+}
+
 #ifdef CONFIG_ARM_DMA_USE_IOMMU
 
 static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs)
@@ -2296,7 +2301,7 @@ void arm_iommu_detach_device(struct device *dev)
        iommu_detach_device(mapping->domain, dev);
        kref_put(&mapping->kref, release_iommu_mapping);
        to_dma_iommu_mapping(dev) = NULL;
-       set_dma_ops(dev, NULL);
+       set_dma_ops(dev, arm_get_dma_map_ops(dev->archdata.dma_coherent));
 
        pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
@@ -2357,11 +2362,6 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { }
 
 #endif /* CONFIG_ARM_DMA_USE_IOMMU */
 
-static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
-{
-       return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
-}
-
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                        const struct iommu_ops *iommu, bool coherent)
 {
index da5d8ac600623fad46152cdd708245029d3ca2aa..50d5848bf22efb5ffed1292bd8aa354689d2f7dd 100644 (file)
@@ -338,6 +338,18 @@ static resource_size_t __init gen3_stolen_base(int num, int slot, int func,
        return bsm & INTEL_BSM_MASK;
 }
 
+static resource_size_t __init gen11_stolen_base(int num, int slot, int func,
+                                               resource_size_t stolen_size)
+{
+       u64 bsm;
+
+       bsm = read_pci_config(num, slot, func, INTEL_GEN11_BSM_DW0);
+       bsm &= INTEL_BSM_MASK;
+       bsm |= (u64)read_pci_config(num, slot, func, INTEL_GEN11_BSM_DW1) << 32;
+
+       return bsm;
+}
+
 static resource_size_t __init i830_stolen_size(int num, int slot, int func)
 {
        u16 gmch_ctrl;
@@ -498,6 +510,11 @@ static const struct intel_early_ops chv_early_ops __initconst = {
        .stolen_size = chv_stolen_size,
 };
 
+static const struct intel_early_ops gen11_early_ops __initconst = {
+       .stolen_base = gen11_stolen_base,
+       .stolen_size = gen9_stolen_size,
+};
+
 static const struct pci_device_id intel_early_ids[] __initconst = {
        INTEL_I830_IDS(&i830_early_ops),
        INTEL_I845G_IDS(&i845_early_ops),
@@ -529,6 +546,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
        INTEL_CFL_IDS(&gen9_early_ops),
        INTEL_GLK_IDS(&gen9_early_ops),
        INTEL_CNL_IDS(&gen9_early_ops),
+       INTEL_ICL_11_IDS(&gen11_early_ops),
 };
 
 struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
index 20bf90f4ee6326b5ab7a174d031d3aac276923ef..6c95f61a32e73d54ed70f461e676826075419f45 100644 (file)
@@ -141,6 +141,7 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
        if (signaled) {
                RCU_INIT_POINTER(fobj->shared[signaled_idx], fence);
        } else {
+               BUG_ON(fobj->shared_count >= fobj->shared_max);
                RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
                fobj->shared_count++;
        }
@@ -230,10 +231,9 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
        old = reservation_object_get_list(obj);
        obj->staged = NULL;
 
-       if (!fobj) {
-               BUG_ON(old->shared_count >= old->shared_max);
+       if (!fobj)
                reservation_object_add_shared_inplace(obj, old, fence);
-       else
+       else
                reservation_object_add_shared_replace(obj, old, fobj, fence);
 }
 EXPORT_SYMBOL(reservation_object_add_shared_fence);
index 2a72d2feb76d3dfb780b968cdaa791a88ffbd149..cb88528e7b10c0aff35dc17f3996a451a064e85a 100644 (file)
@@ -122,6 +122,16 @@ config DRM_LOAD_EDID_FIRMWARE
          default case is N. Details and instructions how to build your own
          EDID data are given in Documentation/EDID/HOWTO.txt.
 
+config DRM_DP_CEC
+       bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
+       select CEC_CORE
+       help
+         Choose this option if you want to enable HDMI CEC support for
+         DisplayPort/USB-C to HDMI adapters.
+
+         Note: not all adapters support this feature, and even for those
+         that do support this they often do not hook up the CEC pin.
+
 config DRM_TTM
        tristate
        depends on DRM && MMU
@@ -213,6 +223,17 @@ config DRM_VGEM
          as used by Mesa's software renderer for enhanced performance.
          If M is selected the module will be called vgem.
 
+config DRM_VKMS
+       tristate "Virtual KMS (EXPERIMENTAL)"
+       depends on DRM
+       select DRM_KMS_HELPER
+       default n
+       help
+         Virtual Kernel Mode-Setting (VKMS) is used for testing or for
+         running GPU in a headless machines. Choose this option to get
+         a VKMS.
+
+         If M is selected the module will be called vkms.
 
 source "drivers/gpu/drm/exynos/Kconfig"
 
index 69c13517ea3a6a866a92607504d21878f6c443e9..a6771cef85e25d74b73f1a2ff29bd34110605488 100644 (file)
@@ -18,7 +18,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
                drm_encoder.o drm_mode_object.o drm_property.o \
                drm_plane.o drm_color_mgmt.o drm_print.o \
                drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-               drm_syncobj.o drm_lease.o drm_writeback.o
+               drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
@@ -41,6 +41,7 @@ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
 drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
+drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
@@ -69,6 +70,7 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/
 obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VIA)  +=via/
 obj-$(CONFIG_DRM_VGEM) += vgem/
+obj-$(CONFIG_DRM_VKMS) += vkms/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
 obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_ROCKCHIP) +=rockchip/
index 8e66851eb427b0f00b83ae5b74a68113fe79f0c1..c770d73352a793fc7c91d871b100a503870ca701 100644 (file)
@@ -212,30 +212,21 @@ static void
 amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
                                      enum drm_connector_status status)
 {
-       struct drm_encoder *best_encoder = NULL;
-       struct drm_encoder *encoder = NULL;
+       struct drm_encoder *best_encoder;
+       struct drm_encoder *encoder;
        const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
        bool connected;
        int i;
 
        best_encoder = connector_funcs->best_encoder(connector);
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-
-               encoder = drm_encoder_find(connector->dev, NULL,
-                                       connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
-
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                if ((encoder == best_encoder) && (status == connector_status_connected))
                        connected = true;
                else
                        connected = false;
 
                amdgpu_atombios_encoder_set_bios_scratch_regs(connector, encoder, connected);
-
        }
 }
 
@@ -246,17 +237,11 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
        struct drm_encoder *encoder;
        int i;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-               encoder = drm_encoder_find(connector->dev, NULL,
-                                       connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
-
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                if (encoder->encoder_type == encoder_type)
                        return encoder;
        }
+
        return NULL;
 }
 
@@ -349,22 +334,24 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
        int ret;
 
        if (amdgpu_connector->edid) {
-               drm_mode_connector_update_edid_property(connector, amdgpu_connector->edid);
+               drm_connector_update_edid_property(connector, amdgpu_connector->edid);
                ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
                return ret;
        }
-       drm_mode_connector_update_edid_property(connector, NULL);
+       drm_connector_update_edid_property(connector, NULL);
        return 0;
 }
 
 static struct drm_encoder *
 amdgpu_connector_best_single_encoder(struct drm_connector *connector)
 {
-       int enc_id = connector->encoder_ids[0];
+       struct drm_encoder *encoder;
+       int i;
+
+       /* pick the first one */
+       drm_connector_for_each_possible_encoder(connector, encoder, i)
+               return encoder;
 
-       /* pick the encoder ids */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
        return NULL;
 }
 
@@ -985,9 +972,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
        struct drm_device *dev = connector->dev;
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
-       struct drm_encoder *encoder = NULL;
        const struct drm_encoder_helper_funcs *encoder_funcs;
-       int i, r;
+       int r;
        enum drm_connector_status ret = connector_status_disconnected;
        bool dret = false, broken_edid = false;
 
@@ -1077,14 +1063,10 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
 
        /* find analog encoder */
        if (amdgpu_connector->dac_load_detect) {
-               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-                       if (connector->encoder_ids[i] == 0)
-                               break;
-
-                       encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
-                       if (!encoder)
-                               continue;
+               struct drm_encoder *encoder;
+               int i;
 
+               drm_connector_for_each_possible_encoder(connector, encoder, i) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
@@ -1132,18 +1114,11 @@ exit:
 static struct drm_encoder *
 amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 {
-       int enc_id = connector->encoder_ids[0];
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
        struct drm_encoder *encoder;
        int i;
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-
-               encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
 
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                if (amdgpu_connector->use_digital == true) {
                        if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
                                return encoder;
@@ -1158,8 +1133,9 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 
        /* then check use digitial */
        /* pick the first one */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
+       drm_connector_for_each_possible_encoder(connector, encoder, i)
+               return encoder;
+
        return NULL;
 }
 
@@ -1296,15 +1272,7 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
        struct amdgpu_encoder *amdgpu_encoder;
        int i;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-
-               encoder = drm_encoder_find(connector->dev, NULL,
-                                       connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
-
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
 
                switch (amdgpu_encoder->encoder_id) {
@@ -1326,14 +1294,7 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector)
        int i;
        bool found = false;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-               encoder = drm_encoder_find(connector->dev, NULL,
-                                       connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
-
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
                if (amdgpu_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
                        found = true;
index 94138abe093b1a9415f08ab713557ebe977fc193..ae8fac34f7a59bbe6dbed55bc0f0954e3de301af 100644 (file)
@@ -46,7 +46,7 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
                list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                        amdgpu_encoder = to_amdgpu_encoder(encoder);
                        if (amdgpu_encoder->devices & amdgpu_connector->devices) {
-                               drm_mode_connector_attach_encoder(connector, encoder);
+                               drm_connector_attach_encoder(connector, encoder);
                                if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
                                        amdgpu_atombios_encoder_init_backlight(amdgpu_encoder, connector);
                                        adev->mode_info.bl_encoder = amdgpu_encoder;
index aea8b89765c61078b6e2dd56e3524c79eafa0b13..15257634a53aa673e30f04068bf3c1e48b541ac7 100644 (file)
@@ -270,25 +270,18 @@ static int dce_virtual_early_init(void *handle)
 static struct drm_encoder *
 dce_virtual_encoder(struct drm_connector *connector)
 {
-       int enc_id = connector->encoder_ids[0];
        struct drm_encoder *encoder;
        int i;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               if (connector->encoder_ids[i] == 0)
-                       break;
-
-               encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
-               if (!encoder)
-                       continue;
-
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
                        return encoder;
        }
 
        /* pick the first one */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
+       drm_connector_for_each_possible_encoder(connector, encoder, i)
+               return encoder;
+
        return NULL;
 }
 
@@ -635,7 +628,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
        drm_connector_register(connector);
 
        /* link them */
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
index 2064cb21d0ed7b49049a5bcd33c4f8a542311137..5fc13e71a3b514e1696e6d8e2b1a957d65b7db1b 100644 (file)
@@ -903,14 +903,14 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)
                                (struct edid *) sink->dc_edid.raw_edid;
 
 
-                       drm_mode_connector_update_edid_property(connector,
+                       drm_connector_update_edid_property(connector,
                                        aconnector->edid);
                }
                amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid);
 
        } else {
                amdgpu_dm_remove_sink_from_freesync_module(connector);
-               drm_mode_connector_update_edid_property(connector, NULL);
+               drm_connector_update_edid_property(connector, NULL);
                aconnector->num_modes = 0;
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
@@ -3676,7 +3676,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
                link,
                link_index);
 
-       drm_mode_connector_attach_encoder(
+       drm_connector_attach_encoder(
                &aconnector->base, &aencoder->base);
 
        drm_connector_register(&aconnector->base);
index 8348d4d46b3015a9541943f10b8330133d152e20..9a300732ba3747a86541d8b62c2562e27e96b9fc 100644 (file)
@@ -251,7 +251,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
                edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
 
                if (!edid) {
-                       drm_mode_connector_update_edid_property(
+                       drm_connector_update_edid_property(
                                &aconnector->base,
                                NULL);
                        return ret;
@@ -279,7 +279,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
                                        connector, aconnector->edid);
        }
 
-       drm_mode_connector_update_edid_property(
+       drm_connector_update_edid_property(
                                        &aconnector->base, aconnector->edid);
 
        ret = drm_add_edid_modes(connector, aconnector->edid);
@@ -363,7 +363,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                                                aconnector, connector->base.id, aconnector->mst_port);
 
                        aconnector->port = port;
-                       drm_mode_connector_set_path_property(connector, pathprop);
+                       drm_connector_set_path_property(connector, pathprop);
 
                        drm_connector_list_iter_end(&conn_iter);
                        aconnector->mst_connected = true;
@@ -411,7 +411,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                dev->mode_config.tile_property,
                0);
 
-       drm_mode_connector_set_path_property(connector, pathprop);
+       drm_connector_set_path_property(connector, pathprop);
 
        /*
         * Initialize connector state before adding the connectror to drm and
@@ -459,7 +459,7 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 static void dm_dp_mst_link_status_reset(struct drm_connector *connector)
 {
        mutex_lock(&connector->dev->mode_config.mutex);
-       drm_mode_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD);
+       drm_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD);
        mutex_unlock(&connector->dev->mode_config.mutex);
 }
 
index b8f6f9a5dfbe32059f3e4568640e4034fa108d8d..68629e6149909fd08d52f22e314296971a3d4618 100644 (file)
@@ -99,7 +99,7 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
                goto error_encoder_cleanup;
        }
 
-       ret = drm_mode_connector_attach_encoder(connector, encoder);
+       ret = drm_connector_attach_encoder(connector, encoder);
        if (ret < 0) {
                dev_err(drm->dev, "could not attach connector to encoder\n");
                drm_connector_unregister(connector);
index 036dff8a1f33321c8101a091712f076d682b7301..5e77d456d9bb9434040107a69536815a270c7865 100644 (file)
@@ -790,12 +790,12 @@ static int ast_get_modes(struct drm_connector *connector)
        if (!flags)
                edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
        if (edid) {
-               drm_mode_connector_update_edid_property(&ast_connector->base, edid);
+               drm_connector_update_edid_property(&ast_connector->base, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
                return ret;
        } else
-               drm_mode_connector_update_edid_property(&ast_connector->base, NULL);
+               drm_connector_update_edid_property(&ast_connector->base, NULL);
        return 0;
 }
 
@@ -900,7 +900,7 @@ static int ast_connector_init(struct drm_device *dev)
        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
        encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        ast_connector->i2c = ast_i2c_create(dev);
        if (!ast_connector->i2c)
index 233980a785912853256373fb7dd8607a6ad20b61..ca5a9afdd5cfa0a338b207888883d112a925938b 100644 (file)
@@ -259,7 +259,7 @@ int bochs_kms_init(struct bochs_device *bochs)
        bochs_crtc_init(bochs->dev);
        bochs_encoder_init(bochs->dev);
        bochs_connector_init(bochs->dev);
-       drm_mode_connector_attach_encoder(&bochs->connector,
+       drm_connector_attach_encoder(&bochs->connector,
                                          &bochs->encoder);
 
        return 0;
index 73021b388e12d3bc1ca7cabfc0178af223f77686..6437b878724a15cbc0e29e7df0808e4deef7a908 100644 (file)
@@ -601,7 +601,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511,
                __adv7511_power_off(adv7511);
 
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        count = drm_add_edid_modes(connector, edid);
 
        adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
@@ -860,7 +860,7 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge)
        }
        drm_connector_helper_add(&adv->connector,
                                 &adv7511_connector_helper_funcs);
-       drm_mode_connector_attach_encoder(&adv->connector, bridge->encoder);
+       drm_connector_attach_encoder(&adv->connector, bridge->encoder);
 
        if (adv->type == ADV7533)
                ret = adv7533_attach_dsi(adv);
index b49043866be612019993b058ce2fbbc53b03ac63..f8433c93f4634620c177c77ac67aea70337288ec 100644 (file)
@@ -969,8 +969,8 @@ static int anx78xx_get_modes(struct drm_connector *connector)
                goto unlock;
        }
 
-       err = drm_mode_connector_update_edid_property(connector,
-                                                     anx78xx->edid);
+       err = drm_connector_update_edid_property(connector,
+                                                anx78xx->edid);
        if (err) {
                DRM_ERROR("Failed to update EDID property: %d\n", err);
                goto unlock;
@@ -1048,8 +1048,8 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge)
 
        anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
-       err = drm_mode_connector_attach_encoder(&anx78xx->connector,
-                                               bridge->encoder);
+       err = drm_connector_attach_encoder(&anx78xx->connector,
+                                          bridge->encoder);
        if (err) {
                DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
                return err;
index 2bcbfadb6ac5535782f8a78e0934365abe0796f8..d68986cea13258bed331d8d023db7b493f720e5b 100644 (file)
@@ -1119,8 +1119,8 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
                edid = drm_get_edid(connector, &dp->aux.ddc);
                pm_runtime_put(dp->dev);
                if (edid) {
-                       drm_mode_connector_update_edid_property(&dp->connector,
-                                                               edid);
+                       drm_connector_update_edid_property(&dp->connector,
+                                                          edid);
                        num_modes += drm_add_edid_modes(&dp->connector, edid);
                        kfree(edid);
                }
@@ -1210,7 +1210,7 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
 
                drm_connector_helper_add(connector,
                                         &analogix_dp_connector_helper_funcs);
-               drm_mode_connector_attach_encoder(connector, encoder);
+               drm_connector_attach_encoder(connector, encoder);
        }
 
        /*
index f2d43f24acfbecfbd92eca83c7430677f057aa9e..ce9496d13986937f9de7a0cbd4d146b9959d3615 100644 (file)
@@ -1152,7 +1152,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
                np = of_node_get(dev->dev.of_node);
 
        panel = of_drm_find_panel(np);
-       if (panel) {
+       if (!IS_ERR(panel)) {
                bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI);
        } else {
                bridge = of_drm_find_bridge(dev->dev.of_node);
index 9837c8d69e6918f0418158054db605b55e082cb8..9b706789a3417615fa74118186318f514376da80 100644 (file)
@@ -55,7 +55,7 @@ static int dumb_vga_get_modes(struct drm_connector *connector)
                goto fallback;
        }
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
        kfree(edid);
        return ret;
@@ -122,7 +122,7 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
                return ret;
        }
 
-       drm_mode_connector_attach_encoder(&vga->connector,
+       drm_connector_attach_encoder(&vga->connector,
                                          bridge->encoder);
 
        return 0;
index 75b0d3f6e4de919301b63af95b28d2b7af4bf79e..f56c92f7af7c484b90fcbac98b9177e36177b949 100644 (file)
@@ -68,9 +68,9 @@ static int lvds_encoder_probe(struct platform_device *pdev)
 
        panel = of_drm_find_panel(panel_node);
        of_node_put(panel_node);
-       if (!panel) {
+       if (IS_ERR(panel)) {
                dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
-               return -EPROBE_DEFER;
+               return PTR_ERR(panel);
        }
 
        lvds_encoder->panel_bridge =
index 7ccadba7c98cd30c3c81e3e0dc183cd050ab6d63..2136c97aeb8ec9463ac1d79766448402b9664504 100644 (file)
@@ -152,7 +152,7 @@ static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
        ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client);
 
        if (ge_b850v3_lvds_ptr->edid) {
-               drm_mode_connector_update_edid_property(connector,
+               drm_connector_update_edid_property(connector,
                                                      ge_b850v3_lvds_ptr->edid);
                num_modes = drm_add_edid_modes(connector,
                                               ge_b850v3_lvds_ptr->edid);
@@ -241,7 +241,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
                return ret;
        }
 
-       ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
+       ret = drm_connector_attach_encoder(connector, bridge->encoder);
        if (ret)
                return ret;
 
index d64a3283822ae7a877175aad01305d32b6d49bf5..a3e817abace101fecc6638b7aa58af2714dbcea3 100644 (file)
@@ -222,7 +222,7 @@ static int ptn3460_get_modes(struct drm_connector *connector)
        }
 
        ptn_bridge->edid = (struct edid *)edid;
-       drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
+       drm_connector_update_edid_property(connector, ptn_bridge->edid);
 
        num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
 
@@ -265,7 +265,7 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge)
        drm_connector_helper_add(&ptn_bridge->connector,
                                        &ptn3460_connector_helper_funcs);
        drm_connector_register(&ptn_bridge->connector);
-       drm_mode_connector_attach_encoder(&ptn_bridge->connector,
+       drm_connector_attach_encoder(&ptn_bridge->connector,
                                                        bridge->encoder);
 
        if (ptn_bridge->panel)
index 6d99d4a3beb36c13aac92a71cee32bc6e6c59cec..7cbaba213ef693d11c430533df45c838a56c1229 100644 (file)
@@ -79,7 +79,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge)
                return ret;
        }
 
-       drm_mode_connector_attach_encoder(&panel_bridge->connector,
+       drm_connector_attach_encoder(&panel_bridge->connector,
                                          bridge->encoder);
 
        ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector);
index 81198f5e9afacf91bf2301652a2ac4671030f7cf..7334d1b62b71f800e7a7fbc0e4b121e0df2bacc2 100644 (file)
@@ -503,7 +503,7 @@ static int ps8622_attach(struct drm_bridge *bridge)
        drm_connector_helper_add(&ps8622->connector,
                                        &ps8622_connector_helper_funcs);
        drm_connector_register(&ps8622->connector);
-       drm_mode_connector_attach_encoder(&ps8622->connector,
+       drm_connector_attach_encoder(&ps8622->connector,
                                                        bridge->encoder);
 
        if (ps8622->panel)
index 60373d7eb22021127cb6f4a9bc7edf646e934be6..e59a135423336bd187f0038956f06ac4574d94dc 100644 (file)
@@ -170,7 +170,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
                return ret;
 
        edid = drm_get_edid(connector, sii902x->i2c->adapter);
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        if (edid) {
                num = drm_add_edid_modes(connector, edid);
                kfree(edid);
@@ -324,7 +324,7 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge)
        else
                sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
 
-       drm_mode_connector_attach_encoder(&sii902x->connector, bridge->encoder);
+       drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
 
        return 0;
 }
index 3c136f2b954fd1344225f5a8c9ff015478786b68..5971976284bf9ddb34434485624d531313791ee3 100644 (file)
@@ -1922,7 +1922,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 
                hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
                hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
@@ -1974,7 +1974,7 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
        drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
                           DRM_MODE_CONNECTOR_HDMIA);
 
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
index 0fd9cf27542c396a2fc36ae7056f3237906d407a..8e28e738cb52dec6ee8ea7eda2d655fc7035be93 100644 (file)
@@ -1140,7 +1140,7 @@ static int tc_connector_get_modes(struct drm_connector *connector)
        if (!edid)
                return 0;
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        count = drm_add_edid_modes(connector, edid);
 
        return count;
@@ -1195,7 +1195,7 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
 
        drm_display_info_set_bus_formats(&tc->connector.display_info,
                                         &bus_format, 1);
-       drm_mode_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
+       drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
 
        return 0;
 }
index acb857030951a0eff0682fce7b5d38d80ba6edb1..c3e32138c6bb08c5cdb6c75e7d6624984914e0c0 100644 (file)
@@ -62,7 +62,7 @@ static int tfp410_get_modes(struct drm_connector *connector)
                goto fallback;
        }
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
 
        return drm_add_edid_modes(connector, edid);
 fallback:
@@ -132,7 +132,7 @@ static int tfp410_attach(struct drm_bridge *bridge)
                return ret;
        }
 
-       drm_mode_connector_attach_encoder(&dvi->connector,
+       drm_connector_attach_encoder(&dvi->connector,
                                          bridge->encoder);
 
        return 0;
index b529f8c8e2a6346d0c4073a95e9644497ed2bce8..336bfda401257f60a17bfa350529e4dc3555b9f9 100644 (file)
@@ -530,7 +530,7 @@ int cirrus_modeset_init(struct cirrus_device *cdev)
                return -1;
        }
 
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        ret = cirrus_fbdev_init(cdev);
        if (ret) {
index 4215be9a9fc5692e99111523b43f443d602b2da4..3eb061e11e2efb2caa36738b6425d2f789c19f6d 100644 (file)
@@ -1111,6 +1111,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
        drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
        drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
        drm_printf(p, "\trotation=%x\n", state->rotation);
+       drm_printf(p, "\tnormalized-zpos=%x\n", state->normalized_zpos);
        drm_printf(p, "\tcolor-encoding=%s\n",
                   drm_get_color_encoding_name(state->color_encoding));
        drm_printf(p, "\tcolor-range=%s\n",
@@ -2427,6 +2428,7 @@ static int prepare_signaling(struct drm_device *dev,
        }
 
        for_each_new_connector_in_state(state, conn, conn_state, i) {
+               struct drm_writeback_connector *wb_conn;
                struct drm_writeback_job *job;
                struct drm_out_fence_state *f;
                struct dma_fence *fence;
@@ -2450,7 +2452,8 @@ static int prepare_signaling(struct drm_device *dev,
                f[*num_fences].out_fence_ptr = fence_ptr;
                *fence_state = f;
 
-               fence = drm_writeback_get_out_fence((struct drm_writeback_connector *)conn);
+               wb_conn = drm_connector_to_writeback(conn);
+               fence = drm_writeback_get_out_fence(wb_conn);
                if (!fence)
                        return -ENOMEM;
 
index 8008a7de2e100a857c7fa144b73a8f60293791f2..866a2cc72ef68458e1003135902c0bb913eda4f7 100644 (file)
@@ -645,7 +645,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                if (ret)
                        return ret;
 
-               connectors_mask += BIT(i);
+               connectors_mask |= BIT(i);
        }
 
        /*
@@ -1184,10 +1184,12 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
                const struct drm_connector_helper_funcs *funcs;
 
                funcs = connector->helper_private;
+               if (!funcs->atomic_commit)
+                       continue;
 
                if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) {
                        WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
-                       funcs->atomic_commit(connector, new_conn_state->writeback_job);
+                       funcs->atomic_commit(connector, new_conn_state);
                }
        }
 }
@@ -1448,6 +1450,8 @@ void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
 
        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);
@@ -1477,6 +1481,8 @@ void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
        drm_atomic_helper_commit_planes(dev, old_state,
                                        DRM_PLANE_COMMIT_ACTIVE_ONLY);
 
+       drm_atomic_helper_fake_vblank(old_state);
+
        drm_atomic_helper_commit_hw_done(old_state);
 
        drm_atomic_helper_wait_for_vblanks(dev, old_state);
@@ -2051,6 +2057,45 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
 }
 EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
 
+/**
+ * drm_atomic_helper_fake_vblank - fake VBLANK events if needed
+ * @old_state: atomic state object with old state structures
+ *
+ * This function walks all CRTCs and fake VBLANK events on those with
+ * &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL.
+ * The primary use of this function is writeback connectors working in oneshot
+ * mode and faking VBLANK events. In this case they only fake the VBLANK event
+ * when a job is queued, and any change to the pipeline that does not touch the
+ * connector is leading to timeouts when calling
+ * drm_atomic_helper_wait_for_vblanks() or
+ * drm_atomic_helper_wait_for_flip_done().
+ *
+ * This is part of the atomic helper support for nonblocking commits, see
+ * drm_atomic_helper_setup_commit() for an overview.
+ */
+void drm_atomic_helper_fake_vblank(struct drm_atomic_state *old_state)
+{
+       struct drm_crtc_state *new_crtc_state;
+       struct drm_crtc *crtc;
+       int i;
+
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
+               unsigned long flags;
+
+               if (!new_crtc_state->no_vblank)
+                       continue;
+
+               spin_lock_irqsave(&old_state->dev->event_lock, flags);
+               if (new_crtc_state->event) {
+                       drm_crtc_send_vblank_event(crtc,
+                                                  new_crtc_state->event);
+                       new_crtc_state->event = NULL;
+               }
+               spin_unlock_irqrestore(&old_state->dev->event_lock, flags);
+       }
+}
+EXPORT_SYMBOL(drm_atomic_helper_fake_vblank);
+
 /**
  * drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
  * @old_state: atomic state object with old state structures
@@ -2822,7 +2867,7 @@ static int update_output_state(struct drm_atomic_state *state,
  * resets the "link-status" property to GOOD, to force any link
  * re-training. The SETCRTC ioctl does not define whether an update does
  * need a full modeset or just a plane update, hence we're allowed to do
- * that. See also drm_mode_connector_set_link_status_property().
+ * that. See also drm_connector_set_link_status_property().
  *
  * Returns:
  * Returns 0 on success, negative errno numbers on failure.
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
new file mode 100644 (file)
index 0000000..baff50a
--- /dev/null
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Noralf Trønnes
+ */
+
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#include <drm/drm_client.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_print.h>
+#include <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * This library provides support for clients running in the kernel like fbdev and bootsplash.
+ * Currently it's only partially implemented, just enough to support fbdev.
+ *
+ * GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
+ */
+
+static int drm_client_open(struct drm_client_dev *client)
+{
+       struct drm_device *dev = client->dev;
+       struct drm_file *file;
+
+       file = drm_file_alloc(dev->primary);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       mutex_lock(&dev->filelist_mutex);
+       list_add(&file->lhead, &dev->filelist_internal);
+       mutex_unlock(&dev->filelist_mutex);
+
+       client->file = file;
+
+       return 0;
+}
+
+static void drm_client_close(struct drm_client_dev *client)
+{
+       struct drm_device *dev = client->dev;
+
+       mutex_lock(&dev->filelist_mutex);
+       list_del(&client->file->lhead);
+       mutex_unlock(&dev->filelist_mutex);
+
+       drm_file_free(client->file);
+}
+EXPORT_SYMBOL(drm_client_close);
+
+/**
+ * drm_client_new - Create a DRM client
+ * @dev: DRM device
+ * @client: DRM client
+ * @name: Client name
+ * @funcs: DRM client functions (optional)
+ *
+ * The caller needs to hold a reference on @dev before calling this function.
+ * The client is freed when the &drm_device is unregistered. See drm_client_release().
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
+                  const char *name, const struct drm_client_funcs *funcs)
+{
+       int ret;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
+           !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
+               return -ENOTSUPP;
+
+       if (funcs && !try_module_get(funcs->owner))
+               return -ENODEV;
+
+       client->dev = dev;
+       client->name = name;
+       client->funcs = funcs;
+
+       ret = drm_client_open(client);
+       if (ret)
+               goto err_put_module;
+
+       mutex_lock(&dev->clientlist_mutex);
+       list_add(&client->list, &dev->clientlist);
+       mutex_unlock(&dev->clientlist_mutex);
+
+       drm_dev_get(dev);
+
+       return 0;
+
+err_put_module:
+       if (funcs)
+               module_put(funcs->owner);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_client_new);
+
+/**
+ * drm_client_release - Release DRM client resources
+ * @client: DRM client
+ *
+ * Releases resources by closing the &drm_file that was opened by drm_client_new().
+ * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
+ *
+ * This function should only be called from the unregister callback. An exception
+ * is fbdev which cannot free the buffer if userspace has open file descriptors.
+ *
+ * Note:
+ * Clients cannot initiate a release by themselves. This is done to keep the code simple.
+ * The driver has to be unloaded before the client can be unloaded.
+ */
+void drm_client_release(struct drm_client_dev *client)
+{
+       struct drm_device *dev = client->dev;
+
+       DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
+
+       drm_client_close(client);
+       drm_dev_put(dev);
+       if (client->funcs)
+               module_put(client->funcs->owner);
+}
+EXPORT_SYMBOL(drm_client_release);
+
+void drm_client_dev_unregister(struct drm_device *dev)
+{
+       struct drm_client_dev *client, *tmp;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
+       mutex_lock(&dev->clientlist_mutex);
+       list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
+               list_del(&client->list);
+               if (client->funcs && client->funcs->unregister) {
+                       client->funcs->unregister(client);
+               } else {
+                       drm_client_release(client);
+                       kfree(client);
+               }
+       }
+       mutex_unlock(&dev->clientlist_mutex);
+}
+
+/**
+ * drm_client_dev_hotplug - Send hotplug event to clients
+ * @dev: DRM device
+ *
+ * This function calls the &drm_client_funcs.hotplug callback on the attached clients.
+ *
+ * drm_kms_helper_hotplug_event() calls this function, so drivers that use it
+ * don't need to call this function themselves.
+ */
+void drm_client_dev_hotplug(struct drm_device *dev)
+{
+       struct drm_client_dev *client;
+       int ret;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
+       mutex_lock(&dev->clientlist_mutex);
+       list_for_each_entry(client, &dev->clientlist, list) {
+               if (!client->funcs || !client->funcs->hotplug)
+                       continue;
+
+               ret = client->funcs->hotplug(client);
+               DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+       }
+       mutex_unlock(&dev->clientlist_mutex);
+}
+EXPORT_SYMBOL(drm_client_dev_hotplug);
+
+void drm_client_dev_restore(struct drm_device *dev)
+{
+       struct drm_client_dev *client;
+       int ret;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
+       mutex_lock(&dev->clientlist_mutex);
+       list_for_each_entry(client, &dev->clientlist, list) {
+               if (!client->funcs || !client->funcs->restore)
+                       continue;
+
+               ret = client->funcs->restore(client);
+               DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+               if (!ret) /* The first one to return zero gets the privilege to restore */
+                       break;
+       }
+       mutex_unlock(&dev->clientlist_mutex);
+}
+
+static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
+{
+       struct drm_device *dev = buffer->client->dev;
+
+       if (buffer->vaddr && dev->driver->gem_prime_vunmap)
+               dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
+
+       if (buffer->gem)
+               drm_gem_object_put_unlocked(buffer->gem);
+
+       if (buffer->handle)
+               drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
+
+       kfree(buffer);
+}
+
+static struct drm_client_buffer *
+drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
+{
+       struct drm_mode_create_dumb dumb_args = { };
+       struct drm_device *dev = client->dev;
+       struct drm_client_buffer *buffer;
+       struct drm_gem_object *obj;
+       void *vaddr;
+       int ret;
+
+       buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+       if (!buffer)
+               return ERR_PTR(-ENOMEM);
+
+       buffer->client = client;
+
+       dumb_args.width = width;
+       dumb_args.height = height;
+       dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
+       ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
+       if (ret)
+               goto err_delete;
+
+       buffer->handle = dumb_args.handle;
+       buffer->pitch = dumb_args.pitch;
+
+       obj = drm_gem_object_lookup(client->file, dumb_args.handle);
+       if (!obj)  {
+               ret = -ENOENT;
+               goto err_delete;
+       }
+
+       buffer->gem = obj;
+
+       /*
+        * FIXME: The dependency on GEM here isn't required, we could
+        * convert the driver handle to a dma-buf instead and use the
+        * backend-agnostic dma-buf vmap support instead. This would
+        * require that the handle2fd prime ioctl is reworked to pull the
+        * fd_install step out of the driver backend hooks, to make that
+        * final step optional for internal users.
+        */
+       vaddr = dev->driver->gem_prime_vmap(obj);
+       if (!vaddr) {
+               ret = -ENOMEM;
+               goto err_delete;
+       }
+
+       buffer->vaddr = vaddr;
+
+       return buffer;
+
+err_delete:
+       drm_client_buffer_delete(buffer);
+
+       return ERR_PTR(ret);
+}
+
+static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
+{
+       int ret;
+
+       if (!buffer->fb)
+               return;
+
+       ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
+       if (ret)
+               DRM_DEV_ERROR(buffer->client->dev->dev,
+                             "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
+
+       buffer->fb = NULL;
+}
+
+static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
+                                  u32 width, u32 height, u32 format)
+{
+       struct drm_client_dev *client = buffer->client;
+       struct drm_mode_fb_cmd fb_req = { };
+       const struct drm_format_info *info;
+       int ret;
+
+       info = drm_format_info(format);
+       fb_req.bpp = info->cpp[0] * 8;
+       fb_req.depth = info->depth;
+       fb_req.width = width;
+       fb_req.height = height;
+       fb_req.handle = buffer->handle;
+       fb_req.pitch = buffer->pitch;
+
+       ret = drm_mode_addfb(client->dev, &fb_req, client->file);
+       if (ret)
+               return ret;
+
+       buffer->fb = drm_framebuffer_lookup(client->dev, buffer->client->file, fb_req.fb_id);
+       if (WARN_ON(!buffer->fb))
+               return -ENOENT;
+
+       /* drop the reference we picked up in framebuffer lookup */
+       drm_framebuffer_put(buffer->fb);
+
+       strscpy(buffer->fb->comm, client->name, TASK_COMM_LEN);
+
+       return 0;
+}
+
+/**
+ * drm_client_framebuffer_create - Create a client framebuffer
+ * @client: DRM client
+ * @width: Framebuffer width
+ * @height: Framebuffer height
+ * @format: Buffer format
+ *
+ * This function creates a &drm_client_buffer which consists of a
+ * &drm_framebuffer backed by a dumb buffer.
+ * Call drm_client_framebuffer_delete() to free the buffer.
+ *
+ * Returns:
+ * Pointer to a client buffer or an error pointer on failure.
+ */
+struct drm_client_buffer *
+drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
+{
+       struct drm_client_buffer *buffer;
+       int ret;
+
+       buffer = drm_client_buffer_create(client, width, height, format);
+       if (IS_ERR(buffer))
+               return buffer;
+
+       ret = drm_client_buffer_addfb(buffer, width, height, format);
+       if (ret) {
+               drm_client_buffer_delete(buffer);
+               return ERR_PTR(ret);
+       }
+
+       return buffer;
+}
+EXPORT_SYMBOL(drm_client_framebuffer_create);
+
+/**
+ * drm_client_framebuffer_delete - Delete a client framebuffer
+ * @buffer: DRM client buffer (can be NULL)
+ */
+void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
+{
+       if (!buffer)
+               return;
+
+       drm_client_buffer_rmfb(buffer);
+       drm_client_buffer_delete(buffer);
+}
+EXPORT_SYMBOL(drm_client_framebuffer_delete);
+
+#ifdef CONFIG_DEBUG_FS
+static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_printer p = drm_seq_file_printer(m);
+       struct drm_client_dev *client;
+
+       mutex_lock(&dev->clientlist_mutex);
+       list_for_each_entry(client, &dev->clientlist, list)
+               drm_printf(&p, "%s\n", client->name);
+       mutex_unlock(&dev->clientlist_mutex);
+
+       return 0;
+}
+
+static const struct drm_info_list drm_client_debugfs_list[] = {
+       { "internal_clients", drm_client_debugfs_internal_clients, 0 },
+};
+
+int drm_client_debugfs_init(struct drm_minor *minor)
+{
+       return drm_debugfs_create_files(drm_client_debugfs_list,
+                                       ARRAY_SIZE(drm_client_debugfs_list),
+                                       minor->debugfs_root, minor);
+}
+#endif
index b09b3a3e4024650b638783f5b9ada16337507b35..6011d769d50bb51197bfd935f3e6fff660878a1b 100644 (file)
@@ -48,7 +48,7 @@
  *
  * Connectors must be attached to an encoder to be used. For devices that map
  * connectors to encoders 1:1, the connector should be attached at
- * initialization time with a call to drm_mode_connector_attach_encoder(). The
+ * initialization time with a call to drm_connector_attach_encoder(). The
  * driver must also set the &drm_connector.encoder field to point to the
  * attached encoder.
  *
@@ -291,7 +291,7 @@ out_put:
 EXPORT_SYMBOL(drm_connector_init);
 
 /**
- * drm_mode_connector_attach_encoder - attach a connector to an encoder
+ * drm_connector_attach_encoder - attach a connector to an encoder
  * @connector: connector to attach
  * @encoder: encoder to attach @connector to
  *
@@ -302,8 +302,8 @@ EXPORT_SYMBOL(drm_connector_init);
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_connector_attach_encoder(struct drm_connector *connector,
-                                     struct drm_encoder *encoder)
+int drm_connector_attach_encoder(struct drm_connector *connector,
+                                struct drm_encoder *encoder)
 {
        int i;
 
@@ -321,7 +321,7 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector,
        if (WARN_ON(connector->encoder))
                return -EINVAL;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+       for (i = 0; i < ARRAY_SIZE(connector->encoder_ids); i++) {
                if (connector->encoder_ids[i] == 0) {
                        connector->encoder_ids[i] = encoder->base.id;
                        return 0;
@@ -329,7 +329,30 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector,
        }
        return -ENOMEM;
 }
-EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
+EXPORT_SYMBOL(drm_connector_attach_encoder);
+
+/**
+ * drm_connector_has_possible_encoder - check if the connector and encoder are assosicated with each other
+ * @connector: the connector
+ * @encoder: the encoder
+ *
+ * Returns:
+ * True if @encoder is one of the possible encoders for @connector.
+ */
+bool drm_connector_has_possible_encoder(struct drm_connector *connector,
+                                       struct drm_encoder *encoder)
+{
+       struct drm_encoder *enc;
+       int i;
+
+       drm_connector_for_each_possible_encoder(connector, enc, i) {
+               if (enc == encoder)
+                       return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(drm_connector_has_possible_encoder);
 
 static void drm_mode_remove(struct drm_connector *connector,
                            struct drm_display_mode *mode)
@@ -583,7 +606,7 @@ __drm_connector_put_safe(struct drm_connector *conn)
 
 /**
  * drm_connector_list_iter_next - return next connector
- * @iter: connectr_list iterator
+ * @iter: connector_list iterator
  *
  * Returns the next connector for @iter, or NULL when the list walk has
  * completed.
@@ -791,7 +814,7 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
  *     Blob property which contains the current EDID read from the sink. This
  *     is useful to parse sink identification information like vendor, model
  *     and serial. Drivers should update this property by calling
- *     drm_mode_connector_update_edid_property(), usually after having parsed
+ *     drm_connector_update_edid_property(), usually after having parsed
  *     the EDID using drm_add_edid_modes(). Userspace cannot change this
  *     property.
  * DPMS:
@@ -829,7 +852,7 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
  * PATH:
  *     Connector path property to identify how this sink is physically
  *     connected. Used by DP MST. This should be set by calling
- *     drm_mode_connector_set_path_property(), in the case of DP MST with the
+ *     drm_connector_set_path_property(), in the case of DP MST with the
  *     path property the MST manager created. Userspace cannot change this
  *     property.
  * TILE:
@@ -840,14 +863,14 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
  *     are not gen-locked. Note that for tiled panels which are genlocked, like
  *     dual-link LVDS or dual-link DSI, the driver should try to not expose the
  *     tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
- *     should update this value using drm_mode_connector_set_tile_property().
+ *     should update this value using drm_connector_set_tile_property().
  *     Userspace cannot change this property.
  * link-status:
  *      Connector link-status property to indicate the status of link. The
  *      default value of link-status is "GOOD". If something fails during or
  *      after modeset, the kernel driver may set this to "BAD" and issue a
  *      hotplug uevent. Drivers should update this value using
- *      drm_mode_connector_set_link_status_property().
+ *      drm_connector_set_link_status_property().
  * non_desktop:
  *     Indicates the output should be ignored for purposes of displaying a
  *     standard desktop environment or console. This is most likely because
@@ -1402,7 +1425,7 @@ int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
 EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
 
 /**
- * drm_mode_connector_set_path_property - set tile property on connector
+ * drm_connector_set_path_property - set tile property on connector
  * @connector: connector to set property on.
  * @path: path to use for property; must not be NULL.
  *
@@ -1414,8 +1437,8 @@ EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_connector_set_path_property(struct drm_connector *connector,
-                                        const char *path)
+int drm_connector_set_path_property(struct drm_connector *connector,
+                                   const char *path)
 {
        struct drm_device *dev = connector->dev;
        int ret;
@@ -1428,10 +1451,10 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
                                               dev->mode_config.path_property);
        return ret;
 }
-EXPORT_SYMBOL(drm_mode_connector_set_path_property);
+EXPORT_SYMBOL(drm_connector_set_path_property);
 
 /**
- * drm_mode_connector_set_tile_property - set tile property on connector
+ * drm_connector_set_tile_property - set tile property on connector
  * @connector: connector to set property on.
  *
  * This looks up the tile information for a connector, and creates a
@@ -1441,7 +1464,7 @@ EXPORT_SYMBOL(drm_mode_connector_set_path_property);
  * Returns:
  * Zero on success, errno on failure.
  */
-int drm_mode_connector_set_tile_property(struct drm_connector *connector)
+int drm_connector_set_tile_property(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        char tile[256];
@@ -1471,10 +1494,10 @@ int drm_mode_connector_set_tile_property(struct drm_connector *connector)
                                               dev->mode_config.tile_property);
        return ret;
 }
-EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
+EXPORT_SYMBOL(drm_connector_set_tile_property);
 
 /**
- * drm_mode_connector_update_edid_property - update the edid property of a connector
+ * drm_connector_update_edid_property - update the edid property of a connector
  * @connector: drm connector
  * @edid: new value of the edid property
  *
@@ -1484,8 +1507,8 @@ EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_connector_update_edid_property(struct drm_connector *connector,
-                                           const struct edid *edid)
+int drm_connector_update_edid_property(struct drm_connector *connector,
+                                      const struct edid *edid)
 {
        struct drm_device *dev = connector->dev;
        size_t size = 0;
@@ -1523,10 +1546,10 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
                                               dev->mode_config.edid_property);
        return ret;
 }
-EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
+EXPORT_SYMBOL(drm_connector_update_edid_property);
 
 /**
- * drm_mode_connector_set_link_status_property - Set link status property of a connector
+ * drm_connector_set_link_status_property - Set link status property of a connector
  * @connector: drm connector
  * @link_status: new value of link status property (0: Good, 1: Bad)
  *
@@ -1544,8 +1567,8 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
  * it is not limited to DP or link training. For example, if we implement
  * asynchronous setcrtc, this property can be used to report any failures in that.
  */
-void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
-                                                uint64_t link_status)
+void drm_connector_set_link_status_property(struct drm_connector *connector,
+                                           uint64_t link_status)
 {
        struct drm_device *dev = connector->dev;
 
@@ -1553,7 +1576,7 @@ void drm_mode_connector_set_link_status_property(struct drm_connector *connector
        connector->state->link_status = link_status;
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
 }
-EXPORT_SYMBOL(drm_mode_connector_set_link_status_property);
+EXPORT_SYMBOL(drm_connector_set_link_status_property);
 
 /**
  * drm_connector_init_panel_orientation_property -
@@ -1606,7 +1629,7 @@ int drm_connector_init_panel_orientation_property(
 }
 EXPORT_SYMBOL(drm_connector_init_panel_orientation_property);
 
-int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
+int drm_connector_set_obj_prop(struct drm_mode_object *obj,
                                    struct drm_property *property,
                                    uint64_t value)
 {
@@ -1624,8 +1647,8 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
        return ret;
 }
 
-int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
-                                      void *data, struct drm_file *file_priv)
+int drm_connector_property_set_ioctl(struct drm_device *dev,
+                                    void *data, struct drm_file *file_priv)
 {
        struct drm_mode_connector_set_property *conn_set_prop = data;
        struct drm_mode_obj_set_property obj_set_prop = {
@@ -1706,22 +1729,19 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        if (!connector)
                return -ENOENT;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
-               if (connector->encoder_ids[i] != 0)
-                       encoders_count++;
+       drm_connector_for_each_possible_encoder(connector, encoder, i)
+               encoders_count++;
 
        if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
                copied = 0;
                encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
-               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-                       if (connector->encoder_ids[i] != 0) {
-                               if (put_user(connector->encoder_ids[i],
-                                            encoder_ptr + copied)) {
-                                       ret = -EFAULT;
-                                       goto out;
-                               }
-                               copied++;
+
+               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+                       if (put_user(encoder->base.id, encoder_ptr + copied)) {
+                               ret = -EFAULT;
+                               goto out;
                        }
+                       copied++;
                }
        }
        out_resp->count_encoders = encoders_count;
index a6906c4ab880f38427a2869d373e12ccb3fe16c5..bae43938c8f6128ce29d75ee03a84c310c779621 100644 (file)
@@ -461,6 +461,8 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
        struct drm_crtc *tmp;
        int ret;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
+
        /*
         * NOTE: ->set_config can also disable other crtcs (if we steal all
         * connectors from it), hence we need to refcount the fbs across all
@@ -478,10 +480,8 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
        if (ret == 0) {
                struct drm_plane *plane = crtc->primary;
 
-               if (!plane->state) {
-                       plane->crtc = fb ? crtc : NULL;
-                       plane->fb = fb;
-               }
+               plane->crtc = fb ? crtc : NULL;
+               plane->fb = fb;
        }
 
        drm_for_each_crtc(tmp, crtc->dev) {
@@ -496,6 +496,7 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
 
        return ret;
 }
+
 /**
  * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
  * @set: modeset config to set
@@ -740,7 +741,11 @@ retry:
        set.connectors = connector_set;
        set.num_connectors = crtc_req->count_connectors;
        set.fb = fb;
-       ret = __drm_mode_set_config_internal(&set, &ctx);
+
+       if (drm_drv_uses_atomic_modeset(dev))
+               ret = crtc->funcs->set_config(&set, &ctx);
+       else
+               ret = __drm_mode_set_config_internal(&set, &ctx);
 
 out:
        if (fb)
index 235d40fce8b54675a47cecc45e35b379a7dae156..b61322763394af2f3dd29f8a49e48a5dc85bf9d1 100644 (file)
@@ -148,7 +148,7 @@ void drm_connector_ida_init(void);
 void drm_connector_ida_destroy(void);
 void drm_connector_unregister_all(struct drm_device *dev);
 int drm_connector_register_all(struct drm_device *dev);
-int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
+int drm_connector_set_obj_prop(struct drm_mode_object *obj,
                                    struct drm_property *property,
                                    uint64_t value);
 int drm_connector_create_standard_properties(struct drm_device *dev);
@@ -156,8 +156,8 @@ const char *drm_get_connector_force_name(enum drm_connector_force force);
 void drm_connector_free_work_fn(struct work_struct *work);
 
 /* IOCTL */
-int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
-                                         void *data, struct drm_file *file_priv);
+int drm_connector_property_set_ioctl(struct drm_device *dev,
+                                    void *data, struct drm_file *file_priv);
 int drm_mode_getconnector(struct drm_device *dev,
                          void *data, struct drm_file *file_priv);
 
index b2482818fee8c22c125c5f725d5d2fb6db1fdc91..6f28fe58f1696ca5010915149173e966df35ffc7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 
+#include <drm/drm_client.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_atomic.h>
@@ -164,6 +165,12 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
                        DRM_ERROR("Failed to create framebuffer debugfs file\n");
                        return ret;
                }
+
+               ret = drm_client_debugfs_init(minor);
+               if (ret) {
+                       DRM_ERROR("Failed to create client debugfs file\n");
+                       return ret;
+               }
        }
 
        if (dev->driver->debugfs_init) {
@@ -307,13 +314,13 @@ static ssize_t edid_write(struct file *file, const char __user *ubuf,
 
        if (len == 5 && !strncmp(buf, "reset", 5)) {
                connector->override_edid = false;
-               ret = drm_mode_connector_update_edid_property(connector, NULL);
+               ret = drm_connector_update_edid_property(connector, NULL);
        } else if (len < EDID_LENGTH ||
                   EDID_LENGTH * (1 + edid->extensions) > len)
                ret = -EINVAL;
        else {
                connector->override_edid = false;
-               ret = drm_mode_connector_update_edid_property(connector, edid);
+               ret = drm_connector_update_edid_property(connector, edid);
                if (!ret)
                        connector->override_edid = true;
        }
index 9f8312137cadec4c5e9eeb03ca7ca6147be3b355..99961192bf034f893cbac5521c996dc98aa49887 100644 (file)
@@ -139,6 +139,7 @@ static int crtc_crc_data_count(struct drm_crtc_crc *crc)
 static void crtc_crc_cleanup(struct drm_crtc_crc *crc)
 {
        kfree(crc->entries);
+       crc->overflow = false;
        crc->entries = NULL;
        crc->head = 0;
        crc->tail = 0;
@@ -391,8 +392,14 @@ int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
        tail = crc->tail;
 
        if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) {
+               bool was_overflow = crc->overflow;
+
+               crc->overflow = true;
                spin_unlock(&crc->lock);
-               DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
+
+               if (!was_overflow)
+                       DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
+
                return -ENOBUFS;
        }
 
diff --git a/drivers/gpu/drm/drm_dp_cec.c b/drivers/gpu/drm/drm_dp_cec.c
new file mode 100644 (file)
index 0000000..ddb1c5a
--- /dev/null
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DisplayPort CEC-Tunneling-over-AUX support
+ *
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <drm/drm_dp_helper.h>
+#include <media/cec.h>
+
+/*
+ * Unfortunately it turns out that we have a chicken-and-egg situation
+ * here. Quite a few active (mini-)DP-to-HDMI or USB-C-to-HDMI adapters
+ * have a converter chip that supports CEC-Tunneling-over-AUX (usually the
+ * Parade PS176), but they do not wire up the CEC pin, thus making CEC
+ * useless.
+ *
+ * Sadly there is no way for this driver to know this. What happens is
+ * that a /dev/cecX device is created that is isolated and unable to see
+ * any of the other CEC devices. Quite literally the CEC wire is cut
+ * (or in this case, never connected in the first place).
+ *
+ * The reason so few adapters support this is that this tunneling protocol
+ * was never supported by any OS. So there was no easy way of testing it,
+ * and no incentive to correctly wire up the CEC pin.
+ *
+ * Hopefully by creating this driver it will be easier for vendors to
+ * finally fix their adapters and test the CEC functionality.
+ *
+ * I keep a list of known working adapters here:
+ *
+ * https://hverkuil.home.xs4all.nl/cec-status.txt
+ *
+ * Please mail me (hverkuil@xs4all.nl) if you find an adapter that works
+ * and is not yet listed there.
+ *
+ * Note that the current implementation does not support CEC over an MST hub.
+ * As far as I can see there is no mechanism defined in the DisplayPort
+ * standard to transport CEC interrupts over an MST device. It might be
+ * possible to do this through polling, but I have not been able to get that
+ * to work.
+ */
+
+/**
+ * DOC: dp cec helpers
+ *
+ * These functions take care of supporting the CEC-Tunneling-over-AUX
+ * feature of DisplayPort-to-HDMI adapters.
+ */
+
+/*
+ * When the EDID is unset because the HPD went low, then the CEC DPCD registers
+ * typically can no longer be read (true for a DP-to-HDMI adapter since it is
+ * powered by the HPD). However, some displays toggle the HPD off and on for a
+ * short period for one reason or another, and that would cause the CEC adapter
+ * to be removed and added again, even though nothing else changed.
+ *
+ * This module parameter sets a delay in seconds before the CEC adapter is
+ * actually unregistered. Only if the HPD does not return within that time will
+ * the CEC adapter be unregistered.
+ *
+ * If it is set to a value >= NEVER_UNREG_DELAY, then the CEC adapter will never
+ * be unregistered for as long as the connector remains registered.
+ *
+ * If it is set to 0, then the CEC adapter will be unregistered immediately as
+ * soon as the HPD disappears.
+ *
+ * The default is one second to prevent short HPD glitches from unregistering
+ * the CEC adapter.
+ *
+ * Note that for integrated HDMI branch devices that support CEC the DPCD
+ * registers remain available even if the HPD goes low since it is not powered
+ * by the HPD. In that case the CEC adapter will never be unregistered during
+ * the life time of the connector. At least, this is the theory since I do not
+ * have hardware with an integrated HDMI branch device that supports CEC.
+ */
+#define NEVER_UNREG_DELAY 1000
+static unsigned int drm_dp_cec_unregister_delay = 1;
+module_param(drm_dp_cec_unregister_delay, uint, 0600);
+MODULE_PARM_DESC(drm_dp_cec_unregister_delay,
+                "CEC unregister delay in seconds, 0: no delay, >= 1000: never unregister");
+
+static int drm_dp_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+       struct drm_dp_aux *aux = cec_get_drvdata(adap);
+       u32 val = enable ? DP_CEC_TUNNELING_ENABLE : 0;
+       ssize_t err = 0;
+
+       err = drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_CONTROL, val);
+       return (enable && err < 0) ? err : 0;
+}
+
+static int drm_dp_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
+{
+       struct drm_dp_aux *aux = cec_get_drvdata(adap);
+       /* Bit 15 (logical address 15) should always be set */
+       u16 la_mask = 1 << CEC_LOG_ADDR_BROADCAST;
+       u8 mask[2];
+       ssize_t err;
+
+       if (addr != CEC_LOG_ADDR_INVALID)
+               la_mask |= adap->log_addrs.log_addr_mask | (1 << addr);
+       mask[0] = la_mask & 0xff;
+       mask[1] = la_mask >> 8;
+       err = drm_dp_dpcd_write(aux, DP_CEC_LOGICAL_ADDRESS_MASK, mask, 2);
+       return (addr != CEC_LOG_ADDR_INVALID && err < 0) ? err : 0;
+}
+
+static int drm_dp_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+                                   u32 signal_free_time, struct cec_msg *msg)
+{
+       struct drm_dp_aux *aux = cec_get_drvdata(adap);
+       unsigned int retries = min(5, attempts - 1);
+       ssize_t err;
+
+       err = drm_dp_dpcd_write(aux, DP_CEC_TX_MESSAGE_BUFFER,
+                               msg->msg, msg->len);
+       if (err < 0)
+               return err;
+
+       err = drm_dp_dpcd_writeb(aux, DP_CEC_TX_MESSAGE_INFO,
+                                (msg->len - 1) | (retries << 4) |
+                                DP_CEC_TX_MESSAGE_SEND);
+       return err < 0 ? err : 0;
+}
+
+static int drm_dp_cec_adap_monitor_all_enable(struct cec_adapter *adap,
+                                             bool enable)
+{
+       struct drm_dp_aux *aux = cec_get_drvdata(adap);
+       ssize_t err;
+       u8 val;
+
+       if (!(adap->capabilities & CEC_CAP_MONITOR_ALL))
+               return 0;
+
+       err = drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_CONTROL, &val);
+       if (err >= 0) {
+               if (enable)
+                       val |= DP_CEC_SNOOPING_ENABLE;
+               else
+                       val &= ~DP_CEC_SNOOPING_ENABLE;
+               err = drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_CONTROL, val);
+       }
+       return (enable && err < 0) ? err : 0;
+}
+
+static void drm_dp_cec_adap_status(struct cec_adapter *adap,
+                                  struct seq_file *file)
+{
+       struct drm_dp_aux *aux = cec_get_drvdata(adap);
+       struct drm_dp_desc desc;
+       struct drm_dp_dpcd_ident *id = &desc.ident;
+
+       if (drm_dp_read_desc(aux, &desc, true))
+               return;
+       seq_printf(file, "OUI: %*pdH\n",
+                  (int)sizeof(id->oui), id->oui);
+       seq_printf(file, "ID: %*pE\n",
+                  (int)strnlen(id->device_id, sizeof(id->device_id)),
+                  id->device_id);
+       seq_printf(file, "HW Rev: %d.%d\n", id->hw_rev >> 4, id->hw_rev & 0xf);
+       /*
+        * Show this both in decimal and hex: at least one vendor
+        * always reports this in hex.
+        */
+       seq_printf(file, "FW/SW Rev: %d.%d (0x%02x.0x%02x)\n",
+                  id->sw_major_rev, id->sw_minor_rev,
+                  id->sw_major_rev, id->sw_minor_rev);
+}
+
+static const struct cec_adap_ops drm_dp_cec_adap_ops = {
+       .adap_enable = drm_dp_cec_adap_enable,
+       .adap_log_addr = drm_dp_cec_adap_log_addr,
+       .adap_transmit = drm_dp_cec_adap_transmit,
+       .adap_monitor_all_enable = drm_dp_cec_adap_monitor_all_enable,
+       .adap_status = drm_dp_cec_adap_status,
+};
+
+static int drm_dp_cec_received(struct drm_dp_aux *aux)
+{
+       struct cec_adapter *adap = aux->cec.adap;
+       struct cec_msg msg;
+       u8 rx_msg_info;
+       ssize_t err;
+
+       err = drm_dp_dpcd_readb(aux, DP_CEC_RX_MESSAGE_INFO, &rx_msg_info);
+       if (err < 0)
+               return err;
+
+       if (!(rx_msg_info & DP_CEC_RX_MESSAGE_ENDED))
+               return 0;
+
+       msg.len = (rx_msg_info & DP_CEC_RX_MESSAGE_LEN_MASK) + 1;
+       err = drm_dp_dpcd_read(aux, DP_CEC_RX_MESSAGE_BUFFER, msg.msg, msg.len);
+       if (err < 0)
+               return err;
+
+       cec_received_msg(adap, &msg);
+       return 0;
+}
+
+static void drm_dp_cec_handle_irq(struct drm_dp_aux *aux)
+{
+       struct cec_adapter *adap = aux->cec.adap;
+       u8 flags;
+
+       if (drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, &flags) < 0)
+               return;
+
+       if (flags & DP_CEC_RX_MESSAGE_INFO_VALID)
+               drm_dp_cec_received(aux);
+
+       if (flags & DP_CEC_TX_MESSAGE_SENT)
+               cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
+       else if (flags & DP_CEC_TX_LINE_ERROR)
+               cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR |
+                                               CEC_TX_STATUS_MAX_RETRIES);
+       else if (flags &
+                (DP_CEC_TX_ADDRESS_NACK_ERROR | DP_CEC_TX_DATA_NACK_ERROR))
+               cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK |
+                                               CEC_TX_STATUS_MAX_RETRIES);
+       drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, flags);
+}
+
+/**
+ * drm_dp_cec_irq() - handle CEC interrupt, if any
+ * @aux: DisplayPort AUX channel
+ *
+ * Should be called when handling an IRQ_HPD request. If CEC-tunneling-over-AUX
+ * is present, then it will check for a CEC_IRQ and handle it accordingly.
+ */
+void drm_dp_cec_irq(struct drm_dp_aux *aux)
+{
+       u8 cec_irq;
+       int ret;
+
+       mutex_lock(&aux->cec.lock);
+       if (!aux->cec.adap)
+               goto unlock;
+
+       ret = drm_dp_dpcd_readb(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1,
+                               &cec_irq);
+       if (ret < 0 || !(cec_irq & DP_CEC_IRQ))
+               goto unlock;
+
+       drm_dp_cec_handle_irq(aux);
+       drm_dp_dpcd_writeb(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1, DP_CEC_IRQ);
+unlock:
+       mutex_unlock(&aux->cec.lock);
+}
+EXPORT_SYMBOL(drm_dp_cec_irq);
+
+static bool drm_dp_cec_cap(struct drm_dp_aux *aux, u8 *cec_cap)
+{
+       u8 cap = 0;
+
+       if (drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_CAPABILITY, &cap) != 1 ||
+           !(cap & DP_CEC_TUNNELING_CAPABLE))
+               return false;
+       if (cec_cap)
+               *cec_cap = cap;
+       return true;
+}
+
+/*
+ * Called if the HPD was low for more than drm_dp_cec_unregister_delay
+ * seconds. This unregisters the CEC adapter.
+ */
+static void drm_dp_cec_unregister_work(struct work_struct *work)
+{
+       struct drm_dp_aux *aux = container_of(work, struct drm_dp_aux,
+                                             cec.unregister_work.work);
+
+       mutex_lock(&aux->cec.lock);
+       cec_unregister_adapter(aux->cec.adap);
+       aux->cec.adap = NULL;
+       mutex_unlock(&aux->cec.lock);
+}
+
+/*
+ * A new EDID is set. If there is no CEC adapter, then create one. If
+ * there was a CEC adapter, then check if the CEC adapter properties
+ * were unchanged and just update the CEC physical address. Otherwise
+ * unregister the old CEC adapter and create a new one.
+ */
+void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
+{
+       u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD;
+       unsigned int num_las = 1;
+       u8 cap;
+
+#ifndef CONFIG_MEDIA_CEC_RC
+       /*
+        * CEC_CAP_RC is part of CEC_CAP_DEFAULTS, but it is stripped by
+        * cec_allocate_adapter() if CONFIG_MEDIA_CEC_RC is undefined.
+        *
+        * Do this here as well to ensure the tests against cec_caps are
+        * correct.
+        */
+       cec_caps &= ~CEC_CAP_RC;
+#endif
+       cancel_delayed_work_sync(&aux->cec.unregister_work);
+
+       mutex_lock(&aux->cec.lock);
+       if (!drm_dp_cec_cap(aux, &cap)) {
+               /* CEC is not supported, unregister any existing adapter */
+               cec_unregister_adapter(aux->cec.adap);
+               aux->cec.adap = NULL;
+               goto unlock;
+       }
+
+       if (cap & DP_CEC_SNOOPING_CAPABLE)
+               cec_caps |= CEC_CAP_MONITOR_ALL;
+       if (cap & DP_CEC_MULTIPLE_LA_CAPABLE)
+               num_las = CEC_MAX_LOG_ADDRS;
+
+       if (aux->cec.adap) {
+               if (aux->cec.adap->capabilities == cec_caps &&
+                   aux->cec.adap->available_log_addrs == num_las) {
+                       /* Unchanged, so just set the phys addr */
+                       cec_s_phys_addr_from_edid(aux->cec.adap, edid);
+                       goto unlock;
+               }
+               /*
+                * The capabilities changed, so unregister the old
+                * adapter first.
+                */
+               cec_unregister_adapter(aux->cec.adap);
+       }
+
+       /* Create a new adapter */
+       aux->cec.adap = cec_allocate_adapter(&drm_dp_cec_adap_ops,
+                                            aux, aux->cec.name, cec_caps,
+                                            num_las);
+       if (IS_ERR(aux->cec.adap)) {
+               aux->cec.adap = NULL;
+               goto unlock;
+       }
+       if (cec_register_adapter(aux->cec.adap, aux->cec.parent)) {
+               cec_delete_adapter(aux->cec.adap);
+               aux->cec.adap = NULL;
+       } else {
+               /*
+                * Update the phys addr for the new CEC adapter. When called
+                * from drm_dp_cec_register_connector() edid == NULL, so in
+                * that case the phys addr is just invalidated.
+                */
+               cec_s_phys_addr_from_edid(aux->cec.adap, edid);
+       }
+unlock:
+       mutex_unlock(&aux->cec.lock);
+}
+EXPORT_SYMBOL(drm_dp_cec_set_edid);
+
+/*
+ * The EDID disappeared (likely because of the HPD going down).
+ */
+void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
+{
+       cancel_delayed_work_sync(&aux->cec.unregister_work);
+
+       mutex_lock(&aux->cec.lock);
+       if (!aux->cec.adap)
+               goto unlock;
+
+       cec_phys_addr_invalidate(aux->cec.adap);
+       /*
+        * We're done if we want to keep the CEC device
+        * (drm_dp_cec_unregister_delay is >= NEVER_UNREG_DELAY) or if the
+        * DPCD still indicates the CEC capability (expected for an integrated
+        * HDMI branch device).
+        */
+       if (drm_dp_cec_unregister_delay < NEVER_UNREG_DELAY &&
+           !drm_dp_cec_cap(aux, NULL)) {
+               /*
+                * Unregister the CEC adapter after drm_dp_cec_unregister_delay
+                * seconds. This to debounce short HPD off-and-on cycles from
+                * displays.
+                */
+               schedule_delayed_work(&aux->cec.unregister_work,
+                                     drm_dp_cec_unregister_delay * HZ);
+       }
+unlock:
+       mutex_unlock(&aux->cec.lock);
+}
+EXPORT_SYMBOL(drm_dp_cec_unset_edid);
+
+/**
+ * drm_dp_cec_register_connector() - register a new connector
+ * @aux: DisplayPort AUX channel
+ * @name: name of the CEC device
+ * @parent: parent device
+ *
+ * A new connector was registered with associated CEC adapter name and
+ * CEC adapter parent device. After registering the name and parent
+ * drm_dp_cec_set_edid() is called to check if the connector supports
+ * CEC and to register a CEC adapter if that is the case.
+ */
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
+                                  struct device *parent)
+{
+       WARN_ON(aux->cec.adap);
+       aux->cec.name = name;
+       aux->cec.parent = parent;
+       INIT_DELAYED_WORK(&aux->cec.unregister_work,
+                         drm_dp_cec_unregister_work);
+
+       drm_dp_cec_set_edid(aux, NULL);
+}
+EXPORT_SYMBOL(drm_dp_cec_register_connector);
+
+/**
+ * drm_dp_cec_unregister_connector() - unregister the CEC adapter, if any
+ * @aux: DisplayPort AUX channel
+ */
+void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux)
+{
+       if (!aux->cec.adap)
+               return;
+       cancel_delayed_work_sync(&aux->cec.unregister_work);
+       cec_unregister_adapter(aux->cec.adap);
+       aux->cec.adap = NULL;
+}
+EXPORT_SYMBOL(drm_dp_cec_unregister_connector);
index a7ba602a43a82bc978d349543b4158196a2c5edf..0cccbcb2d03ea8670e71ee62a9bd6526db6b0b97 100644 (file)
@@ -185,6 +185,20 @@ EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
 
 #define AUX_RETRY_INTERVAL 500 /* us */
 
+static inline void
+drm_dp_dump_access(const struct drm_dp_aux *aux,
+                  u8 request, uint offset, void *buffer, int ret)
+{
+       const char *arrow = request == DP_AUX_NATIVE_READ ? "->" : "<-";
+
+       if (ret > 0)
+               drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
+                       aux->name, offset, arrow, ret, min(ret, 20), buffer);
+       else
+               drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d)\n",
+                       aux->name, offset, arrow, ret);
+}
+
 /**
  * DOC: dp helpers
  *
@@ -288,10 +302,14 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
        ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer,
                                 1);
        if (ret != 1)
-               return ret;
+               goto out;
 
-       return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
-                                 size);
+       ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
+                                size);
+
+out:
+       drm_dp_dump_access(aux, DP_AUX_NATIVE_READ, offset, buffer, ret);
+       return ret;
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read);
 
@@ -312,8 +330,12 @@ EXPORT_SYMBOL(drm_dp_dpcd_read);
 ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
                          void *buffer, size_t size)
 {
-       return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
-                                 size);
+       int ret;
+
+       ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
+                                size);
+       drm_dp_dump_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, ret);
+       return ret;
 }
 EXPORT_SYMBOL(drm_dp_dpcd_write);
 
@@ -1087,6 +1109,7 @@ static void drm_dp_aux_crc_work(struct work_struct *work)
 void drm_dp_aux_init(struct drm_dp_aux *aux)
 {
        mutex_init(&aux->hw_mutex);
+       mutex_init(&aux->cec.lock);
        INIT_WORK(&aux->crc_work, drm_dp_aux_crc_work);
 
        aux->ddc.algo = &drm_dp_i2c_algo;
index 658830620ca3668a706817ce5efb1805d32be9b0..7780567aa6692fa56450aed78ff101b294fe7da6 100644 (file)
@@ -1215,7 +1215,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                     port->pdt == DP_PEER_DEVICE_SST_SINK) &&
                    port->port_num >= DP_MST_LOGICAL_PORT_0) {
                        port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
-                       drm_mode_connector_set_tile_property(port->connector);
+                       drm_connector_set_tile_property(port->connector);
                }
                (*mstb->mgr->cbs->register_connector)(port->connector);
        }
@@ -2559,7 +2559,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
                edid = drm_edid_duplicate(port->cached_edid);
        else {
                edid = drm_get_edid(connector, &port->aux.ddc);
-               drm_mode_connector_set_tile_property(connector);
+               drm_connector_set_tile_property(connector);
        }
        port->has_audio = drm_detect_monitor_audio(edid);
        drm_dp_put_port(port);
index 7af748ed1c58dddfae7cb578760be3344273901c..ea4941da9b273f39fb81ab238eae769589f6a1c7 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/srcu.h>
 
+#include <drm/drm_client.h>
 #include <drm/drm_drv.h>
 #include <drm/drmP.h>
 
@@ -53,13 +54,14 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
 MODULE_DESCRIPTION("DRM shared core routines");
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
-"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
-"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
-"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
-"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
-"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
-"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
-"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)");
+"\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n"
+"\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n"
+"\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n"
+"\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n"
+"\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n"
+"\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n"
+"\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n"
+"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
 module_param_named(debug, drm_debug, int, 0600);
 
 static DEFINE_SPINLOCK(drm_minor_lock);
@@ -505,6 +507,8 @@ int drm_dev_init(struct drm_device *dev,
        dev->driver = driver;
 
        INIT_LIST_HEAD(&dev->filelist);
+       INIT_LIST_HEAD(&dev->filelist_internal);
+       INIT_LIST_HEAD(&dev->clientlist);
        INIT_LIST_HEAD(&dev->ctxlist);
        INIT_LIST_HEAD(&dev->vmalist);
        INIT_LIST_HEAD(&dev->maplist);
@@ -514,6 +518,7 @@ int drm_dev_init(struct drm_device *dev,
        spin_lock_init(&dev->event_lock);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->filelist_mutex);
+       mutex_init(&dev->clientlist_mutex);
        mutex_init(&dev->ctxlist_mutex);
        mutex_init(&dev->master_mutex);
 
@@ -569,6 +574,7 @@ err_minors:
 err_free:
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->ctxlist_mutex);
+       mutex_destroy(&dev->clientlist_mutex);
        mutex_destroy(&dev->filelist_mutex);
        mutex_destroy(&dev->struct_mutex);
        return ret;
@@ -603,6 +609,7 @@ void drm_dev_fini(struct drm_device *dev)
 
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->ctxlist_mutex);
+       mutex_destroy(&dev->clientlist_mutex);
        mutex_destroy(&dev->filelist_mutex);
        mutex_destroy(&dev->struct_mutex);
        kfree(dev->unique);
@@ -858,6 +865,8 @@ void drm_dev_unregister(struct drm_device *dev)
 
        dev->registered = false;
 
+       drm_client_dev_unregister(dev);
+
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                drm_modeset_unregister_all(dev);
 
index 186d00adfb5f86675bfd27a8dd9d812e1475d9fe..9da36a6271d3a24380e6a1221ae027701eba6e52 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_client.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_print.h>
 #include <linux/module.h>
 
-#define DEFAULT_FBDEFIO_DELAY_MS 50
-
 struct drm_fbdev_cma {
        struct drm_fb_helper    fb_helper;
-       const struct drm_framebuffer_funcs *fb_funcs;
 };
 
 /**
@@ -44,36 +42,6 @@ struct drm_fbdev_cma {
  *
  * An fbdev framebuffer backed by cma is also available by calling
  * drm_fb_cma_fbdev_init(). drm_fb_cma_fbdev_fini() tears it down.
- * If the &drm_framebuffer_funcs.dirty callback is set, fb_deferred_io will be
- * set up automatically. &drm_framebuffer_funcs.dirty is called by
- * drm_fb_helper_deferred_io() in process context (&struct delayed_work).
- *
- * Example fbdev deferred io code::
- *
- *     static int driver_fb_dirty(struct drm_framebuffer *fb,
- *                                struct drm_file *file_priv,
- *                                unsigned flags, unsigned color,
- *                                struct drm_clip_rect *clips,
- *                                unsigned num_clips)
- *     {
- *         struct drm_gem_cma_object *cma = drm_fb_cma_get_gem_obj(fb, 0);
- *         ... push changes ...
- *         return 0;
- *     }
- *
- *     static struct drm_framebuffer_funcs driver_fb_funcs = {
- *         .destroy       = drm_gem_fb_destroy,
- *         .create_handle = drm_gem_fb_create_handle,
- *         .dirty         = driver_fb_dirty,
- *     };
- *
- * Initialize::
- *
- *     fbdev = drm_fb_cma_fbdev_init_with_funcs(dev, 16,
- *                                           dev->mode_config.num_crtc,
- *                                           dev->mode_config.num_connector,
- *                                           &driver_fb_funcs);
- *
  */
 
 static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
@@ -131,236 +99,28 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
 
-static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-       return dma_mmap_writecombine(info->device, vma, info->screen_base,
-                                    info->fix.smem_start, info->fix.smem_len);
-}
-
-static struct fb_ops drm_fbdev_cma_ops = {
-       .owner          = THIS_MODULE,
-       DRM_FB_HELPER_DEFAULT_OPS,
-       .fb_fillrect    = drm_fb_helper_sys_fillrect,
-       .fb_copyarea    = drm_fb_helper_sys_copyarea,
-       .fb_imageblit   = drm_fb_helper_sys_imageblit,
-       .fb_mmap        = drm_fb_cma_mmap,
-};
-
-static int drm_fbdev_cma_deferred_io_mmap(struct fb_info *info,
-                                         struct vm_area_struct *vma)
-{
-       fb_deferred_io_mmap(info, vma);
-       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
-       return 0;
-}
-
-static int drm_fbdev_cma_defio_init(struct fb_info *fbi,
-                                   struct drm_gem_cma_object *cma_obj)
-{
-       struct fb_deferred_io *fbdefio;
-       struct fb_ops *fbops;
-
-       /*
-        * Per device structures are needed because:
-        * fbops: fb_deferred_io_cleanup() clears fbops.fb_mmap
-        * fbdefio: individual delays
-        */
-       fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
-       fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
-       if (!fbdefio || !fbops) {
-               kfree(fbdefio);
-               kfree(fbops);
-               return -ENOMEM;
-       }
-
-       /* can't be offset from vaddr since dirty() uses cma_obj */
-       fbi->screen_buffer = cma_obj->vaddr;
-       /* fb_deferred_io_fault() needs a physical address */
-       fbi->fix.smem_start = page_to_phys(virt_to_page(fbi->screen_buffer));
-
-       *fbops = *fbi->fbops;
-       fbi->fbops = fbops;
-
-       fbdefio->delay = msecs_to_jiffies(DEFAULT_FBDEFIO_DELAY_MS);
-       fbdefio->deferred_io = drm_fb_helper_deferred_io;
-       fbi->fbdefio = fbdefio;
-       fb_deferred_io_init(fbi);
-       fbi->fbops->fb_mmap = drm_fbdev_cma_deferred_io_mmap;
-
-       return 0;
-}
-
-static void drm_fbdev_cma_defio_fini(struct fb_info *fbi)
-{
-       if (!fbi->fbdefio)
-               return;
-
-       fb_deferred_io_cleanup(fbi);
-       kfree(fbi->fbdefio);
-       kfree(fbi->fbops);
-}
-
-static int
-drm_fbdev_cma_create(struct drm_fb_helper *helper,
-       struct drm_fb_helper_surface_size *sizes)
-{
-       struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
-       struct drm_device *dev = helper->dev;
-       struct drm_gem_cma_object *obj;
-       struct drm_framebuffer *fb;
-       unsigned int bytes_per_pixel;
-       unsigned long offset;
-       struct fb_info *fbi;
-       size_t size;
-       int ret;
-
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
-                       sizes->surface_width, sizes->surface_height,
-                       sizes->surface_bpp);
-
-       bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
-       size = sizes->surface_width * sizes->surface_height * bytes_per_pixel;
-       obj = drm_gem_cma_create(dev, size);
-       if (IS_ERR(obj))
-               return -ENOMEM;
-
-       fbi = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(fbi)) {
-               ret = PTR_ERR(fbi);
-               goto err_gem_free_object;
-       }
-
-       fb = drm_gem_fbdev_fb_create(dev, sizes, 0, &obj->base,
-                                    fbdev_cma->fb_funcs);
-       if (IS_ERR(fb)) {
-               dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
-               ret = PTR_ERR(fb);
-               goto err_fb_info_destroy;
-       }
-
-       helper->fb = fb;
-
-       fbi->par = helper;
-       fbi->flags = FBINFO_FLAG_DEFAULT;
-       fbi->fbops = &drm_fbdev_cma_ops;
-
-       drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
-       drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
-
-       offset = fbi->var.xoffset * bytes_per_pixel;
-       offset += fbi->var.yoffset * fb->pitches[0];
-
-       dev->mode_config.fb_base = (resource_size_t)obj->paddr;
-       fbi->screen_base = obj->vaddr + offset;
-       fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
-       fbi->screen_size = size;
-       fbi->fix.smem_len = size;
-
-       if (fb->funcs->dirty) {
-               ret = drm_fbdev_cma_defio_init(fbi, obj);
-               if (ret)
-                       goto err_cma_destroy;
-       }
-
-       return 0;
-
-err_cma_destroy:
-       drm_framebuffer_remove(fb);
-err_fb_info_destroy:
-       drm_fb_helper_fini(helper);
-err_gem_free_object:
-       drm_gem_object_put_unlocked(&obj->base);
-       return ret;
-}
-
-static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
-       .fb_probe = drm_fbdev_cma_create,
-};
-
 /**
- * drm_fb_cma_fbdev_init_with_funcs() - Allocate and initialize fbdev emulation
+ * drm_fb_cma_fbdev_init() - Allocate and initialize fbdev emulation
  * @dev: DRM device
  * @preferred_bpp: Preferred bits per pixel for the device.
  *                 @dev->mode_config.preferred_depth is used if this is zero.
  * @max_conn_count: Maximum number of connectors.
  *                  @dev->mode_config.num_connector is used if this is zero.
- * @funcs: Framebuffer functions, in particular a custom dirty() callback.
- *         Can be NULL.
  *
  * Returns:
  * Zero on success or negative error code on failure.
  */
-int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
-       unsigned int preferred_bpp, unsigned int max_conn_count,
-       const struct drm_framebuffer_funcs *funcs)
+int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
+                         unsigned int max_conn_count)
 {
        struct drm_fbdev_cma *fbdev_cma;
-       struct drm_fb_helper *fb_helper;
-       int ret;
-
-       if (!preferred_bpp)
-               preferred_bpp = dev->mode_config.preferred_depth;
-       if (!preferred_bpp)
-               preferred_bpp = 32;
-
-       if (!max_conn_count)
-               max_conn_count = dev->mode_config.num_connector;
-
-       fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
-       if (!fbdev_cma)
-               return -ENOMEM;
 
-       fbdev_cma->fb_funcs = funcs;
-       fb_helper = &fbdev_cma->fb_helper;
-
-       drm_fb_helper_prepare(dev, fb_helper, &drm_fb_cma_helper_funcs);
-
-       ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
-       if (ret < 0) {
-               DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper.\n");
-               goto err_free;
-       }
-
-       ret = drm_fb_helper_single_add_all_connectors(fb_helper);
-       if (ret < 0) {
-               DRM_DEV_ERROR(dev->dev, "Failed to add connectors.\n");
-               goto err_drm_fb_helper_fini;
-       }
-
-       ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
-       if (ret < 0) {
-               DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration.\n");
-               goto err_drm_fb_helper_fini;
-       }
+       /* dev->fb_helper will indirectly point to fbdev_cma after this call */
+       fbdev_cma = drm_fbdev_cma_init(dev, preferred_bpp, max_conn_count);
+       if (IS_ERR(fbdev_cma))
+               return PTR_ERR(fbdev_cma);
 
        return 0;
-
-err_drm_fb_helper_fini:
-       drm_fb_helper_fini(fb_helper);
-err_free:
-       kfree(fbdev_cma);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs);
-
-/**
- * drm_fb_cma_fbdev_init() - Allocate and initialize fbdev emulation
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device.
- *                 @dev->mode_config.preferred_depth is used if this is zero.
- * @max_conn_count: Maximum number of connectors.
- *                  @dev->mode_config.num_connector is used if this is zero.
- *
- * Returns:
- * Zero on success or negative error code on failure.
- */
-int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
-                         unsigned int max_conn_count)
-{
-       return drm_fb_cma_fbdev_init_with_funcs(dev, preferred_bpp,
-                                               max_conn_count, NULL);
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
 
@@ -370,104 +130,54 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
  */
 void drm_fb_cma_fbdev_fini(struct drm_device *dev)
 {
-       struct drm_fb_helper *fb_helper = dev->fb_helper;
-
-       if (!fb_helper)
-               return;
-
-       /* Unregister if it hasn't been done already */
-       if (fb_helper->fbdev && fb_helper->fbdev->dev)
-               drm_fb_helper_unregister_fbi(fb_helper);
-
-       if (fb_helper->fbdev)
-               drm_fbdev_cma_defio_fini(fb_helper->fbdev);
-
-       if (fb_helper->fb)
-               drm_framebuffer_remove(fb_helper->fb);
-
-       drm_fb_helper_fini(fb_helper);
-       kfree(to_fbdev_cma(fb_helper));
+       if (dev->fb_helper)
+               drm_fbdev_cma_fini(to_fbdev_cma(dev->fb_helper));
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_fini);
 
+static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+       .fb_probe = drm_fb_helper_generic_probe,
+};
+
 /**
- * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct
+ * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
  * @dev: DRM device
  * @preferred_bpp: Preferred bits per pixel for the device
  * @max_conn_count: Maximum number of connectors
- * @funcs: fb helper functions, in particular a custom dirty() callback
  *
  * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
  */
-struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
-       unsigned int preferred_bpp, unsigned int max_conn_count,
-       const struct drm_framebuffer_funcs *funcs)
+struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+       unsigned int preferred_bpp, unsigned int max_conn_count)
 {
        struct drm_fbdev_cma *fbdev_cma;
-       struct drm_fb_helper *helper;
+       struct drm_fb_helper *fb_helper;
        int ret;
 
        fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
-       if (!fbdev_cma) {
-               dev_err(dev->dev, "Failed to allocate drm fbdev.\n");
+       if (!fbdev_cma)
                return ERR_PTR(-ENOMEM);
-       }
-       fbdev_cma->fb_funcs = funcs;
 
-       helper = &fbdev_cma->fb_helper;
-
-       drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
+       fb_helper = &fbdev_cma->fb_helper;
 
-       ret = drm_fb_helper_init(dev, helper, max_conn_count);
-       if (ret < 0) {
-               dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
+       ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
+       if (ret)
                goto err_free;
-       }
-
-       ret = drm_fb_helper_single_add_all_connectors(helper);
-       if (ret < 0) {
-               dev_err(dev->dev, "Failed to add connectors.\n");
-               goto err_drm_fb_helper_fini;
-
-       }
 
-       ret = drm_fb_helper_initial_config(helper, preferred_bpp);
-       if (ret < 0) {
-               dev_err(dev->dev, "Failed to set initial hw configuration.\n");
-               goto err_drm_fb_helper_fini;
-       }
+       ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_cma_helper_funcs,
+                                       preferred_bpp, max_conn_count);
+       if (ret)
+               goto err_client_put;
 
        return fbdev_cma;
 
-err_drm_fb_helper_fini:
-       drm_fb_helper_fini(helper);
+err_client_put:
+       drm_client_release(&fb_helper->client);
 err_free:
        kfree(fbdev_cma);
 
        return ERR_PTR(ret);
 }
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs);
-
-static const struct drm_framebuffer_funcs drm_fb_cma_funcs = {
-       .destroy        = drm_gem_fb_destroy,
-       .create_handle  = drm_gem_fb_create_handle,
-};
-
-/**
- * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device
- * @max_conn_count: Maximum number of connectors
- *
- * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
- */
-struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
-       unsigned int preferred_bpp, unsigned int max_conn_count)
-{
-       return drm_fbdev_cma_init_with_funcs(dev, preferred_bpp,
-                                            max_conn_count,
-                                            &drm_fb_cma_funcs);
-}
 EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 
 /**
@@ -477,14 +187,7 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
 {
        drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
-       if (fbdev_cma->fb_helper.fbdev)
-               drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
-
-       if (fbdev_cma->fb_helper.fb)
-               drm_framebuffer_remove(fbdev_cma->fb_helper.fb);
-
-       drm_fb_helper_fini(&fbdev_cma->fb_helper);
-       kfree(fbdev_cma);
+       /* All resources have now been freed by drm_fbdev_fb_destroy() */
 }
 EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
 
index cab14f2533840e071bf3b5f8f32556511a565b76..4b0dd20bccb8f3cc2b7da96eb4c4203dabf2815f 100644 (file)
@@ -30,6 +30,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/console.h>
+#include <linux/dma-buf.h>
 #include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/slab.h>
@@ -66,6 +67,9 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * helper functions used by many drivers to implement the kernel mode setting
  * interfaces.
  *
+ * Drivers that support a dumb buffer with a virtual address and mmap support,
+ * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
+ *
  * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
  * down by calling drm_fb_helper_fbdev_teardown().
  *
@@ -738,6 +742,24 @@ static void drm_fb_helper_resume_worker(struct work_struct *work)
        console_unlock();
 }
 
+static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
+                                         struct drm_clip_rect *clip)
+{
+       struct drm_framebuffer *fb = fb_helper->fb;
+       unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
+       size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
+       void *src = fb_helper->fbdev->screen_buffer + offset;
+       void *dst = fb_helper->buffer->vaddr + offset;
+       size_t len = (clip->x2 - clip->x1) * cpp;
+       unsigned int y;
+
+       for (y = clip->y1; y < clip->y2; y++) {
+               memcpy(dst, src, len);
+               src += fb->pitches[0];
+               dst += fb->pitches[0];
+       }
+}
+
 static void drm_fb_helper_dirty_work(struct work_struct *work)
 {
        struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
@@ -753,8 +775,12 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
        spin_unlock_irqrestore(&helper->dirty_lock, flags);
 
        /* call dirty callback only when it has been really touched */
-       if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2)
+       if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) {
+               /* Generic fbdev uses a shadow buffer */
+               if (helper->buffer)
+                       drm_fb_helper_dirty_blit_real(helper, &clip_copy);
                helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+       }
 }
 
 /**
@@ -2323,6 +2349,20 @@ retry:
        return true;
 }
 
+static bool connector_has_possible_crtc(struct drm_connector *connector,
+                                       struct drm_crtc *crtc)
+{
+       struct drm_encoder *encoder;
+       int i;
+
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               if (encoder->possible_crtcs & drm_crtc_mask(crtc))
+                       return true;
+       }
+
+       return false;
+}
+
 static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
                          struct drm_fb_helper_crtc **best_crtcs,
                          struct drm_display_mode **modes,
@@ -2331,7 +2371,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
        int c, o;
        struct drm_connector *connector;
        const struct drm_connector_helper_funcs *connector_funcs;
-       struct drm_encoder *encoder;
        int my_score, best_score, score;
        struct drm_fb_helper_crtc **crtcs, *crtc;
        struct drm_fb_helper_connector *fb_helper_conn;
@@ -2362,20 +2401,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 
        connector_funcs = connector->helper_private;
 
-       /*
-        * If the DRM device implements atomic hooks and ->best_encoder() is
-        * NULL we fallback to the default drm_atomic_helper_best_encoder()
-        * helper.
-        */
-       if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
-           !connector_funcs->best_encoder)
-               encoder = drm_atomic_helper_best_encoder(connector);
-       else
-               encoder = connector_funcs->best_encoder(connector);
-
-       if (!encoder)
-               goto out;
-
        /*
         * select a crtc for this connector and then attempt to configure
         * remaining connectors
@@ -2383,7 +2408,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
        for (c = 0; c < fb_helper->crtc_count; c++) {
                crtc = &fb_helper->crtc_info[c];
 
-               if ((encoder->possible_crtcs & (1 << c)) == 0)
+               if (!connector_has_possible_crtc(connector,
+                                                crtc->mode_set.crtc))
                        continue;
 
                for (o = 0; o < n; o++)
@@ -2410,7 +2436,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
                               sizeof(struct drm_fb_helper_crtc *));
                }
        }
-out:
+
        kfree(crtcs);
        return best_score;
 }
@@ -2921,6 +2947,294 @@ void drm_fb_helper_output_poll_changed(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
 
+/* @user: 1=userspace, 0=fbcon */
+static int drm_fbdev_fb_open(struct fb_info *info, int user)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+
+       if (!try_module_get(fb_helper->dev->driver->fops->owner))
+               return -ENODEV;
+
+       return 0;
+}
+
+static int drm_fbdev_fb_release(struct fb_info *info, int user)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+
+       module_put(fb_helper->dev->driver->fops->owner);
+
+       return 0;
+}
+
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
+ * unregister_framebuffer() or fb_release().
+ */
+static void drm_fbdev_fb_destroy(struct fb_info *info)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+       struct fb_info *fbi = fb_helper->fbdev;
+       struct fb_ops *fbops = NULL;
+       void *shadow = NULL;
+
+       if (fbi->fbdefio) {
+               fb_deferred_io_cleanup(fbi);
+               shadow = fbi->screen_buffer;
+               fbops = fbi->fbops;
+       }
+
+       drm_fb_helper_fini(fb_helper);
+
+       if (shadow) {
+               vfree(shadow);
+               kfree(fbops);
+       }
+
+       drm_client_framebuffer_delete(fb_helper->buffer);
+       /*
+        * FIXME:
+        * Remove conditional when all CMA drivers have been moved over to using
+        * drm_fbdev_generic_setup().
+        */
+       if (fb_helper->client.funcs) {
+               drm_client_release(&fb_helper->client);
+               kfree(fb_helper);
+       }
+}
+
+static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+
+       if (fb_helper->dev->driver->gem_prime_mmap)
+               return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
+       else
+               return -ENODEV;
+}
+
+static struct fb_ops drm_fbdev_fb_ops = {
+       .owner          = THIS_MODULE,
+       DRM_FB_HELPER_DEFAULT_OPS,
+       .fb_open        = drm_fbdev_fb_open,
+       .fb_release     = drm_fbdev_fb_release,
+       .fb_destroy     = drm_fbdev_fb_destroy,
+       .fb_mmap        = drm_fbdev_fb_mmap,
+       .fb_read        = drm_fb_helper_sys_read,
+       .fb_write       = drm_fb_helper_sys_write,
+       .fb_fillrect    = drm_fb_helper_sys_fillrect,
+       .fb_copyarea    = drm_fb_helper_sys_copyarea,
+       .fb_imageblit   = drm_fb_helper_sys_imageblit,
+};
+
+static struct fb_deferred_io drm_fbdev_defio = {
+       .delay          = HZ / 20,
+       .deferred_io    = drm_fb_helper_deferred_io,
+};
+
+/**
+ * drm_fb_helper_generic_probe - Generic fbdev emulation probe helper
+ * @fb_helper: fbdev helper structure
+ * @sizes: describes fbdev size and scanout surface size
+ *
+ * This function uses the client API to crate a framebuffer backed by a dumb buffer.
+ *
+ * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
+ * fb_copyarea, fb_imageblit.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+                               struct drm_fb_helper_surface_size *sizes)
+{
+       struct drm_client_dev *client = &fb_helper->client;
+       struct drm_client_buffer *buffer;
+       struct drm_framebuffer *fb;
+       struct fb_info *fbi;
+       u32 format;
+       int ret;
+
+       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
+                     sizes->surface_width, sizes->surface_height,
+                     sizes->surface_bpp);
+
+       format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+       buffer = drm_client_framebuffer_create(client, sizes->surface_width,
+                                              sizes->surface_height, format);
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
+
+       fb_helper->buffer = buffer;
+       fb_helper->fb = buffer->fb;
+       fb = buffer->fb;
+
+       fbi = drm_fb_helper_alloc_fbi(fb_helper);
+       if (IS_ERR(fbi)) {
+               ret = PTR_ERR(fbi);
+               goto err_free_buffer;
+       }
+
+       fbi->par = fb_helper;
+       fbi->fbops = &drm_fbdev_fb_ops;
+       fbi->screen_size = fb->height * fb->pitches[0];
+       fbi->fix.smem_len = fbi->screen_size;
+       fbi->screen_buffer = buffer->vaddr;
+       strcpy(fbi->fix.id, "DRM emulated");
+
+       drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
+       drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height);
+
+       if (fb->funcs->dirty) {
+               struct fb_ops *fbops;
+               void *shadow;
+
+               /*
+                * fb_deferred_io_cleanup() clears &fbops->fb_mmap so a per
+                * instance version is necessary.
+                */
+               fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
+               shadow = vzalloc(fbi->screen_size);
+               if (!fbops || !shadow) {
+                       kfree(fbops);
+                       vfree(shadow);
+                       ret = -ENOMEM;
+                       goto err_fb_info_destroy;
+               }
+
+               *fbops = *fbi->fbops;
+               fbi->fbops = fbops;
+               fbi->screen_buffer = shadow;
+               fbi->fbdefio = &drm_fbdev_defio;
+
+               fb_deferred_io_init(fbi);
+       }
+
+       return 0;
+
+err_fb_info_destroy:
+       drm_fb_helper_fini(fb_helper);
+err_free_buffer:
+       drm_client_framebuffer_delete(buffer);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_fb_helper_generic_probe);
+
+static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
+       .fb_probe = drm_fb_helper_generic_probe,
+};
+
+static void drm_fbdev_client_unregister(struct drm_client_dev *client)
+{
+       struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+       if (fb_helper->fbdev) {
+               drm_fb_helper_unregister_fbi(fb_helper);
+               /* drm_fbdev_fb_destroy() takes care of cleanup */
+               return;
+       }
+
+       /* Did drm_fb_helper_fbdev_setup() run? */
+       if (fb_helper->dev)
+               drm_fb_helper_fini(fb_helper);
+
+       drm_client_release(client);
+       kfree(fb_helper);
+}
+
+static int drm_fbdev_client_restore(struct drm_client_dev *client)
+{
+       struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+       drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+
+       return 0;
+}
+
+static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
+{
+       struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+       struct drm_device *dev = client->dev;
+       int ret;
+
+       /* If drm_fb_helper_fbdev_setup() failed, we only try once */
+       if (!fb_helper->dev && fb_helper->funcs)
+               return 0;
+
+       if (dev->fb_helper)
+               return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+       if (!dev->mode_config.num_connector)
+               return 0;
+
+       ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs,
+                                       fb_helper->preferred_bpp, 0);
+       if (ret) {
+               fb_helper->dev = NULL;
+               fb_helper->fbdev = NULL;
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct drm_client_funcs drm_fbdev_client_funcs = {
+       .owner          = THIS_MODULE,
+       .unregister     = drm_fbdev_client_unregister,
+       .restore        = drm_fbdev_client_restore,
+       .hotplug        = drm_fbdev_client_hotplug,
+};
+
+/**
+ * drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device.
+ *                 @dev->mode_config.preferred_depth is used if this is zero.
+ *
+ * This function sets up generic fbdev emulation for drivers that supports
+ * dumb buffers with a virtual address and that can be mmap'ed.
+ *
+ * Restore, hotplug events and teardown are all taken care of. Drivers that do
+ * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
+ * Simple drivers might use drm_mode_config_helper_suspend().
+ *
+ * Drivers that set the dirty callback on their framebuffer will get a shadow
+ * fbdev buffer that is blitted onto the real buffer. This is done in order to
+ * make deferred I/O work with all kinds of buffers.
+ *
+ * This function is safe to call even when there are no connectors present.
+ * Setup will be retried on the next hotplug event.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+       struct drm_fb_helper *fb_helper;
+       int ret;
+
+       if (!drm_fbdev_emulation)
+               return 0;
+
+       fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+       if (!fb_helper)
+               return -ENOMEM;
+
+       ret = drm_client_new(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
+       if (ret) {
+               kfree(fb_helper);
+               return ret;
+       }
+
+       fb_helper->preferred_bpp = preferred_bpp;
+
+       drm_fbdev_client_hotplug(&fb_helper->client);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_fbdev_generic_setup);
+
 /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
  * but the module doesn't depend on any fb console symbols.  At least
  * attempt to load fbcon to avoid leaving the system without a usable console.
index 66bb403dc8abb5fad126c1f20679a41f96ef655a..ffa8dc35515ffaddf0f87c56cc2108e0be4151f6 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <drm/drm_client.h>
 #include <drm/drm_file.h>
 #include <drm/drmP.h>
 
@@ -444,6 +445,8 @@ void drm_lastclose(struct drm_device * dev)
 
        if (drm_core_check_feature(dev, DRIVER_LEGACY))
                drm_legacy_dev_reinit(dev);
+
+       drm_client_dev_restore(dev);
 }
 
 /**
index 5ca6395cd4d39c8f749738c0506fd815e818fcc9..35c1e2742c27751dc9de3a036334664c87b17cde 100644 (file)
@@ -152,27 +152,27 @@ const struct drm_format_info *__drm_format_info(u32 format)
                { .format = DRM_FORMAT_XBGR8888_A8,     .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
                { .format = DRM_FORMAT_RGBX8888_A8,     .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
                { .format = DRM_FORMAT_BGRX8888_A8,     .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
-               { .format = DRM_FORMAT_YUV410,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
-               { .format = DRM_FORMAT_YVU410,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
-               { .format = DRM_FORMAT_YUV411,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
-               { .format = DRM_FORMAT_YVU411,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
-               { .format = DRM_FORMAT_YUV420,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
-               { .format = DRM_FORMAT_YVU420,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
-               { .format = DRM_FORMAT_YUV422,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_YVU422,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_YUV444,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
-               { .format = DRM_FORMAT_YVU444,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
-               { .format = DRM_FORMAT_NV12,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
-               { .format = DRM_FORMAT_NV21,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
-               { .format = DRM_FORMAT_NV16,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_NV61,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_NV24,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
-               { .format = DRM_FORMAT_NV42,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
-               { .format = DRM_FORMAT_YUYV,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_YVYU,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_UYVY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_VYUY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
-               { .format = DRM_FORMAT_AYUV,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
+               { .format = DRM_FORMAT_YUV410,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
+               { .format = DRM_FORMAT_YVU410,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
+               { .format = DRM_FORMAT_YUV411,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YVU411,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YUV420,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+               { .format = DRM_FORMAT_YVU420,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+               { .format = DRM_FORMAT_YUV422,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YVU422,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YUV444,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YVU444,          .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_NV12,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+               { .format = DRM_FORMAT_NV21,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+               { .format = DRM_FORMAT_NV16,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_NV61,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_NV24,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_NV42,            .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YUYV,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_YVYU,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_UYVY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_VYUY,            .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+               { .format = DRM_FORMAT_AYUV,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
        };
 
        unsigned int i;
index 4a16d7b26c89c1a350e5720c46d917f29532e416..bf90625df3c5bf4f34f1a1d187064f46c3599aa1 100644 (file)
@@ -1036,6 +1036,15 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
                return -EACCES;
        }
 
+       if (node->readonly) {
+               if (vma->vm_flags & VM_WRITE) {
+                       drm_gem_object_put_unlocked(obj);
+                       return -EINVAL;
+               }
+
+               vma->vm_flags &= ~VM_MAYWRITE;
+       }
+
        ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
                               vma);
 
index 3c125041a597cc18c195a846ed3d30ea941f441c..ea10e9a26aadd5e8598e837ccd4375a15bfbe3dc 100644 (file)
@@ -641,7 +641,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
        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_mode_connector_property_set_ioctl, DRM_MASTER|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),
index ce4d2fb3281055be81e858f1b9a2707fdb7c31df..fcb0ab0abb75572a165341d00de8f83b01393aa9 100644 (file)
@@ -433,8 +433,7 @@ static int set_property_legacy(struct drm_mode_object *obj,
        drm_modeset_lock_all(dev);
        switch (obj->type) {
        case DRM_MODE_OBJECT_CONNECTOR:
-               ret = drm_mode_connector_set_obj_prop(obj, prop,
-                                                     prop_value);
+               ret = drm_connector_set_obj_prop(obj, prop, prop_value);
                break;
        case DRM_MODE_OBJECT_CRTC:
                ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
index 7f552d5fa88ee55b23cacfc8c8610da9a44c22f3..02db9ac82d7a91a9b7de054a71a92e377d27a3d5 100644 (file)
@@ -659,10 +659,12 @@ EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
  * drm_bus_flags_from_videomode - extract information about pixelclk and
  * DE polarity from videomode and store it in a separate variable
  * @vm: videomode structure to use
- * @bus_flags: information about pixelclk and DE polarity will be stored here
+ * @bus_flags: information about pixelclk, sync and DE polarity will be stored
+ * here
  *
- * Sets DRM_BUS_FLAG_DE_(LOW|HIGH) and DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE
- * in @bus_flags according to DISPLAY_FLAGS found in @vm
+ * Sets DRM_BUS_FLAG_DE_(LOW|HIGH),  DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE and
+ * DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
+ * found in @vm
  */
 void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
 {
@@ -672,6 +674,11 @@ void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
        if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
                *bus_flags |= DRM_BUS_FLAG_PIXDATA_NEGEDGE;
 
+       if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
+               *bus_flags |= DRM_BUS_FLAG_SYNC_POSEDGE;
+       if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE)
+               *bus_flags |= DRM_BUS_FLAG_SYNC_NEGEDGE;
+
        if (vm->flags & DISPLAY_FLAGS_DE_LOW)
                *bus_flags |= DRM_BUS_FLAG_DE_LOW;
        if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
@@ -684,7 +691,7 @@ EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
  * of_get_drm_display_mode - get a drm_display_mode from devicetree
  * @np: device_node with the timing specification
  * @dmode: will be set to the return value
- * @bus_flags: information about pixelclk and DE polarity
+ * @bus_flags: information about pixelclk, sync and DE polarity
  * @index: index into the list of display timings in devicetree
  *
  * This function is expensive and should only be used, if only one mode is to be
@@ -1346,7 +1353,7 @@ void drm_mode_sort(struct list_head *mode_list)
 EXPORT_SYMBOL(drm_mode_sort);
 
 /**
- * drm_mode_connector_list_update - update the mode list for the connector
+ * drm_connector_list_update - update the mode list for the connector
  * @connector: the connector to update
  *
  * This moves the modes from the @connector probed_modes list
@@ -1356,7 +1363,7 @@ EXPORT_SYMBOL(drm_mode_sort);
  * This is just a helper functions doesn't validate any modes itself and also
  * doesn't prune any invalid modes. Callers need to do that themselves.
  */
-void drm_mode_connector_list_update(struct drm_connector *connector)
+void drm_connector_list_update(struct drm_connector *connector)
 {
        struct drm_display_mode *pmode, *pt;
 
@@ -1405,7 +1412,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
                }
        }
 }
-EXPORT_SYMBOL(drm_mode_connector_list_update);
+EXPORT_SYMBOL(drm_connector_list_update);
 
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
index 3b8c7a6a5720da6e3d2b8157bdfba56659c4d512..2763a5ec845b0c14bff58b8aed4d8cb58d80d0a9 100644 (file)
@@ -9,6 +9,13 @@
 #include <drm/drm_panel.h>
 #include <drm/drm_of.h>
 
+/**
+ * DOC: overview
+ *
+ * A set of helper functions to aid DRM drivers in parsing standard DT
+ * properties.
+ */
+
 static void drm_release_of(struct device *dev, void *data)
 {
        of_node_put(data);
@@ -94,7 +101,7 @@ EXPORT_SYMBOL_GPL(drm_of_component_match_add);
  * drm_of_component_probe - Generic probe function for a component based master
  * @dev: master device containing the OF node
  * @compare_of: compare function used for matching components
- * @master_ops: component master ops to be used
+ * @m_ops: component master ops to be used
  *
  * Parse the platform device OF node and bind all the components associated
  * with the master. Interface ports are added before the encoders in order to
@@ -239,10 +246,17 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
        if (!remote)
                return -ENODEV;
 
+       if (!of_device_is_available(remote)) {
+               of_node_put(remote);
+               return -ENODEV;
+       }
+
        if (panel) {
                *panel = of_drm_find_panel(remote);
-               if (*panel)
+               if (!IS_ERR(*panel))
                        ret = 0;
+               else
+                       *panel = NULL;
        }
 
        /* No panel found yet, check for a bridge next. */
index 965530a6f4cd355cc82386a258b46f2363b63430..b902361dee6e1db300c10ce5798de7bada296b65 100644 (file)
@@ -151,12 +151,19 @@ EXPORT_SYMBOL(drm_panel_detach);
  * tree node. If a matching panel is found, return a pointer to it.
  *
  * Return: A pointer to the panel registered for the specified device tree
- * node or NULL if no panel matching the device tree node can be found.
+ * node or an ERR_PTR() if no panel matching the device tree node can be found.
+ * Possible error codes returned by this function:
+ * - EPROBE_DEFER: the panel device has not been probed yet, and the caller
+ *   should retry later
+ * - ENODEV: the device is not available (status != "okay" or "ok")
  */
 struct drm_panel *of_drm_find_panel(const struct device_node *np)
 {
        struct drm_panel *panel;
 
+       if (!of_device_is_available(np))
+               return ERR_PTR(-ENODEV);
+
        mutex_lock(&panel_lock);
 
        list_for_each_entry(panel, &panel_list, list) {
@@ -167,7 +174,7 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np)
        }
 
        mutex_unlock(&panel_lock);
-       return NULL;
+       return ERR_PTR(-EPROBE_DEFER);
 }
 EXPORT_SYMBOL(of_drm_find_panel);
 #endif
index df0b4ebbedbf4e8b803bfbdc5eb791dbad4bc8b7..6153cbda239fe6e6d6506503946c4119d77b7c46 100644 (file)
@@ -583,6 +583,52 @@ int drm_plane_check_pixel_format(struct drm_plane *plane,
        return 0;
 }
 
+static int __setplane_check(struct drm_plane *plane,
+                           struct drm_crtc *crtc,
+                           struct drm_framebuffer *fb,
+                           int32_t crtc_x, int32_t crtc_y,
+                           uint32_t crtc_w, uint32_t crtc_h,
+                           uint32_t src_x, uint32_t src_y,
+                           uint32_t src_w, uint32_t src_h)
+{
+       int ret;
+
+       /* Check whether this plane is usable on this CRTC */
+       if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
+               DRM_DEBUG_KMS("Invalid crtc for plane\n");
+               return -EINVAL;
+       }
+
+       /* Check whether this plane supports the fb pixel format. */
+       ret = drm_plane_check_pixel_format(plane, fb->format->format,
+                                          fb->modifier);
+       if (ret) {
+               struct drm_format_name_buf format_name;
+
+               DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
+                             drm_get_format_name(fb->format->format,
+                                                 &format_name),
+                             fb->modifier);
+               return ret;
+       }
+
+       /* Give drivers some help against integer overflows */
+       if (crtc_w > INT_MAX ||
+           crtc_x > INT_MAX - (int32_t) crtc_w ||
+           crtc_h > INT_MAX ||
+           crtc_y > INT_MAX - (int32_t) crtc_h) {
+               DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
+                             crtc_w, crtc_h, crtc_x, crtc_y);
+               return -ERANGE;
+       }
+
+       ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 /*
  * __setplane_internal - setplane handler for internal callers
  *
@@ -603,6 +649,8 @@ static int __setplane_internal(struct drm_plane *plane,
 {
        int ret = 0;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
+
        /* No fb means shut it down */
        if (!fb) {
                plane->old_fb = plane->fb;
@@ -616,37 +664,9 @@ static int __setplane_internal(struct drm_plane *plane,
                goto out;
        }
 
-       /* Check whether this plane is usable on this CRTC */
-       if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
-               DRM_DEBUG_KMS("Invalid crtc for plane\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* Check whether this plane supports the fb pixel format. */
-       ret = drm_plane_check_pixel_format(plane, fb->format->format,
-                                          fb->modifier);
-       if (ret) {
-               struct drm_format_name_buf format_name;
-               DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
-                             drm_get_format_name(fb->format->format,
-                                                 &format_name),
-                             fb->modifier);
-               goto out;
-       }
-
-       /* Give drivers some help against integer overflows */
-       if (crtc_w > INT_MAX ||
-           crtc_x > INT_MAX - (int32_t) crtc_w ||
-           crtc_h > INT_MAX ||
-           crtc_y > INT_MAX - (int32_t) crtc_h) {
-               DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
-                             crtc_w, crtc_h, crtc_x, crtc_y);
-               ret = -ERANGE;
-               goto out;
-       }
-
-       ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
+       ret = __setplane_check(plane, crtc, fb,
+                              crtc_x, crtc_y, crtc_w, crtc_h,
+                              src_x, src_y, src_w, src_h);
        if (ret)
                goto out;
 
@@ -655,11 +675,9 @@ static int __setplane_internal(struct drm_plane *plane,
                                         crtc_x, crtc_y, crtc_w, crtc_h,
                                         src_x, src_y, src_w, src_h, ctx);
        if (!ret) {
-               if (!plane->state) {
-                       plane->crtc = crtc;
-                       plane->fb = fb;
-                       drm_framebuffer_get(plane->fb);
-               }
+               plane->crtc = crtc;
+               plane->fb = fb;
+               drm_framebuffer_get(plane->fb);
        } else {
                plane->old_fb = NULL;
        }
@@ -672,6 +690,41 @@ out:
        return ret;
 }
 
+static int __setplane_atomic(struct drm_plane *plane,
+                            struct drm_crtc *crtc,
+                            struct drm_framebuffer *fb,
+                            int32_t crtc_x, int32_t crtc_y,
+                            uint32_t crtc_w, uint32_t crtc_h,
+                            uint32_t src_x, uint32_t src_y,
+                            uint32_t src_w, uint32_t src_h,
+                            struct drm_modeset_acquire_ctx *ctx)
+{
+       int ret;
+
+       WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
+
+       /* No fb means shut it down */
+       if (!fb)
+               return plane->funcs->disable_plane(plane, ctx);
+
+       /*
+        * FIXME: This is redundant with drm_atomic_plane_check(),
+        * but the legacy cursor/"async" .update_plane() tricks
+        * don't call that so we still need this here. Should remove
+        * this when all .update_plane() implementations have been
+        * fixed to call drm_atomic_plane_check().
+        */
+       ret = __setplane_check(plane, crtc, fb,
+                              crtc_x, crtc_y, crtc_w, crtc_h,
+                              src_x, src_y, src_w, src_h);
+       if (ret)
+               return ret;
+
+       return plane->funcs->update_plane(plane, crtc, fb,
+                                         crtc_x, crtc_y, crtc_w, crtc_h,
+                                         src_x, src_y, src_w, src_h, ctx);
+}
+
 static int setplane_internal(struct drm_plane *plane,
                             struct drm_crtc *crtc,
                             struct drm_framebuffer *fb,
@@ -689,9 +742,15 @@ retry:
        ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
        if (ret)
                goto fail;
-       ret = __setplane_internal(plane, crtc, fb,
-                                 crtc_x, crtc_y, crtc_w, crtc_h,
-                                 src_x, src_y, src_w, src_h, &ctx);
+
+       if (drm_drv_uses_atomic_modeset(plane->dev))
+               ret = __setplane_atomic(plane, crtc, fb,
+                                       crtc_x, crtc_y, crtc_w, crtc_h,
+                                       src_x, src_y, src_w, src_h, &ctx);
+       else
+               ret = __setplane_internal(plane, crtc, fb,
+                                         crtc_x, crtc_y, crtc_w, crtc_h,
+                                         src_x, src_y, src_w, src_h, &ctx);
 
 fail:
        if (ret == -EDEADLK) {
@@ -823,9 +882,14 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
                src_h = fb->height << 16;
        }
 
-       ret = __setplane_internal(plane, crtc, fb,
-                                 crtc_x, crtc_y, crtc_w, crtc_h,
-                                 0, 0, src_w, src_h, ctx);
+       if (drm_drv_uses_atomic_modeset(dev))
+               ret = __setplane_atomic(plane, crtc, fb,
+                                       crtc_x, crtc_y, crtc_w, crtc_h,
+                                       0, 0, src_w, src_h, ctx);
+       else
+               ret = __setplane_internal(plane, crtc, fb,
+                                         crtc_x, crtc_y, crtc_w, crtc_h,
+                                         0, 0, src_w, src_h, ctx);
 
        if (fb)
                drm_framebuffer_put(fb);
index 527743394150a83b684aba3b5c647ec10a0581a2..a1bb157bfdfaeb9bad32c5f39b200970547ec039 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/moduleparam.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_client.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_crtc_helper.h>
@@ -88,9 +89,9 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
                            struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       uint32_t *ids = connector->encoder_ids;
        enum drm_mode_status ret = MODE_OK;
-       unsigned int i;
+       struct drm_encoder *encoder;
+       int i;
 
        /* Step 1: Validate against connector */
        ret = drm_connector_mode_valid(connector, mode);
@@ -98,13 +99,9 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
                return ret;
 
        /* Step 2: Validate against encoders and crtcs */
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               struct drm_encoder *encoder = drm_encoder_find(dev, NULL, ids[i]);
+       drm_connector_for_each_possible_encoder(connector, encoder, i) {
                struct drm_crtc *crtc;
 
-               if (!encoder)
-                       continue;
-
                ret = drm_encoder_mode_valid(encoder, mode);
                if (ret != MODE_OK) {
                        /* No point in continuing for crtc check as this encoder
@@ -363,7 +360,7 @@ EXPORT_SYMBOL(drm_helper_probe_detect);
  *    using the VESA GTF/CVT formulas.
  *
  * 3. Modes are moved from the probed_modes list to the modes list. Potential
- *    duplicates are merged together (see drm_mode_connector_list_update()).
+ *    duplicates are merged together (see drm_connector_list_update()).
  *    After this step the probed_modes list will be empty again.
  *
  * 4. Any non-stale mode on the modes list then undergoes validation
@@ -475,7 +472,7 @@ retry:
        if (connector->status == connector_status_disconnected) {
                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
                        connector->base.id, connector->name);
-               drm_mode_connector_update_edid_property(connector, NULL);
+               drm_connector_update_edid_property(connector, NULL);
                verbose_prune = false;
                goto prune;
        }
@@ -488,7 +485,7 @@ retry:
        if (count == 0)
                goto prune;
 
-       drm_mode_connector_list_update(connector);
+       drm_connector_list_update(connector);
 
        if (connector->interlace_allowed)
                mode_flags |= DRM_MODE_FLAG_INTERLACE;
@@ -563,6 +560,8 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
        drm_sysfs_hotplug_event(dev);
        if (dev->mode_config.funcs->output_poll_changed)
                dev->mode_config.funcs->output_poll_changed(dev);
+
+       drm_client_dev_hotplug(dev);
 }
 EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
 
index b72fcf1e9605c6bca189019c7f06ed24ef3a2104..51fa978f0d236821ac020b16144f50e2fbb854bb 100644 (file)
@@ -287,7 +287,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
        if (ret || !connector)
                return ret;
 
-       return drm_mode_connector_attach_encoder(connector, encoder);
+       return drm_connector_attach_encoder(connector, encoder);
 }
 EXPORT_SYMBOL(drm_simple_display_pipe_init);
 
index 827395071f0b5ac27b3d3e3efa989461de603a5a..c20e6fe00cb387dba675f10d15ef75a7e39cf7cb 100644 (file)
  * Writeback connectors are used to expose hardware which can write the output
  * from a CRTC to a memory buffer. They are used and act similarly to other
  * types of connectors, with some important differences:
- *  - Writeback connectors don't provide a way to output visually to the user.
- *  - Writeback connectors should always report as "disconnected" (so that
- *    clients which don't understand them will ignore them).
- *  - Writeback connectors don't have EDID.
+ *
+ * * Writeback connectors don't provide a way to output visually to the user.
+ *
+ * * Writeback connectors are visible to userspace only when the client sets
+ *   DRM_CLIENT_CAP_WRITEBACK_CONNECTORS.
+ *
+ * * Writeback connectors don't have EDID.
  *
  * A framebuffer may only be attached to a writeback connector when the
  * connector is attached to a CRTC. The WRITEBACK_FB_ID property which sets the
@@ -199,7 +202,7 @@ int drm_writeback_connector_init(struct drm_device *dev,
        if (ret)
                goto connector_fail;
 
-       ret = drm_mode_connector_attach_encoder(connector,
+       ret = drm_connector_attach_encoder(connector,
                                                &wb_connector->encoder);
        if (ret)
                goto attach_fail;
index 86330f396784ddb8ecc0ba277ebefd0fe3ec50d7..af7ab1ceb50f4d0572b5c56aaa055cfb21b45133 100644 (file)
@@ -232,9 +232,11 @@ static int exynos_dp_probe(struct platform_device *pdev)
        np = of_parse_phandle(dev->of_node, "panel", 0);
        if (np) {
                dp->plat_data.panel = of_drm_find_panel(np);
+
                of_node_put(np);
-               if (!dp->plat_data.panel)
-                       return -EPROBE_DEFER;
+               if (IS_ERR(dp->plat_data.panel))
+                       return PTR_ERR(dp->plat_data.panel);
+
                goto out;
        }
 
index 66945e0dc57fc6c723fe8e891a0fa655d9358354..2f0babb67c5104be6f1e617d5baa57a64d74499c 100644 (file)
@@ -113,7 +113,7 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
@@ -240,8 +240,8 @@ struct drm_encoder *exynos_dpi_probe(struct device *dev)
 
        if (ctx->panel_node) {
                ctx->panel = of_drm_find_panel(ctx->panel_node);
-               if (!ctx->panel)
-                       return ERR_PTR(-EPROBE_DEFER);
+               if (IS_ERR(ctx->panel))
+                       return ERR_CAST(ctx->panel);
        }
 
        return &ctx->encoder;
index 6d29777884f931eab3cde84986823b5341f0df76..a1ed6146a3b5c476db81c4440b04d6a392b33617 100644 (file)
@@ -1479,7 +1479,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
 
        connector->status = connector_status_disconnected;
        drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
@@ -1519,6 +1519,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
        dsi->format = device->format;
        dsi->mode_flags = device->mode_flags;
        dsi->panel = of_drm_find_panel(device->dev.of_node);
+       if (IS_ERR(dsi->panel))
+               dsi->panel = NULL;
+
        if (dsi->panel) {
                drm_panel_attach(dsi->panel, &dsi->connector);
                dsi->connector.status = connector_status_connected;
index e6b0940b1ac273f95a12c9a747fd4097b1e3cd1c..19697c1362d8facf536a55485c45b2b2aaae6a85 100644 (file)
@@ -319,7 +319,7 @@ static int vidi_get_modes(struct drm_connector *connector)
                return -ENOMEM;
        }
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
 
        return drm_add_edid_modes(connector, edid);
 }
@@ -344,7 +344,7 @@ static int vidi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
index db91932550cf77d6459efab1b5540e7c8501dc38..3a11c719a58087a054c43076f432bcbe54656bb6 100644 (file)
@@ -888,7 +888,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
                (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
                edid->width_cm, edid->height_cm);
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        cec_notifier_set_phys_addr_from_edid(hdata->notifier, edid);
 
        ret = drm_add_edid_modes(connector, edid);
@@ -951,7 +951,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        if (hdata->bridge) {
                ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
index c54806d08dd78d0080ef42a314fe5ac2db40d7b6..2298ed2a9e1c02f8e3c37d7f6761a23f0a470ca3 100644 (file)
@@ -117,7 +117,7 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
        if (ret < 0)
                goto err_cleanup;
 
-       ret = drm_mode_connector_attach_encoder(connector, encoder);
+       ret = drm_connector_attach_encoder(connector, encoder);
        if (ret < 0)
                goto err_sysfs;
 
@@ -148,8 +148,9 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
        if (panel_node) {
                fsl_dev->connector.panel = of_drm_find_panel(panel_node);
                of_node_put(panel_node);
-               if (!fsl_dev->connector.panel)
-                       return -EPROBE_DEFER;
+               if (IS_ERR(fsl_dev->connector.panel))
+                       return PTR_ERR(fsl_dev->connector.panel);
+
                return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
        }
 
index 5ea785f07ba8eb9f0e7345356483c17547eea4d0..90ed20083009fb9bf6f3115f671da4edf26d559b 100644 (file)
@@ -1770,7 +1770,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector)
 
        edid = drm_get_edid(connector, &intel_dp->adapter);
        if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
        }
index f0878998526ac3c20b22827a21343f551c5072d2..4e4e4a66eaee3c7b2d3eca73632c9383f9a9a539 100644 (file)
@@ -216,7 +216,7 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector)
 
        edid = drm_get_edid(connector, &gma_encoder->i2c_bus->adapter);
        if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
        }
index 08f17f85b801df22633f74e8d6b9b106b9482983..09c1161a7ac635ebbfc9f4c80a9824b43286aead 100644 (file)
@@ -665,7 +665,7 @@ void gma_connector_attach_encoder(struct gma_connector *connector,
                                  struct gma_encoder *encoder)
 {
        connector->encoder = encoder;
-       drm_mode_connector_attach_encoder(&connector->base,
+       drm_connector_attach_encoder(&connector->base,
                                          &encoder->base);
 }
 
index 978ae4b25e82267ad448b68ed50c0c369c75dc11..e0ccf1d19a4dc46aee14aa3a6cf4581e90767f1e 100644 (file)
@@ -34,7 +34,7 @@ struct vbt_header {
        u8 reserved0;
        u32 bdb_offset;                 /**< from beginning of VBT */
        u32 aim_offset[4];              /**< from beginning of VBT */
-} __attribute__((packed));
+} __packed;
 
 
 struct bdb_header {
@@ -61,7 +61,7 @@ struct vbios_data {
        u8 rsvd4; /* popup memory size */
        u8 resize_pci_bios;
        u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
+} __packed;
 
 /*
  * There are several types of BIOS data blocks (BDBs), each block has
@@ -133,7 +133,7 @@ struct bdb_general_features {
        u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
        u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
        u8 rsvd11:3; /* finish byte */
-} __attribute__((packed));
+} __packed;
 
 /* pre-915 */
 #define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
@@ -213,7 +213,7 @@ struct child_device_config {
        u8  dvo2_wiring;
        u16 extended_type;
        u8  dvo_function;
-} __attribute__((packed));
+} __packed;
 
 
 struct bdb_general_definitions {
@@ -256,7 +256,7 @@ struct bdb_lvds_options {
        u8 lvds_edid:1;
        u8 rsvd2:1;
        u8 rsvd4;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_backlight {
        u8 type:2;
@@ -268,7 +268,7 @@ struct bdb_lvds_backlight {
        u8 i2caddr;
        u8 brightnesscmd;
        /*FIXME: more...*/
-} __attribute__((packed));
+} __packed;
 
 /* LFP pointer table contains entries to the struct below */
 struct bdb_lvds_lfp_data_ptr {
@@ -278,12 +278,12 @@ struct bdb_lvds_lfp_data_ptr {
        u8 dvo_table_size;
        u16 panel_pnp_id_offset;
        u8 pnp_table_size;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data_ptrs {
        u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
        struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
+} __packed;
 
 /* LFP data has 3 blocks per entry */
 struct lvds_fp_timing {
@@ -300,7 +300,7 @@ struct lvds_fp_timing {
        u32 pfit_reg;
        u32 pfit_reg_val;
        u16 terminator;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_dvo_timing {
        u16 clock;              /**< In 10khz */
@@ -328,7 +328,7 @@ struct lvds_dvo_timing {
        u8 vsync_positive:1;
        u8 hsync_positive:1;
        u8 rsvd2:1;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_pnp_id {
        u16 mfg_name;
@@ -336,17 +336,17 @@ struct lvds_pnp_id {
        u32 serial;
        u8 mfg_week;
        u8 mfg_year;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data_entry {
        struct lvds_fp_timing fp_timing;
        struct lvds_dvo_timing dvo_timing;
        struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data {
        struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_header {
        char signature[16];
@@ -354,12 +354,12 @@ struct aimdb_header {
        u16 aimdb_version;
        u16 aimdb_header_size;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_block {
        u8 aimdb_id;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_panel_data {
        u16 fp_timing_offset;
@@ -370,12 +370,12 @@ struct vch_panel_data {
        u8 text_fitting_size;
        u16 graphics_fitting_offset;
        u8 graphics_fitting_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_bdb_22 {
        struct aimdb_block aimdb_block;
        struct vch_panel_data panels[16];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_sdvo_lvds_options {
        u8 panel_backlight;
@@ -391,7 +391,7 @@ struct bdb_sdvo_lvds_options {
        u8 panel_misc_bits_2;
        u8 panel_misc_bits_3;
        u8 panel_misc_bits_4;
-} __attribute__((packed));
+} __packed;
 
 #define BDB_DRIVER_FEATURE_NO_LVDS             0
 #define BDB_DRIVER_FEATURE_INT_LVDS            1
@@ -436,7 +436,7 @@ struct bdb_driver_features {
 
        u8 hdmi_termination;
        u8 custom_vbt_version;
-} __attribute__((packed));
+} __packed;
 
 #define EDP_18BPP      0
 #define EDP_24BPP      1
index a05c020602bda439b03fabdae42781d3dc627385..d0bf5a1e94e8751b187538822c463447a432565f 100644 (file)
@@ -999,7 +999,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
                                p_funcs->encoder_helper_funcs);
 
        /*attach to given connector*/
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        /*set possible crtcs and clones*/
        if (dsi_connector->pipe) {
index 78566a80ad255acc35840a6668ee4ba9383ab29b..c6d72de1c0548bc79e92d76b9946a8a06bd55bbf 100644 (file)
@@ -578,7 +578,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
        }
 
        if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
        }
        return ret;
index e6943fef0611d1202c1f4cab9bda5efe28cdb2d2..83babb815a5d83bde5c87aad065b23aeb444ddbb 100644 (file)
@@ -376,7 +376,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
         * preferred mode is the right one.
         */
        if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                drm_add_edid_modes(connector, edid);
                kfree(edid);
 
index e5360726d80b7531df0006c25327de9e36eac127..fb4da3cd668163c9eba1b491e37615cad195ef84 100644 (file)
@@ -66,7 +66,7 @@ int psb_intel_ddc_get_modes(struct drm_connector *connector,
 
        edid = drm_get_edid(connector, adapter);
        if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
+               drm_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
        }
index 1d40746ab6259d210e5332162667ab5032d13d2a..dd3cec0e3190c835e04c8313410b8bfc88c8eb32 100644 (file)
@@ -1472,7 +1472,7 @@ static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector)
                bool connector_is_digital = !!IS_TMDS(psb_intel_sdvo_connector);
 
                if (connector_is_digital == monitor_is_digital) {
-                       drm_mode_connector_update_edid_property(connector, edid);
+                       drm_connector_update_edid_property(connector, edid);
                        drm_add_edid_modes(connector, edid);
                }
 
index d2f4749ebf8dcf1fe0e685f7d756859a8883d249..744956cea7496afd8ec2672bd953eaf67ef661c3 100644 (file)
@@ -133,7 +133,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
        }
 
        drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
-       drm_mode_connector_attach_encoder(connector, encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return 0;
 }
index 0038c976536ac41d3e0f43f156d81c0fead5e50c..eecdc327b9f880062922351efa8487b82db41c91 100644 (file)
@@ -1243,7 +1243,7 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
                return 0;
        }
 
-       drm_mode_connector_update_edid_property(connector, edid);
+       drm_connector_update_edid_property(connector, edid);
        n = drm_add_edid_modes(connector, edid);
 
        kfree(edid);
@@ -1301,7 +1301,7 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
        if (ret)
                return ret;
 
-       drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
+       drm_connector_attach_encoder(&priv->connector, &priv->encoder);
 
        return 0;
 }
index 9de8b1c51a5ccda8f6f7140f90ed4707b40d1da3..459f8f88a34cda0747ca37e7ccf43c4ca64fe283 100644 (file)
@@ -51,6 +51,18 @@ config DRM_I915_DEBUG_GEM
 
           If in doubt, say "N".
 
+config DRM_I915_ERRLOG_GEM
+       bool "Insert extra logging (very verbose) for common GEM errors"
+       default n
+       depends on DRM_I915_DEBUG_GEM
+       help
+         Enable additional logging that may help track down the cause of
+         principally userspace errors.
+
+         Recommended for driver developers only.
+
+         If in doubt, say "N".
+
 config DRM_I915_TRACE_GEM
        bool "Insert extra ftrace output from the GEM internals"
        depends on DRM_I915_DEBUG_GEM
index 4c6adae23e18e18195e468e2abb959cf0ed67219..5794f102f9b8f0cde364f2a04123e1893ffbfd84 100644 (file)
@@ -135,15 +135,14 @@ i915-y += dvo_ch7017.o \
          dvo_ns2501.o \
          dvo_sil164.o \
          dvo_tfp410.o \
+         icl_dsi.o \
          intel_crt.o \
          intel_ddi.o \
          intel_dp_aux_backlight.o \
          intel_dp_link_training.o \
          intel_dp_mst.o \
          intel_dp.o \
-         intel_dsi.o \
          intel_dsi_dcs_backlight.o \
-         intel_dsi_pll.o \
          intel_dsi_vbt.o \
          intel_dvo.o \
          intel_hdmi.o \
@@ -152,7 +151,9 @@ i915-y += dvo_ch7017.o \
          intel_lvds.o \
          intel_panel.o \
          intel_sdvo.o \
-         intel_tv.o
+         intel_tv.o \
+         vlv_dsi.o \
+         vlv_dsi_pll.o
 
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
index 642e216e0a5b9c28b0d8e2176b781a4165a58fe5..39980dfbbebde6ff96942eb2ee3bd6875bc880ef 100644 (file)
@@ -216,16 +216,22 @@ static struct gtt_type_table_entry gtt_type_table[] = {
                        GTT_TYPE_PPGTT_PDE_PT,
                        GTT_TYPE_PPGTT_PTE_PT,
                        GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+       /* We take IPS bit as 'PSE' for PTE level. */
        GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT,
                        GTT_TYPE_PPGTT_PTE_4K_ENTRY,
                        GTT_TYPE_PPGTT_PTE_PT,
                        GTT_TYPE_INVALID,
-                       GTT_TYPE_INVALID),
+